diff options
author | Christopher Faylor <me@cgf.cx> | 2001-03-21 02:17:58 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2001-03-21 02:17:58 +0000 |
commit | 9a08b2c02eea0c955c5fef0b0287803947fef0b6 (patch) | |
tree | 5ba4bc2c409482b4530eb8e1c2befd557170009e /winsup | |
parent | a1299ba54b1a4977da361a037d6c3392005cbd25 (diff) | |
download | newlib-9a08b2c02eea0c955c5fef0b0287803947fef0b6.zip newlib-9a08b2c02eea0c955c5fef0b0287803947fef0b6.tar.gz newlib-9a08b2c02eea0c955c5fef0b0287803947fef0b6.tar.bz2 |
* sched.cc: New file. Implement sched*.
* include/sched.h: New file. User land includes for sched*.
* Makefile.in: Add sched.o
* cygwin.din: Add exports for sched*.
Diffstat (limited to 'winsup')
-rw-r--r-- | winsup/cygwin/ChangeLog | 7 | ||||
-rw-r--r-- | winsup/cygwin/Makefile.in | 13 | ||||
-rw-r--r-- | winsup/cygwin/include/pthread.h | 132 | ||||
-rw-r--r-- | winsup/cygwin/pinfo.h | 4 | ||||
-rw-r--r-- | winsup/cygwin/pthread.cc | 437 | ||||
-rw-r--r-- | winsup/cygwin/thread.cc | 989 | ||||
-rw-r--r-- | winsup/cygwin/thread.h | 380 |
7 files changed, 1012 insertions, 950 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 5b9a5f8..5a3811e 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,10 @@ +2001-03-21 Robert Collins <rbtcollins@hotmail.com> + + * sched.cc: New file. Implement sched*. + * include/sched.h: New file. User land includes for sched*. + * Makefile.in: Add sched.o + * cygwin.din: Add exports for sched*. + Tue Mar 20 14:48:46 2001 Christopher Faylor <cgf@cygnus.com> * dtable.cc: Guard against new winsock.h/winsock2.h warnings when diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 71f513a..d7d6e84 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -121,13 +121,12 @@ DLL_OFILES:=assert.o autoload.o cygheap.o dcrt0.o debug.o delqueue.o dir.o \ fhandler_serial.o fhandler_socket.o fhandler_tape.o \ fhandler_termios.o fhandler_tty.o fhandler_windows.o fhandler_zero.o \ fork.o glob.o grp.o heap.o init.o ioctl.o localtime.o malloc.o \ - miscfuncs.o mmap.o \ - net.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o pthread.o regexp.o \ - regerror.o regsub.o registry.o resource.o scandir.o security.o select.o \ - shared.o \ - shortcut.o signal.o sigproc.o smallprint.o spawn.o strace.o strsep.o \ - sync.o syscalls.o sysconf.o syslog.o termios.o thread.o times.o tty.o \ - uinfo.o uname.o wait.o window.o \ + miscfuncs.o mmap.o net.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o \ + pthread.o regexp.o regerror.o regsub.o registry.o resource.o scandir.o \ + sched.o security.o select.o shared.o shortcut.o signal.o sigproc.o \ + smallprint.o spawn.o strace.o strsep.o sync.o syscalls.o sysconf.o \ + syslog.o termios.o thread.o times.o tty.o uinfo.o uname.o wait.o \ + window.o \ $(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MT_SAFE_OBJECTS) GMON_OFILES:= gmon.o mcount.o profil.o diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h index 1a96e72..d4b73de 100644 --- a/winsup/cygwin/include/pthread.h +++ b/winsup/cygwin/include/pthread.h @@ -21,7 +21,6 @@ extern "C" { #endif -#define TFD(n) void*(*n)(void*) /* Defines. (These are correctly defined here as per http://www.opengroup.org/onlinepubs/7908799/xsh/pthread.h.html */ @@ -32,94 +31,85 @@ extern "C" #define PTHREAD_PROCESS_PRIVATE 0 #define PTHREAD_PROCESS_SHARED 1 - -typedef int pthread_t; -typedef int pthread_mutex_t; -typedef int sem_t; - -typedef struct pthread_key - { - } -pthread_key_t; - -typedef struct pthread_attr - { - size_t stacksize; - } -pthread_attr_t; - -typedef struct pthread_mutexattr - { - } -pthread_mutexattr_t; - -typedef struct pthread_condattr - { - int shared; - int valid; - } -pthread_condattr_t; - -typedef int pthread_cond_t; +#define PTHREAD_DESTRUCTOR_ITERATIONS 1 +/* Tls has 64 items for pre win2000 - and we don't want to use them all :] + * Before committing discuss this with the list + */ +#define PTHREAD_KEYS_MAX 32 +#define PTHREAD_CREATE_DETACHED 1 +/* the default : joinable */ +#define PTHREAD_CREATE_JOINABLE 0 + + +/* these shouldn't be defined here but in sys/types. + * defining in sys/types mught also allow us to override them for the internal functions + * more easily (internal sys/types vs external sys/type - dev thoughts on this? + */ + typedef void *pthread_t; + typedef void *pthread_mutex_t; + + typedef void *pthread_key_t; + typedef void *pthread_attr_t; + typedef void *pthread_mutexattr_t; + typedef void *pthread_condattr_t; + typedef void *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); -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); + int pthread_create (pthread_t * thread, const pthread_attr_t * attr, + void *(*)(void *), void *arg); + int pthread_attr_init (pthread_attr_t * attr); + int pthread_attr_destroy (pthread_attr_t * attr); + int pthread_attr_setdetachstate (pthread_attr_t *, int); + int pthread_attr_getdetachstate (const pthread_attr_t *, int *); + 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); + 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); + int pthread_detach (pthread_t thread); + int pthread_join (pthread_t thread, void **value_ptr); /* Thread Exit */ -int pthread_exit (void *value_ptr); + void pthread_exit (void *value_ptr); /* Thread SpecificData */ -int pthread_key_create (pthread_key_t * key); -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); + int pthread_key_create (pthread_key_t *, void (*)(void *)); + 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); -/* Thread signal */ -int pthread_kill (pthread_t * thread, int sig); -int pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set); +/* Thread signal (should be in signal.h) */ + int pthread_kill (pthread_t * thread, int sig); + int pthread_sigmask (int operation, const sigset_t * set, + sigset_t * old_set); /* ID */ -pthread_t pthread_self (); -int pthread_equal (pthread_t t1, pthread_t t2); + pthread_t pthread_self (); + int pthread_equal (pthread_t t1, pthread_t t2); /* Mutexes */ -int pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t *); -int pthread_mutex_lock (pthread_mutex_t * mutext); -int pthread_mutex_trylock (pthread_mutex_t * mutext); -int pthread_mutex_unlock (pthread_mutex_t * mutext); -int pthread_mutex_destroy (pthread_mutex_t * mutext); - -/* Solaris Semaphores */ -int sem_init (sem_t * sem, int pshared, unsigned int value); -int sem_destroy (sem_t * sem); -int sem_wait (sem_t * sem); -int sem_trywait (sem_t * sem); -int sem_post (sem_t * sem); + int pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t *); + int pthread_mutex_lock (pthread_mutex_t * mutext); + int pthread_mutex_trylock (pthread_mutex_t * mutext); + int pthread_mutex_unlock (pthread_mutex_t * mutext); + int pthread_mutex_destroy (pthread_mutex_t * mutext); #ifdef __cplusplus } #endif -#endif /* _PTHREAD_H */ +#endif /* _PTHREAD_H */ diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h index 7f46850..89ed546 100644 --- a/winsup/cygwin/pinfo.h +++ b/winsup/cygwin/pinfo.h @@ -116,13 +116,13 @@ public: return thread2signal ? thread2signal->win32_obj_id : hMainThread; } - inline void setthread2signal (void *thr) {thread2signal = (ThreadItem *) thr;} + inline void setthread2signal (void *thr) {thread2signal = (pthread *) thr;} private: struct sigaction sigs[NSIG]; sigset_t sig_mask; /* one set for everything to ignore. */ LONG _sigtodo[NSIG + __SIGOFFSET]; - ThreadItem *thread2signal; // NULL means means thread any other means a pthread + pthread *thread2signal; // NULL means means thread any other means a pthread }; class pinfo diff --git a/winsup/cygwin/pthread.cc b/winsup/cygwin/pthread.cc index 42b3d65..7a92d1d 100644 --- a/winsup/cygwin/pthread.cc +++ b/winsup/cygwin/pthread.cc @@ -13,37 +13,48 @@ #include "winsup.h" #include "thread.h" -extern "C" { -/* ThreadCreation */ -int -pthread_create (pthread_t * thread, const pthread_attr_t * attr, void *(*start_routine) (void *), void *arg) -{ - return __pthread_create (thread, attr, start_routine, arg); -} - -int -pthread_attr_init (pthread_attr_t * attr) -{ - return __pthread_attr_init (attr); -} - -int -pthread_attr_destroy (pthread_attr_t * attr) +extern "C" { - return __pthread_attr_destroy (attr); -} - -int -pthread_attr_setstacksize (pthread_attr_t * attr, size_t size) -{ - return __pthread_attr_setstacksize (attr, size); -} - -int -pthread_attr_getstacksize (pthread_attr_t * attr, size_t * size) -{ - return __pthread_attr_getstacksize (attr, size); -} +/* ThreadCreation */ + int + pthread_create (pthread_t * thread, const pthread_attr_t * attr, + void *(*start_routine) (void *), void *arg) + { + return __pthread_create (thread, attr, start_routine, arg); + } + + int pthread_attr_init (pthread_attr_t * attr) + { + return __pthread_attr_init (attr); + } + + int pthread_attr_destroy (pthread_attr_t * attr) + { + return __pthread_attr_destroy (attr); + } + + int pthread_attr_setdetachstate (pthread_attr_t * attr, int detachstate) + { + return __pthread_attr_setdetachstate (attr, detachstate); + } + + int + pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate) + { + return __pthread_attr_getdetachstate (attr, detachstate); + } + + + int pthread_attr_setstacksize (pthread_attr_t * attr, size_t size) + { + return __pthread_attr_setstacksize (attr, size); + } + + int pthread_attr_getstacksize (pthread_attr_t * attr, size_t * size) + { + return __pthread_attr_getstacksize (attr, size); + } /* @@ -52,216 +63,190 @@ pthread_attr_getstacksize (pthread_attr_t * attr, size_t * size) */ /* Thread Exit */ -int -pthread_exit (void * value_ptr) -{ - return __pthread_exit (value_ptr); -} - -int -pthread_join (pthread_t thread, void **return_val) -{ - return __pthread_join (&thread, (void **)return_val); -} - -int -pthread_detach (pthread_t thread) -{ - return __pthread_detach (&thread); -} - -int -pthread_suspend (pthread_t thread) -{ - return __pthread_suspend (&thread); -} - -int -pthread_continue (pthread_t thread) -{ - return __pthread_continue (&thread); -} - -unsigned long -pthread_getsequence_np (pthread_t * thread) -{ - return __pthread_getsequence_np (thread); -} + void pthread_exit (void *value_ptr) + { + return __pthread_exit (value_ptr); + } + + int pthread_join (pthread_t thread, void **return_val) + { + return __pthread_join (&thread, (void **) return_val); + } + + int pthread_detach (pthread_t thread) + { + return __pthread_detach (&thread); + } + + int pthread_suspend (pthread_t thread) + { + return __pthread_suspend (&thread); + } + + int pthread_continue (pthread_t thread) + { + return __pthread_continue (&thread); + } + + unsigned long pthread_getsequence_np (pthread_t * thread) + { + return __pthread_getsequence_np (thread); + } /* Thread SpecificData */ -int -pthread_key_create (pthread_key_t * key) -{ - return __pthread_key_create (key); -} - -int -pthread_key_delete (pthread_key_t * key) -{ - return __pthread_key_delete (key); -} - -int -pthread_setspecific (pthread_key_t * key, const void *value) -{ - return __pthread_setspecific (key, value); -} - -void * -pthread_getspecific (pthread_key_t * key) -{ - return (void *) __pthread_getspecific (key); -} + int pthread_key_create (pthread_key_t * key, void (*destructor) (void *)) + { + return __pthread_key_create (key, destructor); + } + + int pthread_key_delete (pthread_key_t * key) + { + return __pthread_key_delete (key); + } + + int pthread_setspecific (pthread_key_t key, const void *value) + { + return __pthread_setspecific (key, value); + } + + void *pthread_getspecific (pthread_key_t key) + { + return (void *) __pthread_getspecific (key); + } /* Thread signal */ -int -pthread_kill (pthread_t * thread, int sig) -{ - return __pthread_kill (thread, sig); -} + int pthread_kill (pthread_t * thread, int sig) + { + return __pthread_kill (thread, sig); + } -int -pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set) -{ - return __pthread_sigmask (operation, set, old_set); -} + int + pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set) + { + return __pthread_sigmask (operation, set, old_set); + } /* ID */ -pthread_t -pthread_self () -{ - return __pthread_self (); -} + pthread_t pthread_self () + { + return __pthread_self (); + } -int -pthread_equal (pthread_t t1, pthread_t t2) -{ - return __pthread_equal (&t1, &t2); -} + int pthread_equal (pthread_t t1, pthread_t t2) + { + return __pthread_equal (&t1, &t2); + } /* Mutexes */ -int -pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr) -{ - return __pthread_mutex_init (mutex, attr); -} - -int -pthread_mutex_lock (pthread_mutex_t * mutex) -{ - return __pthread_mutex_lock (mutex); -} - -int -pthread_mutex_trylock (pthread_mutex_t * mutex) -{ - return __pthread_mutex_trylock (mutex); -} - -int -pthread_mutex_unlock (pthread_mutex_t * mutex) -{ - return __pthread_mutex_unlock (mutex); -} - -int -pthread_mutex_destroy (pthread_mutex_t * mutex) -{ - return __pthread_mutex_destroy (mutex); -} + int + pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr) + { + return __pthread_mutex_init (mutex, attr); + } + + int pthread_mutex_lock (pthread_mutex_t * mutex) + { + return __pthread_mutex_lock (mutex); + } + + int pthread_mutex_trylock (pthread_mutex_t * mutex) + { + return __pthread_mutex_trylock (mutex); + } + + int pthread_mutex_unlock (pthread_mutex_t * mutex) + { + return __pthread_mutex_unlock (mutex); + } + + int 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); -} + 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) -{ - return __sem_init (sem, pshared, value); -} - -int -sem_destroy (sem_t * sem) -{ - return __sem_destroy (sem); -} - -int -sem_wait (sem_t * sem) -{ - return __sem_wait (sem); -} - -int -sem_trywait (sem_t * sem) -{ - return __sem_trywait (sem); -} - -int -sem_post (sem_t * sem) -{ - return __sem_post (sem); -} + int sem_init (sem_t * sem, int pshared, unsigned int value) + { + return __sem_init (sem, pshared, value); + } + + int sem_destroy (sem_t * sem) + { + return __sem_destroy (sem); + } + + int sem_wait (sem_t * sem) + { + return __sem_wait (sem); + } + + int sem_trywait (sem_t * sem) + { + return __sem_trywait (sem); + } + + int sem_post (sem_t * sem) + { + return __sem_post (sem); + } } diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index a08df7f..571f3ee 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -18,6 +18,7 @@ details. */ #include "winsup.h" #include <limits.h> #include <errno.h> +#include "cygerrno.h" #include <assert.h> #include <stdlib.h> #include <syslog.h> @@ -26,6 +27,7 @@ details. */ #include "pinfo.h" #include "perprocess.h" #include "security.h" +#include <semaphore.h> extern int threadsafe; @@ -33,53 +35,12 @@ extern int threadsafe; #define NOT_IMP(n) system_printf ("not implemented %s\n", n); return 0; -#define CHECKHANDLE(rval, release) \ - if (!item->HandleOke ()) \ - { \ - if (release) \ - item->used=false; \ - return rval; \ - } - -#define GETTHREAD(n) \ - if (!thread) system_printf ("thread is NULL");\ - SetResourceLock (LOCK_THREAD_LIST, READ_LOCK, n);\ - ThreadItem *item=user_data->threadinterface->GetThread (thread); \ - ReleaseResourceLock (LOCK_THREAD_LIST, READ_LOCK, n); \ - if (!item) return EINVAL; \ - CHECKHANDLE (EINVAL, 0); - -#define GETMUTEX(n) \ - SetResourceLock (LOCK_MUTEX_LIST, READ_LOCK, n); \ - MutexItem* item=user_data->threadinterface->GetMutex (mutex); \ - ReleaseResourceLock (LOCK_MUTEX_LIST, READ_LOCK, n); \ - if (!item) return EINVAL; \ - CHECKHANDLE (EINVAL, 0); - -#define GETSEMA(n) \ - SetResourceLock (LOCK_SEM_LIST, READ_LOCK, n); \ - SemaphoreItem* item=user_data->threadinterface->GetSemaphore (sem); \ - ReleaseResourceLock (LOCK_SEM_LIST, READ_LOCK, n); \ - 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); \ - return EINVAL; }; \ - struct _reent * _reent_clib () { int tmp = GetLastError (); - struct __reent_t *_r = (struct __reent_t *) TlsGetValue (MT_INTERFACE->reent_index); + struct __reent_t *_r = + (struct __reent_t *) TlsGetValue (MT_INTERFACE->reent_index); #ifdef _CYG_THREAD_FAILSAFE if (_r == 0) @@ -111,8 +72,9 @@ ResourceLocks::Lock (int _resid) if (!inited) system_printf ("lock called before initialization"); - thread_printf ("Get Resource lock %d ==> %p for %p , real : %d , threadid %d ", - _resid, &lock, user_data, myself->pid, GetCurrentThreadId ()); + thread_printf + ("Get Resource lock %d ==> %p for %p , real : %d , threadid %d ", _resid, + &lock, user_data, myself->pid, GetCurrentThreadId ()); #endif return &lock; } @@ -136,7 +98,8 @@ void ReleaseResourceLock (int _res_id, int _mode, const char *_function) { #ifdef _CYG_THREAD_FAILSAFE - thread_printf ("Release resource lock %d mode %d for %s done", _res_id, _mode, _function); + thread_printf ("Release resource lock %d mode %d for %s done", _res_id, + _mode, _function); AssertResourceOwner (_res_id, _mode); user_data->resourcelocks->count--; @@ -152,9 +115,10 @@ void AssertResourceOwner (int _res_id, int _mode) { - thread_printf ("Assert Resource lock %d ==> for %p , real : %d , threadid %d count %d owner %d", - _res_id, user_data, myself->pid, GetCurrentThreadId (), - user_data->resourcelocks->count, user_data->resourcelocks->owner); + thread_printf + ("Assert Resource lock %d ==> for %p , real : %d , threadid %d count %d owner %d", + _res_id, user_data, myself->pid, GetCurrentThreadId (), + user_data->resourcelocks->count, user_data->resourcelocks->owner); if (user_data && (user_data->resourcelocks->owner != GetCurrentThreadId ())) system_printf ("assertion failed, not the resource owner"); } @@ -186,77 +150,6 @@ ResourceLocks::Delete () } } -// Thread interface - -void -MTinterface::ReleaseItem (MTitem * _item) -{ - _item->used = false; -} - -MTitem * -MTinterface::Find (void *_value, int (*comp) (void *, void *), register int &_index, MTList * _list) -{ - register MTitem *current = NULL; - for (; _index < _list->index; _index++) - { - current = _list->items[_index]; - if (current->used && comp (current, _value)) - break; - current = NULL; - } - return current; -} - -int -MTinterface::Find (MTitem & _item, MTList * _list) -{ - register MTitem *current; - register int _index = 0; - for (; _index < _list->index; _index++) - { - current = _list->items[_index]; - if (current->used && current == &_item) - break; - } - return (_index == _list->index ? -1 : _index); -} - -int -MTinterface::FindNextUnused (MTList * _list) -{ - register int i = 0; - for (; i < _list->index && _list->items[i] != NULL && _list->items[i]->used && _list->items[i]->joinable != 'Y'; i++) - continue; - return i; -} - -MTitem * -MTinterface::GetItem (int _index, MTList * _list) -{ - return (_index < _list->index ? _list->items[_index] : NULL); -} - -MTitem * -MTinterface::SetItem (int _index, MTitem * _item, MTList * _list) -{ - if (_index == _list->index && _list->index < MT_MAX_ITEMS) - _list->index++; - return (_index < _list->index ? _list->items[_index] = _item : NULL); -} - -int -CmpPthreadObj (void *_i, void *_value) -{ - return ((MTitem *) _i)->Id () == *(int *) _value; -} - -int -CmpThreadId (void *_i, void *_id) -{ - return ((ThreadItem *) _i)->thread_id == * (DWORD *) _id; -} - void MTinterface::Init (int forked) { @@ -288,17 +181,24 @@ MTinterface::Init (int forked) TlsSetValue (reent_index, &reents); // the static reent_data will be used in the main thread + + if (!indexallocated) + { + indexallocated = (-1); + thread_self_dwTlsIndex = TlsAlloc (); + if (thread_self_dwTlsIndex == TLS_OUT_OF_INDEXES) + system_printf + ("local storage for thread couldn't be set\nThis means that we are not thread safe!\n"); + } + if (forked) return; - // create entry for main thread - ThreadItem *item = (ThreadItem *) GetItem (0, &threadlist); - - item = (ThreadItem *) SetItem (0, &mainthread, &threadlist); - item->used = true; - item->win32_obj_id = myself->hProcess; - item->thread_id = GetCurrentThreadId (); + mainthread.win32_obj_id = myself->hProcess; + mainthread.setThreadIdtoCurrent (); + /* store the main thread's self pointer */ + TlsSetValue (thread_self_dwTlsIndex, &mainthread); #if 0 item->function = NULL; @@ -308,245 +208,264 @@ MTinterface::Init (int forked) #endif } -ThreadItem * -MTinterface::CreateThread (pthread_t * t, TFD (func), void *arg, pthread_attr_t a) +pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0) { - AssertResourceOwner (LOCK_THREAD_LIST, WRITE_LOCK | READ_LOCK); +} - int i = FindNextUnused (&threadlist); +pthread::~pthread () +{ + if (win32_obj_id) + CloseHandle (win32_obj_id); +} - ThreadItem *item = (ThreadItem *) GetItem (i, &threadlist); - if (!item) - item = (ThreadItem *) SetItem (i, new ThreadItem (), &threadlist); - if (!item) - system_printf ("thread creation failed"); - item->used = true; - item->function = func; - item->arg = arg; - item->attr = a; +void +pthread::create (void *(*func) (void *), pthread_attr * newattr, + void *threadarg) +{ + /* already running ? */ + if (win32_obj_id) + return; - item->win32_obj_id = ::CreateThread (&sec_none_nih, item->attr.stacksize, - (LPTHREAD_START_ROUTINE) thread_init_wrapper, item, 0, &item->thread_id); + if (newattr) + { + attr.joinable = newattr->joinable; + attr.stacksize = newattr->stacksize; + } + function = func; + arg = threadarg; - CHECKHANDLE (NULL, 1); + win32_obj_id =::CreateThread (&sec_none_nih, attr.stacksize, + (LPTHREAD_START_ROUTINE) thread_init_wrapper, + this, CREATE_SUSPENDED, &thread_id); - *t = (pthread_t) item->win32_obj_id; + if (!win32_obj_id) + magic = 0; + else + ResumeThread (win32_obj_id); +} - return item; +pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC), +joinable (PTHREAD_CREATE_JOINABLE), stacksize (0) +{ } -MutexItem * -MTinterface::CreateMutex (pthread_mutex_t * mutex) +pthread_attr::~pthread_attr () { - AssertResourceOwner (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK); +} - int i = FindNextUnused (&mutexlist); +pthread_condattr::pthread_condattr ():verifyable_object +(PTHREAD_CONDATTR_MAGIC), shared (PTHREAD_PROCESS_PRIVATE) +{ +} - MutexItem *item = (MutexItem *) GetItem (i, &mutexlist); - if (!item) - item = (MutexItem *) SetItem (i, new MutexItem (), &mutexlist); - if (!item) - system_printf ("mutex creation failed"); - item->used = true; +pthread_condattr::~pthread_condattr () +{ +} - item->win32_obj_id = ::CreateMutex (&sec_none_nih, false, NULL); +pthread_cond::pthread_cond (pthread_condattr * attr):verifyable_object (PTHREAD_COND_MAGIC) +{ + this->shared = attr ? attr->shared : PTHREAD_PROCESS_PRIVATE; + this->mutex = NULL; + this->waiting = 0; - CHECKHANDLE (NULL, 1); + this->win32_obj_id =::CreateEvent (&sec_none_nih, + false, /* auto signal reset - which I think is pthreads like ? */ + false, /* start non signaled */ + NULL /* no name */ ); - *mutex = (pthread_mutex_t) item->win32_obj_id; + if (!this->win32_obj_id) + magic = 0; +} - return item; +pthread_cond::~pthread_cond () +{ + if (win32_obj_id) + CloseHandle (win32_obj_id); } -ThreadItem * -MTinterface::GetCallingThread () +void +pthread_cond::BroadCast () { - AssertResourceOwner (LOCK_THREAD_LIST, READ_LOCK); - DWORD id = GetCurrentThreadId (); - int index = 0; - return (ThreadItem *) Find (&id, &CmpThreadId, index, &threadlist); + if (!verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC)) + return; + PulseEvent (win32_obj_id); + while (InterlockedDecrement (&waiting) != 0) + PulseEvent (win32_obj_id); + mutex = NULL; } -ThreadItem * -MTinterface::GetThread (pthread_t * _t) +void +pthread_cond::Signal () +{ + if (!verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC)) + return; + PulseEvent (win32_obj_id); +} + +int +pthread_cond::TimedWait (DWORD dwMilliseconds) { - AssertResourceOwner (LOCK_THREAD_LIST, READ_LOCK); - int index = 0; - return (ThreadItem *) Find (_t, &CmpPthreadObj, index, &threadlist); + DWORD rv = + SignalObjectAndWait (mutex->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; + } } -MutexItem * -MTinterface::GetMutex (pthread_mutex_t * mp) +pthread_key::pthread_key ():verifyable_object (PTHREAD_KEY_MAGIC) { - AssertResourceOwner (LOCK_MUTEX_LIST, READ_LOCK); - int index = 0; - return (MutexItem *) Find (mp, &CmpPthreadObj, index, &mutexlist); + dwTlsIndex = TlsAlloc (); + if (dwTlsIndex == TLS_OUT_OF_INDEXES) + magic = 0; } -SemaphoreItem * -MTinterface::GetSemaphore (sem_t * sp) +pthread_key::~pthread_key () +{ +/* FIXME: New feature completeness. + * bracketed code is to called when the thread exists, not when delete is called + * if (destructor && TlsGetValue(dwTlsIndex)) + * destructor (TlsGetValue(dwTlsIndex)); + */ + TlsFree (dwTlsIndex); +}; + +int +pthread_key::set (const void *value) { - AssertResourceOwner (LOCK_SEM_LIST, READ_LOCK); - int index = 0; - return (SemaphoreItem *) Find (sp, &CmpPthreadObj, index, &semalist); + /* the OS function doesn't perform error checking */ + TlsSetValue (dwTlsIndex, (void *) value); + return 0; } -CondItem * -MTinterface::GetCond (pthread_cond_t * mp) +void * +pthread_key::get () { - AssertResourceOwner (LOCK_COND_LIST, READ_LOCK); - int index = 0; - return (CondItem *) Find (mp, &CmpPthreadObj, index, &condlist); + set_errno (0); + return TlsGetValue (dwTlsIndex); } -void -MTitem::Destroy () +pthread_mutex::pthread_mutex (pthread_mutexattr * attr):verifyable_object (PTHREAD_MUTEX_MAGIC) { - CloseHandle (win32_obj_id); + this->win32_obj_id =::CreateMutex (&sec_none_nih, false, NULL); + if (!this->win32_obj_id) + magic = 0; + condwaits = 0; +}; + +pthread_mutex::~pthread_mutex () +{ + if (win32_obj_id) + CloseHandle (win32_obj_id); } int -MutexItem::Lock () +pthread_mutex::Lock () { return WaitForSingleObject (win32_obj_id, INFINITE); } int -MutexItem::TryLock () +pthread_mutex::TryLock () { return WaitForSingleObject (win32_obj_id, 0); } int -MutexItem::UnLock () +pthread_mutex::UnLock () { return ReleaseMutex (win32_obj_id); } -SemaphoreItem * -MTinterface::CreateSemaphore (sem_t * _s, int pshared, int _v) +semaphore::semaphore (int pshared, unsigned int value):verifyable_object (SEM_MAGIC) { - AssertResourceOwner (LOCK_SEM_LIST, WRITE_LOCK | READ_LOCK); - - int i = FindNextUnused (&semalist); - - SemaphoreItem *item = (SemaphoreItem *) GetItem (i, &semalist); - if (!item) - item = (SemaphoreItem *) SetItem (i, new SemaphoreItem (), &semalist); - if (!item) - system_printf ("semaphore creation failed"); - item->used = true; - item->shared = pshared; - - item->win32_obj_id = ::CreateSemaphore (&sec_none_nih, _v, LONG_MAX, NULL); - - CHECKHANDLE (NULL, 1); - - *_s = (sem_t) item->win32_obj_id; - - return item; + this->win32_obj_id =::CreateSemaphore (&sec_none_nih, value, LONG_MAX, + NULL); + if (!this->win32_obj_id) + magic = 0; + this->shared = pshared; } -int -SemaphoreItem::Wait () +semaphore::~semaphore () { - return WaitForSingleObject (win32_obj_id, INFINITE); + if (win32_obj_id) + CloseHandle (win32_obj_id); } -int -SemaphoreItem::Post () +void +semaphore::Post () { long pc; - return ReleaseSemaphore (win32_obj_id, 1, &pc); + ReleaseSemaphore (win32_obj_id, 1, &pc); } int -SemaphoreItem::TryWait () +semaphore::TryWait () { - return WaitForSingleObject (win32_obj_id, 0); + /* FIXME: signals should be able to interrupt semaphores... + * We probably need WaitForMultipleObjects here. + */ + if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT) + return EAGAIN; + else + return 0; } -/* Condition Items */ -CondItem * -MTinterface::CreateCond (pthread_cond_t * cond, const pthread_condattr_t * attr) +void +semaphore::Wait () { - 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 ? attr->shared: PTHREAD_PROCESS_PRIVATE; - 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; + WaitForSingleObject (win32_obj_id, INFINITE); } - -int -CondItem::Signal () +verifyable_object::verifyable_object (long verifyer): +magic (verifyer) { - return !PulseEvent (win32_obj_id); } -int -CondItem::Wait () +verifyable_object::~verifyable_object () { - 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; - } + magic = 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; - } +/* Generic memory acccess routine - where should it live ? */ +int __stdcall +check_valid_pointer (void *pointer) +{ + MEMORY_BASIC_INFORMATION m; + if (!pointer || !VirtualQuery (pointer, &m, sizeof (m)) + || (m.State != MEM_COMMIT)) + return EFAULT; + return 0; } int -CondItem::BroadCast () +verifyable_object_isvalid (verifyable_object * object, long magic) { - if (!mutexitem) + if (!object) return 0; - PulseEvent (win32_obj_id); - while (InterlockedDecrement (&waiting)!=0) - PulseEvent (win32_obj_id); - mutexitem=NULL; - return 0; + if (check_valid_pointer (object)) + return 0; + if (object->magic != magic) + return 0; + return -1; } /* Pthreads */ - void * thread_init_wrapper (void *_arg) { // Setup the local/global storage of this thread - ThreadItem *thread = (ThreadItem *) _arg; + pthread *thread = (pthread *) _arg; struct __reent_t local_reent; struct _winsup_t local_winsup; struct _reent local_clib; @@ -573,106 +492,144 @@ thread_init_wrapper (void *_arg) local_winsup._process_logmask = LOG_UPTO (LOG_DEBUG); + /* This is not checked by the OS !! */ if (!TlsSetValue (MT_INTERFACE->reent_index, &local_reent)) system_printf ("local storage for thread couldn't be set"); + /* the OS doesn't check this for <=64 Tls entries (pre win2k) */ + TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thread); + #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); + 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); - // FIXME : cleanup code + __pthread_exit (ret); - // thread->used = false; // release thread entry - thread->return_ptr = ret; - ExitThread (0); +#if 0 +// ??? This code only runs if the thread exits by returning. +// it's all now in __pthread_exit(); +#endif + /* never reached */ + return 0; } int -__pthread_create (pthread_t * thread, const pthread_attr_t * attr, TFD (start_routine), void *arg) +__pthread_create (pthread_t * thread, const pthread_attr_t * attr, + void *(*start_routine) (void *), void *arg) { - SetResourceLock (LOCK_THREAD_LIST, WRITE_LOCK | READ_LOCK, "__pthread_create"); - - pthread_attr_t a; - ThreadItem *item; + if (attr && !verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; - if (attr) - item = MT_INTERFACE->CreateThread (thread, start_routine, arg, *attr); - else + *thread = new pthread (); + (*thread)->create (start_routine, attr ? *attr : NULL, arg); + if (!verifyable_object_isvalid (*thread, PTHREAD_MAGIC)) { - __pthread_attr_init (&a); - item = MT_INTERFACE->CreateThread (thread, start_routine, arg, a); + delete (*thread); + *thread = NULL; + return EAGAIN; } - CHECKITEM (LOCK_THREAD_LIST, WRITE_LOCK | READ_LOCK, "__pthread_create") - - ReleaseResourceLock (LOCK_THREAD_LIST, WRITE_LOCK | READ_LOCK, "__pthread_create"); return 0; } int __pthread_attr_init (pthread_attr_t * attr) { - attr->stacksize = 0; + *attr = new pthread_attr; + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + { + delete (*attr); + *attr = NULL; + return EAGAIN; + } + return 0; +} + +int +__pthread_attr_setdetachstate (pthread_attr_t * attr, int detachstate) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + 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 (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; + *detachstate = (*attr)->joinable; return 0; } int __pthread_attr_setstacksize (pthread_attr_t * attr, size_t size) { - attr->stacksize = size; + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; + (*attr)->stacksize = size; return 0; } int __pthread_attr_getstacksize (pthread_attr_t * attr, size_t * size) { - *size = attr->stacksize; + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; + *size = (*attr)->stacksize; return 0; } int -__pthread_attr_destroy (pthread_attr_t * /*attr*/) +__pthread_attr_destroy (pthread_attr_t * attr) { + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; + delete (*attr); + *attr = NULL; return 0; } -int +void __pthread_exit (void *value_ptr) { - ThreadItem *item = MT_INTERFACE->GetCallingThread (); - item->return_ptr = value_ptr; + class pthread *thread = __pthread_self (); + +// FIXME: run the destructors of thread_key items here + + thread->return_ptr = value_ptr; ExitThread (0); - return 0; } int __pthread_join (pthread_t * thread, void **return_val) { - ThreadItem *item=user_data->threadinterface->GetThread (thread); - + if (!verifyable_object_isvalid (*thread, PTHREAD_MAGIC)) + return ESRCH; - if (!item) - return ESRCH; - - if (item->joinable == 'N') - { - if (return_val) + if ((*thread)->joinable == PTHREAD_CREATE_DETACHED) + { + if (return_val) *return_val = NULL; - return EINVAL; - } + return EINVAL; + } else - { - item->joinable = 'N'; - WaitForSingleObject ((HANDLE)*thread, INFINITE); - if (return_val) - *return_val = item->return_ptr; - }/* End if*/ + { + (*thread)->joinable = PTHREAD_CREATE_DETACHED; + WaitForSingleObject ((*thread)->win32_obj_id, INFINITE); + if (return_val) + *return_val = (*thread)->return_ptr; + } /* End if */ return 0; } @@ -680,32 +637,30 @@ __pthread_join (pthread_t * thread, void **return_val) int __pthread_detach (pthread_t * thread) { - ThreadItem *item=user_data->threadinterface->GetThread (thread); - if (!item) - return ESRCH; + if (!verifyable_object_isvalid (*thread, PTHREAD_MAGIC)) + return ESRCH; - if (item->joinable == 'N') - { - item->return_ptr = NULL; - return EINVAL; - } + if ((*thread)->joinable == PTHREAD_CREATE_DETACHED) + { + (*thread)->return_ptr = NULL; + return EINVAL; + } - item->joinable = 'N'; + (*thread)->joinable = PTHREAD_CREATE_DETACHED; return 0; } int __pthread_suspend (pthread_t * thread) { - ThreadItem *item=user_data->threadinterface->GetThread (thread); - if (!item) - return ESRCH; + if (!verifyable_object_isvalid (*thread, PTHREAD_MAGIC)) + return ESRCH; - if (item->suspended == false) - { - item->suspended = true; - SuspendThread ((HANDLE)*thread); - } + if ((*thread)->suspended == false) + { + (*thread)->suspended = true; + SuspendThread ((*thread)->win32_obj_id); + } return 0; } @@ -714,13 +669,12 @@ __pthread_suspend (pthread_t * thread) int __pthread_continue (pthread_t * thread) { - ThreadItem *item=user_data->threadinterface->GetThread (thread); - if (!item) - return ESRCH; + if (!verifyable_object_isvalid (*thread, PTHREAD_MAGIC)) + return ESRCH; - if (item->suspended == true) - ResumeThread ((HANDLE)*thread); - item->suspended = false; + if ((*thread)->suspended == true) + ResumeThread ((*thread)->win32_obj_id); + (*thread)->suspended = false; return 0; } @@ -728,139 +682,172 @@ __pthread_continue (pthread_t * thread) unsigned long __pthread_getsequence_np (pthread_t * thread) { - GETTHREAD ("__pthread_getsequence_np"); - return item->GetThreadId (); + if (!verifyable_object_isvalid (*thread, PTHREAD_MAGIC)) + return EINVAL; + return (*thread)->GetThreadId (); } /* Thread SpecificData */ int -__pthread_key_create (pthread_key_t */*key*/) +__pthread_key_create (pthread_key_t * key, void (*destructor) (void *)) { - NOT_IMP ("_p_key_create\n"); + /* The opengroup docs don't define if we should check this or not, + * but creation is relatively rare.. + */ + if (verifyable_object_isvalid (*key, PTHREAD_KEY_MAGIC)) + return EBUSY; + + *key = new pthread_key (); + + if (!verifyable_object_isvalid (*key, PTHREAD_KEY_MAGIC)) + { + delete (*key); + *key = NULL; + return EAGAIN; + } + return 0; } int -__pthread_key_delete (pthread_key_t */*key*/) +__pthread_key_delete (pthread_key_t * key) { - NOT_IMP ("_p_key_delete\n"); + if (!verifyable_object_isvalid (*key, PTHREAD_KEY_MAGIC)) + return EINVAL; + + delete (*key); + return 0; } + + int -__pthread_setspecific (pthread_key_t */*key*/, const void */*value*/) +__pthread_setspecific (pthread_key_t key, const void *value) { - NOT_IMP ("_p_key_setsp\n"); + if (!verifyable_object_isvalid (key, PTHREAD_KEY_MAGIC)) + return EINVAL; + (key)->set (value); + return 0; } + void * -__pthread_getspecific (pthread_key_t */*key*/) +__pthread_getspecific (pthread_key_t key) { - NOT_IMP ("_p_key_getsp\n"); + if (!verifyable_object_isvalid (key, PTHREAD_KEY_MAGIC)) + return NULL; + + return (key)->get (); + } /* Thread synchronisation */ int -__pthread_cond_destroy (pthread_cond_t *cond) +__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"); + if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC)) + return EINVAL; - item->Destroy (); + /* reads are atomic */ + if ((*cond)->waiting) + return EBUSY; - MT_INTERFACE->ReleaseItem (item); + delete (*cond); + *cond = NULL; - 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) +__pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr) { - if (attr && (attr->valid != 0xf341)) + if (attr && !verifyable_object_isvalid (*attr, PTHREAD_CONDATTR_MAGIC)) return EINVAL; - SetResourceLock (LOCK_COND_LIST, WRITE_LOCK | READ_LOCK, "__pthread_cond_init"); - CondItem *item = MT_INTERFACE->CreateCond (cond, attr); + if (verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC)) + return EBUSY; - CHECKITEM (LOCK_COND_LIST, WRITE_LOCK | READ_LOCK, "__pthread_cond_init"); + *cond = new pthread_cond (attr ? (*attr) : NULL); - ReleaseResourceLock (LOCK_COND_LIST, WRITE_LOCK | READ_LOCK, "__pthread_cond_init"); - return 0; + if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC)) + { + delete (*cond); + *cond = NULL; + return EAGAIN; + } + return 0; } int -__pthread_cond_broadcast (pthread_cond_t *cond) +__pthread_cond_broadcast (pthread_cond_t * cond) { - GETCOND("_pthread_cond_lock"); + if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC)) + return EINVAL; - item->BroadCast (); + (*cond)->BroadCast (); return 0; } int -__pthread_cond_signal (pthread_cond_t *cond) +__pthread_cond_signal (pthread_cond_t * cond) { - GETCOND("_pthread_cond_lock"); + if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC)) + return EINVAL; - item->Signal (); + (*cond)->Signal (); return 0; } int -__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) +__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 ()) - { + if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) return EINVAL; - } - GETCOND("_pthread_cond_lock"); - if (item->mutexitem && (item->mutexitem != mutexitem)) + if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC)) 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; + if ((*cond)->waiting) + if ((*cond)->mutex && ((*cond)->mutex != (*mutex))) + return EINVAL; + InterlockedIncrement (&((*cond)->waiting)); + + (*cond)->mutex = (*mutex); + InterlockedIncrement (&((*mutex)->condwaits)); + rv = (*cond)->TimedWait (abstime->tv_sec * 1000); + (*cond)->mutex->Lock (); + if (InterlockedDecrement (&((*cond)->waiting)) == 0) + (*cond)->mutex = NULL; + InterlockedDecrement (&((*mutex)->condwaits)); return rv; } int -__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) +__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 ()) - { + if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) return EINVAL; - } - GETCOND("_pthread_cond_lock"); - if (item->mutexitem && (item->mutexitem != mutexitem)) + if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC)) return EINVAL; - item->mutexitem=mutexitem; - InterlockedIncrement (&item->waiting); - rv = item->Wait (); - mutexitem->Lock (); - if (InterlockedDecrement (&item->waiting)==0) - item->mutexitem=NULL; + if ((*cond)->waiting) + if ((*cond)->mutex && ((*cond)->mutex != (*mutex))) + return EINVAL; + InterlockedIncrement (&((*cond)->waiting)); + + (*cond)->mutex = (*mutex); + InterlockedIncrement (&((*mutex)->condwaits)); + rv = (*cond)->TimedWait (INFINITE); + (*cond)->mutex->Lock (); + if (InterlockedDecrement (&((*cond)->waiting)) == 0) + (*cond)->mutex = NULL; + InterlockedDecrement (&((*mutex)->condwaits)); return rv; } @@ -868,35 +855,43 @@ __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) int __pthread_condattr_init (pthread_condattr_t * condattr) { - condattr->shared = 0; - condattr->valid = 0xf341; /* Roberts magic number */ + *condattr = new pthread_condattr; + if (!verifyable_object_isvalid (*condattr, PTHREAD_CONDATTR_MAGIC)) + { + delete (*condattr); + *condattr = NULL; + return EAGAIN; + } return 0; } int __pthread_condattr_getpshared (const pthread_condattr_t * attr, int *pshared) { - if (!attr || (attr->valid != 0xf341)) + if (!verifyable_object_isvalid (*attr, PTHREAD_CONDATTR_MAGIC)) return EINVAL; - *pshared = attr->shared; + *pshared = (*attr)->shared; return 0; } int __pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared) { - if (!attr || (attr->valid != 0xf341) || (pshared <0) || (pshared > 1)) + if (!verifyable_object_isvalid (*attr, PTHREAD_CONDATTR_MAGIC)) return EINVAL; - attr->shared = pshared; + if ((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; + if (!verifyable_object_isvalid (*condattr, PTHREAD_CONDATTR_MAGIC)) + return EINVAL; + delete (*condattr); + *condattr = NULL; return 0; } @@ -904,12 +899,14 @@ __pthread_condattr_destroy (pthread_condattr_t * condattr) int __pthread_kill (pthread_t * thread, int sig) { - // lock myself, for the use of thread2signal +// lock myself, for the use of thread2signal // two differ kills might clash: FIXME - GETTHREAD ("__pthread_kill"); - if (item->sigs) - myself->setthread2signal (item); + if (!verifyable_object_isvalid (*thread, PTHREAD_MAGIC)) + return EINVAL; + + if ((*thread)->sigs) + myself->setthread2signal (*thread); int rval = _kill (myself->pid, sig); @@ -920,15 +917,13 @@ __pthread_kill (pthread_t * thread, int sig) int __pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set) { - SetResourceLock (LOCK_THREAD_LIST, READ_LOCK, "__pthread_sigmask"); - ThreadItem *item = MT_INTERFACE->GetCallingThread (); - ReleaseResourceLock (LOCK_THREAD_LIST, READ_LOCK, "__pthread_sigmask"); + pthread *thread = __pthread_self (); // lock this myself, for the use of thread2signal // two differt kills might clash: FIXME - if (item->sigs) - myself->setthread2signal (item); + if (thread->sigs) + myself->setthread2signal (thread); int rval = sigprocmask (operation, set, old_set); @@ -938,16 +933,9 @@ __pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set) } /* ID */ -pthread_t -__pthread_self () +pthread_t __pthread_self () { - SetResourceLock (LOCK_THREAD_LIST, READ_LOCK, "__pthread_self"); - - ThreadItem *item = MT_INTERFACE->GetCallingThread (); - - ReleaseResourceLock (LOCK_THREAD_LIST, READ_LOCK, "__pthread_self"); - return (pthread_t) item->Id (); - + return (pthread *) TlsGetValue (MT_INTERFACE->thread_self_dwTlsIndex); } int @@ -959,63 +947,65 @@ __pthread_equal (pthread_t * t1, pthread_t * t2) /* Mutexes */ int -__pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t */*_attr*/) +__pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr) { - SetResourceLock (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK, "__pthread_mutex_init"); - - MutexItem *item = MT_INTERFACE->CreateMutex (mutex); + if (attr && !verifyable_object_isvalid (*attr, PTHREAD_MUTEXATTR_MAGIC)) + return EINVAL; - CHECKITEM (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK, "__pthread_mutex_init"); + if (verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) + return EBUSY; - ReleaseResourceLock (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK, "__pthread_mutex_init"); + *mutex = new pthread_mutex (attr ? (*attr) : NULL); + if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) + { + delete (*mutex); + *mutex = NULL; + return EAGAIN; + } return 0; } int __pthread_mutex_lock (pthread_mutex_t * mutex) { - GETMUTEX ("_ptherad_mutex_lock"); - - item->Lock (); - + if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) + return EINVAL; + (*mutex)->Lock (); return 0; } int __pthread_mutex_trylock (pthread_mutex_t * mutex) { - GETMUTEX ("_ptherad_mutex_lock"); - - if (item->TryLock () == WAIT_TIMEOUT) + if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) + return EINVAL; + if ((*mutex)->TryLock () == WAIT_TIMEOUT) return EBUSY; - return 0; } int __pthread_mutex_unlock (pthread_mutex_t * mutex) { - GETMUTEX ("_ptherad_mutex_lock"); - - item->UnLock (); - + if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) + return EINVAL; + (*mutex)->UnLock (); return 0; } int __pthread_mutex_destroy (pthread_mutex_t * mutex) { - SetResourceLock (LOCK_MUTEX_LIST, READ_LOCK | WRITE_LOCK, "__pthread_mutex_destroy"); - - MutexItem *item = MT_INTERFACE->GetMutex (mutex); - - CHECKITEM (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK, "__pthread_mutex_init"); - - item->Destroy (); + if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) + return EINVAL; - MT_INTERFACE->ReleaseItem (item); + /* reading a word is atomic */ + if ((*mutex)->condwaits) + return EBUSY; - ReleaseResourceLock (LOCK_MUTEX_LIST, READ_LOCK | WRITE_LOCK, "__pthread_mutex_destroy"); + delete (*mutex); + *mutex = NULL; return 0; } @@ -1023,61 +1013,63 @@ __pthread_mutex_destroy (pthread_mutex_t * mutex) int __sem_init (sem_t * sem, int pshared, unsigned int value) { - SetResourceLock (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_init"); + /* opengroup calls this undefined */ + if (verifyable_object_isvalid (*sem, SEM_MAGIC)) + return EBUSY; - SemaphoreItem *item = MT_INTERFACE->CreateSemaphore (sem, pshared, value); + if (value > SEM_VALUE_MAX) + return EINVAL; - CHECKITEM (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_init"); + *sem = new semaphore (pshared, value); - ReleaseResourceLock (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_init"); + if (!verifyable_object_isvalid (*sem, SEM_MAGIC)) + { + delete (*sem); + *sem = NULL; + return EAGAIN; + } return 0; } int __sem_destroy (sem_t * sem) { - SetResourceLock (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_destroy"); - - SemaphoreItem *item = MT_INTERFACE->GetSemaphore (sem); - - CHECKITEM (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_init"); - - item->Destroy (); + if (!verifyable_object_isvalid (*sem, SEM_MAGIC)) + return EINVAL; - MT_INTERFACE->ReleaseItem (item); + /* FIXME - new feature - test for busy against threads... */ - ReleaseResourceLock (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_destroy"); + delete (*sem); + *sem = NULL; return 0; } int __sem_wait (sem_t * sem) { - GETSEMA ("__sem_wait"); - - item->Wait (); + if (!verifyable_object_isvalid (*sem, SEM_MAGIC)) + return EINVAL; + (*sem)->Wait (); return 0; } int __sem_trywait (sem_t * sem) { - GETSEMA ("__sem_trywait"); - - if (item->TryWait () == WAIT_TIMEOUT) - return EAGAIN; + if (!verifyable_object_isvalid (*sem, SEM_MAGIC)) + return EINVAL; - return 0; + return (*sem)->TryWait (); } int __sem_post (sem_t * sem) { - GETSEMA ("__sem_post"); - - item->Post (); + if (!verifyable_object_isvalid (*sem, SEM_MAGIC)) + return EINVAL; + (*sem)->Post (); return 0; } @@ -1087,7 +1079,8 @@ __sem_post (sem_t * sem) // empty functions needed when makeing the dll without mt_safe support extern "C" { - int __pthread_create (pthread_t *, const pthread_attr_t *, TFD (start_routine), void *arg) + int __pthread_create (pthread_t *, const pthread_attr_t *, + TFD (start_routine), void *arg) { return -1; } @@ -1099,6 +1092,16 @@ extern "C" { return -1; } + int __pthread_attr_setdetachstate (pthread_attr_t * attr, int detachstate) + { + return -1; + } + int + __pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate) + { + return -1; + } int __pthread_attr_setstacksize (pthread_attr_t * attr, size_t size) { return -1; @@ -1107,7 +1110,7 @@ extern "C" { return -1; } -/* +/* these cannot be supported on win32 - the os allocates it's own stack space.. __pthread_attr_setstackaddr (...){ return -1; }; __pthread_attr_getstackaddr (...){ return -1; }; */ @@ -1118,7 +1121,7 @@ extern "C" int __pthread_join (pthread_t thread_id, void **return_val) { - return -1; + return -1; } unsigned long __pthread_getsequence_np (pthread_t * thread) @@ -1145,7 +1148,8 @@ extern "C" { return -1; } - int __pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set) + int __pthread_sigmask (int operation, const sigset_t * set, + sigset_t * old_set) { return -1; } @@ -1193,7 +1197,8 @@ extern "C" { return -1; } - int __pthread_cond_timedwait (pthread_cond_t *, pthread_mutex_t *, const struct timespec *) + int __pthread_cond_timedwait (pthread_cond_t *, pthread_mutex_t *, + const struct timespec *) { return -1; } @@ -1243,4 +1248,4 @@ extern "C" } } -#endif // MT_SAFE +#endif // MT_SAFE diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index 18cb3c3..794a8b9 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -1,9 +1,11 @@ /* thread.h: Locking and threading module definitions Copyright 1998, 1999, 2000 Cygnus Solutions. + Copyright 2001 Red Hat, Inc. Written by Marco Fuykschot <marco@ddi.nl> - + Major update 2001 Robert Collins <rbtcollins@hotmail.com> + This file is part of Cygwin. This software is a copyrighted work licensed under the terms of the @@ -17,10 +19,6 @@ details. */ #define LOCK_MEMORY_LIST 2 #define LOCK_MMAP_LIST 3 #define LOCK_DLL_LIST 4 -#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 @@ -41,80 +39,97 @@ extern "C" #else -#include <pthread.h> +//#include <pthread.h> +/* FIXME: these are defined in pthread.h, but pthread.h defines symbols it shouldn't - + * all the types. + */ +#define PTHREAD_PROCESS_PRIVATE 0 +#define PTHREAD_PROCESS_SHARED 1 +#define PTHREAD_DESTRUCTOR_ITERATIONS 1 +/* Tls has 64 items for pre win2000 - and we don't want to use them all :] + * Before committing discuss this with the list + */ +#define PTHREAD_KEYS_MAX 32 +#define PTHREAD_CREATE_DETACHED 1 +/* the default : joinable */ +#define PTHREAD_CREATE_JOINABLE 0 + +#include <signal.h> #include <pwd.h> #include <grp.h> #define _NOMNTENT_FUNCS #include <mntent.h> -extern "C" { - -struct _winsup_t +extern "C" { + + struct _winsup_t + { /* Needed for the group functions */ - struct group _grp; - char *_namearray[2]; - char _linebuf[100]; - int _grp_pos; + struct group _grp; + char *_namearray[2]; + char _linebuf[100]; + int _grp_pos; /* console.cc */ - unsigned _rarg; + unsigned _rarg; /* dlfcn.cc */ - int _dl_error; - char _dl_buffer[256]; + int _dl_error; + char _dl_buffer[256]; /* passwd.cc */ - struct passwd _res; - char _tmpbuf[100]; - char _pass[_PASSWORD_LEN]; - int _pw_pos; + struct passwd _res; + char _tmpbuf[100]; + char _pass[_PASSWORD_LEN]; + int _pw_pos; /* path.cc */ - struct mntent _ret; - int _iteration; + struct mntent _ret; + int _iteration; /* strerror */ - char _strerror_buf[20]; + char _strerror_buf[20]; /* syscalls.cc */ - char _dacl_buf[1024]; - char _sacl_buf[1024]; - char _ownr_buf[1024]; - char _grp_buf[1024]; + char _dacl_buf[1024]; + char _sacl_buf[1024]; + char _ownr_buf[1024]; + char _grp_buf[1024]; /* sysloc.cc */ - char *_process_ident; - int _process_logopt; - int _process_facility; - int _process_logmask; + char *_process_ident; + int _process_logopt; + int _process_facility; + int _process_logmask; /* times.cc */ - char _b[20]; - struct tm _localtime_buf; - char _buf1[33]; - char _buf2[33]; + char _b[20]; + struct tm _localtime_buf; + char _buf1[33]; + char _buf2[33]; /* uinfo.cc */ - char _username[MAX_USER_NAME]; -}; + char _username[MAX_USER_NAME]; + }; -struct __reent_t -{ - struct _reent *_clib; - struct _winsup_t *_winsup; -}; + struct __reent_t + { + struct _reent *_clib; + struct _winsup_t *_winsup; + }; -_reent *_reent_clib (); -_winsup_t *_reent_winsup (); -void SetResourceLock (int, int, const char *) __attribute__ ((regparm(3))); -void ReleaseResourceLock (int, int, const char *) __attribute__ ((regparm(3))); + _reent *_reent_clib (); + _winsup_t *_reent_winsup (); + void SetResourceLock (int, int, const char *) __attribute__ ((regparm (3))); + void ReleaseResourceLock (int, int, const char *) + __attribute__ ((regparm (3))); #ifdef _CYG_THREAD_FAILSAFE -void AssertResourceOwner (int, int); + void AssertResourceOwner (int, int); #else #define AssertResourceOwner(i,ii) #endif @@ -126,7 +141,9 @@ class pinfo; class ResourceLocks { public: - ResourceLocks () {}; + ResourceLocks () + { + }; LPCRITICAL_SECTION Lock (int); void Init (); void Delete (); @@ -134,196 +151,255 @@ public: DWORD owner; DWORD count; #endif - private: +private: CRITICAL_SECTION lock; bool inited; }; +#define PTHREAD_MAGIC 0xdf0df045 +#define PTHREAD_MUTEX_MAGIC PTHREAD_MAGIC+1 +#define PTHREAD_KEY_MAGIC PTHREAD_MAGIC+2 +#define PTHREAD_ATTR_MAGIC PTHREAD_MAGIC+3 +#define PTHREAD_MUTEXATTR_MAGIC PTHREAD_MAGIC+4 +#define PTHREAD_COND_MAGIC PTHREAD_MAGIC+5 +#define PTHREAD_CONDATTR_MAGIC PTHREAD_MAGIC+6 +#define SEM_MAGIC PTHREAD_MAGIC+7 -#define MT_MAX_ITEMS 128 +class verifyable_object +{ +public: + long magic; -// thread classes\lists + verifyable_object (long); + ~verifyable_object (); +}; + +int verifyable_object_isvalid (verifyable_object *, long); -class MTitem +class pthread_attr:public verifyable_object { - public: - HANDLE win32_obj_id; - UINT return_value; - bool used; - char joinable; // for thread only - bool HandleOke () {return win32_obj_id;} - virtual void Destroy (); - virtual int Id () {return (int) win32_obj_id;} +public: + int joinable; + size_t stacksize; + + pthread_attr (); + ~pthread_attr (); }; -class ThreadItem: public MTitem +class pthread:public verifyable_object { public: - pthread_attr_t attr; - TFD (function); + HANDLE win32_obj_id; + class pthread_attr attr; + void *(*function) (void *); void *arg; void *return_ptr; bool suspended; - DWORD thread_id; - DWORD GetThreadId () {return thread_id;} + int joinable; + DWORD GetThreadId () + { + return thread_id; + } + void setThreadIdtoCurrent () + { + thread_id = GetCurrentThreadId (); + } /* signal handling */ struct sigaction *sigs; sigset_t *sigmask; LONG *sigtodo; + void create (void *(*)(void *), pthread_attr *, void *); + + pthread (); + ~pthread (); + +private: + DWORD thread_id; + }; -class MutexItem: public MTitem +class pthread_mutexattr:public verifyable_object { public: + + pthread_mutexattr (); + ~pthread_mutexattr (); +}; + +class pthread_mutex:public verifyable_object +{ +public: + HANDLE win32_obj_id; + LONG condwaits; + int Lock (); int TryLock (); int UnLock (); + + pthread_mutex (pthread_mutexattr *); + ~pthread_mutex (); }; -class SemaphoreItem: public MTitem +class pthread_key:public verifyable_object +{ +public: + + DWORD dwTlsIndex; + int set (const void *); + void *get (); + + pthread_key (); + ~pthread_key (); +}; + +class pthread_condattr:public verifyable_object { public: int shared; - int Wait (); - int Post (); - int TryWait (); + + pthread_condattr (); + ~pthread_condattr (); }; -class CondItem: public MTitem +class pthread_cond:public verifyable_object { public: int shared; LONG waiting; - MutexItem *mutexitem; - int Wait (); + pthread_mutex *mutex; + HANDLE win32_obj_id; int TimedWait (DWORD dwMilliseconds); - int BroadCast (); - int Signal (); + void BroadCast (); + void Signal (); + + pthread_cond (pthread_condattr *); + ~pthread_cond (); }; -typedef struct +/* shouldn't be here */ +class semaphore:public verifyable_object { - MTitem *items[MT_MAX_ITEMS]; - int index; -} MTList; +public: + HANDLE win32_obj_id; + int shared; + void Wait (); + void Post (); + int TryWait (); + + semaphore (int, unsigned int); + ~semaphore (); +}; + +typedef class pthread *pthread_t; +typedef class pthread_mutex *pthread_mutex_t; +/* sem routines belong in semaphore.cc */ +typedef class semaphore *sem_t; + +typedef class pthread_key *pthread_key_t; +typedef class pthread_attr *pthread_attr_t; +typedef class pthread_mutexattr *pthread_mutexattr_t; +typedef class pthread_condattr *pthread_condattr_t; +typedef class pthread_cond *pthread_cond_t; class MTinterface { public: // General DWORD reent_index; - DWORD thread_key; + DWORD thread_self_dwTlsIndex; + /* we may get 0 for the Tls index.. grrr */ + int indexallocated; // Used for main thread data, and sigproc thread struct __reent_t reents; struct _winsup_t winsup_reent; - ThreadItem mainthread; + pthread mainthread; void Init (int); - void ReleaseItem (MTitem *); - - // Thread functions - ThreadItem *CreateThread (pthread_t *, TFD (func), void *, pthread_attr_t); - ThreadItem *GetCallingThread (); - ThreadItem *GetThread (pthread_t *); - - // Mutex functions - MutexItem *CreateMutex (pthread_mutex_t *); - MutexItem *GetMutex (pthread_mutex_t *); - - // Semaphore functions - 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 *); - MTitem *GetItem (int, MTList *); - MTitem *SetItem (int, MTitem *, MTList *); - int Find (MTitem &, MTList *); - int FindNextUnused (MTList *); - - MTList threadlist; - MTList mutexlist; - MTList semalist; - MTList condlist; + MTinterface ():reent_index (0), indexallocated (0) + { + } }; extern "C" { -void *thread_init_wrapper (void *); + void *thread_init_wrapper (void *); /* ThreadCreation */ -int __pthread_create (pthread_t * thread, const pthread_attr_t * attr, TFD (start_routine), void *arg); -int __pthread_attr_init (pthread_attr_t * attr); -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); + int __pthread_create (pthread_t * thread, const pthread_attr_t * attr, + void *(*start_routine) (void *), void *arg); + int __pthread_attr_init (pthread_attr_t * attr); + int __pthread_attr_destroy (pthread_attr_t * attr); + int __pthread_attr_setdetachstate (pthread_attr_t *, int); + int __pthread_attr_getdetachstate (const pthread_attr_t *, int *); + int __pthread_attr_setstacksize (pthread_attr_t * attr, size_t size); + int __pthread_attr_getstacksize (pthread_attr_t * attr, size_t * size); /* __pthread_attr_setstackaddr(...); __pthread_attr_getstackaddr(...); */ /* Thread Exit */ -int __pthread_exit (void *value_ptr); -int __pthread_join(pthread_t *thread, void **return_val); -int __pthread_detach(pthread_t *thread); + void __pthread_exit (void *value_ptr); + int __pthread_join (pthread_t * thread, void **return_val); + int __pthread_detach (pthread_t * thread); /* Thread suspend */ -int __pthread_suspend(pthread_t *thread); -int __pthread_continue(pthread_t *thread); + int __pthread_suspend (pthread_t * thread); + int __pthread_continue (pthread_t * thread); -unsigned long __pthread_getsequence_np (pthread_t * thread); + unsigned long __pthread_getsequence_np (pthread_t * thread); /* Thread SpecificData */ -int __pthread_key_create (pthread_key_t * key); -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); + int __pthread_key_create (pthread_key_t * key, void (*destructor) (void *)); + 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); + 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); -int __pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set); + int __pthread_kill (pthread_t * thread, int sig); + int __pthread_sigmask (int operation, const sigset_t * set, + sigset_t * old_set); /* ID */ -pthread_t __pthread_self (); -int __pthread_equal (pthread_t * t1, pthread_t * t2); + pthread_t __pthread_self (); + int __pthread_equal (pthread_t * t1, pthread_t * t2); /* Mutexes */ -int __pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *); -int __pthread_mutex_lock (pthread_mutex_t *); -int __pthread_mutex_trylock (pthread_mutex_t *); -int __pthread_mutex_unlock (pthread_mutex_t *); -int __pthread_mutex_destroy (pthread_mutex_t *); + int __pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *); + int __pthread_mutex_lock (pthread_mutex_t *); + int __pthread_mutex_trylock (pthread_mutex_t *); + int __pthread_mutex_unlock (pthread_mutex_t *); + int __pthread_mutex_destroy (pthread_mutex_t *); /* Semaphores */ -int __sem_init (sem_t * sem, int pshared, unsigned int value); -int __sem_destroy (sem_t * sem); -int __sem_wait (sem_t * sem); -int __sem_trywait (sem_t * sem); -int __sem_post (sem_t * sem); + int __sem_init (sem_t * sem, int pshared, unsigned int value); + int __sem_destroy (sem_t * sem); + int __sem_wait (sem_t * sem); + int __sem_trywait (sem_t * sem); + int __sem_post (sem_t * sem); }; |