/*!
 * Select highest priority ready thread as active
 * - if different from current, move current into ready queue (id not NULL) and
 *   move selected thread from ready queue to active queue
 */
void k_schedule_threads ()
{
	int first;
	kthread_t *curr, *next;

	curr = active_thread;

	first = get_top_ready ();

	/* must be an thread to return to, 'curr' or first from 'ready' */
	ASSERT ( ( curr && curr->state == THR_STATE_ACTIVE ) || first >= 0 );

	if ( !curr || curr->state != THR_STATE_ACTIVE ||
		first >= curr->sched.prio )
	{
		/* change active thread, move current to ready queue */
		if ( curr && curr->state == THR_STATE_ACTIVE )
			move_to_ready ( curr );

		next = k_threadq_remove ( &ready_q[first], NULL );
		ASSERT ( next );

		/* no more ready threads in list? */
		if ( k_threadq_get( &ready_q[first] ) == NULL )
			clear_got_ready ( first );

		active_thread = next;
		active_thread->state = THR_STATE_ACTIVE;
		active_thread->queue = NULL;
	}

	/* return to 'active_thread' */
	arch_select_thread ( &active_thread->context );
}
Esempio n. 2
0
/*!
 * Create new thread
 * \param start_func Starting function for new thread
 * \param param Parameter sent to starting function
 * \param exit_func Thread will call this function when it leaves 'start_func'
 * \param prio Thread priority
 * \param stack Address of thread stack (if not NULL)
 * \param stack_size Stack size
 * \param run Move thread descriptor to ready threads?
 * \param proc Process descriptor thread belongs to
 * \return Pointer to descriptor of created kernel thread
 */
kthread_t *k_create_thread ( void *start_func, void *param, void *exit_func,
			     int prio, void *stack, size_t stack_size, int run,
			     kprocess_t *proc )
{
	kthread_t *kthr;

	/* if stack is not defined */
	if ( proc && proc->stack_pool && ( !stack || !stack_size ) )
	{
		stack_size = proc->pi->thread_stack;
		stack = ffs_alloc ( proc->stack_pool, stack_size );
	}
	else if ( !stack || !stack_size )
	{
		if ( !stack_size )
			stack_size = DEFAULT_THREAD_STACK_SIZE;

		stack = kmalloc ( stack_size );
	}
	ASSERT ( stack && stack_size );

	kthr = kmalloc ( sizeof (kthread_t) ); /* thread descriptor */
	ASSERT ( kthr );

	/* initialize thread descriptor */
	kthr->id = k_new_unique_id ();

	kthr->state = THR_STATE_PASSIVE;

	if ( prio < 0 ) prio = 0;
	if ( prio >= PRIO_LEVELS ) prio = PRIO_LEVELS - 1;
	kthr->sched.prio = prio;

	arch_create_thread_context ( &kthr->context, start_func, param,
				     exit_func, stack, stack_size, proc );
	kthr->queue = NULL;
	kthr->exit_status = 0;
	k_threadq_init ( &kthr->join_queue );
	kthr->ref_cnt = 0;

	if ( run ) {
		move_to_ready ( kthr );
		kthr->ref_cnt = 1;
	}

	kthr->stack = stack;
	kthr->stack_size = stack_size;
	kthr->proc = proc;
	kthr->proc->thr_count++;
	kthr->private_storage = NULL;

#ifdef	MESSAGES
	k_thr_msg_init ( &kthr->msg );
#endif
	list_append ( &all_threads, kthr, &kthr->all );

	return kthr;
}
Esempio n. 3
0
// Sends a message to the process
int k_send_message (uint32_t pid, void *message) {
	MessageEnvelope *menv = (MessageEnvelope *)k_request_memory_block();

	if (message == 0)
		return;

	menv->sender_id 	= (current_process())->m_pid; 	// Field 1: Sender
	menv->receiver_id 	= pid; 							// Field 2: Receiver
	menv->message_type 	= 0; 							// Field 3: Message Type
	menv->message 		= message; 						// Field 4: Message

	enqueue_envelope(pid, menv);

	if ((get_process(pid))->m_state == MSG_BLOCKED)
		move_to_ready(pid);
}
/*!
 * Release single thread from given queue (if queue not empty)
 * \param q Queue
 * \returns 1 if thread was released, 0 if queue was empty
 */
int k_release_thread ( kthread_q *q )
{
	kthread_t *kthr;

	ASSERT ( q );

	kthr = k_threadq_remove ( q, NULL );

	if ( kthr )
	{
		move_to_ready ( kthr );
		return 1;
	}
	else {
		return 0;
	}
}
/*!
 * Cancel some other thread
 * \param thread Thread descriptor (user)
 */
int sys__cancel_thread ( void *p )
{
	thread_t *thread;
	kthread_t *kthr;
	int ret_value = -1;

	thread = *( (void **) p );

	ASSERT_ERRNO_AND_EXIT ( thread && thread->thread, E_INVALID_HANDLE );

	kthr = thread->thread;

	if ( kthr->id != thread->thr_id )
		EXIT ( SUCCESS ); /* thread is already finished */

	/* remove thread from queue where its descriptor is */
	switch ( kthr->state )
	{
	case THR_STATE_PASSIVE:
		EXIT ( SUCCESS ); /* thread is already finished */

	case THR_STATE_READY:
	case THR_STATE_WAIT:
		SET_ERRNO ( SUCCESS );
		/* temporary move calling thread (active) to ready */
		move_to_ready ( active_thread );
		/* remove target 'thread' from its queue */
		k_threadq_remove ( kthr->queue, kthr );

		if ( kthr->state == THR_STATE_READY &&
			k_threadq_get( &ready_q[kthr->sched.prio] ) == NULL )
			clear_got_ready ( kthr->sched.prio );

		/* mark it as active and 'end' it normally */
		active_thread = kthr;
		active_thread->state = THR_STATE_ACTIVE;
		active_thread->queue = NULL;
		return sys__thread_exit ( &ret_value );

	case THR_STATE_ACTIVE:
	default:
		EXIT ( E_INVALID_HANDLE ); /* thread descriptor corrupted ! */
	}
}
/*!
 * Release all threads from given queue (if queue not empty)
 * \param q Queue
 * \returns number of thread released, 0 if queue was empty
 */
int k_release_all_threads ( kthread_q *q )
{
	kthread_t *kthr;
	int cnt = 0;

	ASSERT ( q );

	do {
		kthr = k_threadq_remove ( q, NULL );

		if ( kthr )
		{
			move_to_ready ( kthr );
			cnt++;
		}
	}
	while ( kthr );

	return cnt;
}