示例#1
0
int pthread_cancel(pthread_t thread)
{
	_pthread_data_t* ptd;

	/* cancel self */
	if (thread == rt_thread_self()) return 0;

	/* get posix thread data */
	ptd = _pthread_get_data(thread);
	RT_ASSERT(ptd != RT_NULL);

	/* set canceled */
	if (ptd->cancelstate == PTHREAD_CANCEL_ENABLE)
	{
		ptd->canceled = 1;
		if (ptd->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
		{
			/*
			 * to detach thread.
			 * this thread will be removed from scheduler list
			 * and because there is a cleanup function in the
			 * thread (pthread_cleanup), it will move to defunct
			 * thread list and wait for handling in idle thread.
			 */
			rt_thread_detach(thread);
		}
	}

	return 0;
}
示例#2
0
void pthread_cleanup_pop(int execute)
{
	_pthread_data_t* ptd;
	_pthread_cleanup_t* cleanup;

	/* get posix thread data */
	ptd = _pthread_get_data(rt_thread_self());
	RT_ASSERT(ptd != RT_NULL);

	if (execute)
	{
		rt_enter_critical();
		cleanup = ptd->cleanup;
		if (cleanup)
			ptd->cleanup = cleanup->next;
		rt_exit_critical();

		if (cleanup)
		{
			cleanup->cleanup_func(cleanup->parameter);

			rt_free(cleanup);
		}
	}
}
示例#3
0
int pthread_join (pthread_t thread, void **value_ptr)
{
	_pthread_data_t* ptd;
	rt_err_t result;

	if (thread == rt_thread_self())
	{
		/* join self */
		return EDEADLK;
	}

	ptd = _pthread_get_data(thread);
	if (ptd->attr.detachstate == PTHREAD_CREATE_DETACHED)
		return EINVAL; /* join on a detached pthread */

	result = rt_sem_take(ptd->joinable_sem, RT_WAITING_FOREVER);
	if (result == RT_EOK)
	{
		/* get return value */
		if (value_ptr != RT_NULL) *value_ptr = ptd->return_value;

		/* release resource */
		pthread_detach(thread);
	}
	else return ESRCH;
	
	return 0;
}
示例#4
0
void pthread_exit (void* value)
{
	_pthread_data_t* ptd;
	_pthread_cleanup_t* cleanup;
	extern _pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX];

	ptd = _pthread_get_data(rt_thread_self());

	rt_enter_critical();
	/* disable cancel */
	ptd->cancelstate = PTHREAD_CANCEL_DISABLE;
	/* set return value */
	ptd->return_value = value;
	rt_exit_critical();

	/* invoke pushed cleanup */
	while (ptd->cleanup != RT_NULL)
	{
		cleanup = ptd->cleanup;
		ptd->cleanup = cleanup->next;

		cleanup->cleanup_func(cleanup->parameter);
		/* release this cleanup function */
		rt_free(cleanup);
	}

	/* destruct thread local key */
	if (ptd->tls != RT_NULL)
	{
		void* data;
		rt_uint32_t index;
		
		for (index = 0; index < PTHREAD_KEY_MAX; index ++)
		{
			if (_thread_keys[index].is_used)
			{
				data = ptd->tls[index];
				if (data)
					_thread_keys[index].destructor(data);
			}
		}

		/* release tls area */
		rt_free(ptd->tls);
		ptd->tls = RT_NULL;
	}

	if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE)
	{
		/* release the joinable pthread */
		rt_sem_release(ptd->joinable_sem);
	}

	/* detach thread */
	rt_thread_detach(ptd->tid);
	/* reschedule thread */
	rt_schedule();
}
示例#5
0
void pthread_testcancel(void)
{
	int cancel=0;
	_pthread_data_t* ptd;

	/* get posix thread data */
	ptd = _pthread_get_data(rt_thread_self());
	RT_ASSERT(ptd != RT_NULL);

	if (ptd->cancelstate == PTHREAD_CANCEL_ENABLE) cancel = ptd->canceled;
	if (cancel) pthread_exit((void*)PTHREAD_CANCELED);
}
示例#6
0
void *pthread_getspecific(pthread_key_t key)
{
	struct _pthread_data* ptd;

	ptd = _pthread_get_data(rt_thread_self());
	RT_ASSERT(ptd != NULL);

	if (ptd->tls == NULL) return NULL;

	if ((key < PTHREAD_KEY_MAX) && (_thread_keys[key].is_used))
		return ptd->tls[key];

	return NULL;
}
示例#7
0
int pthread_setcanceltype(int type, int *oldtype)
{
	_pthread_data_t* ptd;

	/* get posix thread data */
	ptd = _pthread_get_data(rt_thread_self());
	RT_ASSERT(ptd != RT_NULL);

	if ((type != PTHREAD_CANCEL_DEFERRED) && (type != PTHREAD_CANCEL_ASYNCHRONOUS)) 
		return EINVAL;

	if (oldtype) *oldtype = ptd->canceltype;
	ptd->canceltype = type;

	return 0;
}
示例#8
0
static void _pthread_cleanup(rt_thread_t tid)
{
	_pthread_data_t *ptd;
	ptd = _pthread_get_data(tid);

	/* clear cleanup function */
	tid->cleanup = RT_NULL;
	if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE)
	{
		rt_sem_release(ptd->joinable_sem);
	}
	else
	{
		/* release pthread resource */
		pthread_detach(tid);
	}
}
示例#9
0
int pthread_setspecific(pthread_key_t key, const void *value)
{
	struct _pthread_data* ptd;

	ptd = _pthread_get_data(rt_thread_self());
	RT_ASSERT(ptd != NULL);

	/* check tls area */
	if (ptd->tls == NULL) ptd->tls = rt_malloc(sizeof(void*) * PTHREAD_KEY_MAX);

	if ((key < PTHREAD_KEY_MAX) && _thread_keys[key].is_used)
	{
		ptd->tls[key] = (void *)value;
		return 0;
	}

	return EINVAL;
}
示例#10
0
int pthread_setcancelstate(int state, int *oldstate)
{
	_pthread_data_t* ptd;

	/* get posix thread data */
	ptd = _pthread_get_data(rt_thread_self());
	RT_ASSERT(ptd != RT_NULL);

	if ((state == PTHREAD_CANCEL_ENABLE) || (state == PTHREAD_CANCEL_DISABLE))
	{
    	if (oldstate) *oldstate = ptd->cancelstate;
		ptd->cancelstate = state;

		return 0;
	}

	return EINVAL;
}
示例#11
0
int pthread_detach(pthread_t thread)
{
    _pthread_data_t* ptd;

    ptd = _pthread_get_data(thread);

    if (thread->stat == RT_THREAD_CLOSE)
    {
        /* delete joinable semaphore */
        if (ptd->joinable_sem != RT_NULL)
            rt_sem_delete(ptd->joinable_sem);
        /* detach thread object */
        rt_thread_detach(ptd->tid);

        /* release thread resource */
        if (ptd->attr.stack_base == RT_NULL)
        {
            /* release thread allocated stack */
            rt_free(ptd->tid->stack_addr);
        }

        /*
         * if this thread create the local thread data,
         * delete it
         */
        if (ptd->tls != RT_NULL)
            rt_free(ptd->tls);
        rt_free(ptd->tid);
        rt_free(ptd);
    }
    else
    {
        rt_enter_critical();
        /* change to detach state */
        ptd->attr.detachstate = PTHREAD_CREATE_DETACHED;

        /* detach joinable semaphore */
        rt_sem_delete(ptd->joinable_sem);
        ptd->joinable_sem = RT_NULL;
        rt_exit_critical();
    }

    return 0;
}
示例#12
0
void pthread_cleanup_push(void (*routine)(void*), void *arg)
{
	_pthread_data_t* ptd;
	_pthread_cleanup_t* cleanup;

	/* get posix thread data */
	ptd = _pthread_get_data(rt_thread_self());
	RT_ASSERT(ptd != RT_NULL);

	cleanup = (_pthread_cleanup_t*)rt_malloc(sizeof(_pthread_cleanup_t));
	if (cleanup != RT_NULL)
	{
		cleanup->cleanup_func = routine;
		cleanup->parameter = arg;

		rt_enter_critical();
		cleanup->next = ptd->cleanup;
		ptd->cleanup = cleanup;
		rt_exit_critical();
	}
}