diff options
Diffstat (limited to 'winsup')
-rw-r--r-- | winsup/cygwin/configure.in | 3 | ||||
-rw-r--r-- | winsup/cygwin/cygwin.din | 108 | ||||
-rw-r--r-- | winsup/cygwin/include/cygwin/types.h | 64 | ||||
-rw-r--r-- | winsup/cygwin/include/pthread.h | 196 | ||||
-rw-r--r-- | winsup/cygwin/include/sched.h | 27 | ||||
-rw-r--r-- | winsup/cygwin/pthread.cc | 335 | ||||
-rw-r--r-- | winsup/cygwin/sched.cc | 44 | ||||
-rw-r--r-- | winsup/cygwin/thread.cc | 952 | ||||
-rw-r--r-- | winsup/cygwin/thread.h | 301 |
9 files changed, 1543 insertions, 487 deletions
diff --git a/winsup/cygwin/configure.in b/winsup/cygwin/configure.in index befd40655..81ba6d931 100644 --- a/winsup/cygwin/configure.in +++ b/winsup/cygwin/configure.in @@ -119,7 +119,6 @@ AC_LANG_RESTORE dnl set default mt safeness and then process the options. mt_safe_val=1 MT_SAFE=yes -PTH_ALLOW='' AC_ARG_ENABLE(threadsafe, [ --enable-threadsafe=[runtime] Build a cygwin DLL which is thread safe], @@ -134,7 +133,6 @@ runtime) no) mt_safe_val=0 MT_SAFE=no - PTH_ALLOW=';' ;; esac ]) @@ -159,7 +157,6 @@ fi dnl Makefile uses MT_SAFE, so we subst as well as defining it. AC_SUBST(MT_SAFE) -AC_SUBST(PTH_ALLOW) AC_ARG_ENABLE(debugging, [ --enable-debugging Build a cygwin DLL which has more consistency checking for debugging], diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index 453785f7e..a94af5e2c 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -498,6 +498,7 @@ memset _memset = memset mkdir _mkdir = mkdir +mkfifo mknod _mknod = mknod mkstemp @@ -1075,44 +1076,75 @@ cygwin_attach_handle_to_fd cygwin32_attach_handle_to_fd = cygwin_attach_handle_to_fd cygwin_internal cygwin32_internal = cygwin_internal -@PTH_ALLOW@pthread_create -@PTH_ALLOW@pthread_attr_init -@PTH_ALLOW@pthread_attr_destroy -@PTH_ALLOW@pthread_attr_setstacksize -@PTH_ALLOW@pthread_attr_getstacksize -@PTH_ALLOW@pthread_exit -@PTH_ALLOW@pthread_join -@PTH_ALLOW@pthread_detach -@PTH_ALLOW@pthread_suspend -@PTH_ALLOW@pthread_continue -@PTH_ALLOW@pthread_key_create -@PTH_ALLOW@pthread_key_delete -@PTH_ALLOW@pthread_setspecific -@PTH_ALLOW@pthread_getspecific -@PTH_ALLOW@pthread_kill -@PTH_ALLOW@pthread_sigmask -@PTH_ALLOW@pthread_self -@PTH_ALLOW@pthread_equal -@PTH_ALLOW@pthread_mutex_init -@PTH_ALLOW@pthread_mutex_lock -@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 -@PTH_ALLOW@sem_trywait -@PTH_ALLOW@sem_post +pthread_attr_destroy +pthread_attr_getdetachstate +pthread_attr_getinheritsched +pthread_attr_getschedparam +pthread_attr_getschedpolicy +pthread_attr_getscope +pthread_attr_getstacksize +pthread_attr_init +pthread_attr_setdetachstate +pthread_attr_setinheritsched +pthread_attr_setschedparam +pthread_attr_setschedpolicy +pthread_attr_setscope +pthread_attr_setstacksize +pthread_cancel +pthread_cond_broadcast +pthread_cond_destroy +pthread_cond_init +pthread_cond_signal +pthread_cond_timedwait +pthread_cond_wait +pthread_condattr_destroy +pthread_condattr_getpshared +pthread_condattr_init +pthread_condattr_setpshared +pthread_create +pthread_detach +pthread_equal +pthread_exit +pthread_getconcurrency +pthread_getschedparam +pthread_getspecific +pthread_join +pthread_key_create +pthread_key_delete +pthread_mutex_destroy +pthread_mutex_getprioceiling +pthread_mutex_init +pthread_mutex_lock +pthread_mutex_setprioceiling +pthread_mutex_trylock +pthread_mutex_unlock +pthread_mutexattr_destroy +pthread_mutexattr_getprioceiling +pthread_mutexattr_getprotocol +pthread_mutexattr_getpshared +pthread_mutexattr_gettype +pthread_mutexattr_init +pthread_mutexattr_setprioceiling +pthread_mutexattr_setprotocol +pthread_mutexattr_setpshared +pthread_mutexattr_settype +pthread_once +pthread_self +pthread_setcancelstate +pthread_setcanceltype +pthread_setconcurrency +pthread_setschedparam +pthread_setspecific +pthread_testcancel +pthread_suspend +pthread_continue +pthread_kill +pthread_sigmask +sem_init +sem_destroy +sem_wait +sem_trywait +sem_post sched_get_priority_max sched_get_priority_min sched_getparam diff --git a/winsup/cygwin/include/cygwin/types.h b/winsup/cygwin/include/cygwin/types.h index 51e349710..7114b7c4a 100644 --- a/winsup/cygwin/include/cygwin/types.h +++ b/winsup/cygwin/include/cygwin/types.h @@ -1 +1,63 @@ -/* types.h */ +/* types.h + + Copyright 2001 Red Hat Inc. + Written by Robert Collins <rbtcollins@hotmail.com> + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef _CYGWIN_TYPES_H +#define _CYGWIN_TYPES_H + +#if !defined(__INSIDE_CYGWIN__) || !defined(__cplusplus) + +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; + + /* These variables are not user alterable. This means you!. */ +typedef struct +{ + pthread_mutex_t mutex; + int state; +} +pthread_once_t; +typedef void *pthread_rwlock_t; +typedef void *pthread_rwlockattr_t; + +#else + +/* pthreads types */ + +typedef class pthread *pthread_t; +typedef class pthread_mutex *pthread_mutex_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; +typedef class pthread_once pthread_once_t; +typedef class pthread_rwlock *pthread_rwlock_t; +typedef class pthread_rwlockattr *pthread_rwlockattr_t; + +/* semaphores types */ +typedef class semaphore *sem_t; +#endif /* __INSIDE_CYGWIN__ */ +#endif /* _CYGWIN_TYPES_H */ + +#ifdef __cplusplus +} +#endif diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h index d4b73de82..6f8f9025a 100644 --- a/winsup/cygwin/include/pthread.h +++ b/winsup/cygwin/include/pthread.h @@ -12,6 +12,7 @@ #include <sys/types.h> #include <signal.h> +#include <sched.h> #ifndef _PTHREAD_H #define _PTHREAD_H @@ -29,87 +30,148 @@ extern "C" 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 #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 +/* the default : joinable */ + +#define PTHREAD_CANCEL_ASYNCHRONOUS 1 +/* defaults are enable, deferred */ +#define PTHREAD_CANCEL_ENABLE 0 +#define PTHREAD_CANCEL_DEFERRED 0 +#define PTHREAD_CANCEL_DISABLE 1 +#define PTHREAD_CANCELED +#define PTHREAD_COND_INITIALIZER #define PTHREAD_CREATE_DETACHED 1 /* the default : joinable */ #define PTHREAD_CREATE_JOINABLE 0 +#define PTHREAD_EXPLICIT_SCHED 1 +#define PTHREAD_INHERIT_SCHED 0 +#define PTHREAD_MUTEX_DEFAULT 0 +#define PTHREAD_MUTEX_ERRORCHECK 1 +#define PTHREAD_MUTEX_NORMAL 2 +/* this should be too low to ever be a valid address */ +#define PTHREAD_MUTEX_INITIALIZER (void *)20 +#define PTHREAD_MUTEX_RECURSIVE 0 +#define PTHREAD_ONCE_INIT { PTHREAD_MUTEX_INITIALIZER, 0 } +#define PTHREAD_PRIO_INHERIT +#define PTHREAD_PRIO_NONE +#define PTHREAD_PRIO_PROTECT +#define PTHREAD_PROCESS_SHARED 1 +#define PTHREAD_PROCESS_PRIVATE 0 +#define PTHREAD_RWLOCK_INITIALIZER +/* process is the default */ +#define PTHREAD_SCOPE_PROCESS 0 +#define PTHREAD_SCOPE_SYSTEM 1 + + +/* Attributes */ +int pthread_attr_destroy (pthread_attr_t *); +int pthread_attr_getdetachstate (const pthread_attr_t *, int *); +int pthread_attr_getinheritsched (const pthread_attr_t *, int *); +int pthread_attr_getschedparam (const pthread_attr_t *, struct sched_param *); +int pthread_attr_getschedpolicy (const pthread_attr_t *, int *); +int pthread_attr_getscope (const pthread_attr_t *, int *); +int pthread_attr_init (pthread_attr_t *); +int pthread_attr_setdetachstate (pthread_attr_t *, int); +int pthread_attr_setinheritsched (pthread_attr_t *, int); +int pthread_attr_setschedparam (pthread_attr_t *, const struct sched_param *); +int pthread_attr_setschedpolicy (pthread_attr_t *, int); +int pthread_attr_setscope (pthread_attr_t *, int); + +#ifdef _POSIX_THREAD_ATTR_STACKADDR +/* These functions may be implementable via some low level trickery. For now they are + * Not supported or implemented. The prototypes are here so if someone greps the + * source they will see these comments + */ +int pthread_attr_getstackaddr (const pthread_attr_t *, void **); +int pthread_attr_setstackaddr (pthread_attr_t *, void *); +#endif +#ifdef _POSIX_THREAD_ATTR_STACKSIZE +int pthread_attr_getstacksize (const pthread_attr_t *, size_t *); +int pthread_attr_setstacksize (pthread_attr_t *, size_t); +#endif -/* 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, - 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); +int pthread_cancel (pthread_t); +/* Macros for cleanup_push and pop; + * The function definitions are +void pthread_cleanup_push(void (*routine)(void*), void *arg); +void pthread_cleanup_pop(int execute); +*/ +typedef void __cleanup_routine_type (void *); + +#define pthread_cleanup_push (fn, arg) { __cleanup_routine_type __cleanup_routine=fn; \ +void *__cleanup_param=arg; +#define pthread_cleanup_pop (execute) if (execute) __cleanup_routine(__cleanup_param); } /* 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); - -/* Thread Exit */ - void pthread_exit (void *value_ptr); - -/* Thread SpecificData */ - 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 (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); - -/* 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); +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_create (pthread_t *, const pthread_attr_t *, + void *(*)(void *), void *); +int pthread_detach (pthread_t); +int pthread_equal (pthread_t, pthread_t); +void pthread_exit (void *); +int pthread_getschedparam (pthread_t, int *, struct sched_param *); +void *pthread_getspecific (pthread_key_t); +int pthread_join (pthread_t, void **); +int pthread_key_create (pthread_key_t *, void (*)(void *)); +int pthread_key_delete (pthread_key_t); + +/* Mutex's */ +int pthread_mutex_destroy (pthread_mutex_t *); +int pthread_mutex_getprioceiling (const pthread_mutex_t *, int *); +int pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *); +int pthread_mutex_lock (pthread_mutex_t *); +int pthread_mutex_setprioceiling (pthread_mutex_t *, int, int *); +int pthread_mutex_trylock (pthread_mutex_t *); +int pthread_mutex_unlock (pthread_mutex_t *); +int pthread_mutexattr_destroy (pthread_mutexattr_t *); +int pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *, int *); +int pthread_mutexattr_getprotocol (const pthread_mutexattr_t *, int *); +int pthread_mutexattr_getpshared (const pthread_mutexattr_t *, int *); +int pthread_mutexattr_gettype (const pthread_mutexattr_t *, int *); +int pthread_mutexattr_init (pthread_mutexattr_t *); +int pthread_mutexattr_setprioceiling (pthread_mutexattr_t *, int); +int pthread_mutexattr_setprotocol (pthread_mutexattr_t *, int); +int pthread_mutexattr_setpshared (pthread_mutexattr_t *, int); +int pthread_mutexattr_settype (pthread_mutexattr_t *, int); + +int pthread_once (pthread_once_t *, void (*)(void)); + +/* Concurrency levels - X/Open interface */ +int pthread_getconcurrency (void); +int pthread_setconcurrency (int); + + +pthread_t pthread_self (void); +int pthread_setcancelstate (int, int *); +int pthread_setcanceltype (int, int *); +int pthread_setschedparam (pthread_t, int, const struct sched_param *); +int pthread_setspecific (pthread_key_t, const void *); +void pthread_testcancel (void); + +/* Non posix calls */ + +int pthread_suspend (pthread_t); +int pthread_continue (pthread_t); + #ifdef __cplusplus } #endif -#endif /* _PTHREAD_H */ +#endif /* _PTHREAD_H */ diff --git a/winsup/cygwin/include/sched.h b/winsup/cygwin/include/sched.h index 8b8e277e6..f97b8ebf4 100644 --- a/winsup/cygwin/include/sched.h +++ b/winsup/cygwin/include/sched.h @@ -31,21 +31,32 @@ extern "C" { #endif /* max priority for policy */ - int sched_get_priority_max (int); +int sched_get_priority_max (int); /* min priority for policy */ - int sched_get_priority_min (int); +int sched_get_priority_min (int); /* get sched params for process */ - int sched_getparam (pid_t, struct sched_param *); +int sched_getparam (pid_t, struct sched_param *); /* get the scheduler for pid */ - int sched_getscheduler (pid_t); +int sched_getscheduler (pid_t); /* get the time quantum for pid */ - int sched_rr_get_interval (pid_t, struct timespec *); +int sched_rr_get_interval (pid_t, struct timespec *); /* set the scheduling parameters */ - int sched_setparam (pid_t, const struct sched_param *); +int sched_setparam (pid_t, const struct sched_param *); /* set the scheduler */ - int sched_setscheduler (pid_t, int, const struct sched_param *); +int sched_setscheduler (pid_t, int, const struct sched_param *); /* yield the cpu */ - int sched_yield (void); +int sched_yield (void); + +#if defined(__INSIDE_CYGWIN__) +/* These are private helper functions used to calculate scheduler settings and + * validate parameters */ + +/* check parameters for validity */ +int valid_sched_parameters(const struct sched_param *); +/* set a single thread's priority */ +int sched_set_thread_priority(HANDLE thread, int priority); + +#endif /* INSIDE_CYGWIN */ #ifdef __cplusplus } diff --git a/winsup/cygwin/pthread.cc b/winsup/cygwin/pthread.cc index 171fe6386..c9f0bb2bf 100644 --- a/winsup/cygwin/pthread.cc +++ b/winsup/cygwin/pthread.cc @@ -17,111 +17,193 @@ extern "C" { /* ThreadCreation */ int - pthread_create (pthread_t * thread, const pthread_attr_t * attr, - void *(*start_routine) (void *), void *arg) +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) +int +pthread_once (pthread_once_t * once_control, void (*init_routine) (void)) +{ + return __pthread_once (once_control, init_routine); +} + +int +pthread_attr_init (pthread_attr_t * attr) { return __pthread_attr_init (attr); } -int pthread_attr_destroy (pthread_attr_t * attr) +int +pthread_attr_destroy (pthread_attr_t * attr) { return __pthread_attr_destroy (attr); } -int pthread_attr_setdetachstate (pthread_attr_t * attr, int detachstate) +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) +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) +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) +int +pthread_attr_getstacksize (const pthread_attr_t * attr, size_t * size) { return __pthread_attr_getstacksize (attr, size); } +int +pthread_attr_setinheritsched (pthread_attr_t * attr, int inheritsched) +{ + return __pthread_attr_setinheritsched (attr, inheritsched); +} + +int +pthread_attr_getinheritsched (const pthread_attr_t * attr, int *inheritsched) +{ + return __pthread_attr_getinheritsched (attr, inheritsched); +} + +int +pthread_attr_setschedparam (pthread_attr_t * attr, + const struct sched_param *param) +{ + return __pthread_attr_setschedparam (attr, param); +} + +int +pthread_attr_getschedparam (const pthread_attr_t * attr, + struct sched_param *param) +{ + return __pthread_attr_getschedparam (attr, param); +} + +int +pthread_attr_setschedpolicy (pthread_attr_t * attr, int policy) +{ + return __pthread_attr_setschedpolicy (attr, policy); +} + +int +pthread_attr_getschedpolicy (const pthread_attr_t * attr, int *policy) +{ + return __pthread_attr_getschedpolicy (attr, policy); +} + +int +pthread_attr_setscope (pthread_attr_t * attr, int contentionscope) +{ + return __pthread_attr_setscope (attr, contentionscope); +} + +int +pthread_attr_getscope (const pthread_attr_t * attr, int *contentionscope) +{ + return __pthread_attr_getscope (attr, contentionscope); +} + +#ifdef _POSIX_THREAD_ATTR_STACKADDR +int +pthread_attr_setstackaddr (pthread_attr_t * attr, void *stackaddr) +{ + return __pthread_attr_setstackaddr (attr, stackaddr); +} -/* - pthread_attr_setstackaddr(...){}; - pthread_attr_getstackaddr(...){}; -*/ +int +pthread_attr_getstackaddr (const pthread_attr_t * attr, void **stackaddr) +{ + return __pthread_attr_getstackaddr (attr, stackaddr); +} +#endif /* Thread Exit */ -void pthread_exit (void *value_ptr) +void +pthread_exit (void *value_ptr) { return __pthread_exit (value_ptr); } -int pthread_join (pthread_t thread, void **return_val) +int +pthread_join (pthread_t thread, void **return_val) { return __pthread_join (&thread, (void **) return_val); } -int pthread_detach (pthread_t thread) +int +pthread_detach (pthread_t thread) { return __pthread_detach (&thread); } -int pthread_suspend (pthread_t thread) + +/* This isn't a posix call... should we keep it? */ +int +pthread_suspend (pthread_t thread) { return __pthread_suspend (&thread); } -int pthread_continue (pthread_t thread) +/* same */ +int +pthread_continue (pthread_t thread) { return __pthread_continue (&thread); } -unsigned long pthread_getsequence_np (pthread_t * thread) +unsigned long +pthread_getsequence_np (pthread_t * thread) { return __pthread_getsequence_np (thread); } /* Thread SpecificData */ -int pthread_key_create (pthread_key_t * key, void (*destructor) (void *)) +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) +int +pthread_key_delete (pthread_key_t key) { return __pthread_key_delete (key); } -int pthread_setspecific (pthread_key_t key, const void *value) +int +pthread_setspecific (pthread_key_t key, const void *value) { return __pthread_setspecific (key, value); } -void *pthread_getspecific (pthread_key_t key) +void * +pthread_getspecific (pthread_key_t key) { return (void *) __pthread_getspecific (key); } /* Thread signal */ -int pthread_kill (pthread_t * thread, int 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) +pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set) { return __pthread_sigmask (operation, set, old_set); } @@ -133,120 +215,273 @@ pthread_t pthread_self () return __pthread_self (); } -int pthread_equal (pthread_t t1, pthread_t 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) +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) +int +pthread_mutex_lock (pthread_mutex_t * mutex) { return __pthread_mutex_lock (mutex); } -int pthread_mutex_trylock (pthread_mutex_t * mutex) +int +pthread_mutex_trylock (pthread_mutex_t * mutex) { return __pthread_mutex_trylock (mutex); } -int pthread_mutex_unlock (pthread_mutex_t * mutex) +int +pthread_mutex_unlock (pthread_mutex_t * mutex) { return __pthread_mutex_unlock (mutex); } -int pthread_mutex_destroy (pthread_mutex_t * mutex) +int +pthread_mutex_destroy (pthread_mutex_t * mutex) { return __pthread_mutex_destroy (mutex); } +int +pthread_mutex_setprioceiling (pthread_mutex_t * mutex, + int prioceiling, int *old_ceiling) +{ + return __pthread_mutex_setprioceiling (mutex, prioceiling, old_ceiling); +} + +int +pthread_mutex_getprioceiling (const pthread_mutex_t * mutex, int *prioceiling) +{ + return __pthread_mutex_getprioceiling (mutex, prioceiling); +} + + + +int +pthread_mutexattr_destroy (pthread_mutexattr_t * attr) +{ + return __pthread_mutexattr_destroy (attr); +} + +int +pthread_mutexattr_getprioceiling (const pthread_mutexattr_t * attr, + int *prioceiling) +{ + return __pthread_mutexattr_getprioceiling (attr, prioceiling); +} + +int +pthread_mutexattr_getprotocol (const pthread_mutexattr_t * attr, + int *protocol) +{ + return __pthread_mutexattr_getprotocol (attr, protocol); +} + +int +pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr, int *pshared) +{ + return __pthread_mutexattr_getpshared (attr, pshared); +} + +int +pthread_mutexattr_gettype (const pthread_mutexattr_t * attr, int *type) +{ + return __pthread_mutexattr_gettype (attr, type); +} + +int +pthread_mutexattr_init (pthread_mutexattr_t * attr) +{ + return __pthread_mutexattr_init (attr); +} + +int +pthread_mutexattr_setprioceiling (pthread_mutexattr_t * attr, int prioceiling) +{ + return __pthread_mutexattr_setprioceiling (attr, prioceiling); +} + +int +pthread_mutexattr_setprotocol (pthread_mutexattr_t * attr, int protocol) +{ + return __pthread_mutexattr_setprotocol (attr, protocol); +} + +int +pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, int pshared) +{ + return __pthread_mutexattr_setpshared (attr, pshared); +} + +int +pthread_mutexattr_settype (pthread_mutexattr_t * attr, int type) +{ + return __pthread_mutexattr_settype (attr, type); +} + /* Synchronisation */ -int pthread_cond_destroy (pthread_cond_t * cond) +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) +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) +int +pthread_cond_signal (pthread_cond_t * cond) { return __pthread_cond_signal (cond); } -int pthread_cond_broadcast (pthread_cond_t * 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) +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) +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) +int +pthread_condattr_init (pthread_condattr_t * condattr) { return __pthread_condattr_init (condattr); } -int pthread_condattr_destroy (pthread_condattr_t * 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) +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) +int +pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared) { return __pthread_condattr_setpshared (attr, pshared); } +/* Scheduling */ + +int +pthread_getconcurrency (void) +{ + return __pthread_getconcurrency (); +} + +int +pthread_setconcurrency (int new_level) +{ + return __pthread_setconcurrency (new_level); +} + + + + +int +pthread_getschedparam (pthread_t thread, int *policy, + struct sched_param *param) +{ + return __pthread_getschedparam (thread, policy, param); +} + +int +pthread_setschedparam (pthread_t thread, int policy, + const struct sched_param *param) +{ + return __pthread_setschedparam (thread, policy, param); +} + + +/* Cancelability */ + +int +pthread_cancel (pthread_t thread) +{ + return __pthread_cancel (thread); +} + + + +int +pthread_setcancelstate (int state, int *oldstate) +{ + return __pthread_setcancelstate (state, oldstate); +} + +int +pthread_setcanceltype (int type, int *oldtype) +{ + return __pthread_setcanceltype (type, oldtype); +} + +void +pthread_testcancel (void) +{ + __pthread_testcancel (); +} + /* Semaphores */ -int sem_init (sem_t * sem, int pshared, unsigned int value) +int +sem_init (sem_t * sem, int pshared, unsigned int value) { return __sem_init (sem, pshared, value); } -int sem_destroy (sem_t * sem) +int +sem_destroy (sem_t * sem) { return __sem_destroy (sem); } -int sem_wait (sem_t * sem) +int +sem_wait (sem_t * sem) { return __sem_wait (sem); } -int sem_trywait (sem_t * sem) +int +sem_trywait (sem_t * sem) { return __sem_trywait (sem); } -int sem_post (sem_t * sem) +int +sem_post (sem_t * sem) { return __sem_post (sem); } + } diff --git a/winsup/cygwin/sched.cc b/winsup/cygwin/sched.cc index ef12b69b2..f80803e28 100644 --- a/winsup/cygwin/sched.cc +++ b/winsup/cygwin/sched.cc @@ -81,6 +81,18 @@ sched_get_priority_min (int policy) return 15; } +/* Check a scheduler parameter struct for valid settings */ +int +valid_sched_parameters(const struct sched_param *param) +{ + if (param->sched_priority < -14 || param->sched_priority > 15) + { + return 0; + } + return -1; + +} + /* get sched params for process Note, I'm never returning EPERM, @@ -273,7 +285,7 @@ sched_setparam (pid_t pid, const struct sched_param *param) return -1; } - if (param->sched_priority < -14 || param->sched_priority > 15) + if (!valid_sched_parameters(param)) { set_errno (EINVAL); return -1; @@ -384,6 +396,36 @@ sched_setparam (pid_t pid, const struct sched_param *param) return 0; } +/* we map -14 to 15, and 15 to 1 via (16- ((n+16) >> 1)). This lines up with the allowed + * valueswe return elsewhere in the sched* functions. We then map in groups of three to + * allowed thread priority's. The reason for dropping accuracy while still returning + * a wide range of values is to allow more flexible code in the future. + */ +int +sched_set_thread_priority(HANDLE thread, int priority) +{ + int real_pri; + real_pri = 16 - ((priority + 16) >> 1); + if (real_pri <1 || real_pri > 15) + return EINVAL; + + if (real_pri < 4) + real_pri = THREAD_PRIORITY_LOWEST; + else if (real_pri < 7) + real_pri = THREAD_PRIORITY_BELOW_NORMAL; + else if (real_pri < 10) + real_pri = THREAD_PRIORITY_NORMAL; + else if (real_pri < 13) + real_pri = THREAD_PRIORITY_ABOVE_NORMAL; + else + real_pri = THREAD_PRIORITY_HIGHEST; + + if (!SetThreadPriority(thread, real_pri)) + /* invalid handle, no access are the only expected errors. */ + return EPERM; + return 0; +} + /* set the scheduler */ int sched_setscheduler (pid_t pid, int policy, diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 78ce8116f..e870c3131 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -10,6 +10,21 @@ This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ +/* Implementation overview and caveats: + + Win32 puts some contraints on what can and cannot be implemented. Where possible + we work around those contrainsts. Where we cannot work around the constraints we + either pretend to be conformant, or return an error code. + + Some caveats: PROCESS_SHARED objects while they pretend to be process shared, + may not actually work. Some test cases are needed to determine win32's behaviour. + My suspicion is that the win32 handle needs to be opened with different flags for + proper operation. + + R.Collins, April 2001. + + */ + #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -31,9 +46,93 @@ details. */ extern int threadsafe; -#define MT_INTERFACE user_data->threadinterface +/* pthread_key_destructor_list class: to-be threadsafe single linked list + * FIXME: Put me in a dedicated file, or a least a tools area ! + */ + +pthread_key_destructor * +pthread_key_destructor::InsertAfter (pthread_key_destructor * node) +{ + pthread_key_destructor *temp = next; + next = node; + return temp; +} + +pthread_key_destructor * +pthread_key_destructor::UnlinkNext () +{ + pthread_key_destructor *temp = next; + if (next) + next = next->Next (); + return temp; +} -#define NOT_IMP(n) system_printf ("not implemented %s\n", n); return 0; +pthread_key_destructor * +pthread_key_destructor::Next () +{ + return next; +} + +void +pthread_key_destructor_list::Insert (pthread_key_destructor * node) +{ + if (!node) + return; + head = node->InsertAfter (head); + if (!head) + head = node; /* first node special case */ +} + + /* remove a given dataitem, wherever in the list it is */ +pthread_key_destructor * +pthread_key_destructor_list::Remove (pthread_key * key) +{ + if (!key) + return NULL; + if (!head) + return NULL; + if (key == head->key) + return Pop (); + pthread_key_destructor *temp = head; + while (temp && temp->Next () && !(key == temp->Next ()->key)) + { + temp = temp->Next (); + } + if (temp) + return temp->UnlinkNext (); + return NULL; +} + + /* get the first item and remove at the same time */ +pthread_key_destructor * +pthread_key_destructor_list::Pop () +{ + pthread_key_destructor *temp = head; + head = head->Next (); + return temp; +} + +pthread_key_destructor:: +pthread_key_destructor (void (*thedestructor) (void *), pthread_key * key) +{ + destructor = thedestructor; + next = NULL; + this->key = key; +} + +void +pthread_key_destructor_list::IterateNull () +{ + pthread_key_destructor *temp = head; + while (temp) + { + temp->destructor ((temp->key)->get ()); + temp = temp->Next (); + } +} + + +#define MT_INTERFACE user_data->threadinterface struct _reent * _reent_clib () @@ -191,6 +290,8 @@ MTinterface::Init (int forked) ("local storage for thread couldn't be set\nThis means that we are not thread safe!\n"); } + concurrency = 0; + if (forked) return; @@ -208,7 +309,8 @@ MTinterface::Init (int forked) #endif } -pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0) +pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0), +cancelstate (0), canceltype (0) { } @@ -230,6 +332,8 @@ pthread::create (void *(*func) (void *), pthread_attr * newattr, if (newattr) { attr.joinable = newattr->joinable; + attr.contentionscope = newattr->contentionscope; + attr.inheritsched = newattr->inheritsched; attr.stacksize = newattr->stacksize; } function = func; @@ -242,20 +346,30 @@ pthread::create (void *(*func) (void *), pthread_attr * newattr, if (!win32_obj_id) magic = 0; else - ResumeThread (win32_obj_id); + { + /* FIXME: set the priority appropriately for system contention scope */ + if (attr.inheritsched == PTHREAD_EXPLICIT_SCHED) + { + /* FIXME: set the scheduling settings for the new thread */ + /* sched_thread_setparam(win32_obj_id, attr.schedparam); */ + } + ResumeThread (win32_obj_id); + } } pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC), -joinable (PTHREAD_CREATE_JOINABLE), stacksize (0) +joinable (PTHREAD_CREATE_JOINABLE), contentionscope (PTHREAD_SCOPE_PROCESS), +inheritsched (PTHREAD_INHERIT_SCHED), stacksize (0) { + schedparam.sched_priority = 0; } pthread_attr::~pthread_attr () { } -pthread_condattr::pthread_condattr ():verifyable_object -(PTHREAD_CONDATTR_MAGIC), shared (PTHREAD_PROCESS_PRIVATE) +pthread_condattr::pthread_condattr ():verifyable_object + (PTHREAD_CONDATTR_MAGIC), shared (PTHREAD_PROCESS_PRIVATE) { } @@ -269,10 +383,9 @@ pthread_cond::pthread_cond (pthread_condattr * attr):verifyable_object (PTHREAD_ this->mutex = NULL; this->waiting = 0; - 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 */ ); + 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 */ ); if (!this->win32_obj_id) magic = 0; @@ -312,21 +425,26 @@ pthread_cond::TimedWait (DWORD dwMilliseconds) switch (rv) { case WAIT_FAILED: - return 0; /* POSIX doesn't allow errors after we modify the mutex state */ + 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 */ + return 0; /* we have been signaled */ default: return 0; } } -pthread_key::pthread_key ():verifyable_object (PTHREAD_KEY_MAGIC) +pthread_key::pthread_key (void (*destructor) (void *)):verifyable_object (PTHREAD_KEY_MAGIC) { dwTlsIndex = TlsAlloc (); if (dwTlsIndex == TLS_OUT_OF_INDEXES) magic = 0; + else if (destructor) + { + MT_INTERFACE->destructors. + Insert (new pthread_key_destructor (destructor, this)); + } } pthread_key::~pthread_key () @@ -336,6 +454,8 @@ pthread_key::~pthread_key () * if (destructor && TlsGetValue(dwTlsIndex)) * destructor (TlsGetValue(dwTlsIndex)); */ + if (pthread_key_destructor * dest = MT_INTERFACE->destructors.Remove (this)) + delete dest; TlsFree (dwTlsIndex); }; @@ -360,7 +480,7 @@ pthread_mutex::pthread_mutex (pthread_mutexattr * attr):verifyable_object (PTHRE if (!this->win32_obj_id) magic = 0; condwaits = 0; -}; +} pthread_mutex::~pthread_mutex () { @@ -386,6 +506,15 @@ pthread_mutex::UnLock () return ReleaseMutex (win32_obj_id); } +pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC), +pshared (PTHREAD_PROCESS_PRIVATE), mutextype (PTHREAD_MUTEX_DEFAULT) +{ +} + +pthread_mutexattr::~pthread_mutexattr () +{ +}; + semaphore::semaphore (int pshared, unsigned int value):verifyable_object (SEM_MAGIC) { this->win32_obj_id =::CreateSemaphore (&sec_none_nih, value, LONG_MAX, @@ -540,6 +669,273 @@ __pthread_create (pthread_t * thread, const pthread_attr_t * attr, } int +__pthread_once (pthread_once_t * once_control, void (*init_routine) (void)) +{ + pthread_mutex_lock (&once_control->mutex); + /* Here we must set a cancellation handler to unlock the mutex if needed */ + /* but a cancellation handler is not the right thing. We need this in the thread + * cleanup routine. Assumption: a thread can only be in one pthread_once routine + * at a time. Stote a mutex_t * in the pthread_structure. if that's non null unlock + * on pthread_exit(); + */ + if (once_control->state == 0) + { + init_routine (); + once_control->state = 1; + } + /* Here we must remove our cancellation handler */ + pthread_mutex_unlock (&once_control->mutex); + return 0; +} + +/* Cancelability states */ + + +/* Perform the actual cancel */ +void +__pthread_cleanup (pthread_t thread) +{ +} + + +int +__pthread_cancel (pthread_t thread) +{ + if (!verifyable_object_isvalid (thread, PTHREAD_MAGIC)) + return ESRCH; + if (thread->cancelstate == PTHREAD_CANCEL_ENABLE) + { +#if 0 + /* once all the functions call testcancel(), we will do this */ + if (thread->canceltype == PTHREAD_CANCEL_DEFERRED) + { + } + else + { + /* possible FIXME: this function is meant to return asynchronously + * from the cancellation routine actually firing. So we may need some sort + * of signal to be sent that is immediately recieved and acted on. + */ + __pthread_cleanup (thread); + } +#endif + } +/* return 0; +*/ + + return ESRCH; +/* + we return ESRCH until all the required functions call testcancel(); + this will give applications predictable behaviour. + + the required function list is: +aio_suspend() +close() +creat() +fcntl() +fsync() +getmsg() +getpmsg() +lockf() +mq_receive() +mq_send() +msgrcv() +msgsnd() +msync() +nanosleep() +open() +pause() +poll() +pread() +pthread_cond_timedwait() +pthread_cond_wait() +pthread_join() +pthread_testcancel() +putmsg() +putpmsg() +pwrite() +read() +readv() +select() +sem_wait() +sigpause() +sigsuspend() +sigtimedwait() +sigwait() +sigwaitinfo() +sleep() +system() +tcdrain() +usleep() +wait() +wait3() +waitid() +waitpid() +write() +writev() + +the optional list is: +catclose() +catgets() +catopen() +closedir() +closelog() +ctermid() +dbm_close() +dbm_delete() +dbm_fetch() +dbm_nextkey() +dbm_open() +dbm_store() +dlclose() +dlopen() +endgrent() +endpwent() +endutxent() +fclose() +fcntl() +fflush() +fgetc() +fgetpos() +fgets() +fgetwc() +fgetws() +fopen() +fprintf() +fputc() +fputs() +fputwc() +fputws() +fread() +freopen() +fscanf() +fseek() +fseeko() +fsetpos() +ftell() +ftello() +ftw() +fwprintf() +fwrite() +fwscanf() +getc() +getc_unlocked() +getchar() +getchar_unlocked() +getcwd() +getdate() +getgrent() +getgrgid() +getgrgid_r() +getgrnam() +getgrnam_r() +getlogin() +getlogin_r() +getpwent() +getpwnam() +getpwnam_r() +getpwuid() +getpwuid_r() +gets() +getutxent() +getutxid() +getutxline() +getw() +getwc() +getwchar() +getwd() +glob() +iconv_close() +iconv_open() +ioctl() +lseek() +mkstemp() +nftw() +opendir() +openlog() +pclose() +perror() +popen() +printf() +putc() +putc_unlocked() +putchar() +putchar_unlocked() +puts() +pututxline() +putw() +putwc() +putwchar() +readdir() +readdir_r() +remove() +rename() +rewind() +rewinddir() +scanf() +seekdir() +semop() +setgrent() +setpwent() +setutxent() +strerror() +syslog() +tmpfile() +tmpnam() +ttyname() +ttyname_r() +ungetc() +ungetwc() +unlink() +vfprintf() +vfwprintf() +vprintf() +vwprintf() +wprintf() +wscanf() + +Note, that for fcntl(), for any value of the cmd argument. + +And we must not introduce cancellation points anywhere else that's part of the posix or +opengroup specs. + */ +} + +/* no races in these three functions: they are all current-thread-only */ +int +__pthread_setcancelstate (int state, int *oldstate) +{ + class pthread *thread = __pthread_self (); + if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE) + return EINVAL; + *oldstate = thread->cancelstate; + thread->cancelstate = state; + return 0; +} + +int +__pthread_setcanceltype (int type, int *oldtype) +{ + class pthread *thread = __pthread_self (); + if (type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS) + return EINVAL; + *oldtype = thread->canceltype; + thread->canceltype = type; + return 0; +} + +/* deferred cancellation request handler */ +void +__pthread_testcancel (void) +{ + class pthread *thread = __pthread_self (); + if (thread->cancelstate == PTHREAD_CANCEL_DISABLE) + return; + /* check the cancellation event object here - not neededuntil pthread_cancel actually + * does something*/ +} + +int __pthread_attr_init (pthread_attr_t * attr) { *attr = new pthread_attr; @@ -553,6 +949,49 @@ __pthread_attr_init (pthread_attr_t * attr) } int +__pthread_attr_getinheritsched (const pthread_attr_t * attr, + int *inheritsched) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; + *inheritsched = (*attr)->inheritsched; + return 0; +} + +int +__pthread_attr_getschedparam (const pthread_attr_t * attr, + struct sched_param *param) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; + *param = (*attr)->schedparam; + return 0; +} + +/* From a pure code point of view, this should call a helper in sched.cc, + * to allow for someone adding scheduler policy changes to win32 in the future. + * However that's extremely unlikely, so short and sweet will do us + */ +int +__pthread_attr_getschedpolicy (const pthread_attr_t * attr, int *policy) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; + *policy = SCHED_FIFO; + return 0; +} + + +int +__pthread_attr_getscope (const pthread_attr_t * attr, int *contentionscope) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; + *contentionscope = (*attr)->contentionscope; + return 0; +} + +int __pthread_attr_setdetachstate (pthread_attr_t * attr, int detachstate) { if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) @@ -573,6 +1012,57 @@ __pthread_attr_getdetachstate (const pthread_attr_t * attr, int *detachstate) } int +__pthread_attr_setinheritsched (pthread_attr_t * attr, int inheritsched) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; + if (inheritsched != PTHREAD_INHERIT_SCHED + && inheritsched != PTHREAD_EXPLICIT_SCHED) + return ENOTSUP; + (*attr)->inheritsched = inheritsched; + return 0; +} + +int +__pthread_attr_setschedparam (pthread_attr_t * attr, + const struct sched_param *param) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; + if (!valid_sched_parameters (param)) + return ENOTSUP; + (*attr)->schedparam = *param; + return 0; +} + +/* See __pthread_attr_getschedpolicy for some notes */ +int +__pthread_attr_setschedpolicy (pthread_attr_t * attr, int policy) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; + if (policy != SCHED_FIFO) + return ENOTSUP; + return 0; +} + +int +__pthread_attr_setscope (pthread_attr_t * attr, int contentionscope) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) + return EINVAL; + if (contentionscope != PTHREAD_SCOPE_SYSTEM + && contentionscope != PTHREAD_SCOPE_PROCESS) + return EINVAL; + /* In future, we may be able to support system scope by escalating the thread + * priority to exceed the priority class. For now we only support PROCESS scope. */ + if (contentionscope != PTHREAD_SCOPE_PROCESS) + return ENOTSUP; + (*attr)->contentionscope = contentionscope; + return 0; +} + +int __pthread_attr_setstacksize (pthread_attr_t * attr, size_t size) { if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) @@ -582,7 +1072,7 @@ __pthread_attr_setstacksize (pthread_attr_t * attr, size_t size) } int -__pthread_attr_getstacksize (pthread_attr_t * attr, size_t * size) +__pthread_attr_getstacksize (const pthread_attr_t * attr, size_t * size) { if (!verifyable_object_isvalid (*attr, PTHREAD_ATTR_MAGIC)) return EINVAL; @@ -605,6 +1095,7 @@ __pthread_exit (void *value_ptr) { class pthread *thread = __pthread_self (); + MT_INTERFACE->destructors.IterateNull (); // FIXME: run the destructors of thread_key items here thread->return_ptr = value_ptr; @@ -617,7 +1108,7 @@ __pthread_join (pthread_t * thread, void **return_val) if (!verifyable_object_isvalid (*thread, PTHREAD_MAGIC)) return ESRCH; - if ((*thread)->joinable == PTHREAD_CREATE_DETACHED) + if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED) { if (return_val) *return_val = NULL; @@ -625,7 +1116,7 @@ __pthread_join (pthread_t * thread, void **return_val) } else { - (*thread)->joinable = PTHREAD_CREATE_DETACHED; + (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; WaitForSingleObject ((*thread)->win32_obj_id, INFINITE); if (return_val) *return_val = (*thread)->return_ptr; @@ -640,13 +1131,13 @@ __pthread_detach (pthread_t * thread) if (!verifyable_object_isvalid (*thread, PTHREAD_MAGIC)) return ESRCH; - if ((*thread)->joinable == PTHREAD_CREATE_DETACHED) + if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED) { (*thread)->return_ptr = NULL; return EINVAL; } - (*thread)->joinable = PTHREAD_CREATE_DETACHED; + (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; return 0; } @@ -679,6 +1170,30 @@ __pthread_continue (pthread_t * thread) return 0; } +/* provided for source level compatability. + * See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html + */ +int +__pthread_getconcurrency (void) +{ + return MT_INTERFACE->concurrency; +} + +/* keep this in sync with sched.cc */ +int +__pthread_getschedparam (pthread_t thread, int *policy, + struct sched_param *param) +{ + if (!verifyable_object_isvalid (thread, PTHREAD_MAGIC)) + return ESRCH; + *policy = SCHED_FIFO; + /* we don't return the current effective priority, we return the current requested + * priority */ + *param = thread->attr.schedparam; + return 0; +} + + unsigned long __pthread_getsequence_np (pthread_t * thread) { @@ -697,7 +1212,7 @@ __pthread_key_create (pthread_key_t * key, void (*destructor) (void *)) if (verifyable_object_isvalid (*key, PTHREAD_KEY_MAGIC)) return EBUSY; - *key = new pthread_key (); + *key = new pthread_key (destructor); if (!verifyable_object_isvalid (*key, PTHREAD_KEY_MAGIC)) { @@ -709,15 +1224,45 @@ __pthread_key_create (pthread_key_t * key, void (*destructor) (void *)) } int -__pthread_key_delete (pthread_key_t * key) +__pthread_key_delete (pthread_key_t key) { - if (!verifyable_object_isvalid (*key, PTHREAD_KEY_MAGIC)) + if (!verifyable_object_isvalid (key, PTHREAD_KEY_MAGIC)) return EINVAL; - delete (*key); + delete (key); + return 0; +} + +/* provided for source level compatability. + * See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html + */ +int +__pthread_setconcurrency (int new_level) +{ + if (new_level < 0) + return EINVAL; + MT_INTERFACE->concurrency = new_level; return 0; } +/* keep syncronised with sched.cc */ +int +__pthread_setschedparam (pthread_t thread, int policy, + const struct sched_param *param) +{ + if (!verifyable_object_isvalid (thread, PTHREAD_MAGIC)) + return ESRCH; + if (policy != SCHED_FIFO) + return ENOTSUP; + if (!param) + return EINVAL; + int rv = + sched_set_thread_priority (thread->win32_obj_id, param->sched_priority); + if (!rv) + thread->attr.schedparam.sched_priority = param->sched_priority; + return rv; +} + int __pthread_setspecific (pthread_key_t key, const void *value) @@ -806,6 +1351,8 @@ __pthread_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex, int rv; if (!abstime) return EINVAL; + if (*mutex == PTHREAD_MUTEX_INITIALIZER) + __pthread_mutex_init (mutex, NULL); if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) return EINVAL; if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC)) @@ -831,6 +1378,8 @@ int __pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex) { int rv; + if (*mutex == PTHREAD_MUTEX_INITIALIZER) + __pthread_mutex_init (mutex, NULL); if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) return EINVAL; if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC)) @@ -897,16 +1446,16 @@ __pthread_condattr_destroy (pthread_condattr_t * condattr) /* Thread signal */ int -__pthread_kill (pthread_t * thread, int sig) +__pthread_kill (pthread_t thread, int sig) { // lock myself, for the use of thread2signal // two differ kills might clash: FIXME - if (!verifyable_object_isvalid (*thread, PTHREAD_MAGIC)) + if (!verifyable_object_isvalid (thread, PTHREAD_MAGIC)) return EINVAL; - if ((*thread)->sigs) - myself->setthread2signal (*thread); + if (thread->sigs) + myself->setthread2signal (thread); int rval = _kill (myself->pid, sig); @@ -933,7 +1482,8 @@ __pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set) } /* ID */ -pthread_t __pthread_self () +pthread_t +__pthread_self () { return (pthread *) TlsGetValue (MT_INTERFACE->thread_self_dwTlsIndex); } @@ -946,6 +1496,15 @@ __pthread_equal (pthread_t * t1, pthread_t * 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. + */ + int __pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr) @@ -967,8 +1526,29 @@ __pthread_mutex_init (pthread_mutex_t * mutex, } int +__pthread_mutex_getprioceiling (const pthread_mutex_t * mutex, + int *prioceiling) +{ + if (*mutex == PTHREAD_MUTEX_INITIALIZER) + __pthread_mutex_init ((pthread_mutex_t *) mutex, NULL); + if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) + 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 thre priority. + */ + return ENOSYS; +} + +int __pthread_mutex_lock (pthread_mutex_t * mutex) { + if (*mutex == PTHREAD_MUTEX_INITIALIZER) + __pthread_mutex_init (mutex, NULL); if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) return EINVAL; (*mutex)->Lock (); @@ -978,6 +1558,8 @@ __pthread_mutex_lock (pthread_mutex_t * mutex) int __pthread_mutex_trylock (pthread_mutex_t * mutex) { + if (*mutex == PTHREAD_MUTEX_INITIALIZER) + __pthread_mutex_init (mutex, NULL); if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) return EINVAL; if ((*mutex)->TryLock () == WAIT_TIMEOUT) @@ -988,6 +1570,8 @@ __pthread_mutex_trylock (pthread_mutex_t * mutex) int __pthread_mutex_unlock (pthread_mutex_t * mutex) { + if (*mutex == PTHREAD_MUTEX_INITIALIZER) + __pthread_mutex_init (mutex, NULL); if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) return EINVAL; (*mutex)->UnLock (); @@ -997,6 +1581,8 @@ __pthread_mutex_unlock (pthread_mutex_t * mutex) int __pthread_mutex_destroy (pthread_mutex_t * mutex) { + if (*mutex == PTHREAD_MUTEX_INITIALIZER) + return 0; if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) return EINVAL; @@ -1009,6 +1595,137 @@ __pthread_mutex_destroy (pthread_mutex_t * mutex) return 0; } +int +__pthread_mutex_setprioceiling (pthread_mutex_t * mutex, int prioceiling, + int *old_ceiling) +{ + if (*mutex == PTHREAD_MUTEX_INITIALIZER) + __pthread_mutex_init (mutex, NULL); + if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) + 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 (!verifyable_object_isvalid (*attr, PTHREAD_MUTEX_MAGIC)) + return EINVAL; + return ENOSYS; +} + +int +__pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr, + int *pshared) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_MUTEX_MAGIC)) + 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 (!verifyable_object_isvalid (*attr, PTHREAD_MUTEX_MAGIC)) + 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 (verifyable_object_isvalid (*attr, PTHREAD_MUTEXATTR_MAGIC)) + return EBUSY; + + *attr = new pthread_mutexattr (); + if (!verifyable_object_isvalid (*attr, PTHREAD_MUTEXATTR_MAGIC)) + { + delete (*attr); + *attr = NULL; + return ENOMEM; + } + return 0; +} + +int +__pthread_mutexattr_destroy (pthread_mutexattr_t * attr) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_MUTEXATTR_MAGIC)) + 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 (!verifyable_object_isvalid (*attr, PTHREAD_MUTEXATTR_MAGIC)) + return EINVAL; + return ENOSYS; +} + +/* Win32 doesn't support mutex priorities */ +int +__pthread_mutexattr_setprioceiling (pthread_mutexattr_t * attr, + int prioceiling) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_MUTEXATTR_MAGIC)) + return EINVAL; + return ENOSYS; +} + +int +__pthread_mutexattr_getprioceiling (const pthread_mutexattr_t * attr, + int *prioceiling) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_MUTEXATTR_MAGIC)) + return EINVAL; + return ENOSYS; +} + +int +__pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, int pshared) +{ + if (!verifyable_object_isvalid (*attr, PTHREAD_MUTEXATTR_MAGIC)) + 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 (!verifyable_object_isvalid (*attr, PTHREAD_MUTEXATTR_MAGIC)) + return EINVAL; + if (type != PTHREAD_MUTEX_RECURSIVE) + return EINVAL; + (*attr)->mutextype = type; + return 0; +} + /* Semaphores */ int __sem_init (sem_t * sem, int pshared, unsigned int value) @@ -1073,179 +1790,4 @@ __sem_post (sem_t * sem) return 0; } - -#else - -// 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) -{ - return -1; -} -int __pthread_attr_init (pthread_attr_t * attr) -{ - return -1; -} -int __pthread_attr_destroy (pthread_attr_t * attr) -{ - 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; -} -int __pthread_attr_getstacksize (pthread_attr_t * attr, size_t * size) -{ - 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; }; -*/ -int __pthread_exit (void *value_ptr) -{ - return -1; -} - -int __pthread_join (pthread_t thread_id, void **return_val) -{ - return -1; -} - -unsigned long __pthread_getsequence_np (pthread_t * thread) -{ - return 0; -} -int __pthread_key_create (pthread_key_t * key) -{ - return -1; -} -int __pthread_key_delete (pthread_key_t * key) -{ - return -1; -} -int __pthread_setspecific (pthread_key_t * key, const void *value) -{ - return -1; -} -void *__pthread_getspecific (pthread_key_t * key) -{ - return NULL; -} -int __pthread_kill (pthread_t * thread, int sig) -{ - return -1; -} -int __pthread_sigmask (int operation, const sigset_t * set, - sigset_t * old_set) -{ - return -1; -} -pthread_t __pthread_self () -{ - return -1; -} -int __pthread_equal (pthread_t * t1, pthread_t * t2) -{ - return -1; -} -int __pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *) -{ - return -1; -} -int __pthread_mutex_lock (pthread_mutex_t *) -{ - return -1; -} -int __pthread_mutex_trylock (pthread_mutex_t *) -{ - return -1; -} -int __pthread_mutex_unlock (pthread_mutex_t *) -{ - return -1; -} -int __pthread_mutex_destroy (pthread_mutex_t *) -{ - 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; -} -int __sem_destroy (sem_t * sem) -{ - return -1; -} -int __sem_wait (sem_t * sem) -{ - return -1; -} -int __sem_trywait (sem_t * sem) -{ - return -1; -} -int __sem_post (sem_t * sem) -{ - return -1; -} -struct _reent *_reent_clib () -{ - return NULL; - } -} - -#endif // MT_SAFE +#endif // MT_SAFE diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index deeef50f5..00c10b298 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -26,7 +26,7 @@ details. */ extern "C" { #if defined (_CYG_THREAD_FAILSAFE) && defined (_MT_SAFE) -void AssertResourceOwner (int, int); + void AssertResourceOwner (int, int); #else #define AssertResourceOwner(i,ii) #endif @@ -39,21 +39,7 @@ void AssertResourceOwner (int, int); #else -//#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 <pthread.h> #include <signal.h> #include <pwd.h> #include <grp.h> @@ -66,8 +52,8 @@ extern "C" struct _winsup_t { /* - Needed for the group functions - */ + Needed for the group functions + */ struct group _grp; char *_namearray[2]; int _grp_pos; @@ -136,7 +122,9 @@ class pinfo; class ResourceLocks { public: - ResourceLocks () {} + ResourceLocks () + { + } LPCRITICAL_SECTION Lock (int); void Init (); void Delete (); @@ -157,26 +145,74 @@ private: #define PTHREAD_COND_MAGIC PTHREAD_MAGIC+5 #define PTHREAD_CONDATTR_MAGIC PTHREAD_MAGIC+6 #define SEM_MAGIC PTHREAD_MAGIC+7 +#define PTHREAD_ONCE_MAGIC PTHREAD_MAGIC+8; + +/* verifyable_object should not be defined here - it's a general purpose class */ class verifyable_object { public: long magic; - verifyable_object (long); - ~verifyable_object (); + verifyable_object (long); + ~verifyable_object (); }; int verifyable_object_isvalid (verifyable_object *, long); +class pthread_key:public verifyable_object +{ +public: + + DWORD dwTlsIndex; + int set (const void *); + void *get (); + + pthread_key (void (*)(void *)); + ~pthread_key (); +}; + +/* FIXME: test using multiple inheritance and merging key_destructor into pthread_key + * for efficiency */ +class pthread_key_destructor +{ +public: + void (*destructor) (void *); + pthread_key_destructor *InsertAfter (pthread_key_destructor * node); + pthread_key_destructor *UnlinkNext (); + pthread_key_destructor *Next (); + + pthread_key_destructor (void (*thedestructor) (void *), pthread_key * key); + pthread_key_destructor *next; + pthread_key *key; +}; + +class pthread_key_destructor_list +{ +public: + void Insert (pthread_key_destructor * node); +/* remove a given dataitem, wherever in the list it is */ + pthread_key_destructor *Remove (pthread_key_destructor * item); +/* get the first item and remove at the same time */ + pthread_key_destructor *Pop (); + pthread_key_destructor *Remove (pthread_key * key); + void IterateNull (); +private: + pthread_key_destructor * head; +}; + + class pthread_attr:public verifyable_object { public: int joinable; + int contentionscope; + int inheritsched; + struct sched_param schedparam; size_t stacksize; - pthread_attr (); - ~pthread_attr (); + pthread_attr (); + ~pthread_attr (); }; class pthread:public verifyable_object @@ -188,7 +224,9 @@ public: void *arg; void *return_ptr; bool suspended; - int joinable; + int cancelstate, canceltype; + // int joinable; + DWORD GetThreadId () { return thread_id; @@ -204,18 +242,20 @@ public: LONG *sigtodo; void create (void *(*)(void *), pthread_attr *, void *); - pthread (); - ~pthread (); + pthread (); + ~pthread (); private: - DWORD thread_id; + DWORD thread_id; }; class pthread_mutexattr:public verifyable_object { public: - pthread_mutexattr (); - ~pthread_mutexattr (); + int pshared; + int mutextype; + pthread_mutexattr (); + ~pthread_mutexattr (); }; class pthread_mutex:public verifyable_object @@ -228,20 +268,8 @@ public: int TryLock (); int UnLock (); - pthread_mutex (pthread_mutexattr *); - ~pthread_mutex (); -}; - -class pthread_key:public verifyable_object -{ -public: - - DWORD dwTlsIndex; - int set (const void *); - void *get (); - - pthread_key (); - ~pthread_key (); + pthread_mutex (pthread_mutexattr *); + ~pthread_mutex (); }; class pthread_condattr:public verifyable_object @@ -249,8 +277,8 @@ class pthread_condattr:public verifyable_object public: int shared; - pthread_condattr (); - ~pthread_condattr (); + pthread_condattr (); + ~pthread_condattr (); }; class pthread_cond:public verifyable_object @@ -264,8 +292,15 @@ public: void BroadCast (); void Signal (); - pthread_cond (pthread_condattr *); - ~pthread_cond (); + pthread_cond (pthread_condattr *); + ~pthread_cond (); +}; + +class pthread_once +{ +public: + pthread_mutex_t mutex; + int state; }; /* shouldn't be here */ @@ -278,21 +313,10 @@ public: void Post (); int TryWait (); - semaphore (int, unsigned int); - ~semaphore (); + 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: @@ -301,94 +325,143 @@ public: DWORD thread_self_dwTlsIndex; /* we may get 0 for the Tls index.. grrr */ int indexallocated; + int concurrency; // Used for main thread data, and sigproc thread struct __reent_t reents; struct _winsup_t winsup_reent; pthread mainthread; + pthread_key_destructor_list destructors; + void Init (int); - MTinterface ():reent_index (0), indexallocated (0) - {} + 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, - 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(...); -*/ +int __pthread_create (pthread_t * thread, const pthread_attr_t * attr, + void *(*start_routine) (void *), void *arg); +int __pthread_once (pthread_once_t *, void (*)(void)); + +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 (const pthread_attr_t * attr, size_t * size); + +int __pthread_attr_getinheritsched (const pthread_attr_t *, int *); +int __pthread_attr_getschedparam (const pthread_attr_t *, + struct sched_param *); +int __pthread_attr_getschedpolicy (const pthread_attr_t *, int *); +int __pthread_attr_getscope (const pthread_attr_t *, int *); +int __pthread_attr_getstackaddr (const pthread_attr_t *, void **); +int __pthread_attr_setinheritsched (pthread_attr_t *, int); +int __pthread_attr_setschedparam (pthread_attr_t *, + const struct sched_param *); +int __pthread_attr_setschedpolicy (pthread_attr_t *, int); +int __pthread_attr_setscope (pthread_attr_t *, int); +int __pthread_attr_setstackaddr (pthread_attr_t *, void *); + + /* Thread Exit */ - void __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, 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); +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 *); +int __pthread_mutex_setprioceiling (pthread_mutex_t * mutex, + int prioceiling, int *old_ceiling); +int __pthread_mutex_getprioceiling (const pthread_mutex_t * mutex, + int *prioceiling); + + +int __pthread_mutexattr_destroy (pthread_mutexattr_t *); +int __pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *, int *); +int __pthread_mutexattr_getprotocol (const pthread_mutexattr_t *, int *); +int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *, int *); +int __pthread_mutexattr_gettype (const pthread_mutexattr_t *, int *); +int __pthread_mutexattr_init (pthread_mutexattr_t *); +int __pthread_mutexattr_setprioceiling (pthread_mutexattr_t *, int); +int __pthread_mutexattr_setprotocol (pthread_mutexattr_t *, int); +int __pthread_mutexattr_setpshared (pthread_mutexattr_t *, int); +int __pthread_mutexattr_settype (pthread_mutexattr_t *, int); + + +/* Scheduling */ +int __pthread_getconcurrency (void); +int __pthread_setconcurrency (int new_level); +int __pthread_getschedparam (pthread_t thread, int *policy, + struct sched_param *param); +int __pthread_setschedparam (pthread_t thread, int policy, + const struct sched_param *param); + +/* cancelability states */ +int __pthread_cancel (pthread_t thread); +int __pthread_setcancelstate (int state, int *oldstate); +int __pthread_setcanceltype (int type, int *oldtype); +void __pthread_testcancel (void); + /* 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); }; #endif // MT_SAFE |