⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pthread.c

📁 一个开源的网络开发库ACE
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 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 + -