Ejemplo n.º 1
0
/*!
 * Close a message queue
 * \param mqdes Queue descriptor address (user level descriptor)
 * \return 0 if successful, -1 otherwise and appropriate error number is set
 */
int sys__mq_close ( void *p )
{
	mqd_t *mqdes;

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

	mqdes = *( (mqd_t **) p );

	ASSERT_ERRNO_AND_EXIT ( mqdes, EBADF );

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

	kq_queue = kobj->kobject;
	kq_queue = list_find_and_remove ( &kmq_queue, &kq_queue->list );

	if ( !kq_queue || kq_queue->id != mqdes->id )
		EXIT2 ( EBADF, EXIT_FAILURE );

	kq_queue->ref_cnt--;

	if ( !kq_queue->ref_cnt )
	{
		/* remove messages */
		while( (kmq_msg = list_remove(&kq_queue->msg_list,FIRST,NULL)) )
			kfree (kmq_msg);

		/* remove blocked threads */
		while ( (kthread = kthreadq_remove (&kq_queue->send_q, NULL)) )
		{
			kthread_move_to_ready ( kthread, LAST );
			kthread_set_errno ( kthread, EBADF );
			kthread_set_syscall_retval ( kthread, EXIT_FAILURE );
		}
		while ( (kthread = kthreadq_remove (&kq_queue->recv_q, NULL)) )
		{
			kthread_move_to_ready ( kthread, LAST );
			kthread_set_errno ( kthread, EBADF );
			kthread_set_syscall_retval ( kthread, EXIT_FAILURE );
		}

		list_remove ( &kmq_queue, 0, &kq_queue->list );
		k_free_id ( kq_queue->id );
		kfree ( kq_queue->name );
		kfree ( kq_queue );
	}

	/* remove kernel object descriptor */
	kfree_kobject ( kobj );

	EXIT2 ( EXIT_SUCCESS, EXIT_SUCCESS );
}
Ejemplo n.º 2
0
static int cond_release ( void *p, int release_all )
{
	pthread_cond_t *cond;

	kpthread_cond_t *kcond;
	kpthread_mutex_t *kmutex;
	kobject_t *kobj_cond, *kobj_mutex;
	kthread_t *kthread;
	int retval = 0;

	cond = *( (pthread_cond_t **) p );
	ASSERT_ERRNO_AND_EXIT ( cond, EINVAL );

	kobj_cond = cond->ptr;
	ASSERT_ERRNO_AND_EXIT ( kobj_cond, EINVAL );
	ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj_cond->list ),
				EINVAL );
	kcond = kobj_cond->kobject;
	ASSERT_ERRNO_AND_EXIT ( kcond && kcond->id == cond->id, EINVAL );

	kthread_set_errno ( kthread_get_active (), EXIT_SUCCESS );

	if ( (kthread = kthreadq_remove ( &kcond->queue, NULL )) )
	{
		kobj_mutex = kthread_get_private_param ( kthread );
		kmutex = kobj_mutex->kobject;

		retval = mutex_lock ( kmutex, kthread );
		if ( retval == 0 )
			kthread_move_to_ready ( kthread, LAST );

		/* process other threads in queue */
		while ( release_all &&
			(kthread = kthreadq_remove ( &kcond->queue, NULL )) )
		{
			kthread_set_errno ( kthread, EXIT_SUCCESS );

			kobj_mutex = kthread_get_private_param ( kthread );
			kmutex = kobj_mutex->kobject;

			kthread_enqueue(kthread, &kmutex->queue, 0, NULL, NULL);
		}
	}

	if ( retval > -1 )
		kthreads_schedule ();

	return EXIT_SUCCESS;
}
Ejemplo n.º 3
0
/*! Timer interrupt for edf */
static void edf_period_timer ( void *p )
{
	kthread_t *kthread = p, *test;

	ASSERT ( kthread );

	test = kthreadq_remove ( &ksched_edf.params.edf.wait, kthread );

	LOG( DEBUG, "%x %x [Period alarm]", kthread, test );

	if( test == kthread )
	{
		if ( !edf_check_deadline ( kthread ) )
		{
			//LOG( DEBUG, "%x [Waked, moved to edf.ready]", kthread );
			kthread_enqueue ( kthread, &ksched_edf.params.edf.ready );

			if ( k_edf_schedule () )
				kthreads_schedule ();
		}
	}
	else {
		/*
		 * thread is not in edf.wait queue, but might be running or its
		 * blocked - it is probable (sure?) it missed deadline
		 */
		LOG( DEBUG, "%x [Not in edf.wait. Missed deadline?]", kthread );
	}
}
Ejemplo n.º 4
0
/*! Timer interrupt for edf */
static void edf_period_alarm ( sigval_t sigev_value )
{
	kthread_t *kthread = sigev_value.sival_ptr, *test;
	ksched_t *ksched;

	ASSERT ( kthread );

	ksched = ksched2_get ( kthread_get_sched_policy (kthread) );

	test = kthreadq_remove ( &ksched->params.edf.wait, kthread );

	EDF_LOG ( "%x %x [Period alarm]", kthread, test );

	if( test == kthread )
	{
		if ( !edf_check_deadline ( kthread ) )
		{
			EDF_LOG ( "%x [Waked, moved to edf.ready]", kthread );
			kthread_enqueue ( kthread, &ksched->params.edf.ready );

			edf_schedule (ksched);
		}
		/* else => missed deadline -- handle with deadline timer */
	}
	else {
		/*
		 * thread is not in edf.wait queue, but might be running or its
		 * blocked - it is probable it missed its deadline, but that
		 * will be handled with different timer
		 */
		EDF_LOG ( "%x [Not in edf.wait. Missed deadline?]", kthread );
	}
}
Ejemplo n.º 5
0
static void kthread_release_prematurely ( kthread_t *kthread, void *param )
{
	if ( !kthread )
		kthread = active_thread;
	ASSERT ( kthread );

	if ( kthread->state.state == THR_STATE_WAIT )
	{
		if ( !kthreadq_remove ( kthread->queue, kthread ) )
			ASSERT ( FALSE );
	}
	else if ( kthread->state.state == THR_STATE_READY )
	{
		if ( !kthread_remove_from_ready ( kthread ) )
			ASSERT ( FALSE );
	}
}
Ejemplo n.º 6
0
/*!
 * Release single thread from given queue (if queue not empty)
 * \param q Queue
 * \return 1 if thread was released, 0 if queue was empty
 */
int kthreadq_release ( kthread_q *q )
{
	kthread_t *kthread;

	ASSERT ( q );

	kthread = kthreadq_remove ( q, NULL );

	if ( kthread )
	{
		kthread_move_to_ready ( kthread, LAST );
		return 1;
	}
	else {
		return 0;
	}
}
Ejemplo n.º 7
0
/*! Remove given thread (its descriptor) from ready threads */
kthread_t *kthread_remove_from_ready ( kthread_t *kthread )
{
	int i, j, prio;

	if ( !kthread )
		return NULL;

	prio = kthread_get_prio ( kthread );

	if ( kthreadq_remove ( &ready.rq[prio], kthread ) != kthread )
		return NULL;

	/* no more ready threads in list? */
	if ( kthreadq_get ( &ready.rq[prio] ) == NULL )
	{
		i = prio / UINT_SIZE;
		j = prio % UINT_SIZE;

		ready.mask[i] &= ~( (uint) ( 1 << j ) );
	}

	return kthread;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
/*!
 * Cancel thread (or restore it to previous state)
 * \param kthread Thread descriptor
 */
int kthread_exit ( kthread_t *kthread, void *exit_status, int force )
{
	kthread_state_t *prev;
	int restored = FALSE;
	kthread_t *released;
	kthread_q *q;
	void **p;

	ASSERT ( kthread );

	do {
		prev = list_get ( &kthread->states, FIRST );
		if ( prev )
			restored = kthread_restore_state ( kthread );
	}
	while ( prev && force ); /* if cancel is called, destroy all states */

	if ( restored && !force ) /* restored to previous state */
	{
		if ( kthread == active_thread )
			kthread->state.state = THR_STATE_ACTIVE;

		kthreads_schedule ();

		return EXIT_SUCCESS;
	}

	if ( kthread->state.state == THR_STATE_PASSIVE )
		return EXIT_SUCCESS; /* thread is already finished */

	if ( kthread->state.state == THR_STATE_READY )
	{
		/* remove target 'thread' from its queue */
		if ( !kthread_remove_from_ready ( kthread ) )
			ASSERT ( FALSE );
	}
	else if ( kthread->state.state == THR_STATE_WAIT )
	{
		/* remove target 'thread' from its queue */
		if ( !kthreadq_remove ( kthread->queue, kthread ) )
			ASSERT ( FALSE );
	}
	else if ( kthread->state.state == THR_STATE_SUSPENDED )
	{
		/* cancellation routine */
		if ( kthread->state.cancel_suspend_handler )
			kthread->state.cancel_suspend_handler ( kthread,
				kthread->state.cancel_suspend_param );
	}
	else if ( kthread->state.state == THR_STATE_ACTIVE )
	{
		if ( kthread != active_thread )
			return ESRCH; /* thread descriptor corrupted ! */
	}
	else {
		return ESRCH; /* thread descriptor corrupted ! */
	}

	kthread->state.state = THR_STATE_PASSIVE;
	kthread->ref_cnt--;
	kthread->state.exit_status = exit_status;
	kthread->proc->thread_count--;

	arch_destroy_thread_context ( &kthread->state.context );

	kthread_restore_state ( kthread );

	q = &kthread->join_queue;

	while ( (released = kthreadq_remove ( q, NULL )) != NULL )
	{
		/* save exit status to all waiting threads */
		p = kthread_get_private_param ( released );
		if ( p )
			*p = exit_status;

		kthread_move_to_ready ( released, LAST );
		kthread->ref_cnt--;
	}

	if ( !kthread->ref_cnt )
		kthread_remove_descriptor ( kthread );

	if ( kthread == active_thread )
	{
		active_thread = NULL;
		kthreads_schedule ();
	}

	return EXIT_SUCCESS;
}
Ejemplo n.º 11
0
static void edf_deadline_timer ( void *p )
{
	alarm_t alarm;
	kthread_t *kthread = p, *test;
	kthread_sched_data_t *tsched  = kthread_get_sched_param ( kthread );


	ASSERT ( kthread );

	test = kthreadq_remove ( &ksched_edf.params.edf.wait, kthread );

	LOG( DEBUG, "%x %x [Deadline alarm]", kthread, test );

	if( test == kthread )
	{
		if ( edf_check_deadline ( kthread ) )
		{
			LOG( DEBUG, "%x [Waked, but too late]", kthread );

			kthread_set_syscall_retval ( kthread, -1 );
			kthread_move_to_ready ( kthread, LAST );

			if ( tsched->params.edf.flags & EDF_TERMINATE )
			{
				LOG( DEBUG, "%x [EDF_TERMINATE]", kthread );
				tsched = kthread_get_sched_param ( kthread );
				k_alarm_remove ( tsched->params.edf.edf_period_alarm );
				k_alarm_remove ( tsched->params.edf.edf_deadline_alarm );
				tsched->params.edf.edf_period_alarm = NULL;
				kthread_cancel ( kthread, -E_DEADLINE );
			}

			kthreads_schedule ();
		}
	}
	else {
		/*
		 * thread is not in edf.wait queue, but might be running or its
		 * blocked - it is probable (sure?) it missed deadline
		 */
		LOG( DEBUG, "%x [Not in edf.wait. Missed deadline?]", kthread );

		if ( edf_check_deadline ( kthread ) )
		{
			/* what to do if its missed? kill thread? */
			tsched = kthread_get_sched_param ( kthread );
			if ( tsched->params.edf.flags & EDF_TERMINATE )
			{
				LOG( DEBUG, "%x [EDF_TERMINATE]", kthread );
				k_alarm_remove ( tsched->params.edf.edf_period_alarm );
				k_alarm_remove ( tsched->params.edf.edf_deadline_alarm );
				tsched->params.edf.edf_period_alarm = NULL;
				kthread_cancel ( kthread, -E_DEADLINE );
			}
			else if ( tsched->params.edf.flags & EDF_CONTINUE )
			{
				/* continue as deadline is not missed */
				LOG( DEBUG, "%x [EDF_CONTINUE]", kthread );
			}
			else if ( tsched->params.edf.flags & EDF_SKIP )
			{
				/* skip deadline */
				/* set times for next period */
				LOG( DEBUG, "%x [EDF_SKIP]", kthread );

				time_add ( &tsched->params.edf.next_run,
					   &tsched->params.edf.period );
			
				tsched->params.edf.active_deadline = tsched->params.edf.next_run;
				time_add ( &tsched->params.edf.active_deadline,
					   &tsched->params.edf.relative_deadline );
			
				if ( kthread == ksched_edf.params.edf.active )
					ksched_edf.params.edf.active = NULL;

				alarm.action = edf_deadline_timer;
				alarm.param = kthread;
				alarm.flags = 0;
				alarm.period.sec = alarm.period.nsec = 0;
				alarm.exp_time = tsched->params.edf.active_deadline;

				k_alarm_set ( tsched->params.edf.edf_deadline_alarm, &alarm );

				alarm.action = edf_period_timer;
				alarm.param = kthread;
				alarm.flags = ALARM_PERIODIC;
				alarm.period = tsched->params.edf.period;
				alarm.exp_time = tsched->params.edf.next_run;

				k_alarm_set ( tsched->params.edf.edf_period_alarm, &alarm );

				kthread_enqueue ( kthread, &ksched_edf.params.edf.ready );
				kthreads_schedule (); /* will call edf_schedule() */
			}
		}
	}
}
Ejemplo n.º 12
0
static int k_edf_schedule ()
{
	kthread_t *first, *next, *edf_active;
	kthread_sched_data_t *sch_first, *sch_next;
	ksched_t *gsched = ksched_get ( SCHED_EDF );
	int retval = 0;

	edf_active = gsched->params.edf.active;
	first = kthreadq_get ( &gsched->params.edf.ready );

	LOG( DEBUG, "%x [active]", edf_active );
	LOG( DEBUG, "%x [first]", first );
	//LOG( DEBUG, "%x [next]", next );

	if ( !first )
		return 0; /* no threads in edf.ready queue, edf.active unch. */

	if ( edf_active )
	{
		next = first;
		first = edf_active;
		LOG( DEBUG, "%x [next]", kthreadq_get_next ( next ) );
	}
	else {
		next = kthreadq_get_next ( first );
		LOG( DEBUG, "%x [next]", next );
	}

	while ( first && next )
	{

		sch_first = kthread_get_sched_param ( first );
		sch_next = kthread_get_sched_param ( next );

		if ( time_cmp ( &sch_first->params.edf.active_deadline,
			&sch_next->params.edf.active_deadline ) > 0 )
		{
			first = next;
		}

		next = kthreadq_get_next ( next );
	}

	if ( first && first != edf_active )
	{
		next = kthreadq_remove ( &gsched->params.edf.ready, first );
		LOG ( DEBUG, "%x removed, %x is now first", next, kthreadq_get ( &gsched->params.edf.ready ) );

		if ( edf_active )
		{
			LOG( DEBUG, "%x=>%x [EDF_SCHED_PREEMPT]",
			     edf_active, first );

			/*
			 * change active EDF thread:
			 * -remove it from active/ready list
			 * -put it into edf.ready list
			 */
			if ( kthread_is_ready (edf_active) )
			{
				if ( !kthread_is_active (edf_active) )
				{
					kthread_remove_from_ready (edf_active);

					/*
					 * set "deactivated" flag, don't need
					 * another call to "edf_schedule"
					 */
				}
				else {
					kthread_get_sched_param (edf_active)
						->activated = 0;
				}

				kthread_enqueue ( edf_active,
						  &gsched->params.edf.ready );
			}
			/* else = thread is blocked - leave it there */
		}

		gsched->params.edf.active = first;
		LOG( DEBUG, "%x [new active]", first );

		kthread_move_to_ready ( first, LAST );
		retval = 1;
	}

	return retval;
}
Ejemplo n.º 13
0
/*!
 * Cancel thread (or restore it to previous state)
 * \param kthread Thread descriptor
 */
int kthread_exit ( kthread_t *kthread, void *exit_status, int force )
{
	kthread_state_t *prev;
	int restored = FALSE;
	kthread_t *released;
	kthread_q *q;
	void **p;

	ASSERT ( kthread );
	do {
		prev = list_get ( &kthread->states, FIRST );
		if ( prev )
			restored = kthread_restore_state ( kthread );
	}
	while ( prev && force ); /* if cancel is called, destroy all states */

	if ( restored && !force ) /* restored to previous state */
	{
		if ( kthread == active_thread )
		{
			kthread->state.state = THR_STATE_ACTIVE;
			arch_switch_to_thread ( NULL, &kthread->state.context );
		}
		else {
			ASSERT (FALSE); /* hum, rethink this */
			/* move to ready? */
		}

		kthreads_schedule ();

		return EXIT_SUCCESS;
	}

	if ( kthread->state.state == THR_STATE_PASSIVE )
		return EXIT_SUCCESS; /* thread is already finished */

	if ( kthread->state.state == THR_STATE_READY )
	{
		/* remove target 'thread' from its queue */
		if ( !kthread_remove_from_ready ( kthread ) )
			ASSERT ( FALSE );
	}
	else if ( kthread->state.state == THR_STATE_WAIT )
	{
		/* remove target 'thread' from its queue */
		if ( !kthreadq_remove ( kthread->queue, kthread ) )
			ASSERT ( FALSE );
	}
	else if ( kthread->state.state == THR_STATE_SUSPENDED )
	{
		/* cancellation routine */
		if ( kthread->state.cancel_suspend_handler )
			kthread->state.cancel_suspend_handler ( kthread,
				kthread->state.cancel_suspend_param );
	}
	else if ( kthread->state.state == THR_STATE_ACTIVE )
	{
		if ( kthread != active_thread )
			return ESRCH; /* thread descriptor corrupted ! */
	}
	else {
		return ESRCH; /* thread descriptor corrupted ! */
	}

	kthread->state.state = THR_STATE_PASSIVE;
	kthread->state.exit_status = exit_status;

	/* remove it from its scheduler */
	ksched2_thread_remove ( kthread );

	/* any thread waiting on this? */
	q = &kthread->join_queue;

	while ( (released = kthreadq_remove ( q, NULL )) != NULL )
	{
		/* save exit status to all waiting threads */
		p = kthread_get_private_param ( released );
		if ( p )
			*p = exit_status;

		kthread_move_to_ready ( released, LAST );
		kthread->ref_cnt--;
	}

	/* defer removing thread resources until last moment */
	kthread->state.flags |= THR_FLAG_DELETE;

	if ( kthread == active_thread )
	{
		//active_thread = NULL;
		kthreads_schedule ();
	}

	return EXIT_SUCCESS;
}
Ejemplo n.º 14
0
static void edf_deadline_alarm ( sigval_t sigev_value )
{
	kthread_t *kthread = sigev_value.sival_ptr, *test;
	kthread_sched2_t *tsched;
	ksched_t *ksched;
	itimerspec_t alarm;

	ASSERT ( kthread );

	ksched = ksched2_get ( kthread_get_sched_policy (kthread) );
	tsched = kthread_get_sched2_param ( kthread );

	test = kthreadq_remove ( &ksched->params.edf.wait, kthread );

	EDF_LOG ( "%x %x [Deadline alarm]", kthread, test );

	if( test == kthread )
	{
		EDF_LOG ( "%x [Waked, but too late]", kthread );

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

		if ( tsched->params.edf.flags & EDF_TERMINATE )
		{
			EDF_LOG ( "%x [EDF_TERMINATE]", kthread );
			ktimer_delete ( tsched->params.edf.period_alarm );
			tsched->params.edf.period_alarm = NULL;
			ktimer_delete ( tsched->params.edf.deadline_alarm );
			tsched->params.edf.deadline_alarm = NULL;
			kthread_set_errno ( kthread, ETIMEDOUT );
			kthread_exit ( kthread, NULL, TRUE );
		}
		else {
			edf_schedule (ksched);
		}
	}
	else {
	/*
	 * thread is not in edf.wait queue, but might be running or its
	 * blocked - it is probable (almost certain) that it missed deadline
	 */
	EDF_LOG ( "%x [Not in edf.wait. Missed deadline?]", kthread );

	if ( edf_check_deadline ( kthread ) )
	{
		/* what to do if its missed? kill thread? */
		if ( tsched->params.edf.flags & EDF_TERMINATE )
		{
			EDF_LOG ( "%x [EDF_TERMINATE]", kthread );
			ktimer_delete (tsched->params.edf.period_alarm);
			tsched->params.edf.period_alarm = NULL;
			ktimer_delete ( tsched->params.edf.deadline_alarm );
			tsched->params.edf.deadline_alarm = NULL;
			kthread_set_errno ( kthread, ETIMEDOUT );
			kthread_exit ( kthread, NULL, TRUE );
		}
		else if ( tsched->params.edf.flags & EDF_CONTINUE )
		{
			/* continue as deadline is not missed */
			EDF_LOG ( "%x [EDF_CONTINUE]", kthread );
		}
		else if ( tsched->params.edf.flags & EDF_SKIP )
		{
			/* skip deadline */
			/* set times for next period */
			EDF_LOG ( "%x [EDF_SKIP]", kthread );

			time_add ( &tsched->params.edf.next_run,
				   &tsched->params.edf.period );

			tsched->params.edf.active_deadline =
					tsched->params.edf.next_run;
			time_add ( &tsched->params.edf.active_deadline,
					&tsched->params.edf.relative_deadline );

			if ( kthread == ksched->params.edf.active )
				ksched->params.edf.active = NULL;

			TIME_RESET ( &alarm.it_interval );
			alarm.it_value = tsched->params.edf.active_deadline;
			ktimer_settime ( tsched->params.edf.deadline_alarm,
					 TIMER_ABSTIME, &alarm, NULL );

			alarm.it_interval = tsched->params.edf.period;
			alarm.it_value = tsched->params.edf.next_run;
			ktimer_settime ( tsched->params.edf.period_alarm,
					 TIMER_ABSTIME, &alarm, NULL );

			kthread_enqueue (kthread, &ksched->params.edf.ready);
			edf_schedule (ksched);
		}
	} /* moved 1 tab left for readability */
	}
}
Ejemplo n.º 15
0
static int edf_schedule ( ksched_t *ksched )
{
	kthread_t *first, *next, *edf_active;
	kthread_sched2_t *sch_first, *sch_next, *ea;

	edf_active = ksched->params.edf.active;
	if ( edf_active && !kthread_is_ready ( edf_active ) )
	{
		ksched->params.edf.active = edf_active = NULL;
	}

	first = kthreadq_get ( &ksched->params.edf.ready );

	EDF_LOG ( "%x %x [active, first in queue]", edf_active, first );

	if ( !first )
	{
		kthreads_schedule ();
		return 0; /* no threads in edf.ready queue, edf.active unch. */
	}

	if ( edf_active )
	{
		next = first;
		first = edf_active;
	}
	else {
		next = kthreadq_get_next ( first );
	}

	while ( first && next )
	{

		sch_first = kthread_get_sched2_param ( first );
		sch_next = kthread_get_sched2_param ( next );

		if ( time_cmp ( &sch_first->params.edf.active_deadline,
			&sch_next->params.edf.active_deadline ) > 0 )
		{
			first = next;
		}

		next = kthreadq_get_next ( next );
	}

	if ( first && first != edf_active )
	{
		next = kthreadq_remove ( &ksched->params.edf.ready, first );
		EDF_LOG ( "%x removed, %x is now first", next,
			  kthreadq_get ( &ksched->params.edf.ready ) );

		if ( edf_active )
		{
			EDF_LOG ( "%x=>%x [EDF_SCHED_PREEMPT]",
				  edf_active, first );

			/*
			 * change active EDF thread:
			 * -remove it from active/ready list
			 * -put it into edf.ready list
			 */
			if ( kthread_is_ready (edf_active) )
			{
				if ( !kthread_is_active (edf_active) )
				{
					kthread_remove_from_ready (edf_active);

					/*
					 * set "deactivated" flag, don't need
					 * another call to "edf_schedule"
					 */
				}
				else {
				ea = kthread_get_sched2_param (edf_active);
				ea->activated = 0;
				}

				kthread_enqueue ( edf_active,
						  &ksched->params.edf.ready );
			}
			/* else = thread is blocked - leave it there */
		}

		ksched->params.edf.active = first;
		EDF_LOG ( "%x [new active]", first );

		kthread_move_to_ready ( first, LAST );
	}

	kthreads_schedule ();

	return 0;
}