Esempio n. 1
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 );
}
Esempio n. 2
0
/*! Change thread scheduling parameters ------------------------------------- */
int kthread_setschedparam (kthread_t *kthread, int policy, sched_param_t *param)
{
	int sched_priority;

	ASSERT_ERRNO_AND_EXIT ( kthread, EINVAL );
	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 );

		if ( param->sched_priority )
			sched_priority = param->sched_priority;
		else
			sched_priority = kthread->sched_priority;
	}
	else {
		sched_priority = kthread->sched_priority;
	}

	/* change in priority? */
	if ( kthread->sched_priority != sched_priority )
		kthread_set_prio ( kthread, sched_priority );

	return EXIT_SUCCESS;
}
Esempio n. 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 );
}
Esempio n. 4
0
/*!
 * Deactivate thread because:
 * 1. higher priority thread becomes active
 * 2. this thread blocks on some queue (not in edf_ready)
 */
static int edf_thread_deactivate ( ksched_t *ksched, kthread_t *kthread )
{
	if (	kthread_is_alive (kthread) && !kthread_is_ready (kthread) &&
		kthread_get_queue (kthread) != &ksched->params.edf.ready &&
		kthread_get_queue (kthread) != &ksched->params.edf.wait )
	{
		/* if kthread is blocked, but not in edf.ready */
		ksched->params.edf.active = NULL;
		edf_schedule ( ksched );
	}

	return 0;
}
Esempio n. 5
0
/*! Change thread scheduling parameters ------------------------------------- */
int kthread_setschedparam (kthread_t *kthread, int policy, sched_param_t *param)
{
	int sched_priority;
	sched_supp_t *supp;

	ASSERT_AND_RETURN_ERRNO ( kthread, EINVAL );
	ASSERT_AND_RETURN_ERRNO ( kthread_is_alive (kthread), ESRCH );
	ASSERT_AND_RETURN_ERRNO ( policy >= 0 && policy < SCHED_NUM, EINVAL );

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

		if ( param->sched_priority )
			sched_priority = param->sched_priority;
		else
			sched_priority = kthread->sched_priority;

		supp = &param->supp;
	}
	else {
		sched_priority = kthread->sched_priority;
		supp = NULL;
	}

	/* change in priority? */
	if ( kthread->sched_priority != sched_priority )
		kthread_set_prio ( kthread, sched_priority );

	/* change in scheduling policy? */
	if ( kthread->sched_policy != policy )
	{
		ksched2_thread_remove ( kthread );
		ksched2_schedule ( kthread->sched_policy );
		kthread->sched_policy = policy;
		ksched2_thread_add ( kthread, policy, sched_priority, supp );
		ksched2_schedule ( kthread->sched_policy );
	}
	else if ( supp ) /* if policy changed, parameters are already given */
	{
		ksched2_setsched_param ( kthread, supp );
	}

	return EXIT_SUCCESS;
}
Esempio n. 6
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. 7
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 );
	}
}
Esempio n. 8
0
/*! 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;
}
Esempio n. 9
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;
}
Esempio n. 10
0
/*! 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;
}