summaryrefslogtreecommitdiff
path: root/private.c
diff options
context:
space:
mode:
Diffstat (limited to 'private.c')
-rw-r--r--private.c980
1 files changed, 12 insertions, 968 deletions
diff --git a/private.c b/private.c
index e0ca43a..19a7aeb 100644
--- a/private.c
+++ b/private.c
@@ -36,974 +36,18 @@
*/
#include "pthread.h"
-#include "semaphore.h"
#include "implement.h"
-int
-ptw32_processInitialize (void)
- /*
- * ------------------------------------------------------
- * DOCPRIVATE
- * This function performs process wide initialization for
- * the pthread library.
- *
- * PARAMETERS
- * N/A
- *
- * DESCRIPTION
- * This function performs process wide initialization for
- * the pthread library.
- * If successful, this routine sets the global variable
- * ptw32_processInitialized to TRUE.
- *
- * RESULTS
- * TRUE if successful,
- * FALSE otherwise
- *
- * ------------------------------------------------------
- */
-{
- if (ptw32_processInitialized) {
- /*
- * ignore if already initialized. this is useful for
- * programs that uses a non-dll pthread
- * library. such programs must call ptw32_processInitialize() explicitely,
- * since this initialization routine is automatically called only when
- * the dll is loaded.
- */
- return TRUE;
- }
-
- ptw32_processInitialized = TRUE;
-
- /*
- * Initialize Keys
- */
- if ((pthread_key_create (&ptw32_selfThreadKey, NULL) != 0) ||
- (pthread_key_create (&ptw32_cleanupKey, NULL) != 0))
- {
-
- ptw32_processTerminate ();
- }
-
- /*
- * Set up the global test and init check locks.
- */
- InitializeCriticalSection(&ptw32_mutex_test_init_lock);
- InitializeCriticalSection(&ptw32_cond_test_init_lock);
- InitializeCriticalSection(&ptw32_rwlock_test_init_lock);
- InitializeCriticalSection(&ptw32_spinlock_test_init_lock);
-
- return (ptw32_processInitialized);
-
-} /* processInitialize */
-
-void
-ptw32_processTerminate (void)
- /*
- * ------------------------------------------------------
- * DOCPRIVATE
- * This function performs process wide termination for
- * the pthread library.
- *
- * PARAMETERS
- * N/A
- *
- * DESCRIPTION
- * This function performs process wide termination for
- * the pthread library.
- * This routine sets the global variable
- * ptw32_processInitialized to FALSE
- *
- * RESULTS
- * N/A
- *
- * ------------------------------------------------------
- */
-{
- if (ptw32_processInitialized)
- {
-
- if (ptw32_selfThreadKey != NULL)
- {
- /*
- * Release ptw32_selfThreadKey
- */
- pthread_key_delete (ptw32_selfThreadKey);
-
- ptw32_selfThreadKey = NULL;
- }
-
- if (ptw32_cleanupKey != NULL)
- {
- /*
- * Release ptw32_cleanupKey
- */
- pthread_key_delete (ptw32_cleanupKey);
-
- ptw32_cleanupKey = NULL;
- }
-
- /*
- * Destroy the global test and init check locks.
- */
- DeleteCriticalSection(&ptw32_spinlock_test_init_lock);
- DeleteCriticalSection(&ptw32_rwlock_test_init_lock);
- DeleteCriticalSection(&ptw32_cond_test_init_lock);
- DeleteCriticalSection(&ptw32_mutex_test_init_lock);
-
- ptw32_processInitialized = FALSE;
- }
-
-} /* processTerminate */
-
-#ifdef __CLEANUP_SEH
-
-static DWORD
-ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
-{
- switch (ep->ExceptionRecord->ExceptionCode)
- {
- case EXCEPTION_PTW32_SERVICES:
- {
- 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;
- break;
- }
- default:
- {
- /*
- * A system unexpected exception has occurred running the user's
- * routine. We need to cleanup before letting the exception
- * out of thread scope.
- */
- pthread_t self = pthread_self();
-
- (void) pthread_mutex_destroy(&self->cancelLock);
- ptw32_callUserDestroyRoutines(self);
-
- return EXCEPTION_CONTINUE_SEARCH;
- break;
- }
- }
-}
-
-#elif defined(__CLEANUP_CXX)
-
-#if defined(_MSC_VER)
-#include <eh.h>
-static terminate_function ptw32_oldTerminate;
-#else
-#include <new.h>
-static terminate_handler ptw32_oldTerminate;
-#endif
-
-#if 0
-#include <stdio.h>
-static pthread_mutex_t termLock = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-void
-ptw32_terminate ()
-{
- pthread_t self = pthread_self();
-#if 0
- FILE * fp;
- pthread_mutex_lock(&termLock);
- fp = fopen("pthread.log", "a");
- fprintf(fp, "Terminate\n");
- fclose(fp);
- pthread_mutex_unlock(&termLock);
-#endif
- set_terminate(ptw32_oldTerminate);
- (void) pthread_mutex_destroy(&self->cancelLock);
- ptw32_callUserDestroyRoutines(self);
- terminate();
-}
-
-#endif /* _MSC_VER */
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
-unsigned __stdcall
-#else
-void
-#endif
-ptw32_threadStart (void * vthreadParms)
-{
- ThreadParms *threadParms = (ThreadParms *) vthreadParms;
- pthread_t self;
- void *(*start) (void *);
- void *arg;
-
-#ifdef __CLEANUP_SEH
- DWORD ei[] = {0,0,0};
-#endif
-
-#ifdef __CLEANUP_C
- int setjmp_rc;
-#endif
-
- void * status = (void *) 0;
-
- self = threadParms->tid;
- start = threadParms->start;
- arg = threadParms->arg;
-
- free (threadParms);
-
-#if defined (__MINGW32__) && ! defined (__MSVCRT__)
- /*
- * beginthread does not return the thread id and is running
- * before it returns us the thread handle, and so we do it here.
- */
- self->thread = GetCurrentThreadId ();
- /*
- * Here we're using cancelLock as a general-purpose lock
- * to make the new thread wait until the creating thread
- * has the new handle.
- */
- if (pthread_mutex_lock(&self->cancelLock) == 0)
- {
- (void) pthread_mutex_unlock(&self->cancelLock);
- }
-#endif
-
- pthread_setspecific (ptw32_selfThreadKey, self);
-
- self->state = PThreadStateRunning;
-
-#ifdef __CLEANUP_SEH
-
- __try
- {
- /*
- * Run the caller's routine;
- */
- status = self->exitStatus = (*start) (arg);
-
-#ifdef _UWIN
- if (--pthread_count <= 0)
- exit(0);
-#endif
-
- }
- __except (ExceptionFilter(GetExceptionInformation(), ei))
- {
- switch (ei[0])
- {
- case PTW32_EPS_CANCEL:
- status = PTHREAD_CANCELED;
-#ifdef _UWIN
- if (--pthread_count <= 0)
- exit(0);
-#endif
- break;
- case PTW32_EPS_EXIT:
- status = self->exitStatus;
- break;
- default:
- status = PTHREAD_CANCELED;
- break;
- }
- }
-
-#else /* __CLEANUP_SEH */
-
-#ifdef __CLEANUP_C
-
- setjmp_rc = setjmp( self->start_mark );
-
- if( 0 == setjmp_rc ) {
-
- /*
- * Run the caller's routine;
- */
- status = self->exitStatus = (*start) (arg);
- }
-
- else {
-
- switch (setjmp_rc)
- {
- case PTW32_EPS_CANCEL:
- status = PTHREAD_CANCELED;
- break;
- case PTW32_EPS_EXIT:
- status = self->exitStatus;
- break;
- default:
- status = PTHREAD_CANCELED;
- break;
- }
- }
-
-#else /* __CLEANUP_C */
-
-#ifdef __CLEANUP_CXX
-
- ptw32_oldTerminate = set_terminate(&ptw32_terminate);
-
- try
- {
- /*
- * Run the caller's routine in a nested try block so that we
- * can run the user's terminate function, which may call
- * pthread_exit() or be canceled.
- */
- try
- {
- status = self->exitStatus = (*start) (arg);
- }
- catch (ptw32_exception &)
- {
- /*
- * Pass these through to the outer block.
- */
- throw;
- }
- catch(...)
- {
- /*
- * We want to run the user's terminate function if supplied.
- * That function may call pthread_exit() or be canceled, which will
- * be handled by the outer try block.
- *
- * ptw32_terminate() will be called if there is no user
- * supplied function.
- */
-
-#if defined(_MSC_VER)
- terminate_function term_func = set_terminate(0);
-#else
- terminate_handler term_func = set_terminate(0);
-#endif
-
- set_terminate(term_func);
-
- if (term_func != 0) {
- term_func();
- }
-
- throw;
- }
- }
- catch (ptw32_exception_cancel &)
- {
- /*
- * Thread was canceled.
- */
- status = self->exitStatus = PTHREAD_CANCELED;
- }
- catch (ptw32_exception_exit &)
- {
- /*
- * Thread was exited via pthread_exit().
- */
- status = self->exitStatus;
- }
- catch (...)
- {
- /*
- * A system unexpected exception has occurred running the user's
- * terminate routine. We get control back within this block - cleanup
- * and release the exception out of thread scope.
- */
- status = self->exitStatus = PTHREAD_CANCELED;
- (void) pthread_mutex_lock(&self->cancelLock);
- self->state = PThreadStateException;
- (void) pthread_mutex_unlock(&self->cancelLock);
- (void) pthread_mutex_destroy(&self->cancelLock);
- (void) set_terminate(ptw32_oldTerminate);
- ptw32_callUserDestroyRoutines(self);
- throw;
-
- /*
- * Never reached.
- */
- }
-
- (void) set_terminate(ptw32_oldTerminate);
-
-#else
-
-#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
-
-#endif /* __CLEANUP_CXX */
-#endif /* __CLEANUP_C */
-#endif /* __CLEANUP_SEH */
-
- (void) pthread_mutex_lock(&self->cancelLock);
- self->state = PThreadStateLast;
- (void) pthread_mutex_unlock(&self->cancelLock);
-
-
- (void) pthread_mutex_destroy(&self->cancelLock);
-
-#if 1
- if (self->detachState == PTHREAD_CREATE_DETACHED)
- {
- /*
- * We need to cleanup the pthread now in case we have
- * been statically linked, in which case the cleanup
- * in dllMain won't get done. Joinable threads will
- * be cleaned up by pthread_join().
- *
- * Note that implicitly created pthreads (those created
- * for Win32 threads which have called pthreads routines)
- * must be cleaned up explicitly by the application
- * (by calling pthread_win32_thread_detach_np()) if
- * this library has been statically linked. For the dll,
- * dllMain will do the cleanup automatically.
- */
- (void) pthread_win32_thread_detach_np ();
- }
- else
- {
- ptw32_callUserDestroyRoutines (self);
- }
-#else
- ptw32_callUserDestroyRoutines (self);
-#endif
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
- _endthreadex ((unsigned) status);
-#else
- _endthread ();
-#endif
-
- /*
- * Never reached.
- */
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
- return (unsigned) status;
-#endif
-
-} /* ptw32_threadStart */
-
-void
-ptw32_threadDestroy (pthread_t thread)
-{
- if (thread != NULL)
- {
- ptw32_callUserDestroyRoutines (thread);
-
- if (thread->cancelEvent != NULL)
- {
- CloseHandle (thread->cancelEvent);
- }
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
- /* See documentation for endthread vs endthreadex. */
- if( thread->threadH != 0 )
- {
- CloseHandle( thread->threadH );
- }
-#endif
-
- free (thread);
- }
-
-} /* ptw32_threadDestroy */
-
-int
-ptw32_tkAssocCreate (ThreadKeyAssoc ** assocP,
- pthread_t thread,
- pthread_key_t key)
- /*
- * -------------------------------------------------------------------
- * This routine creates an association that
- * is unique for the given (thread,key) combination.The association
- * is referenced by both the thread and the key.
- * This association allows us to determine what keys the
- * current thread references and what threads a given key
- * references.
- * See the detailed description
- * at the beginning of this file for further details.
- *
- * Notes:
- * 1) New associations are pushed to the beginning of the
- * chain so that the internal ptw32_selfThreadKey association
- * is always last, thus allowing selfThreadExit to
- * be implicitly called by pthread_exit last.
- *
- * Parameters:
- * assocP
- * address into which the association is returned.
- * thread
- * current running thread. If NULL, then association
- * is only added to the key. A NULL thread indicates
- * that the user called pthread_setspecific prior
- * to starting a thread. That's ok.
- * key
- * key on which to create an association.
- * Returns:
- * 0 - if successful,
- * ENOMEM - not enough memory to create assoc or other object
- * EINVAL - an internal error occurred
- * ENOSYS - an internal error occurred
- * -------------------------------------------------------------------
- */
-{
- int result;
- ThreadKeyAssoc *assoc;
-
- /*
- * Have to create an association and add it
- * to both the key and the thread.
- */
- assoc = (ThreadKeyAssoc *) calloc (1, sizeof (*assoc));
-
- if (assoc == NULL)
- {
- result = ENOMEM;
- goto FAIL0;
- }
-
- /*
- * Initialise only when used for the first time.
- */
- assoc->lock = PTHREAD_MUTEX_INITIALIZER;
- assoc->thread = thread;
- assoc->key = key;
-
- /*
- * Register assoc with key
- */
- if ((result = pthread_mutex_lock (&(key->threadsLock))) != 0)
- {
- goto FAIL2;
- }
-
- assoc->nextThread = (ThreadKeyAssoc *) key->threads;
- key->threads = (void *) assoc;
-
- pthread_mutex_unlock (&(key->threadsLock));
-
- if (thread != NULL)
- {
- /*
- * Register assoc with thread
- */
- assoc->nextKey = (ThreadKeyAssoc *) thread->keys;
- thread->keys = (void *) assoc;
- }
-
- *assocP = assoc;
-
- return (result);
-
- /*
- * -------------
- * Failure Code
- * -------------
- */
-FAIL2:
- pthread_mutex_destroy (&(assoc->lock));
- free (assoc);
-
-FAIL0:
-
- return (result);
-
-} /* ptw32_tkAssocCreate */
-
-
-void
-ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc)
- /*
- * -------------------------------------------------------------------
- * This routine releases all resources for the given ThreadKeyAssoc
- * once it is no longer being referenced
- * ie) both the key and thread have stopped referencing it.
- *
- * Parameters:
- * assoc
- * an instance of ThreadKeyAssoc.
- * Returns:
- * N/A
- * -------------------------------------------------------------------
- */
-{
-
- if ((assoc != NULL) &&
- (assoc->key == NULL && assoc->thread == NULL))
- {
-
- pthread_mutex_destroy (&(assoc->lock));
-
- free (assoc);
- }
-
-} /* ptw32_tkAssocDestroy */
-
-
-void
-ptw32_callUserDestroyRoutines (pthread_t thread)
- /*
- * -------------------------------------------------------------------
- * DOCPRIVATE
- *
- * This the routine runs through all thread keys and calls
- * the destroy routines on the user's data for the current thread.
- * It simulates the behaviour of POSIX Threads.
- *
- * PARAMETERS
- * thread
- * an instance of pthread_t
- *
- * RETURNS
- * N/A
- * -------------------------------------------------------------------
- */
-{
- ThreadKeyAssoc **nextP;
- ThreadKeyAssoc *assoc;
-
- if (thread != NULL)
- {
- /*
- * Run through all Thread<-->Key associations
- * for the current thread.
- * If the pthread_key_t still exits (ie the assoc->key
- * is not NULL) then call the user's TSD destroy routine.
- * Notes:
- * If assoc->key is NULL, then the user previously called
- * PThreadKeyDestroy. The association is now only referenced
- * by the current thread and must be released; otherwise
- * the assoc will be destroyed when the key is destroyed.
- */
- nextP = (ThreadKeyAssoc **) & (thread->keys);
- assoc = *nextP;
-
- while (assoc != NULL)
- {
-
- if (pthread_mutex_lock (&(assoc->lock)) == 0)
- {
- pthread_key_t k;
- if ((k = assoc->key) != NULL)
- {
- /*
- * Key still active; pthread_key_delete
- * will block on this same mutex before
- * it can release actual key; therefore,
- * key is valid and we can call the destroy
- * routine;
- */
- void *value = NULL;
-
- value = pthread_getspecific (k);
- if (value != NULL && k->destructor != NULL)
- {
-
-#ifdef __cplusplus
-
- try
- {
- /*
- * Run the caller's cleanup routine.
- */
- (*(k->destructor)) (value);
- }
- catch (...)
- {
- /*
- * A system unexpected exception has occurred
- * running the user's destructor.
- * We get control back within this block in case
- * the application has set up it's own terminate
- * handler. Since we are leaving the thread we
- * should not get any internal pthreads
- * exceptions.
- */
- terminate();
- }
-
-#else /* __cplusplus */
-
- /*
- * Run the caller's cleanup routine.
- */
- (*(k->destructor)) (value);
-
-#endif /* __cplusplus */
- }
- }
-
- /*
- * mark assoc->thread as NULL to indicate the
- * thread no longer references this association
- */
- assoc->thread = NULL;
-
- /*
- * Remove association from the pthread_t chain
- */
- *nextP = assoc->nextKey;
-
- pthread_mutex_unlock (&(assoc->lock));
-
- ptw32_tkAssocDestroy (assoc);
-
- assoc = *nextP;
- }
- }
- }
-
-} /* ptw32_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 INLINE 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 INLINE 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 */
-
-
-DWORD
-ptw32_get_exception_services_code(void)
-{
-#ifdef __CLEANUP_SEH
-
- return EXCEPTION_PTW32_SERVICES;
-
-#else
-
- return (DWORD) NULL;
-
-#endif
-}
-
-
-void
-ptw32_throw(DWORD exception)
-{
-#ifdef __CLEANUP_C
- pthread_t self = pthread_self();
-#endif
-
-
-#ifdef __CLEANUP_SEH
- DWORD exceptionInformation[3];
-#endif
-
- if (exception != PTW32_EPS_CANCEL &&
- exception != PTW32_EPS_EXIT)
- {
- /* Should never enter here */
- exit(1);
- }
-
-#ifdef __CLEANUP_SEH
-
-
- exceptionInformation[0] = (DWORD) (exception);
- exceptionInformation[1] = (DWORD) (0);
- exceptionInformation[2] = (DWORD) (0);
-
- RaiseException (
- EXCEPTION_PTW32_SERVICES,
- 0,
- 3,
- exceptionInformation);
-
-#else /* __CLEANUP_SEH */
-
-#ifdef __CLEANUP_C
-
- ptw32_pop_cleanup_all( 1 );
-
- longjmp( self->start_mark, exception );
-
-#else /* __CLEANUP_C */
-
-#ifdef __CLEANUP_CXX
-
- switch (exception)
- {
- case PTW32_EPS_CANCEL:
- throw ptw32_exception_cancel();
- break;
- case PTW32_EPS_EXIT:
- throw ptw32_exception_exit();
- break;
- }
-
-#else
-
-#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
-
-#endif /* __CLEANUP_CXX */
-
-#endif /* __CLEANUP_C */
-
-#endif /* __CLEANUP_SEH */
-
- /* Never reached */
-}
-
-void
-ptw32_pop_cleanup_all(int execute)
-{
- while( NULL != ptw32_pop_cleanup(execute) ) {
- }
-}
-
-
-/*
- * ptw32_InterlockedCompareExchange --
- *
- * Needed because W95 doesn't support InterlockedCompareExchange.
- * It is only used when running the dll on W95. Other versions of
- * Windows use the Win32 supported version, which may be running on
- * different processor types.
- *
- * This can't be inlined because we need to know it's address so that
- * we can call it through a pointer.
- */
-PTW32_INTERLOCKED_LONG WINAPI
-ptw32_InterlockedCompareExchange(PTW32_INTERLOCKED_LPLONG location,
- PTW32_INTERLOCKED_LONG value,
- PTW32_INTERLOCKED_LONG comparand)
-{
- PTW32_INTERLOCKED_LONG result;
-
-#if defined(_M_IX86) || defined(_X86_)
-
-#if defined(_MSC_VER)
-
- _asm {
- PUSH ecx
- PUSH edx
- MOV ecx,dword ptr [location]
- MOV edx,dword ptr [value]
- MOV eax,dword ptr [comparand]
- LOCK CMPXCHG dword ptr [ecx],edx ; if (EAX == [ECX]),
- ; [ECX] = EDX
- ; else
- ; EAX = [ECX]
- MOV dword ptr [result], eax
- POP edx
- POP ecx
- }
-
-#elif defined(__GNUC__)
-
- __asm__
- (
- "lock\n\t"
- "cmpxchgl %3,(%0)" /* if (EAX == [location]), */
- /* [location] = value */
- /* else */
- /* EAX = [location] */
- :"=r" (location), "=a" (result)
- :"0" (location), "q" (value), "a" (comparand)
- : "memory" );
-
-#endif
-
-#else
-
- /*
- * If execution gets to here then we should be running on a Win95 system
- * but either running on something other than an X86 processor, or a
- * compiler other than MSVC or GCC. Pthreads-win32 doesn't support that
- * platform (yet).
- */
-
- result = 0;
-
-#endif
-
- return result;
-}
-
-
-/*
- * ptw32_getprocessors()
- *
- * Get the number of CPUs available to the process.
- *
- * If the available number of CPUs is 1 then pthread_spin_lock()
- * will block rather than spin if the lock is already owned.
- *
- * pthread_spin_init() calls this routine when initialising
- * a spinlock. If the number of available processors changes
- * (after a call to SetProcessAffinityMask()) then only
- * newly initialised spinlocks will notice.
- */
-int
-ptw32_getprocessors(int * count)
-{
- DWORD vProcessCPUs;
- DWORD vSystemCPUs;
- int result = 0;
-
- if (GetProcessAffinityMask(GetCurrentProcess(),
- &vProcessCPUs,
- &vSystemCPUs))
- {
- DWORD bit;
- int CPUs = 0;
-
- for (bit = 1; bit != 0; bit <<= 1)
- {
- if (vProcessCPUs & bit)
- {
- CPUs++;
- }
- }
- *count = CPUs;
- }
- else
- {
- result = EAGAIN;
- }
-
- return(result);
-}
+#include "ptw32_is_attr.c"
+#include "ptw32_processInitialize.c"
+#include "ptw32_processTerminate.c"
+#include "ptw32_threadStart.c"
+#include "ptw32_threadDestroy.c"
+#include "ptw32_tkAssocCreate.c"
+#include "ptw32_tkAssocDestroy.c"
+#include "ptw32_callUserDestroyRoutines.c"
+#include "ptw32_timespec.c"
+#include "ptw32_throw.c"
+#include "ptw32_InterlockedCompareExchange.c"
+#include "ptw32_getprocessors.c"