Beispiel #1
0
/*!
 * Decrement (lock) semaphore value by 1 (if not 0 when thread is blocked)
 * \param sem Semaphore descriptor (user level descriptor)
 * \return 0 if successful, -1 otherwise and appropriate error number is set
 */
int sys__sem_wait ( sem_t *sem )
{
	ksem_t *ksem;
	kobject_t *kobj;
	kthread_t *kthread;

	SYS_ENTRY();

	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 );
	kthread_set_syscall_retval ( kthread, EXIT_SUCCESS );

	if ( ksem->sem_value > 0 )
	{
		ksem->sem_value--;
		ksem->last_lock = kthread;
	}
	else {
		kthread_enqueue ( kthread, &ksem->queue );
		kthreads_schedule ();
	}

	SYS_EXIT ( kthread_get_errno(NULL), kthread_get_syscall_retval(NULL) );
}
Beispiel #2
0
/*!
 * 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) );
}
Beispiel #3
0
/*!
 * 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 ( sem_t *sem )
{
	ksem_t *ksem;
	kobject_t *kobj;
	kthread_t *kthread, *released;

	SYS_ENTRY();

	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 );
	kthread_set_syscall_retval ( 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 its value
		 * reaches zero (small extension of POSIX semaphore) */
		ksem->sem_value++;
	}
	else {
		kthreadq_release ( &ksem->queue );
		kthreads_schedule ();
	}

	SYS_EXIT ( kthread_get_errno(NULL), kthread_get_syscall_retval(NULL) );
}
Beispiel #4
0
/*!
 * 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 );
	}
}
Beispiel #5
0
int sys__get_errno ( void *p )
{
	return kthread_get_errno (NULL);
}
Beispiel #6
0
int sys__get_errno ()
{
	SYS_ENTRY();
	SYS_RETURN ( kthread_get_errno (NULL) );
}