/*! * Unlock mutex object * \param mutex Mutex descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_mutex_unlock ( void *p ) { pthread_mutex_t *mutex; kpthread_mutex_t *kmutex; kobject_t *kobj; mutex = *( (pthread_mutex_t **) p ); ASSERT_ERRNO_AND_EXIT ( mutex, EINVAL ); kobj = mutex->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EINVAL ); kmutex = kobj->kobject; ASSERT_ERRNO_AND_EXIT ( kmutex && kmutex->id == mutex->id, EINVAL ); if ( kmutex->owner != kthread_get_active() ) { SET_ERRNO ( EPERM ); return EXIT_FAILURE; } SET_ERRNO ( EXIT_SUCCESS ); kmutex->owner = kthreadq_get ( &kmutex->queue ); if ( kmutex->owner ) { kthreadq_release ( &kmutex->queue ); kthreads_schedule (); } return EXIT_SUCCESS; }
/*! Unlock device */ int k_device_unlock ( kdevice_t *dev ) { if ( kthreadq_release ( &dev->thrq ) ) kthreads_schedule (); else dev->locked = FALSE; return 0; }
/*! * Release all threads from given queue (if queue not empty) * \param q Queue * \return number of thread released, 0 if queue was empty */ int kthreadq_release_all ( kthread_q *q ) { ASSERT ( q ); int cnt = 0; while ( kthreadq_release (q) ) cnt++; return cnt; }
/*! * 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) ); }
/*! * Increment (lock) semaphore value by 1 (or unblock one thread that is blocked) * \param sem Semaphore descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__sem_post ( void *p ) { sem_t *sem; ksem_t *ksem; kobject_t *kobj; kthread_t *kthread, *released; sem = *( (sem_t **) p ); ASSERT_ERRNO_AND_EXIT ( sem, EINVAL ); kthread = kthread_get_active (); kobj = sem->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EINVAL ); ksem = kobj->kobject; ASSERT_ERRNO_AND_EXIT ( ksem && ksem->id == sem->id, EINVAL ); kthread_set_errno ( kthread, EXIT_SUCCESS ); released = kthreadq_get ( &ksem->queue ); /* first to release */ if ( !released || ksem->sem_value < 0 ) { /* if initial semaphore value (set by sem_init) was negative, * semaphore will not release threads until until its value * reaches zero (small extension of POSIX semaphore) */ ksem->sem_value++; } else { kthreadq_release ( &ksem->queue ); kthreads_schedule (); } return EXIT_SUCCESS; }