]> sourceware.org Git - newlib-cygwin.git/commitdiff
* configure.in: Remove PTH_ALLOW.
authorRobert Collins <rbtcollins@hotmail.com>
Thu, 12 Apr 2001 04:04:53 +0000 (04:04 +0000)
committerRobert Collins <rbtcollins@hotmail.com>
Thu, 12 Apr 2001 04:04:53 +0000 (04:04 +0000)
* cygwin.din: Remove @PTH_ALLOW@ prefixes to pthread functions.
Add new pthread exports.
* pthread.cc: New wrapper functions for the above new exports.
* sched.cc (valid_sched_parameters): New function.
(sched_setparam): Use it.
(sched_set_thread_priority): New function. Used by pthread_sched*.
* thread.cc (pthread_key_destructor::InsertAfter): New function.
(pthread_key_destructor::UnlinkNext): New function.
(pthread_key_destructor::Next): New function.
(pthread_key_destructor_list::Insert): New function.
(pthread_key_destructor_list::Remove): New function.
(pthread_key_destructor_list::Pop): New function.
(pthread_key_destructor::pthread_key_destructor): New function.
(pthread_key_destructor_list::IterateNull): New function.
(MTinterface::Init): Initialise new member.
(pthread::pthread): Initialise new members.
(pthread::create): Copy new attributes. Set the new thread priority.
(pthread_attr::pthread_attr): Initialise new members.
(pthread_key::pthread_key): Setup destructor function.
(pthread_key::~pthread_key): Remove destructor function.
(pthread_mutexattr::pthread_mutexattr): New function.
(pthread_mutexattr::~pthread_mutexattr): New function.
(__pthread_once): New function.
(__pthread_cleanup): New function.
(__pthread_cancel): New function.
(__pthread_setcancelstate): New function.
(__pthread_setcanceltype): New function.
(__pthread_testcancel): New function.
(__pthread_attr_getinheritsched): New function.
(__pthread_attr_getschedparam): New function.
(__pthread_attr_getschedpolicy): New function.
(__pthread_attr_getscope): New function.
(__pthread_attr_setinheritsched): New function.
(__pthread_attr_setschedparam): New function.
(__pthread_attr_setschedpolicy): New function.
(__pthread_attr_setscope): New function.
(__pthread_exit): Call any key destructors on thread exit.
(__pthread_join): Use the embedded attr values.
(__pthread_detach): Use the embedded attr values.
(__pthread_getconcurrency): New function.
(__pthread_getschedparam): New function.
(__pthread_key_create): Pass the destructor on object creation.
(__pthread_key_delete): Correct incorrect prototype.
(__pthread_setconcurrency): New function.
(__pthread_setschedparam): New function.
(__pthread_cond_timedwait): Support static mutex initialisers.
(__pthread_cond_wait): Ditto.
(__pthread_mutex_getprioceiling): New function.
(__pthread_mutex_lock): Support static mutex initialisers.
(__pthread_mutex_trylock): Ditto.
(__pthread_mutex_unlock): Ditto.
(__pthread_mutex_destroy): Ditto.
(__pthread_mutex_setprioceiling): New function.
(__pthread_mutexattr_getprotocol): New function.
(__pthread_mutexattr_getpshared): New function.
(__pthread_mutexattr_gettype): New function.
(__pthread_mutexattr_init): New function.
(__pthread_mutexattr_destroy): New function.
(__pthread_mutexattr_setprotocol): New function.
(__pthread_mutexattr_setprioceiling): New function.
(__pthread_mutexattr_getprioceiling): New function.
(__pthread_mutexattr_setpshared): New function.
(__pthread_mutexattr_settype): New function.
Remove stubs for non MT_SAFE compilation.
* thread.h: Remove duplicate #defines.
Add prototypes for new functions in thread.cc.
(pthread_key_destructor): New class.
(pthread_key_destructor_list): New class.
(pthread_attr): Add new members.
(pthread): Remove members that are duplicated in the pthread_attr class.
(pthread_mutex_attr): Add new members.
(pthread_once): New class.
* include/pthread.h: Add prototypes for new functions exported from cygwin1.dll.
Remove typedefs.
* include/sched.h: Add prototypes for new functions in sched.cc.
* include/cygwin/types.h: Add typedefs from pthread.h

winsup/cygwin/configure.in
winsup/cygwin/cygwin.din
winsup/cygwin/include/cygwin/types.h
winsup/cygwin/include/pthread.h
winsup/cygwin/include/sched.h
winsup/cygwin/pthread.cc
winsup/cygwin/sched.cc
winsup/cygwin/thread.cc
winsup/cygwin/thread.h

index befd40655c1c473cf727a7489bc376a2ac92a253..81ba6d93122adaa859fc34f46e955c11defe82ac 100644 (file)
@@ -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],
index 453785f7ed1a069bd5c8d7ed708c36e344e7566b..a94af5e2c77d1bb3e21eb76f2bdf2654a34e29a4 100644 (file)
@@ -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
index 51e349710b9aeceb1d26d1e636dbe95750adc73c..7114b7c4a30d336a64e9f618bcab1a0611e132ae 100644 (file)
@@ -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
index d4b73de829e5e9c51ba2a952094362e2988ce3bd..6f8f9025aa2330c62d79a9d99c6f702bdf825d4f 100644 (file)
@@ -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 */
index 8b8e277e6edfc0a6300ce442e3ef05888dcf6103..f97b8ebf407d431106d5b473c88d19783d2ebb39 100644 (file)
@@ -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
 }
index 171fe6386eb1ac5edfb67043c54c6a86ede89da9..c9f0bb2bfca069fb84ea7cfefa49d4b20ef63796 100644 (file)
@@ -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);
 }
+
 }
index ef12b69b25d40c414fc95d18af3649a4976f37f9..f80803e28375bf543a87cce23d064659c3f3ee44 100644 (file)
@@ -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,
index 78ce8116ff3e4f3d525d443f34d081ebd9077e4d..e870c313149a4f4294cc5170a83a57efd1fa29dd 100644 (file)
@@ -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,
@@ -539,6 +668,273 @@ __pthread_create (pthread_t * thread, const pthread_attr_t * attr,
   return 0;
 }
 
+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)
 {
@@ -552,6 +948,49 @@ __pthread_attr_init (pthread_attr_t * attr)
   return 0;
 }
 
+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)
 {
@@ -572,6 +1011,57 @@ __pthread_attr_getdetachstate (const pthread_attr_t * attr, int *detachstate)
   return 0;
 }
 
+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)
 {
@@ -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)
@@ -966,9 +1525,30 @@ __pthread_mutex_init (pthread_mutex_t * mutex,
   return 0;
 }
 
+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
index deeef50f55032a5134eeafff832cd86458185ecf..00c10b29899472d9afacc4d4ae6af468e44f7ee2 100644 (file)
@@ -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
This page took 0.100347 seconds and 5 git commands to generate.