コード例 #1
0
ファイル: signal.c プロジェクト: l30nard0/Benu
/*! Send signal to target thread */
int ksignal_queue ( kthread_t *kthread, siginfo_t *sig )
{
	int enqueue = FALSE;
	int retval = EXIT_SUCCESS;
	int schedule = FALSE;
	ksignal_handling_t *sh;
	sigaction_t *act;
	void (*func) (kthread_t *, void *), *param;
	kprocess_t *proc;
	siginfo_t *us;
	param_t param1, param2, param3;

	ASSERT ( kthread );
	ASSERT ( kthread_check_kthread ( kthread ) );
	ASSERT ( sig->si_signo > 0 && sig->si_signo <= SIGMAX );

	if ( !kthread_is_alive ( kthread ) )
		return ESRCH;

	sh = kthread_get_sigparams ( kthread );

	/* is thread suspended and waits for this signal? */
	if (
		kthread_is_suspended ( kthread, (void **) &func, &param ) &&
		((void *) func) == ((void *) ksignal_received_signal)
	)
	{
		/* thread is waiting for signal */
		if ( !ksignal_received_signal ( kthread, sig ) )
		{
			/* waited for this signal */

			/* do not process this signal further */
			return EXIT_SUCCESS;
		}
	}

	/*
	 * If thread is in interruptable state and signal is not masked:
	 * - process signal
	 * - otherwise queue it
	 */
	if (
		kthread_get_interruptable ( kthread ) &&
		!sigtestset ( sh->mask, sig->si_signo )
	)
	{
		act = &sh->act[sig->si_signo];

		if ( act->sa_flags != SA_SIGINFO )
			return ENOTSUP; /* not supported without SA_SIGINFO! */

		if ( 	act->sa_sigaction == SIG_ERR ||
			act->sa_sigaction == SIG_DFL ||
			act->sa_sigaction == SIG_IGN ||
			act->sa_sigaction == SIG_HOLD	)
		{
			return ENOTSUP; /* not yet supported */
		}

		if ( !kthread_is_ready ( kthread ) )
		{
			/*
			 * thread is suspended/blocked on something else
			 *
			 * 1. handle interruption:
			 *    a) we break suspend/wait state
			 *       (call cancel function)
			 *    b) set errno = EINTR
			 *    c) set return value = FAILURE
			 * 2. create new thread state
			 *    a) process signal in this state
			 */
			void (*func) (kthread_t *, void *), *param;
			kthread_is_suspended (kthread, (void **) &func, &param);

			if ( func )
				func ( kthread, param );

			kthread_move_to_ready ( kthread, LAST );
			kthread_set_errno ( kthread, EINTR );
			kthread_set_syscall_retval ( kthread, EXIT_FAILURE );

			/* thread is unsuspended, but signal
			 * handler will be added first */
			schedule = TRUE;
		}

		/* copy sig to user space */
		proc = kthread_get_process ( kthread );
		us = kprocess_stack_alloc ( proc );
		ASSERT (us);
		/*if ( !us )
			return ENOMEM;*/

		*us = *sig;

		kthread_create_new_state ( kthread, act->sa_sigaction,
					   K2U_GET_ADR ( us, proc ), NULL,
					   HANDLER_STACK_SIZE, TRUE );

		param1.p_ptr = proc;
		param2.p_ptr = us;
		param3.p_ptr = NULL;
		kthread_add_cleanup ( kthread, kprocess_stack_free,
				      param1, param2, param3 );

		/* mask signal in thread mask */
		sigaddset ( sh->mask, sig->si_signo );
		/* mask additional signals in thread mask */
		sigaddsets ( sh->mask, &act->sa_mask );
	}
	else {
		enqueue = TRUE;
	}

	if ( enqueue )
	{
		ksignal_add_to_pending ( sh, sig );

		retval = EAGAIN;
	}

	if ( schedule )
		kthreads_schedule ();

	return retval;
}
コード例 #2
0
/*!
 * Start program defined by 'prog' (loaded as module) as new process:
 * - initialize environment (stack area for threads, stdin, stdout) and start
 *   it's first thread
 * \param prog_name Program name (as given with module)
 * \param param Command line arguments for starting thread (if not NULL)
 * \param prio Priority for starting thread
 * \return Pointer to descriptor of created process
 */
kthread_t *k_proc_start ( char *prog_name, void *param, int prio )
{
	extern kdevice_t *u_stdin, *u_stdout;
	extern list_t progs;
	kprog_t *prog;
	kprocess_t *proc;
	kthread_t *kthr;
	char **args = NULL, *arg, *karg, **kargs;
	size_t argsize;
	int i;

	prog = list_get ( &progs, FIRST );
	while ( prog && strcmp ( prog->prog_name, prog_name ) )
		prog = list_get_next ( &prog->all );

	if ( !prog )
		return NULL;

	if ( prog->started )
		return NULL;

	/* create new process */
	proc = kmalloc ( sizeof ( kprocess_t) );
	ASSERT ( proc );

	proc->prog = prog;
	proc->m.size = prog->m.size;
	proc->m.start = proc->pi = prog->pi;

	proc->pi->stdin = u_stdin;
	proc->pi->stdout = u_stdout;

	/* initialize memory pool for threads stacks */
	proc->stack_pool = ffs_init ( U2K_GET_ADR ( proc->pi->stack, proc ),
				      prog->pi->stack_size );

	proc->thr_count = 0;

	if ( !prio )
		prio = proc->pi->prio;
	if ( !prio )
		prio = THR_DEFAULT_PRIO;

	if ( param ) /* have arguments? */
	{
		/* copy command line arguments from kernel space to process;
		   (use process stack space for arguments) */
		kargs = param;
		for ( i = 0; kargs[i]; i++ ) ;
		argsize = ( (size_t) kargs[i-1] + strlen( kargs[i-1] ) + 1 )
			  - (size_t) param;
		if ( argsize > 0 )
		{
			args = ffs_alloc ( proc->stack_pool, argsize );
			arg = (void *) args + (i + 1) * sizeof (void *);
			kargs = param;
			i = 0;
			do {
				karg = kargs[i];
				strcpy ( arg, karg );
				args[i++] = K2U_GET_ADR ( arg, proc );
				arg += strlen ( arg ) + 1;
			}
			while ( kargs[i] );
			args[i] = NULL;
			args = K2U_GET_ADR ( args, proc );
		}

		kfree ( param );
	}
	kthr = k_create_thread ( proc->pi->init, args, NULL, prio, NULL, 0, 1,
				proc );

	list_append ( &procs, proc, &proc->all );

	prog->started = 1;

	k_schedule_threads ();

	return kthr;
}
コード例 #3
0
/*!
 * Send message to queue or signal to thread
 */
int sys__msg_post ( void *p )
{
	/* parameters on thread stack */
	int dest_type;	/* MSG_QUEUE, MSG_THREAD or MSG_SIGNAL	*/
	void *dest;	/* (msg_q *) or (thread_t *)		*/
	msg_t *msg;	/* { type, size, data[0..size-1] }	*/
	uint flags;
	/* local variables */
	thread_t *thr;
	kthread_t *kthr, *new_kthr;
	kthrmsg_qs *thrmsg;
	kgmsg_q *kgmsgq;
	kmsg_q *kmsgq;
	msg_q *msgq;
	kmsg_t *kmsg;
	msg_t *cmsg;
	kprocess_t *proc;

	dest_type = *( (int *) p );	p += sizeof (int);
	dest = *( (void **) p );	p += sizeof (void *);
	msg = *( (msg_t **) p );	p += sizeof (msg_t *);
	flags = *( (uint *) p );

	ASSERT_ERRNO_AND_EXIT ( dest && msg, E_INVALID_HANDLE );

	dest = U2K_GET_ADR ( dest, k_get_active_process () );
	msg = U2K_GET_ADR ( msg, k_get_active_process () );

	if ( dest_type == MSG_THREAD || dest_type == MSG_SIGNAL )
	{
		thr = dest;
		kthr = k_get_kthread ( thr );
		ASSERT_ERRNO_AND_EXIT ( kthr, E_DONT_EXIST );
		thrmsg = k_get_thrmsg ( kthr );
		kmsgq = &thrmsg->msgq;
	}
	else if ( dest_type == MSG_QUEUE )
	{
		msgq = dest;
		kgmsgq = msgq->handle;
		ASSERT_ERRNO_AND_EXIT ( kgmsgq && kgmsgq->id == msgq->id,
					E_INVALID_HANDLE );
		kmsgq = &kgmsgq->mq;
	}
	else {
		EXIT ( E_INVALID_TYPE );
	}

	if ( dest_type == MSG_THREAD || dest_type == MSG_QUEUE )
	{
		/* send message to queue */
		if ( kmsgq->min_prio <= msg->type ) /* msg has required prio. */
		{
			kmsg = kmalloc ( sizeof (kmsg_t) + msg->size );
			ASSERT_ERRNO_AND_EXIT ( kmsg, E_NO_MEMORY );

			kmsg->msg.type = msg->type;
			kmsg->msg.size = msg->size;
			memcpy ( kmsg->msg.data, msg->data, msg->size );

			list_append ( &kmsgq->msgs, kmsg, &kmsg->list );

			/* is thread waiting for message? */
			if ( k_release_thread ( &kmsgq->thrq ) )
				k_schedule_threads ();

			EXIT ( SUCCESS );
		}
		else { /* ignore message */
			EXIT ( E_IGNORED );
		}
	}

	/* must be MSG_SIGNAL */
	if ( thrmsg->sig_prio <= msg->type )
	{
		/* create thread that will service this signal */

		cmsg = k_create_thread_private_storage ( kthr,
				sizeof (msg_t) + msg->size );
		cmsg->type = msg->type;
		cmsg->size = msg->size;
		memcpy ( cmsg->data, msg->data, msg->size );

		proc = k_get_thread_process ( kthr );

		new_kthr = k_create_thread (
			thrmsg->signal_handler,
			K2U_GET_ADR ( cmsg, proc ), proc->pi->exit,
			k_get_thread_prio ( kthr ) + 1, NULL, 0, 1, proc
		);
		ASSERT_ERRNO_AND_EXIT ( new_kthr, k_get_errno() );

		k_set_thread_private_storage ( new_kthr, cmsg );

		SET_ERRNO ( SUCCESS );

		k_schedule_threads ();

		RETURN ( SUCCESS );
	}
	else { /* ignore signal */
		EXIT ( E_IGNORED );
	}
}
コード例 #4
0
ファイル: signal.c プロジェクト: bkolobara/Benu-pi
/*! Send signal to target thread */
int ksignal_queue ( kthread_t *kthread, siginfo_t *sig )
{
	int enqueue = FALSE;
	int retval = EXIT_SUCCESS;
	int schedule = FALSE;
	ksignal_handling_t *sh;
	sigaction_t *act;
	void (*func) (kthread_t *, void *), *param;
	kprocess_t *proc;
	siginfo_t *us;
	param_t param1, param2, param3;
	ksiginfo_t *ksig;

	ASSERT ( kthread );
	ASSERT ( kthread_check_kthread ( kthread ) );
	ASSERT ( sig->si_signo > 0 && sig->si_signo <= SIGMAX );

	if ( !kthread_is_alive ( kthread ) )
		return ESRCH;

	sh = kthread_get_sigparams ( kthread );

	/* is thread suspended and waits for this signal? */
	if ( kthread_is_suspended ( kthread, (void **) &func, &param ) )
	{
		if ( ((void *) func) == ((void *) ksignal_received_signal) )
		{
			/* thread is waiting for signal */
			if ( !ksignal_received_signal ( kthread, sig ) )
			{
				/* waited for this signal */
				/* should continue with signal handler also? */

				/* do not process this signal further */
				return EXIT_SUCCESS;
			}

		}
		/* else {
		 *	thread is waiting for something else;
		 * 	deal with this later (in next "if")
		 * } */
	}

	/* if signal is not masked in thread signal mask, deliver signal */
	if ( !sigtestset ( sh->mask, sig->si_signo ) )
	{
		act = &sh->act[sig->si_signo];

		if ( act->sa_flags != SA_SIGINFO )
			return ENOTSUP; /* not supported without SA_SIGINFO! */

		if ( 	act->sa_sigaction == SIG_ERR ||
			act->sa_sigaction == SIG_DFL ||
			act->sa_sigaction == SIG_IGN ||
			act->sa_sigaction == SIG_HOLD	)
		{
			return ENOTSUP; /* not yet supported */
		}

		/* current implementation
			* - if thread is active or ready
			* -- save old context in list
			* -- create new context
			* - else
			* -- enqueue signal or cancel wait state (todo)
			*
			* on sys__exit check if its handler or thread!!!
			*/

		if ( !kthread_is_ready ( kthread ) )
		{
			void (*func) (kthread_t *, void *), *param;
			if ( kthread_is_suspended ( kthread,
						    (void **) &func, &param ) )
			{
				/*
					* thread is suspended on something
					* else; interrupt it or not?
					*
					* -handle interruption (kernel part)
					* -interrupt it (resume)
					* -process signal
					*
					* to do above just move thread to
					* ready, set errno & retval
					*/
				if ( func )
					func ( kthread, param );

				kthread_move_to_ready ( kthread, LAST );
				kthread_set_errno ( kthread, EINTR );
				kthread_set_syscall_retval(kthread,EXIT_FAILURE);

				/* thread is unsuspended, but signal
				 * handler will be added first */
				schedule = TRUE;
			}
			else {
				/* what else? this is error */
				ASSERT ( FALSE );
			}
		}

		/* copy sig to user space */
		proc = kthread_get_process ( kthread );
		us = ffs_alloc(proc->stack_pool, sizeof (siginfo_t));
		ASSERT (us);
		/*if ( !us )
			return ENOMEM;*/

		*us = *sig;

		kthread_create_new_state ( kthread, act->sa_sigaction,
					   K2U_GET_ADR ( us, proc ), NULL,
					   HANDLER_STACK_SIZE, TRUE );

		param1.p_ptr = proc->stack_pool;
		param2.p_ptr = us;
		param3.p_ptr = NULL;
		kthread_add_cleanup ( kthread, kthread_param_free,
				      param1, param2, param3 );

		/* mask signal in thread mask */
		sigaddset ( sh->mask, sig->si_signo );
		/* mask additional signals in thread mask */
		sigaddsets ( sh->mask, &act->sa_mask );
	}
	else {
		enqueue = TRUE;
	}

	if ( enqueue )
	{
		/* mask signal in thread mask */
		sigaddset ( sh->mask, sig->si_signo );

		/* add signal to list of pending signals */
		ksig = kmalloc ( sizeof (ksiginfo_t) );
		ksig->siginfo = *sig;

		list_append ( &sh->pending_signals, ksig, &ksig->list );
		/* list_sort_add ( &sh->pending_signals, ksig, &ksig->list,
				ksignal_compare ); */
		retval = EAGAIN;
	}

	if ( schedule )
		kthreads_schedule ();

	return retval;
}