* cygwin.din: Export the new functions.
* pthread.cc (pthread_cond_*): Add wrapper functions that call __pthread_cond* functions. * thread.cc (__pthread_cond_*): Implement the pthread_cond* functions. * thread.h: Add new class entries and prototypes for __pthread_cond* functions. * include/pthread.h: user land header prototypes for pthread_cond* functions and related defines.
This commit is contained in:
		| @@ -1,3 +1,14 @@ | ||||
| aturday Mar 17 01:19 2001 Robert Collins rbtcollins@hotmail.com | ||||
|     | ||||
| 	* cygwin.din: Export the new functions. | ||||
| 	* pthread.cc (pthread_cond_*): Add wrapper functions that call | ||||
| 	__pthread_cond* functions. | ||||
| 	* thread.cc (__pthread_cond_*): Implement the pthread_cond* functions. | ||||
| 	* thread.h: Add new class entries and prototypes for __pthread_cond* | ||||
| 	functions. | ||||
| 	* include/pthread.h: user land header prototypes for pthread_cond* | ||||
| 	functions and related defines. | ||||
|  | ||||
| Wed Mar 14 16:30:00 2001  Corinna Vinschen <corinna@vinschen.de> | ||||
|  | ||||
| 	* environ.cc (parse_options): Use strtok_r instead of strtok. | ||||
|   | ||||
| @@ -1099,6 +1099,16 @@ cygwin32_internal = cygwin_internal | ||||
| @PTH_ALLOW@pthread_mutex_trylock | ||||
| @PTH_ALLOW@pthread_mutex_unlock | ||||
| @PTH_ALLOW@pthread_mutex_destroy | ||||
| @PTH_ALLOW@pthread_cond_init | ||||
| @PTH_ALLOW@pthread_cond_destroy | ||||
| @PTH_ALLOW@pthread_cond_broadcast | ||||
| @PTH_ALLOW@pthread_cond_signal | ||||
| @PTH_ALLOW@pthread_cond_wait | ||||
| @PTH_ALLOW@pthread_cond_timedwait | ||||
| @PTH_ALLOW@pthread_condattr_init | ||||
| @PTH_ALLOW@pthread_condattr_destroy | ||||
| @PTH_ALLOW@pthread_condattr_getpshared | ||||
| @PTH_ALLOW@pthread_condattr_setpshared | ||||
| @PTH_ALLOW@sem_init | ||||
| @PTH_ALLOW@sem_destroy | ||||
| @PTH_ALLOW@sem_wait | ||||
|   | ||||
| @@ -23,6 +23,16 @@ extern "C" | ||||
|  | ||||
| #define TFD(n) void*(*n)(void*) | ||||
|  | ||||
| /* Defines. (These are correctly defined here as per | ||||
|    http://www.opengroup.org/onlinepubs/7908799/xsh/pthread.h.html */ | ||||
|  | ||||
| /* FIXME: this should allocate a new cond variable, and return the value  that | ||||
|  would normally be written to the passed parameter of pthread_cond_init(lvalue, NULL); */ | ||||
| // #define PTHREAD_COND_INITIALIZER 0 | ||||
|  | ||||
| #define PTHREAD_PROCESS_PRIVATE 0 | ||||
| #define PTHREAD_PROCESS_SHARED  1 | ||||
|  | ||||
| typedef int pthread_t; | ||||
| typedef int pthread_mutex_t; | ||||
| typedef int sem_t; | ||||
| @@ -43,6 +53,15 @@ typedef struct pthread_mutexattr | ||||
|   } | ||||
| pthread_mutexattr_t; | ||||
|  | ||||
| typedef struct pthread_condattr | ||||
|   { | ||||
|     int shared; | ||||
|     int valid; | ||||
|   } | ||||
| pthread_condattr_t; | ||||
|  | ||||
| typedef int pthread_cond_t; | ||||
|  | ||||
| /*  ThreadCreation */ | ||||
| int pthread_create (pthread_t * thread, const pthread_attr_t * attr, TFD (function), void *arg); | ||||
| int pthread_attr_init (pthread_attr_t * attr); | ||||
| @@ -50,6 +69,20 @@ int pthread_attr_destroy (pthread_attr_t * attr); | ||||
| int pthread_attr_setstacksize (pthread_attr_t * attr, size_t size); | ||||
| int pthread_attr_getstacksize (pthread_attr_t * attr, size_t * size); | ||||
|  | ||||
| /* Condition variables */ | ||||
| int   pthread_cond_broadcast(pthread_cond_t *); | ||||
| int   pthread_cond_destroy(pthread_cond_t *); | ||||
| int   pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *); | ||||
| int   pthread_cond_signal(pthread_cond_t *); | ||||
| int   pthread_cond_timedwait(pthread_cond_t *,  | ||||
|           pthread_mutex_t *, const struct timespec *); | ||||
| int   pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *); | ||||
| int   pthread_condattr_destroy(pthread_condattr_t *); | ||||
| int   pthread_condattr_getpshared(const pthread_condattr_t *, int *); | ||||
| int   pthread_condattr_init(pthread_condattr_t *); | ||||
| int   pthread_condattr_setpshared(pthread_condattr_t *, int); | ||||
|  | ||||
|  | ||||
| /* Thread Control */ | ||||
| int pthread_detach (pthread_t thread); | ||||
| int pthread_join (pthread_t thread, void **value_ptr); | ||||
|   | ||||
| @@ -171,6 +171,67 @@ pthread_mutex_destroy (pthread_mutex_t * mutex) | ||||
|   return __pthread_mutex_destroy (mutex); | ||||
| } | ||||
|  | ||||
| /* Synchronisation */ | ||||
|  | ||||
| int | ||||
| pthread_cond_destroy(pthread_cond_t *cond) | ||||
| { | ||||
|   return  __pthread_cond_destroy (cond); | ||||
| } | ||||
|  | ||||
| int | ||||
| pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) | ||||
| { | ||||
|   return __pthread_cond_init (cond, attr); | ||||
| } | ||||
|  | ||||
| int | ||||
| pthread_cond_signal(pthread_cond_t *cond) | ||||
| { | ||||
|   return __pthread_cond_signal (cond); | ||||
| } | ||||
|  | ||||
| int pthread_cond_broadcast(pthread_cond_t *cond) | ||||
| { | ||||
|   return __pthread_cond_broadcast (cond); | ||||
| } | ||||
|  | ||||
| int | ||||
| pthread_cond_timedwait(pthread_cond_t *cond, | ||||
| 	 pthread_mutex_t *mutex, const struct timespec *abstime) | ||||
| { | ||||
|   return __pthread_cond_timedwait (cond, mutex, abstime); | ||||
| } | ||||
|  | ||||
| int | ||||
| pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) | ||||
| { | ||||
|   return __pthread_cond_wait (cond, mutex); | ||||
| } | ||||
|  | ||||
| int | ||||
| pthread_condattr_init(pthread_condattr_t *condattr) | ||||
| { | ||||
|   return __pthread_condattr_init (condattr); | ||||
| } | ||||
|  | ||||
| int | ||||
| pthread_condattr_destroy(pthread_condattr_t *condattr) | ||||
| { | ||||
|   return __pthread_condattr_destroy (condattr); | ||||
| } | ||||
|  | ||||
| int | ||||
| pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared) | ||||
| { | ||||
|   return __pthread_condattr_getpshared (attr, pshared); | ||||
| } | ||||
|  | ||||
| int pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared) | ||||
| { | ||||
|   return __pthread_condattr_setpshared (attr, pshared); | ||||
| } | ||||
|  | ||||
| /* Semaphores */ | ||||
| int | ||||
| sem_init (sem_t * sem, int pshared, unsigned int value) | ||||
|   | ||||
| @@ -63,6 +63,13 @@ extern int threadsafe; | ||||
|   if (!item) return EINVAL; \ | ||||
|   CHECKHANDLE (EINVAL, 0); | ||||
|  | ||||
| #define GETCOND(n) \ | ||||
|   SetResourceLock (LOCK_COND_LIST, READ_LOCK, n); \ | ||||
|   CondItem *item=user_data->threadinterface->GetCond (cond); \ | ||||
|   ReleaseResourceLock (LOCK_COND_LIST, READ_LOCK, n); \ | ||||
|   if (!item) return EINVAL; \ | ||||
|   CHECKHANDLE (EINVAL, 0); | ||||
|  | ||||
| #define CHECKITEM(rn, rm, fn) \ | ||||
|   if (!item) { \ | ||||
|     ReleaseResourceLock (rn, rm, fn); \ | ||||
| @@ -387,6 +394,13 @@ MTinterface::GetSemaphore (sem_t * sp) | ||||
|   return (SemaphoreItem *) Find (sp, &CmpPthreadObj, index, &semalist); | ||||
| } | ||||
|  | ||||
| CondItem * | ||||
| MTinterface::GetCond (pthread_cond_t * mp) | ||||
| { | ||||
|   AssertResourceOwner (LOCK_COND_LIST, READ_LOCK); | ||||
|   int index = 0; | ||||
|   return (CondItem *) Find (mp, &CmpPthreadObj, index, &condlist); | ||||
| } | ||||
|  | ||||
| void | ||||
| MTitem::Destroy () | ||||
| @@ -455,6 +469,78 @@ SemaphoreItem::TryWait () | ||||
|   return WaitForSingleObject (win32_obj_id, 0); | ||||
| } | ||||
|  | ||||
| /* Condition Items */ | ||||
| CondItem * | ||||
| MTinterface::CreateCond (pthread_cond_t * cond, const pthread_condattr_t * attr) | ||||
| { | ||||
|   AssertResourceOwner (LOCK_COND_LIST, WRITE_LOCK | READ_LOCK); | ||||
|  | ||||
|   int i = FindNextUnused (&condlist); | ||||
|  | ||||
|   CondItem *item = (CondItem *) GetItem (i, &condlist); | ||||
|   if (!item) | ||||
|     item = (CondItem *) SetItem (i, new CondItem (), &condlist); | ||||
|   if (!item) | ||||
|     system_printf ("cond creation failed"); | ||||
|   item->used = true; | ||||
|   item->shared = attr->shared; | ||||
|   item->mutexitem=NULL; | ||||
|   item->waiting=0; | ||||
|  | ||||
|   item->win32_obj_id = ::CreateEvent (&sec_none_nih,  | ||||
| 	false, /* auto signal reset - which I think is pthreads like ? */ | ||||
| 	false, /* start non signaled */ | ||||
| 	NULL /* no name */ ); | ||||
|  | ||||
|  | ||||
|   CHECKHANDLE (NULL, 1); | ||||
|  | ||||
|   *cond = (pthread_cond_t) item->win32_obj_id; | ||||
|  | ||||
|   return item; | ||||
| } | ||||
|  | ||||
|  | ||||
| int | ||||
| CondItem::Signal () | ||||
| { | ||||
|   return !PulseEvent(win32_obj_id); | ||||
| } | ||||
|  | ||||
| int | ||||
| CondItem::Wait () | ||||
| { | ||||
|   DWORD rv = SignalObjectAndWait (mutexitem->win32_obj_id, win32_obj_id, INFINITE, false); | ||||
|   switch (rv) { | ||||
|     case WAIT_FAILED: return 0; /* POSIX doesn't allow errors after we modify the mutex state */ | ||||
|     case WAIT_OBJECT_0: return 0; /* we have been signaled */ | ||||
|     default: return 0; | ||||
|   } | ||||
| } | ||||
|  | ||||
| int | ||||
| CondItem::TimedWait (DWORD dwMilliseconds) | ||||
| { | ||||
|   DWORD rv = SignalObjectAndWait (mutexitem->win32_obj_id, win32_obj_id, dwMilliseconds, false); | ||||
|   switch (rv) { | ||||
|     case WAIT_FAILED: return 0; /* POSIX doesn't allow errors after we modify the mutex state */ | ||||
|     case WAIT_ABANDONED: return ETIMEDOUT; | ||||
|     case WAIT_OBJECT_0: return 0; /* we have been signaled */ | ||||
|     default: return 0; | ||||
|   } | ||||
| } | ||||
|  | ||||
| int | ||||
| CondItem::BroadCast () | ||||
| { | ||||
|   if (!mutexitem) | ||||
|     return 0; | ||||
|   PulseEvent(win32_obj_id); | ||||
|   while (InterlockedDecrement(&waiting)!=0) | ||||
|     PulseEvent(win32_obj_id); | ||||
|   mutexitem=NULL; | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| //////////////////////////  Pthreads | ||||
|  | ||||
| @@ -678,6 +764,147 @@ __pthread_getspecific (pthread_key_t */*key*/) | ||||
|   NOT_IMP ("_p_key_getsp\n"); | ||||
| } | ||||
|  | ||||
| /* Thread synchronisation */ | ||||
|  | ||||
| int | ||||
| __pthread_cond_destroy(pthread_cond_t *cond) | ||||
| { | ||||
|   SetResourceLock (LOCK_COND_LIST, READ_LOCK | WRITE_LOCK, "__pthread_cond_destroy"); | ||||
|  | ||||
|   CondItem *item = MT_INTERFACE->GetCond (cond); | ||||
|  | ||||
|   CHECKITEM (LOCK_COND_LIST, WRITE_LOCK | READ_LOCK, "__pthread_cond_init"); | ||||
|  | ||||
|   item->Destroy (); | ||||
|  | ||||
|   MT_INTERFACE->ReleaseItem (item); | ||||
|  | ||||
|   ReleaseResourceLock (LOCK_COND_LIST, READ_LOCK | WRITE_LOCK, "__pthread_cond_destroy") | ||||
| ; | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int | ||||
| __pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) | ||||
| { | ||||
|   if (attr && (attr->valid != 0xf341)) | ||||
|     return EINVAL; | ||||
|   SetResourceLock (LOCK_COND_LIST, WRITE_LOCK | READ_LOCK, "__pthread_cond_init"); | ||||
|  | ||||
|   CondItem *item = MT_INTERFACE->CreateCond (cond, attr); | ||||
|  | ||||
|   CHECKITEM (LOCK_COND_LIST, WRITE_LOCK | READ_LOCK, "__pthread_cond_init"); | ||||
|  | ||||
|   ReleaseResourceLock (LOCK_COND_LIST, WRITE_LOCK | READ_LOCK, "__pthread_cond_init"); | ||||
|   return 0; | ||||
|  | ||||
| } | ||||
|  | ||||
| int __pthread_cond_broadcast(pthread_cond_t *cond) | ||||
| { | ||||
|   GETCOND("_pthread_cond_lock"); | ||||
|    | ||||
|   item->BroadCast(); | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int __pthread_cond_signal(pthread_cond_t *cond) | ||||
| { | ||||
|   GETCOND("_pthread_cond_lock"); | ||||
|  | ||||
|   item->Signal(); | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) | ||||
| { | ||||
|   int rv; | ||||
|   if (!abstime) | ||||
|     return EINVAL; | ||||
|   SetResourceLock (LOCK_MUTEX_LIST, READ_LOCK, "_ptherad_mutex_lock"); | ||||
|   MutexItem* mutexitem=user_data->threadinterface->GetMutex (mutex); | ||||
|   ReleaseResourceLock (LOCK_MUTEX_LIST, READ_LOCK, "_ptherad_mutex_lock"); | ||||
|   if (!mutexitem) return EINVAL; | ||||
|   if (!mutexitem->HandleOke ()) | ||||
|   { | ||||
|     return EINVAL; | ||||
|   } | ||||
|   GETCOND("_pthread_cond_lock"); | ||||
|   if (item->mutexitem && (item->mutexitem != mutexitem)) | ||||
|     return EINVAL; | ||||
|  | ||||
|   item->mutexitem=mutexitem; | ||||
|   InterlockedIncrement(&item->waiting); | ||||
|   rv = item->TimedWait(abstime->tv_sec*1000); | ||||
|   mutexitem->Lock(); | ||||
|   if (InterlockedDecrement(&item->waiting)==0) | ||||
|     item->mutexitem=NULL; | ||||
|  | ||||
|   return rv; | ||||
| } | ||||
|  | ||||
| int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) | ||||
| {  | ||||
|   int rv; | ||||
|   SetResourceLock (LOCK_MUTEX_LIST, READ_LOCK, "_ptherad_mutex_lock");  | ||||
|   MutexItem* mutexitem=user_data->threadinterface->GetMutex (mutex);  | ||||
|   ReleaseResourceLock (LOCK_MUTEX_LIST, READ_LOCK, "_ptherad_mutex_lock");  | ||||
|   if (!mutexitem) return EINVAL;   | ||||
|   if (!mutexitem->HandleOke ()) | ||||
|   {  | ||||
|     return EINVAL;  | ||||
|   } | ||||
|   GETCOND("_pthread_cond_lock"); | ||||
|   if (item->mutexitem && (item->mutexitem != mutexitem)) | ||||
|     return EINVAL; | ||||
|    | ||||
|   item->mutexitem=mutexitem; | ||||
|   InterlockedIncrement(&item->waiting); | ||||
|   rv = item->Wait();   | ||||
|   mutexitem->Lock(); | ||||
|   if (InterlockedDecrement(&item->waiting)==0) | ||||
|     item->mutexitem=NULL; | ||||
|   | ||||
|   return rv; | ||||
| } | ||||
|  | ||||
| int | ||||
| __pthread_condattr_init (pthread_condattr_t * condattr) | ||||
| { | ||||
|   condattr->shared = 0; | ||||
|   condattr->valid  = 0xf341; /* Roberts magic number */ | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int | ||||
| __pthread_condattr_getpshared (const pthread_condattr_t * attr, int *pshared) | ||||
| { | ||||
|   if (!attr || (attr->valid != 0xf341)) | ||||
|     return EINVAL; | ||||
|   *pshared = attr->shared; | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int | ||||
| __pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared) | ||||
| { | ||||
|   if (!attr || (attr->valid != 0xf341) || (pshared <0) || (pshared > 1 )) | ||||
|     return EINVAL; | ||||
|   attr->shared = pshared; | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int | ||||
| __pthread_condattr_destroy (pthread_condattr_t * condattr) | ||||
| { | ||||
|   if (!condattr || (condattr->valid != 0xf341)) | ||||
|       return EINVAL; | ||||
|   condattr->valid=0; | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| /* Thread signal */ | ||||
| int | ||||
| __pthread_kill (pthread_t * thread, int sig) | ||||
| @@ -693,7 +920,6 @@ __pthread_kill (pthread_t * thread, int sig) | ||||
|  | ||||
| // unlock myself | ||||
|   return rval; | ||||
|  | ||||
| } | ||||
|  | ||||
| int | ||||
| @@ -956,6 +1182,46 @@ extern "C" | ||||
|   { | ||||
|     return -1; | ||||
|   } | ||||
|   int __pthread_cond_destroy(pthread_cond_t *) | ||||
|   { | ||||
|     return -1; | ||||
|   } | ||||
|   int __pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *) | ||||
|   { | ||||
|     return -1; | ||||
|   } | ||||
|   int __pthread_cond_signal(pthread_cond_t *) | ||||
|   { | ||||
|     return -1; | ||||
|   } | ||||
|   int __pthread_cond_broadcast(pthread_cond_t *) | ||||
|   { | ||||
|     return -1; | ||||
|   } | ||||
|   int __pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *, const struct timespec *) | ||||
|   { | ||||
|     return -1; | ||||
|   } | ||||
|   int __pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *) | ||||
|   { | ||||
|     return -1; | ||||
|   } | ||||
|   int __pthread_condattr_init (pthread_condattr_t *) | ||||
|   { | ||||
|     return -1; | ||||
|   } | ||||
|   int __pthread_condattr_destroy (pthread_condattr_t *) | ||||
|   { | ||||
|     return -1; | ||||
|   } | ||||
|   int __pthread_condattr_getpshared (pthread_condattr_t *, int *) | ||||
|   { | ||||
|     return -1; | ||||
|   } | ||||
|   int __pthread_condattr_setpshared (pthread_condattr_t *, int) | ||||
|   { | ||||
|     return -1; | ||||
|   } | ||||
|   int __sem_init (sem_t * sem, int pshared, unsigned int value) | ||||
|   { | ||||
|     return -1; | ||||
|   | ||||
| @@ -20,6 +20,7 @@ details. */ | ||||
| #define LOCK_THREAD_LIST 5 | ||||
| #define LOCK_MUTEX_LIST  6 | ||||
| #define LOCK_SEM_LIST    7 | ||||
| #define LOCK_COND_LIST   8 | ||||
|  | ||||
| #define WRITE_LOCK 1 | ||||
| #define READ_LOCK  2 | ||||
| @@ -190,6 +191,17 @@ public: | ||||
|   int TryWait (); | ||||
| }; | ||||
|  | ||||
| class CondItem: public MTitem | ||||
| { | ||||
| public: | ||||
|   int shared; | ||||
|   LONG waiting; | ||||
|   MutexItem *mutexitem; | ||||
|   int Wait (); | ||||
|   int TimedWait (DWORD dwMilliseconds); | ||||
|   int BroadCast (); | ||||
|   int Signal (); | ||||
| }; | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
| @@ -226,6 +238,10 @@ public: | ||||
|   SemaphoreItem *CreateSemaphore (sem_t *, int, int); | ||||
|   SemaphoreItem *GetSemaphore (sem_t * t); | ||||
|  | ||||
|   // Condition functions | ||||
|   CondItem *CreateCond (pthread_cond_t *, const pthread_condattr_t *);  | ||||
|   CondItem *GetCond (pthread_cond_t *); | ||||
|  | ||||
| private: | ||||
|   // General Administration | ||||
|   MTitem * Find (void *, int (*compare) (void *, void *), int &, MTList *); | ||||
| @@ -237,6 +253,7 @@ private: | ||||
|   MTList threadlist; | ||||
|   MTList mutexlist; | ||||
|   MTList semalist; | ||||
|   MTList condlist; | ||||
| }; | ||||
|  | ||||
|  | ||||
| @@ -274,6 +291,17 @@ int __pthread_key_delete (pthread_key_t * key); | ||||
| int __pthread_setspecific (pthread_key_t * key, const void *value); | ||||
| void *__pthread_getspecific (pthread_key_t * key); | ||||
|  | ||||
| /* Thead synchroniation */ | ||||
| int __pthread_cond_destroy(pthread_cond_t *cond); | ||||
| int __pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); | ||||
| int __pthread_cond_signal(pthread_cond_t *cond); | ||||
| int __pthread_cond_broadcast(pthread_cond_t *cond); | ||||
| int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime); | ||||
| int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); | ||||
| int __pthread_condattr_init (pthread_condattr_t * condattr); | ||||
| int __pthread_condattr_destroy (pthread_condattr_t * condattr); | ||||
| int __pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared); | ||||
| int __pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared); | ||||
|  | ||||
| /* Thread signal */ | ||||
| int __pthread_kill (pthread_t * thread, int sig); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user