/*! * Suspend thread until given time elapses * \param clockid Clock to use * \param flags Flags (TIMER_ABSTIME) * \param request Suspend duration * \param remain Remainder time if interrupted during suspension * \return status */ int sys__clock_nanosleep ( void *p ) { clockid_t clockid; int flags; timespec_t *request; timespec_t *remain; int retval = EXIT_SUCCESS; kthread_t *kthread = kthread_get_active (); ktimer_t *ktimer; sigevent_t evp; itimerspec_t itimer; clockid = *( (clockid_t *) p ); p += sizeof (clockid_t); flags = *( (int *) p ); p += sizeof (int); request = *( (timespec_t **) p ); p += sizeof (timespec_t *); remain = *( (timespec_t **) p ); ASSERT_ERRNO_AND_EXIT ( (clockid==CLOCK_REALTIME || clockid==CLOCK_MONOTONIC) && request && TIME_IS_SET(request), EINVAL ); /* Timers are used for "sleep" operations through steps 1-4 */ /* 1. create timer, but not arm it yet */ evp.sigev_notify = SIGEV_WAKE_THREAD; evp.sigev_value.sival_ptr = kthread; evp.sigev_notify_function = kclock_wake_thread; retval += ktimer_create ( clockid, &evp, &ktimer, kthread ); ASSERT ( retval == EXIT_SUCCESS ); /* save remainder location, if provided */ ktimer->param = remain; /* 2. suspend thread */ kthread_set_private_param ( kthread, ktimer ); retval += kthread_suspend ( kthread, kclock_interrupt_sleep, ktimer ); ASSERT ( retval == EXIT_SUCCESS ); /* 3. arm timer */ TIME_RESET ( &itimer.it_interval ); itimer.it_value = *request; retval += ktimer_settime ( ktimer, flags, &itimer, NULL ); ASSERT ( retval == EXIT_SUCCESS ); /* 4. pick other thread as active */ kthreads_schedule (); EXIT ( retval ); }
/*! * Wait on conditional variable * \param cond conditional variable descriptor (user level descriptor) * \param mutex Mutex descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_cond_wait ( void *p ) { pthread_cond_t *cond; pthread_mutex_t *mutex; kpthread_cond_t *kcond; kpthread_mutex_t *kmutex; kobject_t *kobj_cond, *kobj_mutex; int retval = EXIT_SUCCESS; cond = *( (pthread_cond_t **) p ); p += sizeof (pthread_cond_t *); mutex = *( (pthread_mutex_t **) p ); ASSERT_ERRNO_AND_EXIT ( cond && mutex, EINVAL ); kobj_cond = cond->ptr; ASSERT_ERRNO_AND_EXIT ( kobj_cond, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj_cond->list ), EINVAL ); kcond = kobj_cond->kobject; ASSERT_ERRNO_AND_EXIT ( kcond && kcond->id == cond->id, EINVAL ); kobj_mutex = mutex->ptr; ASSERT_ERRNO_AND_EXIT ( kobj_mutex, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj_mutex->list), EINVAL ); kmutex = kobj_mutex->kobject; ASSERT_ERRNO_AND_EXIT ( kmutex && kmutex->id == mutex->id, EINVAL ); ASSERT_ERRNO_AND_EXIT ( kmutex->owner == kthread_get_active(), EPERM ); SET_ERRNO ( EXIT_SUCCESS ); /* move thread in conditional variable queue */ kthread_enqueue ( NULL, &kcond->queue, 0, NULL, NULL ); /* save reference to mutex object */ kthread_set_private_param ( NULL, kobj_mutex ); /* release mutex */ kmutex->owner = kthreadq_get ( &kmutex->queue ); if ( kmutex->owner ) kthreadq_release ( &kmutex->queue ); kthreads_schedule (); return retval; }
/*! * Wait on conditional variable * \param cond conditional variable descriptor (user level descriptor) * \param mutex Mutex descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_cond_wait ( pthread_cond_t *cond, pthread_mutex_t *mutex ) { kpthread_cond_t *kcond; kpthread_mutex_t *kmutex; kobject_t *kobj_cond, *kobj_mutex; SYS_ENTRY(); ASSERT_ERRNO_AND_EXIT ( cond && mutex, EINVAL ); kobj_cond = cond->ptr; ASSERT_ERRNO_AND_EXIT ( kobj_cond, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj_cond->list ), EINVAL ); kcond = kobj_cond->kobject; ASSERT_ERRNO_AND_EXIT ( kcond && kcond->id == cond->id, EINVAL ); kobj_mutex = mutex->ptr; ASSERT_ERRNO_AND_EXIT ( kobj_mutex, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj_mutex->list), EINVAL ); kmutex = kobj_mutex->kobject; ASSERT_ERRNO_AND_EXIT ( kmutex && kmutex->id == mutex->id, EINVAL ); ASSERT_ERRNO_AND_EXIT ( kmutex->owner == kthread_get_active(), EPERM ); kthread_set_errno ( NULL, EXIT_SUCCESS ); kthread_set_syscall_retval ( NULL, EXIT_SUCCESS ); /* move thread in conditional variable queue */ kthread_enqueue ( NULL, &kcond->queue ); /* save reference to mutex object */ kthread_set_private_param ( NULL, kobj_mutex ); /* release mutex */ kmutex->owner = kthreadq_get ( &kmutex->queue ); if ( kmutex->owner ) kthreadq_release ( &kmutex->queue ); kthreads_schedule (); SYS_EXIT ( kthread_get_errno(NULL), kthread_get_syscall_retval(NULL) ); }
/*! * Wait for thread termination * \param thread Thread descriptor (user level descriptor) * \param retval Where to store exit status of joined thread * \return 0 if thread already gone; -1 if not finished and 'wait' not set; * 'thread exit status' otherwise */ int sys__pthread_join ( void *p ) { pthread_t *thread; void **retval; kthread_t *kthread; int ret_value = 0; thread = *( (pthread_t **) p ); p += sizeof (pthread_t *); retval = *( (void ***) p ); ASSERT_ERRNO_AND_EXIT ( thread, ESRCH ); kthread = thread->ptr; if ( kthread_get_id (kthread) != thread->id ) { /* at 'kthread' is now something else */ ret_value = EXIT_FAILURE; SET_ERRNO ( ESRCH ); } else if ( kthread_is_alive (kthread) ) { ret_value = EXIT_SUCCESS; SET_ERRNO ( EXIT_SUCCESS ); kthread_set_private_param ( kthread_get_active(), retval ); kthread_wait_thread ( NULL, kthread ); kthreads_schedule (); } else { /* target thread is passive, collect status and free descr. */ ret_value = EXIT_SUCCESS; SET_ERRNO ( EXIT_SUCCESS ); kthread_collect_status ( kthread, retval ); } return ret_value; }
/*! * Wait for thread termination * \param thread Thread descriptor (user level descriptor) * \param retval Where to store exit status of joined thread * \return 0 if thread already gone; -1 if not finished and 'wait' not set; * 'thread exit status' otherwise */ int sys__pthread_join ( pthread_t *thread, void **retval ) { kthread_t *kthread; SYS_ENTRY(); ASSERT_ERRNO_AND_EXIT ( thread, ESRCH ); kthread = thread->ptr; if ( kthread_get_id (kthread) != thread->id ) { /* at 'kthread' is now something else */ SYS_EXIT ( ESRCH, EXIT_FAILURE ); } else if ( kthread_is_alive (kthread) ) { kthread_set_errno ( NULL, EXIT_SUCCESS ); kthread_set_syscall_retval ( NULL, EXIT_SUCCESS ); kthread_set_private_param ( kthread_get_active(), retval ); kthread_wait_thread ( NULL, kthread ); kthreads_schedule (); SYS_EXIT ( kthread_get_errno(NULL), kthread_get_syscall_retval(NULL) ); } else { /* target thread is passive, collect status and free descr. */ kthread_collect_status ( kthread, retval ); SYS_EXIT ( EXIT_SUCCESS, EXIT_SUCCESS ); } }