summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog69
-rw-r--r--attr.c354
-rw-r--r--buildlib.bat3
-rw-r--r--cleanup.c135
-rw-r--r--create.c7
-rw-r--r--dll.c4
-rw-r--r--fork.c6
-rw-r--r--implement.h101
-rw-r--r--misc.c1
-rw-r--r--private.c2
-rw-r--r--pthread.def4
-rw-r--r--pthread.h160
-rw-r--r--sched.c20
-rw-r--r--semaphore.c257
-rw-r--r--semaphore.h65
-rw-r--r--sync.c5
-rw-r--r--tsd.c4
17 files changed, 1039 insertions, 158 deletions
diff --git a/ChangeLog b/ChangeLog
index c28edd6..cf87143 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,72 @@
+Tue Dec 29 13:11:16 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+
+ * implement.h: Move the following struct definitions to pthread.h:
+ pthread_t_, pthread_attr_t_, pthread_mutex_t_, pthread_mutex_t_,
+ pthread_mutexattr_t_, pthread_key_t_, pthread_cond_t_,
+ pthread_condattr_t_, pthread_once_t_.
+
+ * pthread.h: Add "_" prefix to pthread_push_cleanup and
+ pthread_pop_cleanup internal routines, and associated struct and
+ typedefs.
+
+ * buildlib.bat: Add compile command for semaphore.c
+
+ * pthread.def: Comment out pthread_atfork routine name.
+ Now unimplemented.
+
+ * tsd.c (pthread_setspecific): Rename tkAssocCreate to
+ _pthread_tkAssocCreate.
+ (pthread_key_delete): Rename tkAssocDestroy to
+ _pthread_tkAssocDestroy.
+
+ * sync.c (pthread_join): Rename threadDestroy to _pthread_threadDestroy
+
+ * sched.c (is_attr): attr is now **attr (was *attr), so add extra
+ NULL pointer test.
+ (pthread_attr_setschedparam): Increase redirection for attr which is
+ now a **.
+ (pthread_attr_getschedparam): Ditto.
+ (pthread_setschedparam): Change thread validation and rename "thread"
+ Win32 thread Handle element name to match John Bossom's version.
+ (pthread_getschedparam): Ditto.
+
+ * private.c (_pthread_threadDestroy): Rename call to
+ callUserDestroyRoutines() as _pthread_callUserDestroyRoutines()
+
+ * misc.c: Add #include "implement.h".
+
+ * dll.c: Remove defined(KLUDGE) wrapped code.
+
+ * fork.c: Remove redefinition of ENOMEM.
+
+ * create.c (pthread_create): Rename threadStart and threadDestroy calls
+ to _pthread_threadStart and _pthread_threadDestroy.
+
+ * implement.h: Rename "detachedstate" to "detachstate".
+
+ * attr.c: Rename "detachedstate" to "detachstate".
+
+Mon Dec 28 09:54:39 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+
+ * pthread.h (pthread_attr_t_): Change to *pthread_attr_t.
+
+ * attr.c (pthread_attr_setstacksize): Merge with John Bossom's version.
+ (pthread_attr_getstacksize): Merge with John Bossom's version.
+ (pthread_attr_setstackaddr): Merge with John Bossom's version.
+ (pthread_attr_getstackaddr): Merge with John Bossom's version.
+ (pthread_attr_init): Merge with John Bossom's version.
+ (pthread_attr_destroy): Merge with John Bossom's version.
+ (pthread_attr_getdetachstate): Merge with John Bossom's version.
+ (pthread_attr_setdetachstate): Merge with John Bossom's version.
+ (is_attr): attr is now **attr (was *attr), so add extra NULL pointer
+ test.
+
+ * implement.h (pthread_attr_t_): Add and rename elements in JEB's
+ version to correspond to original, so that it can be used with
+ original attr routines.
+
+ * pthread.h: Add #endif at end which was truncated in merging.
+
Sun Dec 20 14:51:58 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
* misc.c (pthreadCancelableWait): New function by John Bossom. Non-standard
diff --git a/attr.c b/attr.c
index 418c3e8..33d897d 100644
--- a/attr.c
+++ b/attr.c
@@ -16,15 +16,57 @@ is_attr(const pthread_attr_t *attr)
{
/* Return 0 if the attr object is valid, non-zero otherwise. */
- return (attr == NULL || attr->valid != _PTHREAD_ATTR_VALID);
+ return (attr == NULL ||
+ *attr == NULL ||
+ (*attr)->valid != _PTHREAD_ATTR_VALID);
}
-#ifdef _POSIX_THREAD_ATTR_STACKSIZE
int
pthread_attr_setstacksize(pthread_attr_t *attr,
size_t stacksize)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function specifies the size of the stack on
+ * which threads created with 'attr' will run.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ * stacksize
+ * stack size, in bytes.
+ *
+ *
+ * DESCRIPTION
+ * This function specifies the size of the stack on
+ * which threads created with 'attr' will run.
+ *
+ * NOTES:
+ * 1) Function supported only if this macro is
+ * defined:
+ *
+ * _POSIX_THREAD_ATTR_STACKSIZE
+ *
+ * 2) Find the default first (using
+ * pthread_attr_getstacksize), then increase
+ * by multiplying.
+ *
+ * 3) Only use if thread needs more than the
+ * default.
+ *
+ * RESULTS
+ * 0 successfully set stack size,
+ * EINVAL 'attr' is invalid or stacksize too
+ * small or too big.
+ * ENOSYS function not supported
+ *
+ * ------------------------------------------------------
+ */
{
+#ifdef _POSIX_THREAD_ATTR_STACKSIZE
+
/* Verify that the stack size is within range. */
if (stacksize < PTHREAD_STACK_MIN)
{
@@ -37,89 +79,295 @@ pthread_attr_setstacksize(pthread_attr_t *attr,
}
/* Everything is okay. */
- attr->stacksize = stacksize;
+ (*attr)->stacksize = stacksize;
return 0;
+
+#else
+
+ return ENOSYS;
+
+#endif /* _POSIX_THREAD_ATTR_STACKSIZE */
+
}
int
pthread_attr_getstacksize(const pthread_attr_t *attr,
size_t *stacksize)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function determines the size of the stack on
+ * which threads created with 'attr' will run.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ * stacksize
+ * pointer to size_t into which is returned the
+ * stack size, in bytes.
+ *
+ *
+ * DESCRIPTION
+ * This function determines the size of the stack on
+ * which threads created with 'attr' will run.
+ *
+ * NOTES:
+ * 1) Function supported only if this macro is
+ * defined:
+ *
+ * _POSIX_THREAD_ATTR_STACKSIZE
+ *
+ * 2) Use on newly created attributes object to
+ * find the default stack size.
+ *
+ * RESULTS
+ * 0 successfully retrieved stack size,
+ * EINVAL 'attr' is invalid
+ * ENOSYS function not supported
+ *
+ * ------------------------------------------------------
+ */
{
+#ifdef _POSIX_THREAD_ATTR_STACKSIZE
+
if (is_attr(attr) != 0)
{
return EINVAL;
}
/* Everything is okay. */
- *stacksize = attr->stacksize;
+ *stacksize = (*attr)->stacksize;
return 0;
-}
+
+#else
+
+ return ENOSYS;
#endif /* _POSIX_THREAD_ATTR_STACKSIZE */
-#ifdef _POSIX_THREAD_ATTR_STACKADDR
+}
+
int
pthread_attr_setstackaddr(pthread_attr_t *attr,
void *stackaddr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Threads created with 'attr' will run on the stack
+ * starting at 'stackaddr'.
+ * Stack must be at least PTHREAD_STACK_MIN bytes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ * stacksize
+ * stack size, in bytes.
+ *
+ *
+ * DESCRIPTION
+ * Threads created with 'attr' will run on the stack
+ * starting at 'stackaddr'.
+ * Stack must be at least PTHREAD_STACK_MIN bytes.
+ *
+ * NOTES:
+ * 1) Function supported only if this macro is
+ * defined:
+ *
+ * _POSIX_THREAD_ATTR_STACKADDR
+ *
+ * 2) Create only one thread for each stack
+ * address..
+ *
+ * 3) Ensure that stackaddr is aligned.
+ *
+ * RESULTS
+ * 0 successfully set stack address,
+ * EINVAL 'attr' is invalid
+ * ENOSYS function not supported
+ *
+ * ------------------------------------------------------
+ */
{
+#if defined( _POSIX_THREAD_ATTR_STACKADDR )
+
if (is_attr(attr) != 0)
{
return EINVAL;
}
+
+ (*attr)->stackaddr = stackaddr;
+ return 0;
+
+#else
+
return ENOSYS;
+
+#endif /* _POSIX_THREAD_ATTR_STACKADDR */
}
int
pthread_attr_getstackaddr(const pthread_attr_t *attr,
void **stackaddr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function determines the address of the stack
+ * on which threads created with 'attr' will run.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ * stackaddr
+ * pointer into which is returned the stack address.
+ *
+ *
+ * DESCRIPTION
+ * This function determines the address of the stack
+ * on which threads created with 'attr' will run.
+ *
+ * NOTES:
+ * 1) Function supported only if this macro is
+ * defined:
+ *
+ * _POSIX_THREAD_ATTR_STACKADDR
+ *
+ * 2) Create only one thread for each stack
+ * address..
+ *
+ * RESULTS
+ * 0 successfully retreived stack address,
+ * EINVAL 'attr' is invalid
+ * ENOSYS function not supported
+ *
+ * ------------------------------------------------------
+ */
{
+#if defined( _POSIX_THREAD_ATTR_STACKADDR )
+
if (is_attr(attr) != 0)
{
return EINVAL;
}
+
+ *stackaddr = (*attr)->stackaddr;
+ return 0;
+
+#else
+
return ENOSYS;
-}
#endif /* _POSIX_THREAD_ATTR_STACKADDR */
+}
int
pthread_attr_init(pthread_attr_t *attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Initializes a thread attributes object with default
+ * attributes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ *
+ * DESCRIPTION
+ * Initializes a thread attributes object with default
+ * attributes.
+ *
+ * NOTES:
+ * 1) Used to define thread attributes
+ *
+ * RESULTS
+ * 0 successfully initialized attr,
+ * ENOMEM insufficient memory for attr.
+ *
+ * ------------------------------------------------------
+ */
{
+ pthread_attr_t attr_result;
+ int result = 0;
+
if (attr == NULL)
{
/* This is disallowed. */
return EINVAL;
}
+ attr_result = malloc (sizeof (*attr_result));
+
+ if (attr_result == NULL)
+ {
+ return ENOMEM;
+ }
+
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
- attr->stacksize = PTHREAD_STACK_MIN;
+ attr_result->stacksize = PTHREAD_STACK_MIN;
+#endif
+
+#ifdef _POSIX_THREAD_ATTR_STACKADDR
+ /* FIXME: Set this to something sensible when we support it. */
+ attr_result->stackaddr = NULL;
#endif
- attr->detachedstate = PTHREAD_CREATE_JOINABLE;
+ attr_result->detachstate = PTHREAD_CREATE_JOINABLE;
+
#if HAVE_SIGSET_T
- memset(&(attr->sigmask), 0, sizeof(sigset_t));
+ memset(&(attr_result->sigmask), 0, sizeof(sigset_t));
#endif /* HAVE_SIGSET_T */
/* Priority uses Win32 priority values. */
- attr->priority = THREAD_PRIORITY_NORMAL;
+ attr_result->priority = THREAD_PRIORITY_NORMAL;
- attr->valid = _PTHREAD_ATTR_VALID;
+ attr_result->valid = _PTHREAD_ATTR_VALID;
+
+ *attr = attr_result;
return 0;
}
int
pthread_attr_destroy(pthread_attr_t *attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Destroys a thread attributes object.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ *
+ * DESCRIPTION
+ * Destroys a thread attributes object.
+ *
+ * NOTES:
+ * 1) Does not affect threads created with 'attr'.
+ *
+ * RESULTS
+ * 0 successfully destroyed attr,
+ * EINVAL 'attr' is invalid.
+ *
+ * ------------------------------------------------------
+ */
{
if (is_attr(attr) != 0)
{
return EINVAL;
}
- /* Set the attribute object to a specific invalid value. */
- attr->valid = 0;
+ /*
+ * Set the attribute object to a specific invalid value.
+ */
+ (*attr)->valid = 0;
+ free (*attr);
+ *attr = NULL;
return 0;
}
@@ -127,19 +375,89 @@ pthread_attr_destroy(pthread_attr_t *attr)
int
pthread_attr_getdetachstate(const pthread_attr_t *attr,
int *detachstate)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function determines whether threads created with
+ * 'attr' will run detached.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ * detachstate
+ * pointer to an integer into which is returned one
+ * of:
+ *
+ * PTHREAD_CREATE_JOINABLE
+ * Thread ID is valid, must be joined
+ *
+ * PTHREAD_CREATE_DETACHED
+ * Thread ID is invalid, cannot be joined,
+ * canceled, or modified
+ *
+ *
+ * DESCRIPTION
+ * This function determines whether threads created with
+ * 'attr' will run detached.
+ *
+ * NOTES:
+ * 1) You cannot join or cancel detached threads.
+ *
+ * RESULTS
+ * 0 successfully retrieved detach state,
+ * EINVAL 'attr' is invalid
+ *
+ * ------------------------------------------------------
+ */
{
if (is_attr(attr) != 0 || detachstate == NULL)
{
+ *detachstate = PTHREAD_CREATE_DETACHED;
return EINVAL;
}
- *detachstate = attr->detachedstate;
+ *detachstate = (*attr)->detachstate;
return 0;
}
int
pthread_attr_setdetachstate(pthread_attr_t *attr,
int detachstate)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function specifies whether threads created with
+ * 'attr' will run detached.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ * detachstate
+ * an integer containing one of:
+ *
+ * PTHREAD_CREATE_JOINABLE
+ * Thread ID is valid, must be joined
+ *
+ * PTHREAD_CREATE_DETACHED
+ * Thread ID is invalid, cannot be joined,
+ * canceled, or modified
+ *
+ *
+ * DESCRIPTION
+ * This function specifies whether threads created with
+ * 'attr' will run detached.
+ *
+ * NOTES:
+ * 1) You cannot join or cancel detached threads.
+ *
+ * RESULTS
+ * 0 successfully set detach state,
+ * EINVAL 'attr' or 'detachstate' is invalid
+ *
+ * ------------------------------------------------------
+ */
{
if (is_attr(attr) != 0)
{
@@ -152,6 +470,10 @@ pthread_attr_setdetachstate(pthread_attr_t *attr,
return EINVAL;
}
- attr->detachedstate = detachstate;
+ (*attr)->detachstate = detachstate;
return 0;
}
+
+
+
+
diff --git a/buildlib.bat b/buildlib.bat
index e8a674e..5e2e1c8 100644
--- a/buildlib.bat
+++ b/buildlib.bat
@@ -16,5 +16,8 @@ cl /W3 /MT /nologo /Yd /Zi -I. -D_WIN32_WINNT=0x400 -DSTDCALL=_stdcall -c sched.
cl /W3 /MT /nologo /Yd /Zi -I. -D_WIN32_WINNT=0x400 -DSTDCALL=_stdcall -c signal.c
cl /W3 /MT /nologo /Yd /Zi -I. -D_WIN32_WINNT=0x400 -DSTDCALL=_stdcall -c sync.c
cl /W3 /MT /nologo /Yd /Zi -I. -D_WIN32_WINNT=0x400 -DSTDCALL=_stdcall -c tsd.c
+cl /W3 /MT /nologo /Yd /Zi -I. -D_WIN32_WINNT=0x400 -DSTDCALL=_stdcall -c semaphore.c
cl /LD /Zi *.obj /Fepthread.dll /link /nodefaultlib:libcmt /implib:pthread.lib msvcrt.lib /def:pthread.def
+
+
diff --git a/cleanup.c b/cleanup.c
index 0a5ae3f..b0817d7 100644
--- a/cleanup.c
+++ b/cleanup.c
@@ -12,6 +12,139 @@
#include "pthread.h"
#include "implement.h"
+/*
+ * Code contributed by John E. Bossom <JEB>.
+ */
+
+_pthread_cleanup_t *
+_pthread_pop_cleanup (int execute)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function pops the most recently pushed cleanup
+ * handler. If execute is nonzero, then the cleanup handler
+ * is executed if non-null.
+ *
+ * PARAMETERS
+ * execute
+ * if nonzero, execute the cleanup handler
+ *
+ *
+ * DESCRIPTION
+ * This function pops the most recently pushed cleanup
+ * handler. If execute is nonzero, then the cleanup handler
+ * is executed if non-null.
+ * NOTE: specify 'execute' as nonzero to avoid duplication
+ * of common cleanup code.
+ *
+ * RESULTS
+ * N/A
+ *
+ * ------------------------------------------------------
+ */
+{
+ _pthread_cleanup_t *cleanup;
+
+ cleanup = pthread_getspecific (_pthread_cleanupKey);
+
+ if (cleanup != NULL)
+ {
+ if (execute && (cleanup->routine != NULL))
+ {
+
+#ifdef _WIN32
+
+ __try
+ {
+ /*
+ * Run the caller's cleanup routine.
+ */
+ (*cleanup->routine) (cleanup->arg);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ /*
+ * A system unexpected exception had occurred
+ * running the user's cleanup routine.
+ * We get control back within this block.
+ */
+ }
+ }
+
+#else
+
+ /*
+ * Run the caller's cleanup routine.
+ */
+ (*cleanup->routine) (cleanup->arg);
+
+#endif /* _WIN32 */
+
+ pthread_setspecific (_pthread_cleanupKey, cleanup->prev);
+ }
+
+ return (cleanup);
+
+} /* _pthread_pop_cleanup */
+
+
+void
+_pthread_push_cleanup (_pthread_cleanup_t * cleanup,
+ void (*routine) (void *),
+ void *arg)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function pushes a new cleanup handler onto the thread's stack
+ * of cleanup handlers. Each cleanup handler pushed onto the stack is
+ * popped and invoked with the argument 'arg' when
+ * a) the thread exits by calling 'pthread_exit',
+ * b) when the thread acts on a cancellation request,
+ * c) or when the thrad calls pthread_cleanup_pop with a nonzero
+ * 'execute' argument
+ *
+ * PARAMETERS
+ * cleanup
+ * a pointer to an instance of pthread_cleanup_t,
+ *
+ * routine
+ * pointer to a cleanup handler,
+ *
+ * arg
+ * parameter to be passed to the cleanup handler
+ *
+ *
+ * DESCRIPTION
+ * This function pushes a new cleanup handler onto the thread's stack
+ * of cleanup handlers. Each cleanup handler pushed onto the stack is
+ * popped and invoked with the argument 'arg' when
+ * a) the thread exits by calling 'pthread_exit',
+ * b) when the thread acts on a cancellation request,
+ * c) or when the thrad calls pthread_cleanup_pop with a nonzero
+ * 'execute' argument
+ * NOTE: pthread_push_cleanup, pthread_pop_cleanup must be paired
+ * in the same lexical scope.
+ *
+ * RESULTS
+ * pthread_cleanup_t *
+ * pointer to the previous cleanup
+ *
+ * ------------------------------------------------------
+ */
+{
+ cleanup->routine = routine;
+ cleanup->arg = arg;
+ cleanup->prev = pthread_getspecific (_pthread_cleanupKey);
+
+ pthread_setspecific (_pthread_cleanupKey, (void *) cleanup);
+
+} /* _pthread_push_cleanup */
+
+/* </JEB> */
+
+
+#if 0 /* Pre Bossom */
+
int
_pthread_handler_push(int stack,
int poporder,
@@ -214,3 +347,5 @@ _pthread_destructor_run_all()
break;
}
}
+
+#endif /* Pre Bossom */
diff --git a/create.c b/create.c
index d5f097e..8f7142b 100644
--- a/create.c
+++ b/create.c
@@ -90,7 +90,6 @@ pthread_create (pthread_t * tid,
{
stackSize = (*attr)->stacksize;
thread->detachState = (*attr)->detachstate;
-
}
else
{
@@ -109,7 +108,7 @@ pthread_create (pthread_t * tid,
_beginthreadex (
(void *) NULL, /* No security info */
(unsigned) stackSize, /* default stack size */
- (unsigned (__stdcall *) (void *)) threadStart,
+ (unsigned (__stdcall *) (void *)) _pthread_threadStart,
parms,
(unsigned) run ? 0 : CREATE_SUSPENDED,
(unsigned *) &(thread->thread));
@@ -130,7 +129,7 @@ FAIL0:
if (result != 0)
{
- threadDestroy (thread);
+ _pthread_threadDestroy (thread);
thread = NULL;
if (parms != NULL)
@@ -235,7 +234,7 @@ pthread_create(pthread_t *thread,
attr_copy->stacksize = PTHREAD_STACK_MIN;
}
- attr_copy->detachedstate = attr->detachedstate;
+ attr_copy->detachstate = attr->detachstate;
attr_copy->priority = attr->priority;
#if HAVE_SIGSET_T
diff --git a/dll.c b/dll.c
index 940a0dd..c44d0df 100644
--- a/dll.c
+++ b/dll.c
@@ -69,10 +69,6 @@ DllMain (
if (_pthread_processInitialized)
{
-#if defined( KLUDGE )
- _pthread_cleanupStack ();
-#endif /* KLUDGE */
-
self = (pthread_t) pthread_getspecific (_pthread_selfThreadKey);
/*
diff --git a/fork.c b/fork.c
index 3a25c48..61da545 100644
--- a/fork.c
+++ b/fork.c
@@ -5,12 +5,12 @@
* Implementation of fork() for POSIX threads.
*/
-/* FIXME! */
-#define ENOMEM 0
#include "pthread.h"
#include "implement.h"
+#if 0 /* Pre Bossom */
+
int
pthread_atfork(void (*prepare)(void),
void (*parent)(void),
@@ -139,3 +139,5 @@ fork()
}
#endif /* HAVE_PID_T && HAVE_FORK */
+
+#endif /* Pre Bossom */
diff --git a/implement.h b/implement.h
index 523f475..c3be637 100644
--- a/implement.h
+++ b/implement.h
@@ -13,107 +13,6 @@
* Code contributed by John E. Bossom <JEB>.
*/
-typedef enum {
- /*
- * This enumeration represents the state of the thread;
- * The thread is still "alive" if the numeric value of the
- * state is greater or equal "PThreadStateRunning".
- */
- PThreadStateInitial = 0, /* Thread not running */
- PThreadStateRunning, /* Thread alive & kicking */
- PThreadStateSuspended, /* Thread alive but suspended */
- PThreadStateCanceling, /* Thread alive but and is */
- /* in the process of terminating */
- /* due to a cancellation request */
- PThreadStateException, /* Thread alive but exiting */
- /* due to an exception */
- PThreadStateLast
-}
-PThreadState;
-
-
-typedef enum {
- /*
- * This enumeration represents the reason why a thread has
- * terminated/is terminating.
- */
- PThreadDemisePeaceful = 0, /* Death due natural causes */
- PThreadDemiseCancelled, /* Death due to user cancel */
- PThreadDemiseException, /* Death due to unhandled */
- /* exception */
- PThreadDemiseNotDead /* I'm not dead! */
-}
-PThreadDemise;
-
-
-struct pthread_t_ {
- DWORD thread;
- HANDLE threadH;
- PThreadState state;
- PThreadDemise demise;
- void *exitStatus;
- void *parms;
- int detachState;
- int cancelState;
- int cancelType;
- HANDLE cancelEvent;
- int implicit:1;
- void *keys;
-};
-
-
-struct pthread_attr_t_ {
- void *stackaddr;
- size_t stacksize;
- int detachstate;
-};
-
-
-struct pthread_key_t_ {
- DWORD key;
- void (*destructor) (void *);
- pthread_mutex_t threadsLock;
- void *threads;
-};
-
-
-struct pthread_mutexattr_t_ {
- int pshared;
-};
-
-
-struct pthread_mutex_t_ {
- int valid;
- CRITICAL_SECTION cs;
- };
-
-
-struct pthread_cond_t_ {
- long waiters; /* # waiting threads */
- pthread_mutex_t waitersLock; /* Mutex that guards access to
- waiter count */
- sem_t sema; /* Queue up threads waiting for the
- condition to become signaled */
- HANDLE waitersDone; /* An auto reset event used by the
- broadcast/signal thread to wait
- for the waiting thread(s) to wake
- up and get a chance at the
- semaphore */
- int wasBroadcast; /* keeps track if we are signaling
- or broadcasting */
-};
-
-
-struct pthread_condattr_t_ {
- int pshared;
-};
-
-
-struct pthread_once_t_ {
- unsigned short flag;
- pthread_mutex_t lock;
-};
-
typedef struct ThreadParms ThreadParms;
typedef struct ThreadKeyAssoc ThreadKeyAssoc;
diff --git a/misc.c b/misc.c
index e244701..534f9f6 100644
--- a/misc.c
+++ b/misc.c
@@ -8,6 +8,7 @@
#include <errno.h>
#include "pthread.h"
+#include "implement.h"
int
pthread_once(pthread_once_t *once_control,
diff --git a/private.c b/private.c
index 9891660..d27e4bf 100644
--- a/private.c
+++ b/private.c
@@ -155,7 +155,7 @@ _pthread_threadDestroy (pthread_t thread)
if (thread != NULL)
{
- callUserDestroyRoutines (thread);
+ _pthread_callUserDestroyRoutines (thread);
if (thread->cancelEvent != NULL)
{
diff --git a/pthread.def b/pthread.def
index 63687f5..df689cc 100644
--- a/pthread.def
+++ b/pthread.def
@@ -1,12 +1,12 @@
; pthread.def
-; Last updated: $Date: 1998/10/04 23:01:59 $
+; Last updated: $Date: 1998/12/28 23:01:11 $
; Currently unimplemented functions are commented out.
LIBRARY pthread
EXPORTS
-pthread_atfork
+;pthread_atfork
pthread_attr_destroy
pthread_attr_getdetachstate
;pthread_attr_getinheritsched
diff --git a/pthread.h b/pthread.h
index 458ef6e..dfde977 100644
--- a/pthread.h
+++ b/pthread.h
@@ -234,7 +234,7 @@ struct timespec {
#include <semaphore.h>
-#include <sched.h>
+/* #include <sched.h> /**/
#ifdef __cplusplus
@@ -397,7 +397,7 @@ extern "C"
typedef struct pthread_t_ *pthread_t;
- typedef struct pthread_attr_t_ pthread_attr_t;
+ typedef struct pthread_attr_t_ *pthread_attr_t;
typedef struct pthread_once_t_ pthread_once_t;
typedef struct pthread_key_t_ *pthread_key_t;
typedef struct pthread_mutex_t_ pthread_mutex_t;
@@ -483,6 +483,126 @@ extern "C"
/*
* ====================
* ====================
+ * Opaque Structure Definitions
+ * ====================
+ * ====================
+ */
+
+typedef enum {
+ /*
+ * This enumeration represents the state of the thread;
+ * The thread is still "alive" if the numeric value of the
+ * state is greater or equal "PThreadStateRunning".
+ */
+ PThreadStateInitial = 0, /* Thread not running */
+ PThreadStateRunning, /* Thread alive & kicking */
+ PThreadStateSuspended, /* Thread alive but suspended */
+ PThreadStateCanceling, /* Thread alive but and is */
+ /* in the process of terminating */
+ /* due to a cancellation request */
+ PThreadStateException, /* Thread alive but exiting */
+ /* due to an exception */
+ PThreadStateLast
+}
+PThreadState;
+
+
+typedef enum {
+ /*
+ * This enumeration represents the reason why a thread has
+ * terminated/is terminating.
+ */
+ PThreadDemisePeaceful = 0, /* Death due natural causes */
+ PThreadDemiseCancelled, /* Death due to user cancel */
+ PThreadDemiseException, /* Death due to unhandled */
+ /* exception */
+ PThreadDemiseNotDead /* I'm not dead! */
+}
+PThreadDemise;
+
+
+struct pthread_t_ {
+ DWORD thread;
+ HANDLE threadH;
+ PThreadState state;
+ PThreadDemise demise;
+ void *exitStatus;
+ void *parms;
+ int detachState;
+ int cancelState;
+ int cancelType;
+ HANDLE cancelEvent;
+ int implicit:1;
+ void *keys;
+};
+
+
+/*
+ * Special value to mark attribute objects as valid.
+ */
+#define _PTHREAD_ATTR_VALID 0xC4C0FFEE
+
+struct pthread_attr_t_ {
+ long valid;
+ void *stackaddr;
+ size_t stacksize;
+ int detachstate;
+ int priority;
+#if HAVE_SIGSET_T
+ sigset_t sigmask;
+#endif /* HAVE_SIGSET_T */
+};
+
+
+struct pthread_mutex_t_ {
+ int valid;
+ CRITICAL_SECTION cs;
+ };
+
+
+struct pthread_mutexattr_t_ {
+ int pshared;
+};
+
+
+struct pthread_key_t_ {
+ DWORD key;
+ void (*destructor) (void *);
+ pthread_mutex_t threadsLock;
+ void *threads;
+};
+
+
+struct pthread_cond_t_ {
+ long waiters; /* # waiting threads */
+ pthread_mutex_t waitersLock; /* Mutex that guards access to
+ waiter count */
+ sem_t sema; /* Queue up threads waiting for the
+ condition to become signaled */
+ HANDLE waitersDone; /* An auto reset event used by the
+ broadcast/signal thread to wait
+ for the waiting thread(s) to wake
+ up and get a chance at the
+ semaphore */
+ int wasBroadcast; /* keeps track if we are signaling
+ or broadcasting */
+};
+
+
+struct pthread_condattr_t_ {
+ int pshared;
+};
+
+
+struct pthread_once_t_ {
+ unsigned short flag;
+ pthread_mutex_t lock;
+};
+
+
+/*
+ * ====================
+ * ====================
* Scheduling
* ====================
* ====================
@@ -510,28 +630,31 @@ extern "C"
* WIN32 SEH or C++
*/
-#ifndef __cplusplus
+ typedef struct _pthread_cleanup_t _pthread_cleanup_t;
-/*
- * C implementation of PThreads cancel cleanup
- */
- typedef struct pthread_cleanup_t pthread_cleanup_t;
-
- struct pthread_cleanup_t
+ struct _pthread_cleanup_t
{
void (*routine) (void *);
void *arg;
- pthread_cleanup_t *prev;
+#if !defined(__cplusplus)
+ _pthread_cleanup_t *prev;
+#endif
};
+#ifndef __cplusplus
+
+/*
+ * C implementation of PThreads cancel cleanup
+ */
+
#define pthread_cleanup_push( _rout, _arg ) \
{ \
- pthread_cleanup_t cleanup; \
+ _pthread_cleanup_t _cleanup; \
\
- pthread_push_cleanup( &cleanup, (_rout), (_arg) ); \
+ _pthread_push_cleanup( &_cleanup, (_rout), (_arg) ); \
#define pthread_cleanup_pop( _execute ) \
- (void) pthread_pop_cleanup( _execute ); \
+ (void) _pthread_pop_cleanup( _execute ); \
}
#else /* !__cplusplus */
@@ -543,7 +666,7 @@ extern "C"
#define pthread_cleanup_push( _rout, _arg ) \
{ \
- pthread_cleanup_t _cleanup; \
+ _pthread_cleanup_t _cleanup; \
\
_cleanup.routine = (_rout); \
_cleanup.arg = (_arg); \
@@ -571,7 +694,7 @@ extern "C"
#define pthread_cleanup_push( _rout, _arg ) \
{ \
- pthread_cleanup_t _cleanup; \
+ _pthread_cleanup_t _cleanup; \
\
_cleanup.routine = (_rout); \
_cleanup.arg = (_arg); \
@@ -652,11 +775,13 @@ pthread_t pthread_self (void);
int pthread_cancel (pthread_t thread);
-pthread_cleanup_t *pthread_pop_cleanup (int execute);
+#ifndef __cplusplus
+_pthread_cleanup_t *_pthread_pop_cleanup (int execute);
-void pthread_push_cleanup (pthread_cleanup_t * cleanup,
+void _pthread_push_cleanup (_pthread_cleanup_t * cleanup,
void (*routine) (void *),
void *arg);
+#endif /* !__cplusplus */
int pthread_setcancelstate (int state,
int *oldstate);
@@ -817,3 +942,4 @@ int pthreadCancelableWait (HANDLE waitHandle);
} /* End of extern "C" */
#endif /* __cplusplus */
+#endif /* PTHREAD_H */
diff --git a/sched.c b/sched.c
index e3c3ae7..4680b8f 100644
--- a/sched.c
+++ b/sched.c
@@ -15,7 +15,9 @@
static int
is_attr(const pthread_attr_t *attr)
{
- return (attr == NULL || attr->valid != _PTHREAD_ATTR_VALID) ? 1 : 0;
+ return (attr == NULL ||
+ *attr == NULL ||
+ (*attr)->valid != _PTHREAD_ATTR_VALID) ? 1 : 0;
}
int
@@ -27,11 +29,12 @@ pthread_attr_setschedparam(pthread_attr_t *attr,
return EINVAL;
}
- attr->priority = param->sched_priority;
+ (*attr)->priority = param->sched_priority;
return 0;
}
-int pthread_attr_getschedparam(const pthread_attr_t *attr,
+int
+pthread_attr_getschedparam(const pthread_attr_t *attr,
struct sched_param *param)
{
if (is_attr(attr) != 0 || param == NULL)
@@ -39,7 +42,7 @@ int pthread_attr_getschedparam(const pthread_attr_t *attr,
return EINVAL;
}
- param->sched_priority = attr->priority;
+ param->sched_priority = (*attr)->priority;
return 0;
}
@@ -47,7 +50,7 @@ int pthread_setschedparam(pthread_t thread, int policy,
const struct sched_param *param)
{
/* Validate the thread id. */
- if (_PTHREAD_VALID(thread) < 0)
+ if (thread == NULL || thread->threadH == 0)
{
return EINVAL;
}
@@ -72,7 +75,8 @@ int pthread_setschedparam(pthread_t thread, int policy,
}
/* This is practically guaranteed to return TRUE. */
- (void) SetThreadPriority(thread->win32handle, param->sched_priority);
+ (void) SetThreadPriority(thread->threadH, param->sched_priority);
+
return 0;
}
@@ -82,7 +86,7 @@ int pthread_getschedparam(pthread_t thread, int *policy,
int prio;
/* Validate the thread id. */
- if (_PTHREAD_VALID(thread) != 0)
+ if (thread == NULL || thread->threadH == 0)
{
return EINVAL;
}
@@ -97,7 +101,7 @@ int pthread_getschedparam(pthread_t thread, int *policy,
*policy = SCHED_OTHER;
/* Fill out the sched_param structure. */
- prio = GetThreadPriority(thread->win32handle);
+ prio = GetThreadPriority(thread->threadH);
if (prio == THREAD_PRIORITY_ERROR_RETURN)
{
return EINVAL;
diff --git a/semaphore.c b/semaphore.c
new file mode 100644
index 0000000..04e99f5
--- /dev/null
+++ b/semaphore.c
@@ -0,0 +1,257 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * $Header: /cvs/pthreads-win32/pthreads/semaphore.c,v 1.1.2.1 1998/12/28 23:01:14 rpj Exp $
+ *
+ * Module: semaphore.c
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * They are supposed to follow the older UNIX convention for
+ * reporting errors. That is, on failure they are supposed
+ * to return a value of -1 and store the appropriate error
+ * number into 'errno'.
+ * HOWEVER,errno cannot be modified in a multithreaded
+ * program on WIN32; therefore, the value is returned as
+ * the function value.
+ * It is recommended that you compare for zero (0) for success
+ * instead of -1 for failure when checking the status of
+ * these functions.
+ *
+ * Contents:
+ * Public Methods Author
+ * -------------- ------
+ * sem_init John E. Bossom Mar 1998
+ * sem_destroy John E. Bossom Mar 1998
+ * sem_trywait John E. Bossom Mar 1998
+ * sem_wait John E. Bossom Mar 1998
+ * sem_post John E. Bossom Mar 1998
+ *
+ * Private Methods
+ * ---------------
+ *
+ * -------------------------------------------------------------
+ */
+#include <pthread.h>
+#include <windows.h>
+#include <process.h>
+#include <errno.h>
+#include <string.h>
+
+#include "semaphore.h"
+
+
+
+int
+sem_init (sem_t * sem, int pshared, unsigned int value)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function initializes an unnamed semaphore. the
+ * initial value of the semaphore is 'value'
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * pshared
+ * if zero, this semaphore may only be shared between
+ * threads in the same process.
+ * if nonzero, the semaphore can be shared between
+ * processes
+ *
+ * value
+ * initial value of the semaphore counter
+ *
+ * DESCRIPTION
+ * This function initializes an unnamed semaphore. The
+ * initial value of the semaphore is set to 'value'.
+ *
+ * RESULTS
+ * 0 successfully created semaphore,
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSPC a required resource has been exhausted,
+ * ENOSYS semaphores are not supported,
+ * EPERM the process lacks appropriate privilege
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+
+ if (pshared != 0)
+ {
+ /*
+ * Creating a semaphore that can be shared between
+ * processes
+ */
+ result = EPERM;
+
+ }
+ else
+ {
+ /*
+ * NOTE: Taking advantage of the fact that
+ * sem_t is a simple structure with one entry;
+ * We don't have to allocate it...
+ */
+ *sem = CreateSemaphore (
+ 0,
+ value,
+ 0x7FFFFFF,
+ NULL);
+
+ if (*sem == 0)
+ {
+ result = ENOSPC;
+ }
+ }
+
+ return (result);
+
+} /* sem_init */
+
+
+int
+sem_destroy (sem_t * sem)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function destroys an unnamed semaphore.
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * DESCRIPTION
+ * This function destroys an unnamed semaphore.
+ *
+ * RESULTS
+ * 0 successfully destroyed semaphore,
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSYS semaphores are not supported,
+ * EBUSY threads (or processes) are currently
+ * blocked on 'sem'
+ *
+ * ------------------------------------------------------
+ */
+{
+ return ((sem == NULL)
+ ? EINVAL
+ : (CloseHandle (*sem)
+ ? 0
+ : EINVAL));
+
+} /* sem_destroy */
+
+
+int
+sem_trywait (sem_t * sem)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function tries to wait on a semaphore.
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * DESCRIPTION
+ * This function tries to wait on a semaphore. If the
+ * semaphore value is greater than zero, it decreases
+ * its value by one. If the semaphore value is zero, then
+ * this function returns immediately with the error EAGAIN
+ *
+ * RESULTS
+ * 0 successfully destroyed semaphore,
+ * EAGAIN the semaphore was already locked,
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSYS semaphores are not supported,
+ * EINTR the function was interrupted by a signal,
+ * EDEADLK a deadlock condition was detected.
+ *
+ * ------------------------------------------------------
+ */
+{
+ return ((sem == NULL)
+ ? EINVAL
+ : ((WaitForSingleObject (*sem, 0) == WAIT_TIMEOUT)
+ ? EAGAIN
+ : 0));
+
+} /* sem_trywait */
+
+
+int
+sem_wait (sem_t * sem)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function waits on a semaphore.
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * DESCRIPTION
+ * This function waits on a semaphore. If the
+ * semaphore value is greater than zero, it decreases
+ * its value by one. If the semaphore value is zero, then
+ * the calling thread (or process) is blocked until it can
+ * successfully decrease the value or until interrupted by
+ * a signal.
+ *
+ * RESULTS
+ * 0 successfully destroyed semaphore,
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSYS semaphores are not supported,
+ * EINTR the function was interrupted by a signal,
+ * EDEADLK a deadlock condition was detected.
+ *
+ * ------------------------------------------------------
+ */
+{
+
+ return ((sem == NULL)
+ ? EINVAL
+ : pthreadCancelableWait (*sem)
+ );
+
+} /* sem_wait */
+
+
+int
+sem_post (sem_t * sem)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function posts a wakeup to a semaphore.
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * DESCRIPTION
+ * This function posts a wakeup to a semaphore. If there
+ * are waiting threads (or processes), on is awakened;
+ * otherwise, the semaphore value is incremented by one.
+ *
+ * RESULTS
+ * 0 successfully destroyed semaphore,
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSYS semaphores are not supported,
+ *
+ * ------------------------------------------------------
+ */
+{
+ return ((sem == NULL)
+ ? EINVAL
+ : (ReleaseSemaphore (*sem, 1, 0)
+ ? 0
+ : EINVAL));
+
+} /* sem_post */
diff --git a/semaphore.h b/semaphore.h
new file mode 100644
index 0000000..7b9d352
--- /dev/null
+++ b/semaphore.h
@@ -0,0 +1,65 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * $Header: /cvs/pthreads-win32/pthreads/semaphore.h,v 1.1.2.1 1998/12/28 23:01:15 rpj Exp $
+ *
+ * Module: semaphore.h
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * They are supposed to follow the older UNIX convention for
+ * reporting errors. That is, on failure they are supposed
+ * to return a value of -1 and store the appropriate error
+ * number into 'errno'.
+ * HOWEVER,errno cannot be modified in a multithreaded
+ * program on WIN32; therefore, the value is returned as
+ * the function value.
+ * It is recommended that you compare for zero (0) for success
+ * instead of -1 for failure when checking the status of
+ * these functions.
+ *
+ * Disclaimer:
+ * This software is provided "as is".
+ *
+ * The author makes no warranty or representation, either
+ * express or implied, with respect to this software, its
+ * quality, performance, merchantability, or fitness for a
+ * particular purpose. In no event will the author be
+ * liable for direct, indirect, special, incidental, or
+ * consequential damages arising out of the use or inability
+ * to use the software.
+ *
+ * -------------------------------------------------------------
+ */
+#if !defined( SEMAPHORE_H )
+#define SEMAPHORE_H
+
+#include <process.h>
+#include <errno.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+typedef HANDLE sem_t;
+
+int sem_init (sem_t * sem, int pshared, unsigned int value);
+
+int sem_destroy (sem_t * sem);
+
+int sem_trywait (sem_t * sem);
+
+int sem_wait (sem_t * sem);
+
+int sem_post (sem_t * sem);
+
+#ifdef __cplusplus
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !SEMAPHORE_H */
diff --git a/sync.c b/sync.c
index 3d64df9..628e5bb 100644
--- a/sync.c
+++ b/sync.c
@@ -10,6 +10,9 @@
* Code contributed by John E. Bossom <JEB>.
*/
+#include "pthread.h"
+#include "implement.h"
+
int
pthread_detach (pthread_t tid)
/*
@@ -112,7 +115,7 @@ pthread_join (pthread_t thread, void **value_ptr)
}
else
{
- threadDestroy (thread);
+ _pthread_threadDestroy (thread);
}
}
diff --git a/tsd.c b/tsd.c
index 757ea9f..6ea2eb0 100644
--- a/tsd.c
+++ b/tsd.c
@@ -189,7 +189,7 @@ pthread_key_delete (pthread_key_t key)
pthread_mutex_unlock (&(assoc->lock));
- tkAssocDestroy (assoc);
+ _pthread_tkAssocDestroy (assoc);
assoc = next;
}
@@ -304,7 +304,7 @@ pthread_setspecific (pthread_key_t key, const void *value)
* create an association if not found
*/
result = (assoc == NULL)
- ? tkAssocCreate (&assoc, self, key)
+ ? _pthread_tkAssocCreate (&assoc, self, key)
: 0;
}
else