Beispiel #1
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 ) );
}
Beispiel #2
0
/*!
 * Change scheduling parameters
 * \param thread User level thread descriptor
 * \param policy Thread scheduling policy
 * \param param Additional scheduling parameters (when policy != SCHED_FIFO)
 * \return 0
 */
int sys__pthread_setschedparam ( void *p )
{
	pthread_t *thread;
	int policy;
	sched_param_t *param;

	kthread_t *kthread;

	thread = *( (pthread_t **) p );		p += sizeof (pthread_t *);
	policy = *( (int *) p );		p += sizeof (int);
	param =  *( (sched_param_t **) p );

	kthread = thread->ptr;
	ASSERT_ERRNO_AND_EXIT ( kthread, EINVAL );
	ASSERT_ERRNO_AND_EXIT ( kthread_get_id (kthread) == thread->id, ESRCH );
	ASSERT_ERRNO_AND_EXIT ( kthread_is_alive (kthread), ESRCH );

	ASSERT_ERRNO_AND_EXIT ( policy >= 0 && policy < SCHED_NUM, EINVAL );

	if ( param )
	{
		ASSERT_ERRNO_AND_EXIT (
			param->sched_priority >= THREAD_MIN_PRIO &&
			param->sched_priority <= THREAD_MAX_PRIO, EINVAL );
	}

	return kthread_setschedparam ( kthread, policy, param );
}
Beispiel #3
0
/*!
 * Change scheduling parameters
 * \param thread User level thread descriptor
 * \param policy Thread scheduling policy
 * \param param Additional scheduling parameters (when policy != SCHED_FIFO)
 * \return 0
 */
int sys__pthread_setschedparam ( pthread_t *thread, int policy,
				 sched_param_t *param )
{
	kthread_t *kthread;
	int retval;

	SYS_ENTRY();

	kthread = thread->ptr;
	ASSERT_ERRNO_AND_EXIT ( kthread, EINVAL );
	ASSERT_ERRNO_AND_EXIT ( kthread_get_id (kthread) == thread->id, ESRCH );
	ASSERT_ERRNO_AND_EXIT ( kthread_is_alive (kthread), ESRCH );

	ASSERT_ERRNO_AND_EXIT ( policy == SCHED_FIFO, ENOTSUP );

	if ( param )
	{
		ASSERT_ERRNO_AND_EXIT (
			param->sched_priority >= THREAD_MIN_PRIO &&
			param->sched_priority <= THREAD_MAX_PRIO, EINVAL );
	}

	retval = kthread_setschedparam ( kthread, policy, param );
	if ( retval == EXIT_SUCCESS )
		SYS_EXIT ( EXIT_SUCCESS, retval );
	else
		SYS_EXIT ( retval, EXIT_FAILURE );
}
Beispiel #4
0
/*!
 * Create new thread (params on user stack!)
 * \param thread User level thread descriptor
 * \param attr Thread attributes
 * \param start_routine Starting function for new thread
 * \param arg Parameter sent to starting function
 * (parameters are on calling thread stack)
 */
int sys__pthread_create ( void *p )
{
	pthread_t *thread;
	pthread_attr_t *attr;
	void *(*start_routine) (void *);
	void *arg;

	kthread_t *kthread;
	uint flags = 0;
	int sched_policy = SCHED_FIFO;
	int sched_priority = THREAD_DEF_PRIO;
	void *stackaddr = NULL;
	size_t stacksize = 0;

	thread = *( (pthread_t **) p );		p += sizeof (pthread_t *);
	attr = *( (pthread_attr_t **) p );	p += sizeof (pthread_attr_t *);
	start_routine = *( (void **) p );	p += sizeof (void *);
	arg = *( (void **) p );

	if ( attr )
	{
		flags = attr->flags;
		sched_policy = attr->sched_policy;
		sched_priority = attr->sched_params.sched_priority;
		stackaddr = attr->stackaddr;
		stacksize = attr->stacksize;

		ASSERT_ERRNO_AND_EXIT (
			sched_policy >= 0 && sched_policy < SCHED_NUM,
			ENOTSUP
		);
		ASSERT_ERRNO_AND_EXIT (
			sched_priority >= THREAD_MIN_PRIO &&
			sched_priority <= THREAD_MAX_PRIO,
			ENOMEM
		);

		/* if ( flags & SOMETHING ) change attributes ... */
	}

	kthread = kthread_create ( start_routine, arg, flags,
				   sched_policy, sched_priority,
				   stackaddr, stacksize );

	ASSERT_ERRNO_AND_EXIT ( kthread, ENOMEM );

	if ( thread )
	{
		thread->ptr = kthread;
		thread->id = kthread_get_id (kthread);
	}

	SET_ERRNO ( EXIT_SUCCESS );

	kthreads_schedule ();

	return EXIT_SUCCESS;
}
Beispiel #5
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 );
}
Beispiel #6
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 );
}
Beispiel #7
0
/*!
 * Create new thread (params on user stack!)
 * \param thread User level thread descriptor
 * \param attr Thread attributes
 * \param start_routine Starting function for new thread
 * \param arg Parameter sent to starting function
 * (parameters are on calling thread stack)
 */
int sys__pthread_create ( pthread_t *thread, pthread_attr_t *attr,
			  void *(*start_routine) (void *), void *arg )
{
	kthread_t *kthread;
	uint flags = 0;
	int sched_policy = SCHED_FIFO;
	int sched_priority = THREAD_DEF_PRIO;
	void *stackaddr = NULL;
	size_t stacksize = 0;

	SYS_ENTRY();

	if ( attr )
	{
		flags = attr->flags;
		sched_policy = attr->sched_policy;
		sched_priority = attr->sched_params.sched_priority;
		stackaddr = attr->stackaddr;
		stacksize = attr->stacksize;

		ASSERT_ERRNO_AND_EXIT ( sched_policy == SCHED_FIFO,
					ENOTSUP );
		ASSERT_ERRNO_AND_EXIT (
			sched_priority >= THREAD_MIN_PRIO &&
			sched_priority <= THREAD_MAX_PRIO,
			ENOMEM
		);

		/* if ( flags & SOMETHING ) change attributes ... */
	}

	kthread = kthread_create ( start_routine, arg, flags,
				   sched_policy, sched_priority,
				   stackaddr, stacksize );

	ASSERT_ERRNO_AND_EXIT ( kthread, ENOMEM );

	if ( thread )
	{
		thread->ptr = kthread;
		thread->id = kthread_get_id (kthread);
	}

	kthreads_schedule ();

	SYS_EXIT ( EXIT_SUCCESS, EXIT_SUCCESS );
}
Beispiel #8
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;
}
Beispiel #9
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 #10
0
/*! Process event defined with sigevent_t */
int ksignal_process_event ( sigevent_t *evp, kthread_t *kthread, int code )
{
	int retval = EXIT_SUCCESS;
	kthread_t *target = kthread;
	siginfo_t sig;
	pid_t pid;
	void (*func) ( sigval_t );

	ASSERT ( evp && kthread );

	switch ( evp->sigev_notify )
	{
	case SIGEV_WAKE_THREAD:
		func = evp->sigev_notify_function;
		func ( evp->sigev_value );
		break;

	case SIGEV_NONE:
		break;

	case SIGEV_THREAD_ID:
		pid = evp->sigev_notify_thread_id;
		target = pid.ptr;

		if ( !target || !kthread_is_alive (target) ||
			pid.id != kthread_get_id (target) )
			return ESRCH;

	case SIGEV_SIGNAL:
		sig.si_signo = evp->sigev_signo;
		sig.si_value = evp->sigev_value;
		sig.si_code = code;
		sig.si_errno = 0;
		sig.si_pid.id = kthread_get_id ( kthread );
		sig.si_pid.ptr = kthread;

		retval = ksignal_queue ( target, &sig );

		break;

	case SIGEV_THREAD:
		if ( evp->sigev_notify_function )
		{
			if ( !kthread_create (	evp->sigev_notify_function,
						evp->sigev_value.sival_ptr, 0,
						SCHED_FIFO, THREAD_DEF_PRIO,
						NULL, 0,
						kthread_get_process(kthread) ) )
				retval = EINVAL;
		}
		else {
			retval = EINVAL;
		}
		break;

	default:
		retval = EINVAL;
		break;
	}

	return retval;
}