Esempio n. 1
0
/*!
 * Create new timer
 * \param clockid	Clock used in timer
 * \param evp		Timer expiration action
 * \param timerid	Timer descriptor is returned in this variable
 * \return status	0 for success
 */
int sys__timer_create ( void *p )
{
	clockid_t clockid;
	sigevent_t *evp;
	timer_t *timerid;

	ktimer_t *ktimer;
	int retval = EXIT_SUCCESS;
	kobject_t *kobj;

	clockid =	*( (clockid_t *) p );	p += sizeof (clockid_t);
	evp =		*( (sigevent_t **) p );	p += sizeof (sigevent_t *);
	timerid =	*( (timer_t **) p );

	ASSERT_ERRNO_AND_EXIT (
	clockid == CLOCK_REALTIME || clockid == CLOCK_MONOTONIC, EINVAL );
	ASSERT_ERRNO_AND_EXIT ( evp && timerid, EINVAL );

	retval = ktimer_create ( clockid, evp, &ktimer, kthread_get_active() );
	if ( retval == EXIT_SUCCESS )
	{
		kobj = kmalloc_kobject ( 0 );
		kobj->kobject = ktimer;
		timerid->id = ktimer->id;
		timerid->ptr = kobj;
	}
	EXIT ( retval );
}
Esempio n. 2
0
/*!
 * Lock 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_lock ( void *p )
{
	pthread_mutex_t *mutex;

	kpthread_mutex_t *kmutex;
	kobject_t *kobj;
	int retval = EXIT_SUCCESS;

	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 );

	retval = mutex_lock ( kmutex, kthread_get_active () );

	if ( retval == 1 )
		kthreads_schedule ();

	return retval != -1;
}
Esempio n. 3
0
/*!
 * Send signal to thread (from thread)
 * \param pid Thread descriptor (user level descriptor)
 * \param signo Signal number
 * \param sigval Parameter to send with signal
 * \return 0 if successful, -1 otherwise and appropriate error number is set
 */
int sys__sigqueue ( void *p )
{
	pid_t pid;
	int signo;
	sigval_t sigval;

	pthread_t thread, sender;
	kthread_t *kthread;
	siginfo_t sig;

	pid =    *( (pid_t *) p );	p += sizeof (pid_t);
	signo =  *( (int *) p );	p += sizeof (int);
	sigval = *( (sigval_t *) p );

	ASSERT_ERRNO_AND_EXIT ( signo > 0 && signo <= SIGMAX, EINVAL );

	thread = (pthread_t) pid; /* pid_t should be pthread_t */
	ASSERT_ERRNO_AND_EXIT ( thread.ptr, EINVAL );

	kthread = thread.ptr;
	ASSERT_ERRNO_AND_EXIT ( kthread_get_id (kthread) == thread.id, EINVAL );
	ASSERT_ERRNO_AND_EXIT ( kthread_check_kthread ( kthread ), EINVAL );

	sender.id = kthread_get_id (NULL);
	sender.ptr = kthread_get_active ();

	sig.si_signo = signo;
	sig.si_value = sigval;
	sig.si_pid = sender;
	sig.si_code = SI_USER;
	sig.si_errno = 0;

	EXIT ( ksignal_queue ( kthread, &sig ) );
}
Esempio n. 4
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 ( void *p )
{
	sem_t *sem;

	ksem_t *ksem;
	kobject_t *kobj;
	kthread_t *kthread;

	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 );

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

	return EXIT_SUCCESS;
}
Esempio n. 5
0
/*!
 * 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;
}
Esempio n. 6
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) );
}
Esempio n. 7
0
/*!
 * Lock 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_lock ( pthread_mutex_t *mutex )
{
	kpthread_mutex_t *kmutex;
	kobject_t *kobj;
	int retval = EXIT_SUCCESS;

	SYS_ENTRY();

	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 );

	retval = mutex_lock ( kmutex, kthread_get_active () );

	if ( retval == 1 )
		kthreads_schedule ();

	 /* errno is already set */
	if ( retval != -1 )
		SYS_RETURN ( EXIT_SUCCESS );
	else
		SYS_RETURN ( EXIT_FAILURE );
}
Esempio n. 8
0
/*!
 * End current thread (exit from it)
 * \param retval Pointer to exit status
 */
int sys__pthread_exit ( void *p )
{
	void *retval;

	retval = *( (void **) p );
	kthread_exit ( kthread_get_active(), retval, FALSE );

	return 0;
}
Esempio n. 9
0
/*!
 * End current thread (exit from it)
 * \param retval Pointer to exit status
 */
int sys__pthread_exit ( void *retval )
{
	SYS_ENTRY();

	kthread_exit ( kthread_get_active(), retval );

	ASSERT ( FALSE ); /* should not return here! */

	SYS_EXIT ( EXIT_FAILURE, EXIT_FAILURE );
}
Esempio n. 10
0
/*!
 * Select ready thread with highest priority  as active
 * - if different from current, move current into ready queue (id not NULL) and
 *   move selected thread from ready queue to active queue
 */
void kthreads_schedule ()
{
	kthread_t *curr, *next = NULL;

	curr = kthread_get_active();
	next = get_first_ready ();

	/* must exist an thread to return to, 'curr' or first from 'ready' */
	ASSERT ( ( curr && kthread_is_active ( curr ) ) || next );

	if ( !sys__feature ( FEATURE_SCHEDULER, FEATURE_GET, 0 ) &&
		curr && kthread_is_active ( curr ) )
		return;/*scheduler disabled, don't switch from current thread */

	if ( !curr || !kthread_is_active ( curr ) ||
		kthread_get_prio ( curr ) < kthread_get_prio ( next ) )
	{
		if ( curr && !kthread_is_passive (curr) ) /* deactivate curr */
		{
			/* move last active to ready queue, if still ready */
			if ( kthread_is_active ( curr ) )
				kthread_move_to_ready ( curr, LAST );

			/* deactivation might change ready thread list */
			next = get_first_ready ();
			ASSERT (next);
		}

		/* activate next */
		next = kthread_remove_from_ready ( next );
		ASSERT ( next );

		kthread_set_active ( next );
	}

	/* process pending signals (if any) */
	ksignal_process_pending ( kthread_get_active() );

	if ( curr != kthread_get_active() )
		kthread_switch_to_thread ( curr, kthread_get_active() );
	/* else => continue with current thread */
}
Esempio n. 11
0
/*!
 * 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 );
}
Esempio n. 12
0
/*! Return calling thread descriptor
 * \param thread Thread descriptor (user level descriptor)
 * \return 0
 */
int sys__pthread_self ( pthread_t *thread )
{
	SYS_ENTRY();

	ASSERT_ERRNO_AND_EXIT ( thread, ESRCH );

	thread->ptr = kthread_get_active ();
	thread->id = kthread_get_id (NULL);

	SYS_EXIT ( EXIT_SUCCESS, EXIT_SUCCESS );
}
Esempio n. 13
0
/*!
 * Simple Round-Robin scheduler:
 * - on timer tick move active into ready queue and pick next ready task
 */
static void  ksched_rr_tick ( sigval_t sigval )
{
	if ( sys__feature ( FEATURE_SCHED_RR, FEATURE_GET, 0 ) == 0 )
		return;

	kthread_t *active_thread = kthread_get_active();
	if ( kthread_is_active ( active_thread ) ) {
		kthread_move_to_ready ( active_thread, LAST );
		kthreads_schedule ();
	}
}
Esempio n. 14
0
/*!
 * Wait for signal
 * \param set Signals thread is waiting for
 * \param info Where to save caught signal
 * \return signal number if signal is caught,
 *         -1 otherwise and appropriate error number is set
 */
int sys__sigwaitinfo ( void *p )
{
	sigset_t *set;
	siginfo_t *info;

	kthread_t *kthread;
	ksignal_handling_t *sh;
	ksiginfo_t *ksig, *next;
	int retval;

	set =   *( (sigset_t **) p );		p += sizeof (sigset_t *);
	info =  *( (siginfo_t **) p );

	ASSERT_ERRNO_AND_EXIT ( set, EINVAL );
	set = U2K_GET_ADR ( set, kthread_get_process (NULL) );
	ASSERT_ERRNO_AND_EXIT ( set, EINVAL );

	if ( info )
		info = U2K_GET_ADR ( info, kthread_get_process (NULL) );

	kthread = kthread_get_active ();
	sh = kthread_get_sigparams ( kthread );

	/* first, search for such signal in pending signals */
	ksig = list_get ( &sh->pending_signals, FIRST );
	while ( ksig )
	{
		next = list_get_next ( &ksig->list );

		if ( sigtestset ( set, ksig->siginfo.si_signo ) )
		{
			retval = ksig->siginfo.si_signo;
			if ( info )
				*info = ksig->siginfo;

			list_remove ( &sh->pending_signals, 0, &ksig->list );
			kfree ( ksig );

			EXIT2 ( EXIT_SUCCESS, retval );
		}

		ksig = next;
	}

	/*
	 * if no pending signal found that matches given mask
	 * suspend thread until signal is received
	 */
	kthread_suspend ( kthread, ksignal_received_signal, NULL );
	kthreads_schedule ();

	EXIT ( EINTR ); /* if other events wake thread */
}
Esempio n. 15
0
/*! Return calling thread descriptor
 * \param thread Thread descriptor (user level descriptor)
 * \return 0
 */
int sys__pthread_self ( void *p )
{
	pthread_t *thread;

	thread = *( (void **) p );

	ASSERT_ERRNO_AND_EXIT ( thread, ESRCH );

	thread->ptr = kthread_get_active ();
	thread->id = kthread_get_id (NULL);

	EXIT ( EXIT_SUCCESS );
}
Esempio n. 16
0
static int cond_release ( void *p, int release_all )
{
	pthread_cond_t *cond;

	kpthread_cond_t *kcond;
	kpthread_mutex_t *kmutex;
	kobject_t *kobj_cond, *kobj_mutex;
	kthread_t *kthread;
	int retval = 0;

	cond = *( (pthread_cond_t **) p );
	ASSERT_ERRNO_AND_EXIT ( cond, 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 );

	kthread_set_errno ( kthread_get_active (), EXIT_SUCCESS );

	if ( (kthread = kthreadq_remove ( &kcond->queue, NULL )) )
	{
		kobj_mutex = kthread_get_private_param ( kthread );
		kmutex = kobj_mutex->kobject;

		retval = mutex_lock ( kmutex, kthread );
		if ( retval == 0 )
			kthread_move_to_ready ( kthread, LAST );

		/* process other threads in queue */
		while ( release_all &&
			(kthread = kthreadq_remove ( &kcond->queue, NULL )) )
		{
			kthread_set_errno ( kthread, EXIT_SUCCESS );

			kobj_mutex = kthread_get_private_param ( kthread );
			kmutex = kobj_mutex->kobject;

			kthread_enqueue(kthread, &kmutex->queue, 0, NULL, NULL);
		}
	}

	if ( retval > -1 )
		kthreads_schedule ();

	return EXIT_SUCCESS;
}
Esempio n. 17
0
/*!
 * Modify thread signal mask
 * \param how How to modify current must
 * \param set Mask to use in modification
 * \param oset Where to store old mask
 * \return 0 if successful, -1 otherwise and appropriate error number is set
 */
int sys__pthread_sigmask ( void *p )
{
	int how;
	sigset_t *set;
	sigset_t *oset;

	ksignal_handling_t *sh;
	int retval = EXIT_SUCCESS;

	how =  *( (int *) p );		p += sizeof (int);
	set =  *( (sigset_t **) p );	p += sizeof (sigset_t *);
	oset = *( (sigset_t **) p );

	ASSERT_ERRNO_AND_EXIT ( set, EINVAL );
	set = U2K_GET_ADR ( set, kthread_get_process (NULL) );
	ASSERT_ERRNO_AND_EXIT ( set, EINVAL );

	sh = kthread_get_sigparams ( NULL );

	if (oset)
		oset = U2K_GET_ADR ( oset, kthread_get_process (NULL) );

	if (oset)
		*oset = *sh->mask;

	switch ( how )
	{
	case SIG_BLOCK:
		sigaddsets ( sh->mask, set );
		break;

	case SIG_UNBLOCK:
		sigaddsets ( sh->mask, set );
		break;

	case SIG_SETMASK:
		*sh->mask = *set;
		break;

	default:
		retval = EINVAL;
	}

	/* reevaluate pending signals with new mask */
	if ( retval == EXIT_SUCCESS )
		retval = ksignal_process_pending ( kthread_get_active () );

	EXIT ( retval );
}
Esempio n. 18
0
/*! Handle memory fault interrupt (and others undefined) */
void k_memory_fault ()
{
	LOG ( ERROR, "Undefined fault (exception)!!!");

	if ( arch_prev_mode () == KERNEL_MODE )
	{
		LOG ( ERROR, "PANIC: kernel caused GPF!");
		halt ();
	}
	else {
		/* terminate active thread */
		LOG ( ERROR, "Thread caused GPF, terminating!");
		kthread_exit ( kthread_get_active(), NULL, TRUE );
	}
}
Esempio n. 19
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 ( 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;
}
Esempio n. 20
0
/*!
 * Modify thread signal mask
 * \param sig Signal number
 * \param act Signal handling behavior
 * \param oact Where to save old signal behavior
 * \return 0 if successful, -1 otherwise and appropriate error number is set
 */
int sys__sigaction ( void *p )
{
	int sig;
	sigaction_t *act;
	sigaction_t *oact;

	ksignal_handling_t *sh;

	sig =  *( (int *) p );			p += sizeof (int);
	act =  *( (sigaction_t **) p );		p += sizeof (sigaction_t *);
	oact =  *( (sigaction_t **) p );

	ASSERT_ERRNO_AND_EXIT ( sig > 0 && sig <= SIGMAX, EINVAL );

	if ( act )
		act = U2K_GET_ADR ( act, kthread_get_process (NULL) );

	if ( oact )
		oact = U2K_GET_ADR ( oact, kthread_get_process (NULL) );

	sh = kthread_get_sigparams ( NULL );

	if ( oact )
		*oact = sh->act[sig];

	if ( act )
	{
		if ( !( act->sa_flags & SA_SIGINFO ) )
			EXIT ( ENOTSUP );

		if (	act->sa_sigaction == SIG_ERR ||
			act->sa_sigaction == SIG_DFL ||
			act->sa_sigaction == SIG_IGN ||
			act->sa_sigaction == SIG_HOLD	)
		{
			EXIT ( ENOTSUP );
		}

		sh->act[sig] = *act;
		sigdelset ( sh->mask, sig ); /* accept sig */

		/* reevaluate pending signals with changed behavior */
		ksignal_process_pending ( kthread_get_active () );
	}

	EXIT ( EXIT_SUCCESS );
}
Esempio n. 21
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) );
}
Esempio n. 22
0
/*!
 * Send a message to a message queue
 * \param mqdes Queue descriptor address (user level descriptor)
 * \param msg_ptr Message to be sent
 * \param msg_len Message size
 * \param msg_prio Message priority
 * \return 0 if successful, -1 otherwise and appropriate error number is set
 */
int sys__mq_send ( void *p )
{
	kthread_t *kthread;
	int retval;

	kthread = kthread_get_active ();

	retval = kmq_send ( p, kthread );

	if ( retval == EXIT_SUCCESS )
	{
		kthread_set_errno ( kthread, EXIT_SUCCESS );
	}
	else {
		kthread_set_errno ( kthread, retval );
		retval = EXIT_FAILURE;
	}

	return retval;
}
Esempio n. 23
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 ( 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;
}
Esempio n. 24
0
/*! Timer interrupt for Round Robin */
static void rr_timer ( void *p )
{
	kthread_t *kthread = p;
	kthread_sched_data_t *tsched;

	if ( kthread_get_active () != kthread )
	{
		/* bug or rr thread got canceled! Let asume second :) */
		return;
	}

	tsched = kthread_get_sched_param ( kthread );

	/* given time is elapsed, set remainder to zero */
	tsched->params.rr.remainder.sec = tsched->params.rr.remainder.nsec = 0;

	/* move thread to ready queue - as last in coresponding queue */
	kthread_move_to_ready ( kthread, LAST );

	kthreads_schedule ();
}
Esempio n. 25
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 ( 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;
}
Esempio n. 26
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 );
	}
}