예제 #1
0
파일: signal.c 프로젝트: l30nard0/Benu
/*! Process pending signals for thread (called from kthreads_schedule ()) */
int ksignal_process_pending ( kthread_t *kthread )
{
	ksignal_handling_t *sh;
	int retval = EXIT_SUCCESS;
	ksiginfo_t *ksig, *next;

	ASSERT ( kthread );

	sh = kthread_get_sigparams ( kthread );

	ksig = list_get ( &sh->pending_signals, FIRST );
	while ( ksig )
	{
		next = list_get_next ( &ksig->list );

		if ( !sigtestset ( sh->mask, ksig->siginfo.si_signo ) )
		{
			list_remove ( &sh->pending_signals, 0, &ksig->list );

			retval = ksignal_queue ( kthread, &ksig->siginfo );

			kfree ( ksig );

			/* handle only first signal?
				* no, all of them - they will mask ... */
			/*if ( retval == EXIT_SUCCESS )
				break;*/
		}

		ksig = next;
	}

	return retval;
}
예제 #2
0
파일: signal.c 프로젝트: l30nard0/Benu
/*!
 * 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 */
}
예제 #3
0
파일: signal.c 프로젝트: l30nard0/Benu
/*! Initialize thread signal handling data */
int ksignal_thread_init ( kthread_t *kthread )
{
	ksignal_handling_t *sh;

	ASSERT ( kthread );

	sh = kthread_get_sigparams ( kthread );

	sigfillset ( sh->mask ); /* all signals are blocked */

	list_init ( &sh->pending_signals );

	return EXIT_SUCCESS;
}
예제 #4
0
파일: signal.c 프로젝트: l30nard0/Benu
/*!
 * 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 );
}
예제 #5
0
파일: signal.c 프로젝트: l30nard0/Benu
/*!
 * 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 );
}
예제 #6
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;
}
예제 #7
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;
}