summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--condvar.c231
-rw-r--r--config.h13
-rw-r--r--config.h.in16
-rw-r--r--errno.c4
-rw-r--r--implement.h62
-rw-r--r--misc.c24
-rw-r--r--mutex.c60
-rw-r--r--private.c225
-rw-r--r--pthread.def212
-rw-r--r--pthread.h86
-rw-r--r--sched.h4
-rw-r--r--semaphore.c126
-rw-r--r--semaphore.h13
-rw-r--r--signal.c3
-rw-r--r--tsd.c5
15 files changed, 551 insertions, 533 deletions
diff --git a/condvar.c b/condvar.c
index 4b41a23..2413b02 100644
--- a/condvar.c
+++ b/condvar.c
@@ -65,15 +65,6 @@ _cond_check_need_init(pthread_cond_t *cond)
{
result = pthread_cond_init(cond, NULL);
}
- else if (*cond == NULL)
- {
- /*
- * The cv has been destroyed while we were waiting to
- * initialise it, so the operation that caused the
- * auto-initialisation should fail.
- */
- result = EINVAL;
- }
LeaveCriticalSection(&_pthread_cond_test_init_lock);
@@ -464,126 +455,27 @@ pthread_cond_destroy (pthread_cond_t * cond)
return EINVAL;
}
- if (*cond != (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT)
- {
- cv = *cond;
-
- if (pthread_mutex_lock(&(cv->waitersLock)) != 0)
- {
- return EINVAL;
- }
+ cv = *cond;
+ if (cv != (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT)
+ {
if (cv->waiters > 0)
{
- (void) pthread_mutex_unlock(&(cv->waitersLock));
return EBUSY;
}
(void) sem_destroy (&(cv->sema));
- (void) CloseHandle (cv->waitersDone);
- (void) pthread_mutex_unlock(&(cv->waitersLock));
(void) pthread_mutex_destroy (&(cv->waitersLock));
+ (void) CloseHandle (cv->waitersDone);
free(cv);
- *cond = NULL;
}
- else
- {
- /*
- * See notes in _cond_check_need_init() above also.
- */
- EnterCriticalSection(&_pthread_cond_test_init_lock);
- /*
- * Check again.
- */
- if (*cond == (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT)
- {
- /*
- * This is all we need to do to destroy a statically
- * initialised cond that has not yet been used (initialised).
- * If we get to here, another thread
- * waiting to initialise this cond will get an EINVAL.
- */
- *cond = NULL;
- }
- else
- {
- /*
- * The cv has been initialised while we were waiting
- * so assume it's in use.
- */
- result = EBUSY;
- }
-
- LeaveCriticalSection(&_pthread_cond_test_init_lock);
- }
+ *cond = NULL;
return (result);
}
-/*
- * Arguments for cond_wait_cleanup, since we can only pass a
- * single void * to it.
- */
-typedef struct {
- pthread_mutex_t * mutexPtr;
- pthread_cond_t cv;
- int * resultPtr;
-} cond_wait_cleanup_args_t;
-
-static void
-cond_wait_cleanup(void * args)
-{
- cond_wait_cleanup_args_t * cleanup_args = (cond_wait_cleanup_args_t *) args;
- pthread_mutex_t * mutexPtr = cleanup_args->mutexPtr;
- pthread_cond_t cv = cleanup_args->cv;
- int * resultPtr = cleanup_args->resultPtr;
- int lock_result;
- int lastWaiter;
-
- if ((lock_result = pthread_mutex_lock (&(cv->waitersLock))) == 0)
- {
- /*
- * The waiter is responsible for decrementing
- * its count, protected by an internal mutex.
- */
-
- cv->waiters--;
-
- lastWaiter = cv->wasBroadcast && (cv->waiters == 0);
-
- if (lastWaiter)
- {
- cv->wasBroadcast = FALSE;
- }
-
- lock_result = pthread_mutex_unlock (&(cv->waitersLock));
- }
-
- if ((*resultPtr == 0 || *resultPtr == ETIMEDOUT) && lock_result == 0)
- {
- if (lastWaiter)
- {
- /*
- * If we are the last waiter on this broadcast
- * let the thread doing the broadcast proceed
- */
- if (!SetEvent (cv->waitersDone))
- {
- *resultPtr = EINVAL;
- }
- }
- }
-
- /*
- * We must always regain the external mutex, even when
- * errors occur, because that's the guarantee that we give
- * to our callers
- */
- (void) pthread_mutex_lock (mutexPtr);
-}
-
static int
cond_timedwait (pthread_cond_t * cond,
pthread_mutex_t * mutex,
@@ -593,7 +485,6 @@ cond_timedwait (pthread_cond_t * cond,
int internal_result = 0;
int lastWaiter = FALSE;
pthread_cond_t cv;
- cond_wait_cleanup_args_t cleanup_args;
if (cond == NULL || *cond == NULL)
{
@@ -619,22 +510,10 @@ cond_timedwait (pthread_cond_t * cond,
cv = *cond;
/*
- * It's not OK to increment cond->waiters while the caller locked 'mutex',
- * there may be other threads just waking up (with 'mutex' unlocked)
- * and cv->... data is not protected.
+ * OK to increment cond->waiters because the caller locked 'mutex'
*/
- if (pthread_mutex_lock(&(cv->waitersLock)) != 0)
- {
- return EINVAL;
- }
-
cv->waiters++;
- if (pthread_mutex_unlock(&(cv->waitersLock)) != 0)
- {
- return EINVAL;
- }
-
/*
* We keep the lock held just long enough to increment the count of
* waiters by one (above).
@@ -642,41 +521,67 @@ cond_timedwait (pthread_cond_t * cond,
* call to sem_wait since that will deadlock other calls
* to pthread_cond_signal
*/
- cleanup_args.mutexPtr = mutex;
- cleanup_args.cv = cv;
- cleanup_args.resultPtr = &result;
-
- pthread_cleanup_push (cond_wait_cleanup, (void *) &cleanup_args);
-
if ((result = pthread_mutex_unlock (mutex)) == 0)
{
/*
* Wait to be awakened by
* pthread_cond_signal, or
* pthread_cond_broadcast
- * timeout
*
* Note:
- * _pthread_sem_timedwait is a cancelation point,
+ * _pthread_sem_timedwait is a cancellation point,
* hence providing the
- * mechanism for making pthread_cond_wait a cancelation
+ * mechanism for making pthread_cond_wait a cancellation
* point. We use the cleanup mechanism to ensure we
- * re-lock the mutex and decrement the waiters count
- * if we are canceled.
+ * re-lock the mutex if we are cancelled.
*/
+ pthread_cleanup_push (pthread_mutex_lock, mutex);
+
if (_pthread_sem_timedwait (&(cv->sema), abstime) == -1)
{
result = errno;
}
+
+ pthread_cleanup_pop (0);
}
- pthread_cleanup_pop (1);
+ if ((internal_result = pthread_mutex_lock (&(cv->waitersLock))) == 0)
+ {
+ /*
+ * By making the waiter responsible for decrementing
+ * its count we don't have to worry about having an internal
+ * mutex.
+ */
+ cv->waiters--;
+
+ lastWaiter = cv->wasBroadcast && (cv->waiters == 0);
+
+ internal_result = pthread_mutex_unlock (&(cv->waitersLock));
+ }
+
+ if (result == 0 && internal_result == 0)
+ {
+ if (lastWaiter)
+ {
+ /*
+ * If we are the last waiter on this broadcast
+ * let the thread doing the broadcast proceed
+ */
+ if (!SetEvent (cv->waitersDone))
+ {
+ result = EINVAL;
+ }
+ }
+ }
/*
- * "result" can be modified by the cleanup handler.
- * Specifically, if we are the last waiting thread and failed
- * to notify the broadcast thread to proceed.
+ * We must always regain the external mutex, even when
+ * errors occur because that's the guarantee that we give
+ * to our callers
*/
+ (void) pthread_mutex_lock (mutex);
+
+
return (result);
} /* cond_timedwait */
@@ -855,7 +760,6 @@ pthread_cond_signal (pthread_cond_t * cond)
/*
* No-op if the CV is static and hasn't been initialised yet.
- * Assuming that race conditions are harmless.
*/
if (cv == (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT)
{
@@ -864,7 +768,6 @@ pthread_cond_signal (pthread_cond_t * cond)
/*
* If there aren't any waiters, then this is a no-op.
- * Assuming that race conditions are harmless.
*/
if (cv->waiters > 0)
{
@@ -914,7 +817,6 @@ pthread_cond_broadcast (pthread_cond_t * cond)
*/
{
int result = 0;
- int wereWaiters = FALSE;
pthread_cond_t cv;
if (cond == NULL || *cond == NULL)
@@ -926,41 +828,40 @@ pthread_cond_broadcast (pthread_cond_t * cond)
/*
* No-op if the CV is static and hasn't been initialised yet.
- * Assuming that any race condition is harmless.
*/
if (cv == (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT)
{
return 0;
}
- if (pthread_mutex_lock(&(cv->waitersLock)) == EINVAL)
- {
- return EINVAL;
- }
-
cv->wasBroadcast = TRUE;
- wereWaiters = (cv->waiters > 0);
- if (wereWaiters)
- {
- /*
- * Wake up all waiters
- */
- result = (ReleaseSemaphore( cv->sema, cv->waiters, NULL )
- ? 0
- : EINVAL );
- }
+ /*
+ * Wake up all waiters
+ */
+
+#ifdef NEED_SEM
+
+ result = (_pthread_increase_semaphore( &cv->sema, cv->waiters )
+ ? 0
+ : EINVAL);
+
+#else /* NEED_SEM */
+
+ result = (ReleaseSemaphore( cv->sema, cv->waiters, NULL )
+ ? 0
+ : EINVAL);
- (void) pthread_mutex_unlock(&(cv->waitersLock));
+#endif /* NEED_SEM */
- if (wereWaiters && result == 0)
+ if (cv->waiters > 0 && result == 0)
{
/*
* Wait for all the awakened threads to acquire their part of
* the counting semaphore
*/
- if (WaitForSingleObject (cv->waitersDone, INFINITE)
- == WAIT_OBJECT_0)
+ if (WaitForSingleObject (cv->waitersDone, INFINITE) ==
+ WAIT_OBJECT_0)
{
result = 0;
}
diff --git a/config.h b/config.h
index 920b9c4..82805c1 100644
--- a/config.h
+++ b/config.h
@@ -9,5 +9,14 @@
/* Define if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
-/* Define if you have the <windows.h> header file. */
-#undef HAVE_WINDOWS_H
+/* Define if you don't have errno. (eg. WinCE) */
+#undef NEED_ERRNO
+
+/* Define if you don't have calloc. (eg. WinCE) */
+#undef NEED_CALLOC
+
+/* Define if you don't have ftime. (eg. WinCE) */
+#undef NEED_FTIME
+
+/* Define if you don't have semaphores. (eg. WinCE) */
+#undef NEED_SEM
diff --git a/config.h.in b/config.h.in
index 6671c7f..82805c1 100644
--- a/config.h.in
+++ b/config.h.in
@@ -3,8 +3,20 @@
/* Do we know about the C type sigset_t? */
#undef HAVE_SIGSET_T
+/* Do we have the `_stdcall' keyword? */
+#undef STDCALL
+
/* Define if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
-/* Define if you have the <windows.h> header file. */
-#undef HAVE_WINDOWS_H
+/* Define if you don't have errno. (eg. WinCE) */
+#undef NEED_ERRNO
+
+/* Define if you don't have calloc. (eg. WinCE) */
+#undef NEED_CALLOC
+
+/* Define if you don't have ftime. (eg. WinCE) */
+#undef NEED_FTIME
+
+/* Define if you don't have semaphores. (eg. WinCE) */
+#undef NEED_SEM
diff --git a/errno.c b/errno.c
index c457dd7..77c747a 100644
--- a/errno.c
+++ b/errno.c
@@ -24,7 +24,7 @@
* MA 02111-1307, USA
*/
-#if ! defined( _REENTRANT ) && ! defined( _MT )
+#if (! defined(HAVE_ERRNO)) || (! defined( _REENTRANT ) && ! defined( _MT ))
#include "pthread.h"
#include "implement.h"
@@ -79,4 +79,4 @@ int * _errno( void )
} /* _errno */
-#endif /* !_REENTRANT && !_MT */
+#endif /* (! HAVE_ERRNO) || (!_REENTRANT && !_MT) */
diff --git a/implement.h b/implement.h
index 70836dc..71ebf05 100644
--- a/implement.h
+++ b/implement.h
@@ -27,9 +27,8 @@
#ifndef _IMPLEMENT_H
#define _IMPLEMENT_H
-#define PT_STDCALL __stdcall
-
-#include <semaphore.h>
+/* changed include from <semaphore.h> to use local file during development */
+#include "semaphore.h"
typedef enum {
/*
@@ -161,22 +160,6 @@ struct pthread_condattr_t_ {
int pshared;
};
-#define RW_MAGIC 0x19283746
-
-struct pthread_rwlock_t_ {
- pthread_mutex_t rw_lock; /* basic lock on this struct */
- pthread_cond_t rw_condreaders; /* for reader threads waiting */
- pthread_cond_t rw_condwriters; /* for writer threads waiting */
- int rw_magic; /* for error checking */
- int rw_nwaitreaders; /* the number waiting */
- int rw_nwaitwriters; /* the number waiting */
- int rw_refcount; /* -1 if writer has the lock,
- else # readers holding the lock */
-};
-
-struct pthread_rwlockattr_t_ {
- int pshared;
-};
struct ThreadKeyAssoc {
/*
@@ -274,27 +257,18 @@ struct ThreadKeyAssoc {
*/
#define EXCEPTION_PTHREAD_SERVICES \
MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \
- _PTHREAD_SERVICES_FACILITY, \
- _PTHREAD_SERVICES_ERROR )
+ PTHREAD_SERVICES_FACILITY, \
+ PTHREAD_SERVICES_ERROR )
-#define _PTHREAD_SERVICES_FACILITY 0xBAD
-#define _PTHREAD_SERVICES_ERROR 0xDEED
-/*
- * Services available through EXCEPTION_PTHREAD_SERVICES
- */
-#define _PTHREAD_EPS_CANCEL 0
-#define _PTHREAD_EPS_EXIT 1
+#define PTHREAD_SERVICES_FACILITY 0xBAD
+#define PTHREAD_SERVICES_ERROR 0xDEED
#else
#ifdef __cplusplus
-/*
- * Exceptions similar to the SEH exceptions above.
- */
-class Pthread_exception_cancel {};
-class Pthread_exception_exit {};
+class Pthread_exception {};
#else /* __cplusplus */
@@ -313,7 +287,12 @@ extern pthread_key_t _pthread_selfThreadKey;
extern pthread_key_t _pthread_cleanupKey;
extern CRITICAL_SECTION _pthread_mutex_test_init_lock;
extern CRITICAL_SECTION _pthread_cond_test_init_lock;
-extern CRITICAL_SECTION _pthread_rwlock_test_init_lock;
+
+/* Declared in misc.c */
+#ifdef NEED_CALLOC
+#define calloc(n, s) _pthread_calloc(n, s)
+void *_pthread_calloc(size_t n, size_t s);
+#endif
#ifdef __cplusplus
@@ -335,12 +314,7 @@ void _pthread_threadDestroy (pthread_t tid);
void _pthread_cleanupStack (void);
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
-unsigned PT_STDCALL
-#else
-void
-#endif
-_pthread_threadStart (ThreadParms * threadParms);
+void *_pthread_threadStart (ThreadParms * threadParms);
void _pthread_callUserDestroyRoutines (pthread_t thread);
@@ -353,6 +327,12 @@ void _pthread_tkAssocDestroy (ThreadKeyAssoc * assoc);
int _pthread_sem_timedwait (sem_t * sem,
const struct timespec * abstime);
+#ifdef NEED_SEM
+void _pthread_decrease_semaphore(sem_t * sem);
+BOOL _pthread_increase_semaphore(sem_t * sem,
+ unsigned int n);
+#endif /* NEED_SEM */
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
@@ -365,7 +345,7 @@ int _pthread_sem_timedwait (sem_t * sem,
*
* Patch by Anders Norlander <anorland@hem2.passagen.se>
*/
-#if defined(__CYGWIN32__) || defined(__CYGWIN__)
+#if defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(_PTHREAD_CREATETHREAD)
/*
* Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE
diff --git a/misc.c b/misc.c
index 208541a..cd9caa1 100644
--- a/misc.c
+++ b/misc.c
@@ -163,6 +163,10 @@ pthread_self (void)
self->thread = GetCurrentThreadId ();
+#ifdef UNDER_CE
+ /* DuplicateHandle does not exist on WinCE */
+ self->threadH = GetCurrentThread();
+#else
if( !DuplicateHandle(
GetCurrentProcess(),
GetCurrentThread(),
@@ -175,6 +179,7 @@ pthread_self (void)
free( self );
return (NULL);
}
+#endif
}
pthread_setspecific (_pthread_selfThreadKey, self);
@@ -314,7 +319,7 @@ CancelableWait (HANDLE waitHandle, DWORD timeout)
DWORD exceptionInformation[3];
- exceptionInformation[0] = (DWORD) (_PTHREAD_EPS_CANCEL);
+ exceptionInformation[0] = (DWORD) (0);
exceptionInformation[1] = (DWORD) (0);
exceptionInformation[2] = (DWORD) (0);
@@ -328,7 +333,7 @@ CancelableWait (HANDLE waitHandle, DWORD timeout)
#ifdef __cplusplus
- throw Pthread_exception_cancel();
+ throw Pthread_exception();
#endif /* __cplusplus */
@@ -361,4 +366,17 @@ pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout)
return (CancelableWait(waitHandle, timeout));
}
-
+#ifdef NEED_CALLOC
+void
+*_pthread_calloc(size_t n, size_t s) {
+ unsigned int m = n*s;
+ void *p;
+
+ p = malloc(m);
+ if (p == NULL) return NULL;
+
+ memset(p, 0, m);
+
+ return p;
+}
+#endif
diff --git a/mutex.c b/mutex.c
index 16e911c..830c0f1 100644
--- a/mutex.c
+++ b/mutex.c
@@ -22,8 +22,9 @@
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA
*/
-
-#include <errno.h>
+
+/* errno.h or a replacement file is included by pthread.h */
+//#include <errno.h>
#include "pthread.h"
#include "implement.h"
@@ -69,15 +70,6 @@ _mutex_check_need_init(pthread_mutex_t *mutex)
{
result = pthread_mutex_init(mutex, NULL);
}
- else if (*mutex == NULL)
- {
- /*
- * The mutex has been destroyed while we were waiting to
- * initialise it, so the operation that caused the
- * auto-initialisation should fail.
- */
- result = EINVAL;
- }
LeaveCriticalSection(&_pthread_mutex_test_init_lock);
@@ -186,13 +178,13 @@ pthread_mutex_destroy(pthread_mutex_t *mutex)
return EINVAL;
}
+ mx = *mutex;
+
/*
* Check to see if we have something to delete.
*/
- if (*mutex != (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT)
+ if (mx != (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT)
{
- mx = *mutex;
-
if (mx->mutex == 0)
{
DeleteCriticalSection(&mx->cs);
@@ -201,44 +193,12 @@ pthread_mutex_destroy(pthread_mutex_t *mutex)
{
result = (CloseHandle (mx->mutex) ? 0 : EINVAL);
}
-
- if (result == 0)
- {
- mx->mutex = 0;
- free(mx);
- *mutex = NULL;
- }
}
- else
- {
- /*
- * See notes in _mutex_check_need_init() above also.
- */
- EnterCriticalSection(&_pthread_mutex_test_init_lock);
- /*
- * Check again.
- */
- if (*mutex == (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT)
- {
- /*
- * This is all we need to do to destroy a statically
- * initialised mutex that has not yet been used (initialised).
- * If we get to here, another thread
- * waiting to initialise this mutex will get an EINVAL.
- */
- *mutex = NULL;
- }
- else
- {
- /*
- * The mutex has been initialised while we were waiting
- * so assume it's in use.
- */
- result = EBUSY;
- }
-
- LeaveCriticalSection(&_pthread_mutex_test_init_lock);
+ if (result == 0)
+ {
+ mx->mutex = 0;
+ *mutex = NULL;
}
return(result);
diff --git a/private.c b/private.c
index cd01fe5..5ff2cff 100644
--- a/private.c
+++ b/private.c
@@ -30,7 +30,7 @@
#endif /* !_MSC_VER && !__cplusplus && __GNUC__ */
-#include <sys/timeb.h>
+//#include <sys/timeb.h>
#include "pthread.h"
#include "semaphore.h"
#include "implement.h"
@@ -60,6 +60,17 @@ _pthread_processInitialize (void)
* ------------------------------------------------------
*/
{
+ if (_pthread_processInitialized) {
+ /*
+ * ignore if already initialized. this is useful for
+ * programs that uses a non-dll pthread
+ * library. such programs must call _pthread_processInitialize() explicitely,
+ * since this initialization routine is automatically called only when
+ * the dll is loaded.
+ */
+ return TRUE;
+ }
+
_pthread_processInitialized = TRUE;
/*
@@ -77,7 +88,6 @@ _pthread_processInitialize (void)
*/
InitializeCriticalSection(&_pthread_mutex_test_init_lock);
InitializeCriticalSection(&_pthread_cond_test_init_lock);
- InitializeCriticalSection(&_pthread_rwlock_test_init_lock);
return (_pthread_processInitialized);
@@ -132,66 +142,30 @@ _pthread_processTerminate (void)
/*
* Destroy the global test and init check locks.
*/
- DeleteCriticalSection(&_pthread_rwlock_test_init_lock);
- DeleteCriticalSection(&_pthread_cond_test_init_lock);
DeleteCriticalSection(&_pthread_mutex_test_init_lock);
+ DeleteCriticalSection(&_pthread_cond_test_init_lock);
_pthread_processInitialized = FALSE;
}
} /* processTerminate */
-#ifdef _MSC_VER
-
-static DWORD
-ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
-{
- DWORD param;
- DWORD numParams = ep->ExceptionRecord->NumberParameters;
-
- numParams = (numParams > 3) ? 3 : numParams;
-
- for (param = 0; param < numParams; param++)
- {
- ei[param] = ep->ExceptionRecord->ExceptionInformation[param];
- }
-
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-#endif /* _MSC_VER */
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
-unsigned PT_STDCALL
-#else
-void
-#endif
+void *
_pthread_threadStart (ThreadParms * threadParms)
{
- pthread_t self;
+ pthread_t tid;
void *(*start) (void *);
void *arg;
-#ifdef _MSC_VER
-
- DWORD ei[3];
-
-#endif
-
void * status;
- self = threadParms->tid;
+ tid = threadParms->tid;
start = threadParms->start;
arg = threadParms->arg;
-#if defined (__MINGW32__) && ! defined (__MSVCRT__)
- /* beginthread does not return the thread id, and so we do it here. */
- self->thread = GetCurrentThreadId ();
-#endif
-
free (threadParms);
- pthread_setspecific (_pthread_selfThreadKey, self);
+ pthread_setspecific (_pthread_selfThreadKey, tid);
#ifdef _MSC_VER
@@ -200,34 +174,16 @@ _pthread_threadStart (ThreadParms * threadParms)
/*
* Run the caller's routine;
*/
- status = (*start) (arg);
+ (*start) (arg);
+ status = (void *) 0;
}
- __except (ExceptionFilter(GetExceptionInformation(), ei))
+ __except (EXCEPTION_EXECUTE_HANDLER)
{
- DWORD ec = GetExceptionCode();
-
- if (ec == EXCEPTION_PTHREAD_SERVICES)
- {
- switch (ei[0])
- {
- case _PTHREAD_EPS_CANCEL:
- status = PTHREAD_CANCELED;
- break;
- case _PTHREAD_EPS_EXIT:
- status = (void *) ei[1];
- break;
- default:
- status = PTHREAD_CANCELED;
- }
- }
- else
- {
- /*
- * A system unexpected exception had occurred running the user's
- * routine. We get control back within this block.
- */
- status = PTHREAD_CANCELED;
- }
+ /*
+ * A system unexpected exception had occurred running the user's
+ * routine. We get control back within this block.
+ */
+ status = PTHREAD_CANCELED;
}
#else /* _MSC_VER */
@@ -239,22 +195,16 @@ _pthread_threadStart (ThreadParms * threadParms)
/*
* Run the caller's routine;
*/
- status = self->exitStatus = (*start) (arg);
+ (*start) (arg);
+ status = (void *) 0;
}
- catch (Pthread_exception_cancel)
+ catch (Pthread_exception)
{
/*
* Thread was cancelled.
*/
status = PTHREAD_CANCELED;
}
- catch (Pthread_exception_exit)
- {
- /*
- * Thread was exited via pthread_exit().
- */
- status = self->exitStatus;
- }
catch (...)
{
/*
@@ -270,27 +220,19 @@ _pthread_threadStart (ThreadParms * threadParms)
* Run the caller's routine; no cancelation or other exceptions will
* be honoured.
*/
- status = (*start) (arg);
+ (*start) (arg);
+ status = (void *) 0;
#endif /* __cplusplus */
-#endif /* _MSC_VER */
+#endif /* _WIN32 */
- _pthread_callUserDestroyRoutines(self);
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
- _endthreadex ((unsigned) status);
-#else
- _endthread ();
-#endif
+ pthread_exit (status);
/*
* Never reached.
*/
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
- return (unsigned) status;
-#endif
+ return (status);
} /* _pthread_threadStart */
@@ -306,13 +248,10 @@ _pthread_threadDestroy (pthread_t thread)
CloseHandle (thread->cancelEvent);
}
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
- /* See documentation for endthread vs endthreadex. */
if( thread->threadH != 0 )
{
CloseHandle( thread->threadH );
}
-#endif
free (thread);
}
@@ -586,6 +525,46 @@ _pthread_callUserDestroyRoutines (pthread_t thread)
} /* _pthread_callUserDestroyRoutines */
+
+#ifdef NEED_FTIME
+
+/*
+ * time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds
+ */
+#define TIMESPEC_TO_FILETIME_OFFSET \
+ ( ((LONGLONG) 27111902 << 32) + (LONGLONG) 3577643008 )
+
+static void
+timespec_to_filetime(const struct timespec *ts, FILETIME *ft)
+ /*
+ * -------------------------------------------------------------------
+ * converts struct timespec
+ * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
+ * into FILETIME (as set by GetSystemTimeAsFileTime), where the time is
+ * expressed in 100 nanoseconds from Jan 1, 1601,
+ * -------------------------------------------------------------------
+ */
+{
+ *(LONGLONG *)ft = ts->tv_sec * 10000000 + (ts->tv_nsec + 50) / 100 + TIMESPEC_TO_FILETIME_OFFSET;
+}
+
+static void
+filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
+ /*
+ * -------------------------------------------------------------------
+ * converts FILETIME (as set by GetSystemTimeAsFileTime), where the time is
+ * expressed in 100 nanoseconds from Jan 1, 1601,
+ * into struct timespec
+ * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
+ * -------------------------------------------------------------------
+ */
+{
+ ts->tv_sec = (int)((*(LONGLONG *)ft - TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
+ ts->tv_nsec = (int)((*(LONGLONG *)ft - TIMESPEC_TO_FILETIME_OFFSET - ((LONGLONG)ts->tv_sec * (LONGLONG)10000000)) * 100);
+}
+
+#endif /* NEED_FTIME */
+
int
_pthread_sem_timedwait (sem_t * sem, const struct timespec * abstime)
/*
@@ -628,15 +607,21 @@ _pthread_sem_timedwait (sem_t * sem, const struct timespec * abstime)
{
int result = 0;
+#ifdef NEED_FTIME
+
+ struct timespec currSysTime;
+
+#else /* NEED_FTIME */
#if defined(__MINGW32__)
struct timeb currSysTime;
-#else
+#else /* __MINGW32__ */
struct _timeb currSysTime;
-#endif
+#endif /* __MINGW32__ */
+#endif /* NEED_FTIME */
const DWORD NANOSEC_PER_MILLISEC = 1000000;
const DWORD MILLISEC_PER_SEC = 1000;
@@ -659,18 +644,56 @@ _pthread_sem_timedwait (sem_t * sem, const struct timespec * abstime)
*/
/* get current system time */
+
+#ifdef NEED_FTIME
+
+ {
+ FILETIME ft;
+ SYSTEMTIME st;
+
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &ft);
+ /*
+ * GetSystemTimeAsFileTime(&ft); would be faster,
+ * but it does not exist on WinCE
+ */
+
+ filetime_to_timespec(&ft, &currSysTime);
+ }
+
+ /*
+ * subtract current system time from abstime
+ */
+ milliseconds = (abstime->tv_sec - currSysTime.tv_sec) * MILLISEC_PER_SEC;
+ milliseconds += ((abstime->tv_nsec - currSysTime.tv_nsec) + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;
+
+#else /* NEED_FTIME */
_ftime(&currSysTime);
- /* subtract current system time from abstime */
+ /*
+ * subtract current system time from abstime
+ */
milliseconds = (abstime->tv_sec - currSysTime.time) * MILLISEC_PER_SEC;
- milliseconds += (abstime->tv_nsec / NANOSEC_PER_MILLISEC) -
+ milliseconds += ((abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC) -
currSysTime.millitm;
+#endif /* NEED_FTIME */
+
+
if (((int) milliseconds) < 0)
milliseconds = 0;
}
+#ifdef NEED_SEM
+
+ result = (pthreadCancelableTimedWait (sem->event, milliseconds));
+
+#else /* NEED_SEM */
+
result = (pthreadCancelableTimedWait (*sem, milliseconds));
+
+#endif
+
}
if (result != 0)
@@ -681,6 +704,12 @@ _pthread_sem_timedwait (sem_t * sem, const struct timespec * abstime)
}
+#ifdef NEED_SEM
+
+ _pthread_decrease_semaphore(sem);
+
+#endif /* NEED_SEM */
+
return 0;
} /* _pthread_sem_timedwait */
diff --git a/pthread.def b/pthread.def
index 6920d5a..3581dbe 100644
--- a/pthread.def
+++ b/pthread.def
@@ -1,110 +1,102 @@
-; pthread.def
-; Last updated: $Date: 1999/09/15 00:56:22 $
-
-; Currently unimplemented functions are commented out.
-
-LIBRARY pthread
-
-EXPORTS
-;pthread_atfork
-pthread_attr_destroy
-pthread_attr_getdetachstate
-;pthread_attr_getinheritsched
-pthread_attr_getschedparam
-;pthread_attr_getschedpolicy
-;pthread_attr_getscope
-pthread_attr_getstackaddr
-pthread_attr_getstacksize
-pthread_attr_init
-pthread_attr_setdetachstate
-;pthread_attr_setinheritsched
-pthread_attr_setschedparam
-;pthread_attr_setschedpolicy
-;pthread_attr_setscope
-pthread_attr_setstackaddr
-pthread_attr_setstacksize
-pthread_cancel
-;
-; These are implemented as macros
-;
-;pthread_cleanup_pop
-;pthread_cleanup_push
-;
-pthread_condattr_destroy
-pthread_condattr_getpshared
-pthread_condattr_init
-pthread_condattr_setpshared
-pthread_cond_broadcast
-pthread_cond_destroy
-pthread_cond_init
-pthread_cond_signal
-pthread_cond_timedwait
-pthread_cond_wait
-pthread_create
-pthread_detach
-pthread_equal
-pthread_exit
-pthread_getschedparam
-pthread_getspecific
-pthread_join
-pthread_key_create
-pthread_key_delete
-;pthread_kill
-pthread_mutexattr_destroy
-;pthread_mutexattr_getprioceiling
-;pthread_mutexattr_getprotocol
-pthread_mutexattr_getpshared
-pthread_mutexattr_init
-;pthread_mutexattr_setprioceiling
-;pthread_mutexattr_setprotocol
-pthread_mutexattr_setpshared
-pthread_mutexattr_destroy
-pthread_mutex_init
-pthread_mutex_destroy
-pthread_mutex_lock
-pthread_mutex_trylock
-pthread_mutex_unlock
-pthread_once
-pthread_self
-pthread_setcancelstate
-pthread_setcanceltype
-pthread_setschedparam
-pthread_setspecific
-;pthread_sigmask
-pthread_testcancel
-;
-; POSIX 1.b
-;
-sched_get_priority_min
-sched_get_priority_max
-sched_yield
-sem_init
-sem_destroy
-sem_trywait
-sem_wait
-sem_post
-sem_open
-sem_close
-sem_unlink
-sem_getvalue
-;
-; Read/Write Locks
-;
-pthread_rwlock_init
-pthread_rwlock_destroy
-pthread_rwlock_tryrdlock
-pthread_rwlock_trywrlock
-pthread_rwlock_rdlock
-pthread_rwlock_wrlock
-pthread_rwlock_unlock
-;
-; Non-portable but useful
-;
-pthread_mutexattr_setforcecs_np
-pthreadCancelableWait
-pthreadCancelableTimedWait
-;
-; Needed if !defined(_MSC_VER) && !defined(__cplusplus)
-;
-pthread_push_cleanup
-pthread_pop_cleanup
+; pthread.def
+; Last updated: $Date: 1999/11/04 14:56:51 $
+
+; Currently unimplemented functions are commented out.
+
+LIBRARY pthread
+
+EXPORTS
+_pthread_processInitialize
+;pthread_atfork
+pthread_attr_destroy
+pthread_attr_getdetachstate
+;pthread_attr_getinheritsched
+pthread_attr_getschedparam
+;pthread_attr_getschedpolicy
+;pthread_attr_getscope
+pthread_attr_getstackaddr
+pthread_attr_getstacksize
+pthread_attr_init
+pthread_attr_setdetachstate
+;pthread_attr_setinheritsched
+pthread_attr_setschedparam
+;pthread_attr_setschedpolicy
+;pthread_attr_setscope
+pthread_attr_setstackaddr
+pthread_attr_setstacksize
+pthread_cancel
+;
+; These are implemented as macros
+;
+;pthread_cleanup_pop
+;pthread_cleanup_push
+;
+pthread_condattr_destroy
+pthread_condattr_getpshared
+pthread_condattr_init
+pthread_condattr_setpshared
+pthread_cond_broadcast
+pthread_cond_destroy
+pthread_cond_init
+pthread_cond_signal
+pthread_cond_timedwait
+pthread_cond_wait
+pthread_create
+pthread_detach
+pthread_equal
+pthread_exit
+pthread_getschedparam
+pthread_getspecific
+pthread_join
+pthread_key_create
+pthread_key_delete
+;pthread_kill
+pthread_mutexattr_destroy
+;pthread_mutexattr_getprioceiling
+;pthread_mutexattr_getprotocol
+pthread_mutexattr_getpshared
+pthread_mutexattr_init
+;pthread_mutexattr_setprioceiling
+;pthread_mutexattr_setprotocol
+pthread_mutexattr_setpshared
+pthread_mutexattr_destroy
+pthread_mutex_init
+pthread_mutex_destroy
+pthread_mutex_lock
+pthread_mutex_trylock
+pthread_mutex_unlock
+pthread_once
+pthread_self
+pthread_setcancelstate
+pthread_setcanceltype
+pthread_setschedparam
+pthread_setspecific
+;pthread_sigmask
+pthread_testcancel
+;
+; POSIX 1.b
+;
+sched_get_priority_min
+sched_get_priority_max
+sched_yield
+sem_init
+sem_destroy
+sem_trywait
+sem_wait
+sem_post
+sem_open
+sem_close
+sem_unlink
+sem_getvalue
+;
+; Non-portable but useful
+;
+pthread_mutexattr_setforcecs_np
+pthreadCancelableWait
+pthreadCancelableTimedWait
+;
+; Needed if !defined(_MSC_VER) && !defined(__cplusplus)
+;
+pthread_push_cleanup
+pthread_pop_cleanup
+
diff --git a/pthread.h b/pthread.h
index 87f769e..7acb41d 100644
--- a/pthread.h
+++ b/pthread.h
@@ -122,17 +122,6 @@
* ---------------------------
* pthread_sigmask
*
- * ---------------------------
- * Read/Write Locks:
- * ---------------------------
- * pthread_rwlock_init
- * pthread_rwlock_destroy
- * pthread_rwlock_tryrdlock
- * pthread_rwlock_trywrlock
- * pthread_rwlock_rdlock
- * pthread_rwlock_rwlock
- * pthread_rwlock_unlock
- *
* Limitations
* ===========
* The following functions are not implemented:
@@ -215,7 +204,12 @@
#endif /* HAVE_CONFIG_H */
#include <windows.h>
+
+#ifndef NEED_FTIME
#include <time.h>
+#else /* NEED_FTIME */
+/* use native WIN32 time API */
+#endif /* NEED_FTIME */
#if HAVE_SIGNAL_H
#include <signal.h>
@@ -243,14 +237,22 @@ struct timespec {
#endif /* SIG_SETMASK */
-#include <process.h>
+/*
+ * note: ETIMEDOUT is correctly defined in winsock.h on winCE
+ */
+#ifdef HAVE_WINSOCK_H
+#include <winsock.h>
+#endif
+
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
#include <errno.h>
+#endif
-#ifdef _WIN32
#ifndef ETIMEDOUT
-#define ETIMEDOUT 19981220 /* Let's hope this is unique */
+#define ETIMEDOUT 19981220 /* FIXME: Need the proper value here. */
#endif
-#endif /* _WIN32 */
#ifdef _MSC_VER
/*
@@ -264,6 +266,13 @@ struct timespec {
#define FALSE 0
#endif /* !TRUE */
+#ifdef __MINGW32__
+#define PT_STDCALL
+#else
+#define PT_STDCALL __stdcall
+#endif
+
+
/*
* This should perhaps be in autoconf or
* possibly fixed in Mingw32 to
@@ -376,9 +385,7 @@ extern "C"
/*
* POSIX Options
*/
-#ifndef _POSIX_THREADS
#define _POSIX_THREADS
-#endif
#define _POSIX_THREAD_SAFE_FUNCTIONS
#define _POSIX_THREAD_ATTR_STACKSIZE
@@ -431,8 +438,6 @@ typedef struct pthread_mutex_t_ *pthread_mutex_t;
typedef struct pthread_mutexattr_t_ *pthread_mutexattr_t;
typedef struct pthread_cond_t_ *pthread_cond_t;
typedef struct pthread_condattr_t_ *pthread_condattr_t;
-typedef struct pthread_rwlock_t_ *pthread_rwlock_t;
-typedef struct pthread_rwlockattr_t_ *pthread_rwlockattr_t;
/*
@@ -511,8 +516,6 @@ struct pthread_once_t_
#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1)
-#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1)
-
/*
* ====================
@@ -551,14 +554,6 @@ struct sched_param {
* WIN32 SEH
* C
* C++
- *
- * Please note that exiting a push/pop block via
- * "return", "exit", "break", or "continue" will
- * lead to different behaviour amongst applications
- * depending upon whether the library was built
- * using SEH, C++, or C. For example, a library built
- * with SEH will call the cleanup routine, while both
- * C++ and C built versions will not.
*/
typedef struct _pthread_cleanup_t _pthread_cleanup_t;
@@ -569,7 +564,7 @@ struct _pthread_cleanup_t
void *arg;
#if !defined(_MSC_VER) && !defined(__cplusplus)
_pthread_cleanup_t *prev;
-#endif /* !_MSC_VER && ! __cplusplus */
+#endif
};
#ifdef _MSC_VER
@@ -704,6 +699,12 @@ struct _pthread_cleanup_t
*/
/*
+ * Useful if an application wants to statically link
+ * the lib rather than load the DLL at run-time.
+ */
+int pthread_win32_initialize_np(void);
+
+/*
* PThread Attribute Functions
*/
int pthread_attr_init (pthread_attr_t * attr);
@@ -863,25 +864,6 @@ int pthread_attr_setschedparam (pthread_attr_t *attr,
const struct sched_param *param);
/*
- * Read-Write Lock Functions
- */
-
-int pthread_rwlock_init(pthread_rwlock_t *lock,
- const pthread_rwlockattr_t *attr);
-
-int pthread_rwlock_destroy(pthread_rwlock_t *lock);
-
-int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
-
-int pthread_rwlock_trywrlock(pthread_rwlock_t *);
-
-int pthread_rwlock_rdlock(pthread_rwlock_t *lock);
-
-int pthread_rwlock_wrlock(pthread_rwlock_t *lock);
-
-int pthread_rwlock_unlock(pthread_rwlock_t *lock);
-
-/*
* Protected Methods
*
* This function blocks until the given WIN32 handle
@@ -902,7 +884,7 @@ int pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout);
/*
* Thread-Safe C Runtime Library Mappings.
*/
-#if ! defined( _REENTRANT ) && ! defined( _MT )
+#if (! defined(NEED_ERRNO)) || (! defined( _REENTRANT ) && ! defined( _MT ))
int * _errno( void );
#endif
@@ -925,8 +907,8 @@ int * _errno( void );
(_buf) )
#define ctime_r( _clock, _buf ) \
- ( strcpy( (_buf), ctime( (_tm) ) ), \
- (_buf) )
+ ( strcpy( (_buf), ctime( (_tm) ) ), \
+ (_buf) )
#define gmtime_r( _clock, _result ) \
( *(_result) = *gmtime( (_clock) ), \
diff --git a/sched.h b/sched.h
index 2f498d3..197ac7b 100644
--- a/sched.h
+++ b/sched.h
@@ -43,8 +43,8 @@
#endif
#include <windows.h>
-#include <process.h>
-#include <errno.h>
+//#include <process.h>
+//#include <errno.h>
#ifdef _MSC_VER
/*
diff --git a/semaphore.c b/semaphore.c
index 0fcfc94..a8c346e 100644
--- a/semaphore.c
+++ b/semaphore.c
@@ -43,14 +43,13 @@
*/
#include <windows.h>
-#include <process.h>
-#include <sys/timeb.h>
+//#include <process.h>
+//#include <sys/timeb.h>
#include <string.h>
#include "pthread.h"
#include "semaphore.h"
-
int
sem_init (sem_t * sem, int pshared, unsigned int value)
/*
@@ -90,6 +89,7 @@ sem_init (sem_t * sem, int pshared, unsigned int value)
{
int result = 0;
+
if (pshared != 0)
{
/*
@@ -101,6 +101,22 @@ sem_init (sem_t * sem, int pshared, unsigned int value)
}
else
{
+
+#ifdef NEED_SEM
+
+ sem->value = value;
+ pthread_mutex_init(&sem->mutex, NULL);
+ sem->event = CreateEvent (NULL,
+ FALSE, /* manual reset */
+ FALSE, /* initial state */
+ NULL);
+ if (value != 0)
+ {
+ SetEvent(sem->event);
+ }
+
+#else /* NEED_SEM */
+
/*
* NOTE: Taking advantage of the fact that
* sem_t is a simple structure with one entry;
@@ -116,6 +132,9 @@ sem_init (sem_t * sem, int pshared, unsigned int value)
{
result = ENOSPC;
}
+
+#endif /* NEED_SEM */
+
}
if (result != 0)
@@ -161,11 +180,27 @@ sem_destroy (sem_t * sem)
{
result = EINVAL;
}
+
+#ifdef NEED_SEM
+
+ else
+ {
+ pthread_mutex_destroy(&sem->mutex);
+ if (!CloseHandle(sem->event))
+ {
+ result = EINVAL;
+ }
+ }
+
+#else /* NEED_SEM */
+
else if (! CloseHandle (*sem))
{
result = EINVAL;
}
+#endif /* NEED_SEM */
+
if (result != 0)
{
errno = result;
@@ -213,11 +248,22 @@ sem_trywait (sem_t * sem)
{
result = EINVAL;
}
+
+#ifdef NEED_SEM
+
+ /* not yet implemented! */
+ result = EINVAL;
+ return -1;
+
+#else /* NEED_SEM */
+
else if (WaitForSingleObject (*sem, 0) == WAIT_TIMEOUT)
{
result = EAGAIN;
}
+#endif /* NEED_SEM */
+
if (result != 0)
{
errno = result;
@@ -229,6 +275,53 @@ sem_trywait (sem_t * sem)
} /* sem_trywait */
+#ifdef NEED_SEM
+
+void
+_pthread_decrease_semaphore(sem_t * sem)
+{
+ pthread_mutex_lock(&sem->mutex);
+
+ if (sem->value != 0)
+ {
+ sem->value--;
+ if (sem->value != 0)
+ {
+ SetEvent(sem->event);
+ }
+ }
+ else
+ {
+ /* this case should not happen! */
+ }
+
+ pthread_mutex_unlock(&sem->mutex);
+}
+
+BOOL
+_pthread_increase_semaphore(sem_t * sem, unsigned int n)
+{
+ BOOL result;
+
+ pthread_mutex_lock(&sem->mutex);
+
+ if (sem->value + n > sem->value)
+ {
+ sem->value += n;
+ SetEvent(sem->event);
+ result = TRUE;
+ }
+ else
+ {
+ result = FALSE;
+ }
+
+ pthread_mutex_unlock(&sem->mutex);
+ return result;
+}
+
+#endif /* NEED_SEM */
+
int
sem_wait (sem_t * sem)
/*
@@ -268,7 +361,17 @@ sem_wait (sem_t * sem)
}
else
{
+
+#ifdef NEED_SEM
+
+ result = pthreadCancelableWait (sem->event);
+
+#else /* NEED_SEM */
+
result = pthreadCancelableWait (*sem);
+
+#endif /* NEED_SEM */
+
}
if (result != 0)
@@ -277,6 +380,12 @@ sem_wait (sem_t * sem)
return -1;
}
+#ifdef NEED_SEM
+
+ _decrease_semaphore(sem);
+
+#endif /* NEED_SEM */
+
return 0;
} /* sem_wait */
@@ -314,12 +423,21 @@ sem_post (sem_t * sem)
{
result = EINVAL;
}
+
+#ifdef NEED_SEM
+
+ else if (! _increase_semaphore (sem, 1))
+
+#else /* NEED_SEM */
+
else if (! ReleaseSemaphore (*sem, 1, 0))
+
+#endif /* NEED_SEM */
+
{
result = EINVAL;
}
-
if (result != 0)
{
errno = result;
diff --git a/semaphore.h b/semaphore.h
index fb475a0..8af8be8 100644
--- a/semaphore.h
+++ b/semaphore.h
@@ -28,8 +28,11 @@
#if !defined( SEMAPHORE_H )
#define SEMAPHORE_H
-#include <process.h>
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
#include <errno.h>
+#endif
#define _POSIX_SEMAPHORES
@@ -42,7 +45,15 @@ extern "C"
typedef unsigned int mode_t;
#endif
+#ifdef NEED_SEM
+typedef struct {
+ unsigned int value;
+ pthread_mutex_t mutex;
+ HANDLE event;
+} sem_t;
+#else /* NEED_SEM */
typedef HANDLE sem_t;
+#endif /* NEED_SEM */
int sem_init (sem_t * sem,
int pshared,
diff --git a/signal.c b/signal.c
index 504b235..db0feec 100644
--- a/signal.c
+++ b/signal.c
@@ -23,7 +23,8 @@
* MA 02111-1307, USA
*/
-#include <errno.h>
+/* errno.h or a replacement file is included by pthread.h */
+//#include <errno.h>
#include "pthread.h"
#include "implement.h"
diff --git a/tsd.c b/tsd.c
index 0766744..f8656ce 100644
--- a/tsd.c
+++ b/tsd.c
@@ -25,6 +25,11 @@
#include "pthread.h"
#include "implement.h"
+
+/* TLS_OUT_OF_INDEXES not defined on WinCE */
+#ifndef TLS_OUT_OF_INDEXES
+#define TLS_OUT_OF_INDEXES 0xffffffff
+#endif
int
pthread_key_create (pthread_key_t * key, void (*destructor) (void *))