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

📄 thread.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 4 页
字号:
{  if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) != VALID_STATIC_OBJECT)    return false;  return true;}boolpthread_cond::isGoodInitializerOrObject (pthread_cond_t const *cond){  if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) == INVALID_OBJECT)    return false;  return true;}int__pthread_cond_destroy (pthread_cond_t *cond){  if (pthread_cond::isGoodInitializer (cond))    return 0;  if (!pthread_cond::isGoodObject (cond))    return EINVAL;  /* reads are atomic */  if ((*cond)->waiting)    return EBUSY;  delete (*cond);  *cond = NULL;  return 0;}int__pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr){  if (attr && !pthread_condattr::isGoodObject (attr))    return EINVAL;  if (pthread_cond::isGoodObject (cond))    return EBUSY;  *cond = new pthread_cond (attr ? (*attr) : NULL);  if (!pthread_cond::isGoodObject (cond))    {      delete (*cond);      *cond = NULL;      return EAGAIN;    }  return 0;}int__pthread_cond_broadcast (pthread_cond_t *cond){  if (pthread_cond::isGoodInitializer (cond))    __pthread_cond_init (cond, NULL);  if (!pthread_cond::isGoodObject (cond))    return EINVAL;  (*cond)->BroadCast ();  return 0;}int__pthread_cond_signal (pthread_cond_t *cond){  if (pthread_cond::isGoodInitializer (cond))    __pthread_cond_init (cond, NULL);  if (!pthread_cond::isGoodObject (cond))    return EINVAL;  (*cond)->Signal ();  return 0;}int__pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex,		       long waitlength){// and yes cond_access here is still open to a race. (we increment, context swap,// broadcast occurs -  we miss the broadcast. the functions aren't split properly.  int rv;  pthread_mutex **themutex = NULL;  if (pthread_mutex::isGoodInitializer (mutex))    pthread_mutex::init (mutex, NULL);  themutex = mutex;  if (pthread_cond::isGoodInitializer (cond))    __pthread_cond_init (cond, NULL);  if (!pthread_mutex::isGoodObject (themutex))    return EINVAL;  if (!pthread_cond::isGoodObject (cond))    return EINVAL;  /* if the cond variable is blocked, then the above timer test maybe wrong. *shrug**/  if (pthread_mutex_lock (&(*cond)->cond_access))    system_printf ("Failed to lock condition variable access mutex, this %p", *cond);  if ((*cond)->waiting)    if ((*cond)->mutex && ((*cond)->mutex != (*themutex)))      {	if (pthread_mutex_unlock (&(*cond)->cond_access))	  system_printf ("Failed to unlock condition variable access mutex, this %p", *cond);	return EINVAL;      }  InterlockedIncrement (&((*cond)->waiting));  (*cond)->mutex = (*themutex);  InterlockedIncrement (&((*themutex)->condwaits));  if (pthread_mutex_unlock (&(*cond)->cond_access))    system_printf ("Failed to unlock condition variable access mutex, this %p", *cond);  /* At this point calls to Signal will progress evebn if we aren' yet waiting     However, the loop there should allow us to get scheduled and call wait,     and have them call PulseEvent again if we dont' respond.  */  rv = (*cond)->TimedWait (waitlength);  /* this may allow a race on the mutex acquisition and waits.     But doing this within the cond access mutex creates a different race */  InterlockedDecrement (&((*cond)->waiting));  /* Tell Signal that we have been released */  InterlockedDecrement (&((*cond)->ExitingWait));  (*themutex)->Lock ();  if (pthread_mutex_lock (&(*cond)->cond_access))    system_printf ("Failed to lock condition variable access mutex, this %p", *cond);  if ((*cond)->waiting == 0)    (*cond)->mutex = NULL;  InterlockedDecrement (&((*themutex)->condwaits));  if (pthread_mutex_unlock (&(*cond)->cond_access))    system_printf ("Failed to unlock condition variable access mutex, this %p", *cond);  return rv;}extern "C" intpthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,			const struct timespec *abstime){  if (check_valid_pointer (abstime))    return EINVAL;  struct timeb currSysTime;  long waitlength;  ftime (&currSysTime);  waitlength = (abstime->tv_sec - currSysTime.time) * 1000;  if (waitlength < 0)    return ETIMEDOUT;  return __pthread_cond_dowait (cond, mutex, waitlength);}extern "C" intpthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex){  return __pthread_cond_dowait (cond, mutex, INFINITE);}int__pthread_condattr_init (pthread_condattr_t *condattr){  if (check_valid_pointer (condattr))    return EINVAL;  *condattr = new pthread_condattr;  if (!pthread_condattr::isGoodObject (condattr))    {      delete (*condattr);      *condattr = NULL;      return EAGAIN;    }  return 0;}int__pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared){  if (!pthread_condattr::isGoodObject (attr))    return EINVAL;  *pshared = (*attr)->shared;  return 0;}int__pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared){  if (!pthread_condattr::isGoodObject (attr))    return EINVAL;  if ((pshared < 0) || (pshared > 1))    return EINVAL;  /* shared cond vars not currently supported */  if (pshared != PTHREAD_PROCESS_PRIVATE)    return EINVAL;  (*attr)->shared = pshared;  return 0;}int__pthread_condattr_destroy (pthread_condattr_t *condattr){  if (!pthread_condattr::isGoodObject (condattr))    return EINVAL;  delete (*condattr);  *condattr = NULL;  return 0;}/* Thread signal */int__pthread_kill (pthread_t thread, int sig){  // lock myself, for the use of thread2signal  // two different kills might clash: FIXME  if (!pthread::isGoodObject (&thread))    return EINVAL;  if (thread->sigs)    myself->setthread2signal (thread);  int rval = raise (sig);  // unlock myself  return rval;}int__pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set){  pthread *thread = pthread::self ();  // lock this myself, for the use of thread2signal  // two differt kills might clash: FIXME  if (thread->sigs)    myself->setthread2signal (thread);  int rval = sigprocmask (operation, set, old_set);  // unlock this myself  return rval;}/* ID */int__pthread_equal (pthread_t *t1, pthread_t *t2){  return (*t1 == *t2);}/* Mutexes  *//* FIXME: there's a potential race with PTHREAD_MUTEX_INITALIZER:   the mutex is not actually inited until the first use.   So two threads trying to lock/trylock may collide.   Solution: we need a global mutex on mutex creation, or possibly simply   on all constructors that allow INITIALIZER macros.   the lock should be very small: only around the init routine, not   every test, or all mutex access will be synchronised.  */intpthread_mutex::init (pthread_mutex_t *mutex,		      const pthread_mutexattr_t *attr){  if (attr && !pthread_mutexattr::isGoodObject (attr) || check_valid_pointer (mutex))    return EINVAL;  if (!mutexInitializationLock.lock ())    return EINVAL;  if (!isGoodInitializerOrBadObject (mutex))    {      mutexInitializationLock.unlock ();      return EBUSY;    }  *mutex = new pthread_mutex (attr ? (*attr) : NULL);  if (!isGoodObject (mutex))    {      delete (*mutex);      *mutex = NULL;      mutexInitializationLock.unlock ();      return EAGAIN;    }  mutexInitializationLock.unlock ();  return 0;}int__pthread_mutex_getprioceiling (const pthread_mutex_t *mutex,				int *prioceiling){  pthread_mutex_t *themutex = (pthread_mutex_t *) mutex;  if (pthread_mutex::isGoodInitializer (mutex))    pthread_mutex::init ((pthread_mutex_t *) mutex, NULL);  if (!pthread_mutex::isGoodObject (themutex))    return EINVAL;  /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support     mutex priorities.     We can support mutex priorities in the future though:     Store a priority with each mutex.     When the mutex is optained, set the thread priority as appropriate     When the mutex is released, reset the thread priority.  */  return ENOSYS;}int__pthread_mutex_lock (pthread_mutex_t *mutex){  pthread_mutex_t *themutex = mutex;  /* This could be simplified via isGoodInitializerOrObject     and isGoodInitializer, but in a performance critical call like this....     no.  */  switch (verifyable_object_isvalid (themutex, PTHREAD_MUTEX_MAGIC, PTHREAD_MUTEX_INITIALIZER))    {    case INVALID_OBJECT:      return EINVAL;      break;    case VALID_STATIC_OBJECT:      if (pthread_mutex::isGoodInitializer (mutex))	{	  int rv = pthread_mutex::init (mutex, NULL);	  if (rv && rv != EBUSY)	    return rv;	}      /* No else needed. If it's been initialized while we waited,	 we can just attempt to lock it */      break;    case VALID_OBJECT:      break;    }  (*themutex)->Lock ();  return 0;}int__pthread_mutex_trylock (pthread_mutex_t *mutex){  pthread_mutex_t *themutex = mutex;  if (pthread_mutex::isGoodInitializer (mutex))    pthread_mutex::init (mutex, NULL);  if (!pthread_mutex::isGoodObject (themutex))    return EINVAL;  if ((*themutex)->TryLock ())    return EBUSY;  return 0;}int__pthread_mutex_unlock (pthread_mutex_t *mutex){  if (pthread_mutex::isGoodInitializer (mutex))    pthread_mutex::init (mutex, NULL);  if (!pthread_mutex::isGoodObject (mutex))    return EINVAL;  (*mutex)->UnLock ();  return 0;}int__pthread_mutex_destroy (pthread_mutex_t *mutex){  if (pthread_mutex::isGoodInitializer (mutex))    return 0;  if (!pthread_mutex::isGoodObject (mutex))    return EINVAL;  /* reading a word is atomic */  if ((*mutex)->condwaits)    return EBUSY;  delete (*mutex);  *mutex = NULL;  return 0;}int__pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling,				int *old_ceiling){  pthread_mutex_t *themutex = mutex;  if (pthread_mutex::isGoodInitializer (mutex))    pthread_mutex::init (mutex, NULL);  if (!pthread_mutex::isGoodObject (themutex))    return EINVAL;  return ENOSYS;}/* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling   for more detail */int__pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attr,				 int *protocol){  if (!pthread_mutexattr::isGoodObject (attr))    return EINVAL;  return ENOSYS;}int__pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr,				int *pshared){  if (!pthread_mutexattr::isGoodObject (attr))    return EINVAL;  *pshared = (*attr)->pshared;  return 0;}/* Win32 mutex's are equivalent to posix RECURSIVE mutexs.   We need to put glue in place to support other types of mutex's. We map   PTHREAD_MUTEX_DEFAULT to PTHREAD_MUTEX_RECURSIVE and return EINVAL for   other types.  */int__pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type){  if (!pthread_mutexattr::isGoodObject (attr))    return EINVAL;  *type = (*attr)->mutextype;  return 0;}/* Currently pthread_mutex_init ignores the attr variable, this is because   none of the variables have any impact on it's behaviour.   FIXME: write and test process shared mutex's.  */int__pthread_mutexattr_init (pthread_mutexattr_t *attr){  if (pthread_mutexattr::isGoodObject (attr))    return EBUSY;  *attr = new pthread_mutexattr ();  if (!pthread_mutexattr::isGoodObject (attr))    {      delete (*attr);      *attr = NULL;      return ENOMEM;    }  return 0;}int__pthread_mutexattr_destroy (pthread_mutexattr_t *attr){  if (!pthread_mutexattr::isGoodObject (attr))    return EINVAL;  delete (*attr);  *attr = NULL;  return 0;}/* Win32 doesn't support mutex priorities */int__pthread_mutexattr_setprotocol (pthread_mutexattr_t *attr, int protocol){  if (!pthread_mutexattr::isGoodObject (attr))    return EINVAL;  return ENOSYS;}/* Win32 doesn't support mutex priorities */int__pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr,				    int prioceiling){  if (!pthread_mutexattr::isGoodObject (attr))    return EINVAL;  return ENOSYS;}int__pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *attr,				    int *prioceiling){  if (!pthread_mutexattr::isGoodObject (attr))    return EINVAL;  return ENOSYS;}int__pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared){  if (!pthread_mutexattr::isGoodObject (attr))    return EINVAL;  /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED   *functionality   */  if (pshared != PTHREAD_PROCESS_PRIVATE)    return EINVAL;  (*attr)->pshared = pshared;  return 0;}/* see __pthread_mutex_gettype */int__pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type){  if (!pthread_mutexattr::isGoodObject (attr))    return EINVAL;  if (type != PTHREAD_MUTEX_RECURSIVE)    return EINVAL;  (*attr)->mutextype = type;  return 0;}/* Semaphores *//* static members */boolsemaphore::isGoodObject (sem_t const * sem){  if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)    return false;  return true;}intsemaphore::init (sem_t *sem, int pshared, unsigned int value){  /* opengroup calls this undefined */  if (isGoodObject (sem))    return EBUSY;  if (value > SEM_VALUE_MAX)    return EINVAL;  *sem = new semaphore (pshared, value);  if (!isGoodObject (sem))    {      delete (*sem);      *sem = NULL;      return EAGAIN;    }  return 0;}intsemaphore::destroy (sem_t *sem){  if (!isGoodObject (sem))    return EINVAL;  /* FIXME - new feature - test for busy against threads... */  delete (*sem);  *sem = NULL;  return 0;}intsemaphore::wait (sem_t *sem){  if (!isGoodObject (sem))    {      set_errno (EINVAL);      return -1;    }  (*sem)->Wait ();  return 0;}intsemaphore::trywait (sem_t *sem){  if (!isGoodObject (sem))    {      set_errno (EINVAL);      return -1;    }  return (*sem)->TryWait ();}intsemaphore::post (sem_t *sem){  if (!isGoodObject (sem))    return EINVAL;  (*sem)->Post ();  return 0;}/* pthreadNull */pthread *pthreadNull::getNullpthread (){  /* because of weird entry points */  _instance.magic = 0;  return &_instance;}pthreadNull::pthreadNull (){  attr.joinable = PTHREAD_CREATE_DETACHED;  /* Mark ourselves as invalid */  magic = 0;}pthreadNull::~pthreadNull (){}voidpthreadNull::create (void *(*)(void *), pthread_attr *, void *){}voidpthreadNull::exit (void *value_ptr){  ExitThread (0);}intpthreadNull::cancel (){  return 0;}voidpthreadNull::testcancel (){}intpthreadNull::setcancelstate (int state, int *oldstate){  return EINVAL;}intpthreadNull::setcanceltype (int type, int *oldtype){  return EINVAL;}voidpthreadNull::push_cleanup_handler (__pthread_cleanup_handler *handler){}voidpthreadNull::pop_cleanup_handler (int const execute){}unsigned longpthreadNull::getsequence_np (){  return 0;}pthreadNull pthreadNull::_instance;#endif // MT_SAFE

⌨️ 快捷键说明

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