Пример #1
0
kthread_t *kthreadq_remove ( kthread_q *q, kthread_t *kthread )
{
	ASSERT ( q );
	if ( kthread )
		return list_find_and_remove ( &q->q, &kthread->list );
	else
		return list_remove ( &q->q, FIRST, NULL );
}
Пример #2
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 );
}
Пример #3
0
/*! Free space reserved by kernel object */
void *kfree_kobject ( kobject_t *kobj )
{
	ASSERT ( kobj );
#ifndef DEBUG
	list_remove ( &kobjects, 0, &kobj->list );
#else /* DEBUG */
	ASSERT ( list_find_and_remove ( &kobjects, &kobj->list ) );
#endif

	kfree ( kobj );

	return EXIT_SUCCESS;
}
Пример #4
0
/*! Internal function for removing (freeing) thread descriptor */
static void kthread_remove_descriptor ( kthread_t *kthread )
{
	ASSERT ( kthread );

	k_free_id ( kthread->id );
	kthread->id = 0;

#ifdef DEBUG
	ASSERT( kthread == list_find_and_remove (&all_threads, &kthread->all) );
#else
	(void) list_remove ( &all_threads, 0, &kthread->all );
#endif

	kfree ( kthread );
}
Пример #5
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--;

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

	arch_destroy_thread_context ( &kthread->state.context );

	kthread_restore_state ( kthread );

	if ( kthread->proc->thread_count == 0 && kthread->proc->pi )
	{
		/* last (non-kernel) thread - remove process */

		kfree_process_kobjects ( kthread->proc );

		kthread->proc->prog->started = FALSE;
#ifdef DEBUG
		ASSERT ( kthread->proc ==
			list_find_and_remove ( &procs, &kthread->proc->list ) );
#else
		(void) list_remove ( &procs, 0, &kthread->proc->list );
#endif
		kfree ( kthread->proc );
	}


	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;
}