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

📄 thread.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 4 页
字号:
    api_fatal ("doesn't understand PROCESS_SHARED semaphores variables");  /* FIXME: duplicate code here and in the constructor. */  this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, currentvalue, LONG_MAX, NULL);  if (!win32_obj_id)    api_fatal ("failed to create new win32 semaphore");}verifyable_object::verifyable_object (long verifyer):magic (verifyer){}verifyable_object::~verifyable_object (){  magic = 0;}/* Generic memory acccess routine - where should it live ? */int __stdcallcheck_valid_pointer (void const *pointer){  if (!pointer || IsBadWritePtr ((void *) pointer, sizeof (verifyable_object)))    return EFAULT;  return 0;}verifyable_object_stateverifyable_object_isvalid (void const * objectptr, long magic, void *static_ptr){  verifyable_object **object = (verifyable_object **)objectptr;  if (check_valid_pointer (object))    return INVALID_OBJECT;  if (static_ptr && *object == static_ptr)    return VALID_STATIC_OBJECT;  if (!*object)    return INVALID_OBJECT;  if (check_valid_pointer (*object))    return INVALID_OBJECT;  if ((*object)->magic != magic)    return INVALID_OBJECT;  return VALID_OBJECT;}verifyable_object_stateverifyable_object_isvalid (void const * objectptr, long magic){  return verifyable_object_isvalid (objectptr, magic, NULL);}/* Pthreads */void *pthread::thread_init_wrapper (void *_arg){  // Setup the local/global storage of this thread  pthread *thread = (pthread *) _arg;  struct __reent_t local_reent;  struct _winsup_t local_winsup;  struct _reent local_clib = _REENT_INIT (local_clib);  struct sigaction _sigs[NSIG];  sigset_t _sig_mask;		/* one set for everything to ignore. */  LONG _sigtodo[NSIG + __SIGOFFSET];  // setup signal structures  thread->sigs = _sigs;  thread->sigmask = &_sig_mask;  thread->sigtodo = _sigtodo;  memset (&local_winsup, 0, sizeof (struct _winsup_t));  local_reent._clib = &local_clib;  local_reent._winsup = &local_winsup;  local_winsup._process_logmask = LOG_UPTO (LOG_DEBUG);  MT_INTERFACE->reent_key.set (&local_reent);  thread->setThreadIdtoCurrent ();  setTlsSelfPointer (thread);  thread->mutex.Lock ();  // if thread is detached force cleanup on exit  if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL)    thread->joiner = thread;  thread->mutex.UnLock ();#ifdef _CYG_THREAD_FAILSAFE  if (_REENT == _impure_ptr)    system_printf ("local storage for thread isn't setup correctly");#endif  thread_printf ("started thread %p %p %p %p %p %p", _arg, &local_clib,		 _impure_ptr, thread, thread->function, thread->arg);  // call the user's thread  void *ret = thread->function (thread->arg);  thread->exit (ret);#if 0// ??? This code only runs if the thread exits by returning.// it's all now in __pthread_exit ();#endif  /* never reached */  return 0;}boolpthread::isGoodObject (pthread_t const *thread){  if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT)    return false;  return true;}unsigned longpthread::getsequence_np (){  return getThreadId ();}intpthread::create (pthread_t *thread, const pthread_attr_t *attr,		  void *(*start_routine) (void *), void *arg){  DECLARE_TLS_STORAGE;  if (attr && !pthread_attr::isGoodObject (attr))    return EINVAL;  *thread = new pthread ();  (*thread)->create (start_routine, attr ? *attr : NULL, arg);  if (!isGoodObject (thread))    {      delete (*thread);      *thread = NULL;      return EAGAIN;    }  return 0;}intpthread::once (pthread_once_t *once_control, void (*init_routine) (void)){  // already done ?  if (once_control->state)    return 0;  pthread_mutex_lock (&once_control->mutex);  /* Here we must set a cancellation handler to unlock the mutex if needed */  /* but a cancellation handler is not the right thing. We need this in the thread   *cleanup routine. Assumption: a thread can only be in one pthread_once routine   *at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock   *on pthread_exit ();   */  if (!once_control->state)    {      init_routine ();      once_control->state = 1;    }  /* Here we must remove our cancellation handler */  pthread_mutex_unlock (&once_control->mutex);  return 0;}intpthread::cancel (pthread_t thread){  if (!isGoodObject (&thread))    return ESRCH;  return thread->cancel ();}/* Races in pthread_atfork:   We are race safe in that any additions to the lists are made via   InterlockedExchangePointer.   However, if the user application doesn't perform syncronisation of some sort   It's not guaranteed that a near simultaneous call to pthread_atfork and fork   will result in the new atfork handlers being calls.   More rigorous internal syncronisation isn't needed as the user program isn't   guaranteeing their own state.   as far as multiple calls to pthread_atfork, the worst case is simultaneous calls   will result in an indeterminate order for parent and child calls (what gets inserted   first isn't guaranteed.)   There is one potential race... Does the result of InterlockedExchangePointer   get committed to the return location _before_ any context switches can occur?   If yes, we're safe, if no, we're not.  */voidpthread::atforkprepare (void){  MT_INTERFACE->fixup_before_fork ();  callback *cb = MT_INTERFACE->pthread_prepare;  while (cb)    {      cb->cb ();      cb = cb->next;    }}voidpthread::atforkparent (void){  callback *cb = MT_INTERFACE->pthread_parent;  while (cb)    {      cb->cb ();      cb = cb->next;    }}voidpthread::atforkchild (void){  MT_INTERFACE->fixup_after_fork ();  callback *cb = MT_INTERFACE->pthread_child;  while (cb)    {      cb->cb ();      cb = cb->next;    }}/* Register a set of functions to run before and after fork.   prepare calls are called in LI-FC order.   parent and child calls are called in FI-FC order.  */intpthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void)){  callback *prepcb = NULL, *parentcb = NULL, *childcb = NULL;  if (prepare)    {      prepcb = new callback;      if (!prepcb)	return ENOMEM;    }  if (parent)    {      parentcb = new callback;      if (!parentcb)	{	  if (prepcb)	    delete prepcb;	  return ENOMEM;	}    }  if (child)    {      childcb = new callback;      if (!childcb)	{	  if (prepcb)	    delete prepcb;	  if (parentcb)	    delete parentcb;	  return ENOMEM;	}    }  if (prepcb)  {    prepcb->cb = prepare;    prepcb->next = (callback *) InterlockedExchangePointer ((LONG *) &MT_INTERFACE->pthread_prepare, (long int) prepcb);  }  if (parentcb)  {    parentcb->cb = parent;    callback **t = &MT_INTERFACE->pthread_parent;    while (*t)      t = &(*t)->next;    /* t = pointer to last next in the list */    parentcb->next = (callback *) InterlockedExchangePointer ((LONG *) t, (long int) parentcb);  }  if (childcb)  {    childcb->cb = child;    callback **t = &MT_INTERFACE->pthread_child;    while (*t)      t = &(*t)->next;    /* t = pointer to last next in the list */    childcb->next = (callback *) InterlockedExchangePointer ((LONG *) t, (long int) childcb);  }  return 0;}int__pthread_attr_init (pthread_attr_t *attr){  if (check_valid_pointer (attr))    return EINVAL;  *attr = new pthread_attr;  if (!pthread_attr::isGoodObject (attr))    {      delete (*attr);      *attr = NULL;      return EAGAIN;    }  return 0;}int__pthread_attr_getinheritsched (const pthread_attr_t *attr,				int *inheritsched){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  *inheritsched = (*attr)->inheritsched;  return 0;}int__pthread_attr_getschedparam (const pthread_attr_t *attr,			      struct sched_param *param){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  *param = (*attr)->schedparam;  return 0;}/* From a pure code point of view, this should call a helper in sched.cc,   to allow for someone adding scheduler policy changes to win32 in the future.   However that's extremely unlikely, so short and sweet will do us */int__pthread_attr_getschedpolicy (const pthread_attr_t *attr, int *policy){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  *policy = SCHED_FIFO;  return 0;}int__pthread_attr_getscope (const pthread_attr_t *attr, int *contentionscope){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  *contentionscope = (*attr)->contentionscope;  return 0;}int__pthread_attr_setdetachstate (pthread_attr_t *attr, int detachstate){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  if (detachstate < 0 || detachstate > 1)    return EINVAL;  (*attr)->joinable = detachstate;  return 0;}int__pthread_attr_getdetachstate (const pthread_attr_t *attr, int *detachstate){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  *detachstate = (*attr)->joinable;  return 0;}int__pthread_attr_setinheritsched (pthread_attr_t *attr, int inheritsched){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  if (inheritsched != PTHREAD_INHERIT_SCHED      && inheritsched != PTHREAD_EXPLICIT_SCHED)    return ENOTSUP;  (*attr)->inheritsched = inheritsched;  return 0;}int__pthread_attr_setschedparam (pthread_attr_t *attr,			      const struct sched_param *param){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  if (!valid_sched_parameters (param))    return ENOTSUP;  (*attr)->schedparam = *param;  return 0;}/* See __pthread_attr_getschedpolicy for some notes */int__pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  if (policy != SCHED_FIFO)    return ENOTSUP;  return 0;}int__pthread_attr_setscope (pthread_attr_t *attr, int contentionscope){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  if (contentionscope != PTHREAD_SCOPE_SYSTEM      && contentionscope != PTHREAD_SCOPE_PROCESS)    return EINVAL;  /* In future, we may be able to support system scope by escalating the thread     priority to exceed the priority class. For now we only support PROCESS scope. */  if (contentionscope != PTHREAD_SCOPE_PROCESS)    return ENOTSUP;  (*attr)->contentionscope = contentionscope;  return 0;}int__pthread_attr_setstacksize (pthread_attr_t *attr, size_t size){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  (*attr)->stacksize = size;  return 0;}int__pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *size){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  *size = (*attr)->stacksize;  return 0;}int__pthread_attr_destroy (pthread_attr_t *attr){  if (!pthread_attr::isGoodObject (attr))    return EINVAL;  delete (*attr);  *attr = NULL;  return 0;}intpthread::join (pthread_t *thread, void **return_val){   pthread_t joiner = self ();   if (!isGoodObject (&joiner))     return EINVAL;   // Initialize return val with NULL   if (return_val)     *return_val = NULL;  /* FIXME: wait on the thread cancellation event as well - we are a cancellation point*/  if (!isGoodObject (thread))    return ESRCH;  if (__pthread_equal (thread,&joiner))    return EDEADLK;  (*thread)->mutex.Lock ();  if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)    {      (*thread)->mutex.UnLock ();      return EINVAL;    }  else    {      (*thread)->joiner = joiner;      (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;      (*thread)->mutex.UnLock ();      WaitForSingleObject ((*thread)->win32_obj_id, INFINITE);      if (return_val)	 *return_val = (*thread)->return_ptr;      // cleanup      delete (*thread);    }	/* End if */  pthread_testcancel ();  return 0;}intpthread::detach (pthread_t *thread){  if (!isGoodObject (thread))    return ESRCH;  (*thread)->mutex.Lock ();  if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)    {      (*thread)->mutex.UnLock ();      return EINVAL;    }  // check if thread is still alive  if (WAIT_TIMEOUT == WaitForSingleObject ((*thread)->win32_obj_id, 0))    {      // force cleanup on exit      (*thread)->joiner = *thread;      (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;      (*thread)->mutex.UnLock ();    }  else    {      // thread has already terminated.      (*thread)->mutex.UnLock ();      delete (*thread);    }  return 0;}intpthread::suspend (pthread_t *thread){  if (!isGoodObject (thread))    return ESRCH;  if ((*thread)->suspended == false)    {      (*thread)->suspended = true;      SuspendThread ((*thread)->win32_obj_id);    }  return 0;}intpthread::resume (pthread_t *thread){  if (!isGoodObject (thread))    return ESRCH;  if ((*thread)->suspended == true)    ResumeThread ((*thread)->win32_obj_id);  (*thread)->suspended = false;  return 0;}/* provided for source level compatability.   See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html*/int__pthread_getconcurrency (void){  return MT_INTERFACE->concurrency;}/* keep this in sync with sched.cc */int__pthread_getschedparam (pthread_t thread, int *policy,			 struct sched_param *param){  if (!pthread::isGoodObject (&thread))    return ESRCH;  *policy = SCHED_FIFO;  /* we don't return the current effective priority, we return the current     requested priority */  *param = thread->attr.schedparam;  return 0;}/* Thread SpecificData */int__pthread_key_create (pthread_key_t *key, void (*destructor) (void *)){  /* The opengroup docs don't define if we should check this or not,     but creation is relatively rare.  */  if (pthread_key::isGoodObject (key))    return EBUSY;  *key = new pthread_key (destructor);  if (!pthread_key::isGoodObject (key))    {      delete (*key);      *key = NULL;      return EAGAIN;    }  return 0;}int__pthread_key_delete (pthread_key_t key){  if (!pthread_key::isGoodObject (&key))    return EINVAL;  delete (key);  return 0;}/* provided for source level compatability.  Seehttp://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html*/int__pthread_setconcurrency (int new_level){  if (new_level < 0)    return EINVAL;  MT_INTERFACE->concurrency = new_level;  return 0;}/* keep syncronised with sched.cc */int__pthread_setschedparam (pthread_t thread, int policy,			 const struct sched_param *param){  if (!pthread::isGoodObject (&thread))    return ESRCH;  if (policy != SCHED_FIFO)    return ENOTSUP;  if (!param)    return EINVAL;  int rv =    sched_set_thread_priority (thread->win32_obj_id, param->sched_priority);  if (!rv)    thread->attr.schedparam.sched_priority = param->sched_priority;  return rv;}int__pthread_setspecific (pthread_key_t key, const void *value){  if (!pthread_key::isGoodObject (&key))    return EINVAL;  (key)->set (value);  return 0;}void *__pthread_getspecific (pthread_key_t key){  if (!pthread_key::isGoodObject (&key))    return NULL;  return (key)->get ();}/* Thread synchronisation */boolpthread_cond::isGoodObject (pthread_cond_t const *cond){  if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)    return false;  return true;}boolpthread_cond::isGoodInitializer (pthread_cond_t const *cond)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -