📄 pthread.c
字号:
/* pthread.c,v 1.7 2001/10/04 16:07:15 joeh Exp
* =============================================================================
*
* = LIBRARY
* pace
*
* = FILENAME
* pace/vxworks/pthread.c
*
* = AUTHOR
* Joe Hoffert. The *VAST* majority of the pthread code for VxWorks
* has been supplied by Hughes Network Systems via Braeton Taylor.
*
* ============================================================================= */
#include "pace/pthread.h"
/* pthread queue */
static pthread_q_entry pthread_queue[PTHEAD_QUEUE_MAX_LEN];
static pthread_q_entry * first = NULL;
static pthread_q_entry * current = NULL;
static int pthread_count = 0;
/*static pthread_q_entry * pthread_queue_get_entry();*/
static int initialized = 0;
static int registered_cleanup_init = 0;
static pthread_key_entry keyList[PTHREAD_KEYS_MAX];
/*
* The defaut pthread attr structure, if calling task
* does not pass attr, this default will be used
*/
static struct _PTHREAD_ATTR _pthread_attr_default_s =
{
PTHREAD_DEFAULT_STACK_SIZE, /* stacksize */
{ '\0' }, /* name */
{100}, /* priority */
PTHREAD_SCOPE_SYSTEM, /* scope */
SCHED_FIFO, /* indirect function */
/* According to the POSIX standard PTHREAD_CREATE_JOINABLE
* is the default
*/
/*PTHREAD_CREATE_DETACHED * detached */
PTHREAD_CREATE_JOINABLE /* joinable */
};
/* global default access */
pace_pthread_attr_t pthread_attr_default = &_pthread_attr_default_s;
#if !defined (PACE_HAS_INLINE)
# include "pace/vxworks/pthread.inl"
#endif /* ! PACE_HAS_INLINE */
/*
* VxWorks Helper Functions
*/
/*
* Setup the thread information needed for main. This function
* mimics much of what's in pthread_create below but this is
* only for registering a thread already created (as in the case
* of main).
*/
STATUS
pacevx_vxworks_init()
{
WIND_TCB *pTcb;
pace_pthread_t pthread;
int taskid;
unsigned int i;
STATUS status;
PACE_TRACE("pacevx_vxworks_init");
/* Fill in the main thread's TCB with the information needed
* for POSIX emulation.
*/
taskid = taskIdSelf();
if ((pTcb = taskTcb(taskid)) == NULL)
{
taskDelete(taskid);
return ERROR;
}
pthread = (pace_pthread_t )malloc(sizeof(struct _PTHREAD_T));
if (pthread == NULL)
{
taskDelete(taskid);
return ERROR;
}
/* construct pace_pthread_t structure */
bzero((char *)pthread, sizeof(struct _PTHREAD_T));
pthread->tid = taskid;
pthread->stateflag = PTHREAD_CANCEL_ENABLE;
pthread->canceltype = PTHREAD_CANCEL_ASYNCHRONOUS;
/*pthread->detachflag = PTHREAD_CREATE_JOINABLE;*/
pthread->detachflag = PTHREAD_CREATE_DETACHED;
/* initialize the join semaphore also */
if ((pthread->joinSem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY)) == NULL)
{
free((void *)pthread);
taskDelete(taskid);
return ERROR;
}
/* save to the WIND_TCB for reference afterward */
pTcb->_USER_SPARE4 = (int) pthread;
/* I guess this doesn't need to get added for the main thread.
* It seems to cause problems for main.
if (registered_cleanup_init == 0)
{
status = taskDeleteHookAdd((FUNCPTR)pacevx_pthread_run_cleanup);
if (status == ERROR)
{
return ERROR;
}
registered_cleanup_init = 1;
}
pacevx_pthread_queue_add(pthread);
*/
return OK;
}
/*
* Get a free entry from the pthread queue.
*/
#if (PACE_HAS_POSIX_NONUOF_FUNCS)
pthread_q_entry *
pacevx_pthread_queue_get_entry ()
{
int i;
PACE_TRACE("pacevx_pthread_queue_get_entry");
for (i = 0; i < PTHEAD_QUEUE_MAX_LEN; i++)
{
if (pthread_queue[i].status == FALSE)
return &pthread_queue[i];
}
/* error condition, can alloc more in future */
return NULL;
}
#endif /* PACE_HAS_NONUOF_FUNCS */
/*
* Run the destructor functions for the specific data key
*/
#if (PACE_HAS_POSIX_NONUOF_FUNCS)
void
pacevx_pthread_destructor_key (pace_pthread_key_t key, void * arg)
{
PACE_TRACE("pacevx_pthread_destructor_key");
if (pacevx_pthread_key_validate(key))
{
if (keyList[key].destructor != NULL)
{
(*(keyList[key].destructor))(arg);
}
}
}
#endif /* PACE_HAS_NONUOF_FUNCS */
/*
* Run the destructor functions for the thread
* For each key value, if there is a non-NULL destructor pointer,
* and the thread has a non-NULL value associated with that key,
* the function pointed to is called with the current associated
* value as its sole argument.
*
* return: none.
*/
#if (PACE_HAS_POSIX_NONUOF_FUNCS)
void
pacevx_pthread_destructor_thread (pace_pthread_t pthread)
{
int i;
PACE_TRACE("pacevx_pthread_destructor_thread");
for (i = 0; i < PTHREAD_KEYS_MAX; i ++)
{
if (pthread->keyvaluelist[i] != NULL)
{
pacevx_pthread_destructor_key(i, pthread->keyvaluelist[i]);
}
}
}
#endif /* PACE_HAS_NONUOF_FUNCS */
/*
* General exit processing.
*/
#if (PACE_HAS_POSIX_NONUOF_FUNCS)
void
pacevx_pthread_proc_exit (pace_pthread_t pthread, void *value_ptr)
{
int key;
int needgive = 0;
PACE_TRACE("pacevx_pthread_proc_exit");
pacevx_pthread_cleanup_popall(pthread);
/* thread storage data cleanup is automatically*/
pacevx_pthread_destructor_thread(pthread);
/* joinable or detached */
if (pthread->detachflag == PTHREAD_CREATE_DETACHED)
{
free(pthread);
}
else
{
key = intLock();
/* pass the value */
pthread->joinvalue = value_ptr;
switch (pthread->joinstate)
{
case JOIN_PENDING:
pthread->joinstate = JOIN_TERMINATED;
needgive = 1;
break;
case JOIN_NORMAL:
default:
pthread->joinstate = JOIN_TERMINATED;
break;
}
intUnlock(key);
/* unblock the calling thread */
if (needgive)
semGive(((pace_pthread_t)(pthread->jointhread))->joinSem);
}
}
#endif /* PACE_HAS_NONUOF_FUNCS */
#if (PACE_HAS_POSIX_NONUOF_FUNCS)
int
pacevx_pthread_verify (pace_pthread_t pthread)
{
int key;
pthread_q_entry * entry;
PACE_TRACE("pacevx_pthread_verify");
key = intLock();
/* if queue is empty */
if (first == NULL)
{
intUnlock(key);
return ERROR;
}
entry = first; /* get the first one */
while (entry != NULL)
{
if (entry->pthread == pthread)
{
intUnlock(key);
return TRUE;
}
entry = entry->next;
}
intUnlock(key);
return FALSE;
}
#endif /* PACE_HAS_NONUOF_FUNCS */
/*
* The cleanup routine that will be called if the task get deleted.
*/
#if (PACE_HAS_POSIX_NONUOF_FUNCS)
void
pacevx_pthread_run_cleanup (WIND_TCB *pTcb)
/* pointer to deleted task's WIND_TCB */
{
pace_pthread_t pthread;
PACE_TRACE("pacevx_pthread_run_cleanup");
/* free thread tcb only*/
if (pTcb->_USER_SPARE4 != 0)
{
pthread = (pace_pthread_t) pTcb->_USER_SPARE4;
pacevx_pthread_proc_exit(pthread, NULL);
}
}
#endif /* PACE_HAS_NONUOF_FUNCS */
/*
* Add to the pthread queue.
*/
#if (PACE_HAS_POSIX_NONUOF_FUNCS)
int
pacevx_pthread_queue_add (pace_pthread_t pthread)
{
int key;
pthread_q_entry * entry;
PACE_TRACE("pacevx_pthread_queue_add");
key = intLock();
if ((entry = pacevx_pthread_queue_get_entry()) != NULL)
{
entry->status = TRUE;
entry->pthread = pthread;
if (first == NULL)
{
first = entry;
current = entry;
}
else
{
current->next = entry;
current = entry;
}
pthread_count ++;
intUnlock(key);
return OK;
}
intUnlock(key);
return ERROR;
}
#endif /* PACE_HAS_NONUOF_FUNCS */
/*
* Remove an entry to the pthread queue.
*/
#if (PACE_HAS_POSIX_NONUOF_FUNCS)
int
pacevx_pthread_queue_remove (pace_pthread_t pthread)
{
int key;
pthread_q_entry * entry1;
pthread_q_entry * entry2;
PACE_TRACE("pacevx_pthread_queue_remove");
key = intLock();
if (first == NULL)
{
intUnlock(key);
return ERROR;
}
/* if it is the first one, simple */
if (first->pthread == pthread)
{
first->status = FALSE;
first->pthread = NULL;
entry1 = first->next;
first->next = NULL;
/* if it is the only one */
if (current == first)
current = entry1;
first = entry1;
/* Check for the last thread and unregister cleanup function */
if (first == NULL)
taskDeleteHookDelete((FUNCPTR)pacevx_pthread_run_cleanup);
intUnlock(key);
return OK;
}
/* else */
entry1 = first;
entry2 = entry1->next;
while (entry2 != NULL)
{
if (entry2->pthread == pthread)
{
if (current == entry2)
current = entry1;
entry1->next = entry2->next; /* remove the node */
/* set invalid and put back to the list */
entry2->status = FALSE;
entry2->pthread = NULL;
entry2->next = NULL;
intUnlock(key);
return OK;
}
entry1 = entry2;
entry2 = entry2->next;
}
intUnlock(key);
return ERROR;
}
#endif /* PACE_HAS_NONUOF_FUNCS */
/*
* Run the rest of cleanup routines left in the stack.
*/
#if (PACE_HAS_POSIX_NONUOF_FUNCS)
void
pacevx_pthread_cleanup_popall (pace_pthread_t thread)
{
int count;
int i;
PACE_TRACE("pacevx_pthread_cleanup_popall");
count = thread->rtnCount - 1;
/*
* We don't currently support any way
* to add cleanup routines since pace_pthread_cleanup_push and
* pace_pthread_cleanup_pop are undefined macros for VxWorks.
*/
for (i = count; i > 0 ; i--)
{
thread->rtnCount --;
(*(thread->cleanupRtn[i].routine))(thread->cleanupRtn[i].args);
}
}
#endif /* PACE_HAS_NONUOF_FUNCS */
/*
* Validate the key to see if the key is already created (valid)
*/
#if (PACE_HAS_POSIX_NONUOF_FUNCS)
int
pacevx_pthread_key_validate (pace_pthread_key_t key)
{
int intkey;
PACE_TRACE("pacevx_pthread_key_validate");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -