Exemple #1
0
void kthread_set_syscall_retval ( kthread_t *kthread, int ret_val )
{
	if ( !kthread )
		kthread = active_thread;
	ASSERT ( kthread );
	arch_syscall_set_retval ( kthread_get_context(kthread), ret_val );
}
Exemple #2
0
/*! Switch to other thread */
void kthread_switch_to_thread ( kthread_t *from, kthread_t *to )
{
	ASSERT ( to == active_thread );

	if ( from && ( from->state.flags & THR_FLAG_DELETE ) )
	{
		/* delete thread resources with switch */
		from->state.flags &= ~THR_FLAG_DELETE;

		arch_switch_to_thread_with_cleanup (
			from, kthread_get_context ( to )
		);
	}
	else {
		arch_switch_to_thread (
		/* from */	( from ? kthread_get_context ( from ) : NULL ),
		/* to */	kthread_get_context ( to )
		);
	}
}
Exemple #3
0
static int kmq_send ( void *p, kthread_t *sender )
{
	mqd_t *mqdes;
	char *msg_ptr;
	size_t msg_len;
	uint msg_prio;

	kmq_queue_t *kq_queue;
	kobject_t *kobj;
	kmq_msg_t *kmq_msg;
	kthread_t *kthread;
	int retval;

	mqdes =		*( (mqd_t **) p );	p += sizeof (mqd_t *);
	msg_ptr = 	*( (char **) p );	p += sizeof (char *);
	msg_len = 	*( (size_t *) p );	p += sizeof (size_t);
	msg_prio =	*( (uint *) p );

	ASSERT_ERRNO_AND_EXIT ( mqdes && msg_ptr, EINVAL );
	ASSERT_ERRNO_AND_EXIT ( msg_prio <= MQ_PRIO_MAX, EINVAL );

	kobj = mqdes->ptr;
	ASSERT_ERRNO_AND_EXIT ( kobj, EBADF );
	ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ),
				EBADF );

	kq_queue = kobj->kobject;
	ASSERT_ERRNO_AND_EXIT ( kq_queue->id == mqdes->id, EBADF );
	ASSERT_ERRNO_AND_EXIT ( list_find ( &kmq_queue, &kq_queue->list ),
				EBADF );

	if ( kq_queue->attr.mq_curmsgs >= kq_queue->attr.mq_maxmsg )
	{
		if ( (kobj->flags & O_NONBLOCK) )
			return EAGAIN;

		/* block thread */
		kthread_enqueue ( sender, &kq_queue->send_q, 1, NULL, NULL );
		kthreads_schedule ();

		return EAGAIN;
	}

	if ( msg_len > kq_queue->attr.mq_msgsize )
		return EMSGSIZE;

	kmq_msg = kmalloc ( sizeof (kmq_msg_t) + msg_len );
	ASSERT_ERRNO_AND_EXIT ( kmq_msg, ENOMEM );

	/* create message */
	kmq_msg->msg_size = msg_len;
	kmq_msg->msg_prio = msg_prio;
	memcpy ( &kmq_msg->msg_data[0], msg_ptr, msg_len );

	list_sort_add ( &kq_queue->msg_list, kmq_msg, &kmq_msg->list,
			( int (*)(void *, void *) ) cmp_mq_msg );

	kq_queue->attr.mq_curmsgs++;

	/* is there a blocked receiver? */
	if ( (kthread = kthreadq_remove ( &kq_queue->recv_q, NULL )) )
	{
		/* "save" sender thread */
		kthread_move_to_ready ( sender, FIRST );
		kthread_set_errno ( sender, EXIT_SUCCESS );
		kthread_set_syscall_retval ( sender, EXIT_SUCCESS );

		/* unblock receiver */
		kthread_set_active ( kthread ); /* temporary */
		p = arch_syscall_get_params ( kthread_get_context (kthread) );

		retval = kmq_receive ( p, kthread );

		if ( retval >= 0 )
		{
			kthread_set_errno ( kthread, EXIT_SUCCESS );
			kthread_set_syscall_retval ( kthread, retval );
		}
		else {
			kthread_set_errno ( kthread, -retval );
			kthread_set_syscall_retval ( kthread, EXIT_FAILURE );
		}

		kthreads_schedule ();
	}

	return EXIT_SUCCESS;
}
Exemple #4
0
static int kmq_receive ( void *p, kthread_t *receiver )
{
	mqd_t *mqdes;
	char *msg_ptr;
	size_t msg_len;
	uint *msg_prio;

	kmq_queue_t *kq_queue;
	kobject_t *kobj;
	kmq_msg_t *kmq_msg;
	kthread_t *kthread;
	int retval;

	mqdes =		*( (mqd_t **) p );	p += sizeof (mqd_t *);
	msg_ptr = 	*( (char **) p );	p += sizeof (char *);
	msg_len = 	*( (size_t *) p );	p += sizeof (size_t);
	msg_prio =	*( (uint **) p );

	ASSERT_ERRNO_AND_EXIT ( mqdes && msg_ptr, -EINVAL );

	kobj = mqdes->ptr;
	ASSERT_ERRNO_AND_EXIT ( kobj, -EBADF );
	ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ),
				-EBADF );

	kq_queue = kobj->kobject;
	ASSERT_ERRNO_AND_EXIT ( kq_queue->id == mqdes->id, -EBADF );
	ASSERT_ERRNO_AND_EXIT ( list_find ( &kmq_queue, &kq_queue->list ),
				-EBADF );

	if ( kq_queue->attr.mq_curmsgs == 0 )
	{
		if ( (kobj->flags & O_NONBLOCK) )
			return -EAGAIN;

		/* block thread */
		kthread_enqueue ( receiver, &kq_queue->recv_q, 1, NULL, NULL );
		kthreads_schedule ();

		return -EAGAIN;
	}

	if ( msg_len < kq_queue->attr.mq_msgsize )
		return -EMSGSIZE;

	kmq_msg = list_remove ( &kq_queue->msg_list, FIRST, NULL );

	memcpy ( msg_ptr, &kmq_msg->msg_data[0], kmq_msg->msg_size );
	msg_len = kmq_msg->msg_size;
	if ( msg_prio )
		*msg_prio = kmq_msg->msg_prio;

	kfree (kmq_msg);

	kq_queue->attr.mq_curmsgs--;

	/* is there a blocked sender? */
	if ( (kthread = kthreadq_remove ( &kq_queue->send_q, NULL )) )
	{
		/* "save" receiver thread */
		kthread_move_to_ready ( receiver, FIRST );
		kthread_set_errno ( receiver, EXIT_SUCCESS );
		kthread_set_syscall_retval ( receiver, msg_len );

		/* unblock sender */
		kthread_set_active ( kthread ); /* temporary */
		p = arch_syscall_get_params ( kthread_get_context (kthread) );

		retval = kmq_send ( p, kthread );

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

		kthreads_schedule ();
	}

	return msg_len;
}
Exemple #5
0
/*! Callback function called when a signal is delivered to suspended thread */
static int ksignal_received_signal ( kthread_t *kthread, void *param )
{
	siginfo_t *sig;
	context_t *context;
	uint sysid;
	void *p;
	sigset_t *set;
	siginfo_t *info;
	int retval = EXIT_SUCCESS;

	ASSERT ( kthread );

	/* thread waked by signal or other event? */
	if ( param == NULL )
	{
		kthread_set_errno ( kthread, EINTR );
		kthread_set_syscall_retval ( kthread, EXIT_FAILURE );

		return EXIT_FAILURE; /* other event interrupted thread */
	}

	/* signal interrupted, but did thread waited for this signal? */
	sig = param;

	/* get syscall which caused thread to be suspend */
	context = kthread_get_context ( kthread );
	sysid = arch_syscall_get_id ( context );

	switch ( sysid )
	{
	case SIGWAITINFO: /* sigwaitinfo */
		p = arch_syscall_get_params ( context );

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

		ASSERT ( set );
		set = U2K_GET_ADR ( set, kthread_get_process (NULL) );
		ASSERT ( set );

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

		retval = EXIT_FAILURE;

		if ( sigtestset ( set, sig->si_signo ) )
		{
			retval = sig->si_signo;
			kthread_set_syscall_retval ( kthread, retval );

			if ( info )
				*info = *sig;

			kthread_set_errno ( kthread, EXIT_SUCCESS );

			/* resume with thread */
			kthread_move_to_ready ( kthread, LAST );

			kthreads_schedule ();

			return EXIT_SUCCESS;
		}
		else {
			/* not waiting for this signal */
			return EXIT_FAILURE;
		}
	default:
		return EXIT_FAILURE;
	}
}