mirror of
https://github.com/libretro/RetroArch
synced 2025-04-18 14:42:30 +00:00
(pthreads) Cleanups
This commit is contained in:
parent
4c0c842451
commit
dbaa237c71
443
deps/pthreads/pte.c
vendored
443
deps/pthreads/pte.c
vendored
@ -74,9 +74,8 @@ static int pte_thread_detach_common (unsigned char threadShouldExit)
|
|||||||
*/
|
*/
|
||||||
pte_thread_t * sp = (pte_thread_t *) pthread_getspecific (pte_selfThreadKey);
|
pte_thread_t * sp = (pte_thread_t *) pthread_getspecific (pte_selfThreadKey);
|
||||||
|
|
||||||
if (sp != NULL) // otherwise OS thread with no implicit POSIX handle.
|
if (sp) // otherwise OS thread with no implicit POSIX handle.
|
||||||
{
|
{
|
||||||
|
|
||||||
pte_callUserDestroyRoutines (sp);
|
pte_callUserDestroyRoutines (sp);
|
||||||
|
|
||||||
(void) pthread_mutex_lock (&sp->cancelLock);
|
(void) pthread_mutex_lock (&sp->cancelLock);
|
||||||
@ -91,22 +90,18 @@ static int pte_thread_detach_common (unsigned char threadShouldExit)
|
|||||||
if (sp->detachState == PTHREAD_CREATE_DETACHED)
|
if (sp->detachState == PTHREAD_CREATE_DETACHED)
|
||||||
{
|
{
|
||||||
if (threadShouldExit)
|
if (threadShouldExit)
|
||||||
{
|
|
||||||
pte_threadExitAndDestroy (sp);
|
pte_threadExitAndDestroy (sp);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
pte_threadDestroy (sp);
|
pte_threadDestroy (sp);
|
||||||
}
|
|
||||||
|
|
||||||
// pte_osTlsSetValue (pte_selfThreadKey->key, NULL);
|
#if 0
|
||||||
|
pte_osTlsSetValue (pte_selfThreadKey->key, NULL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (threadShouldExit)
|
if (threadShouldExit)
|
||||||
{
|
|
||||||
pte_osThreadExit();
|
pte_osThreadExit();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,41 +111,34 @@ static int pte_thread_detach_common (unsigned char threadShouldExit)
|
|||||||
|
|
||||||
static void pte_threadDestroyCommon (pthread_t thread, unsigned char shouldThreadExit)
|
static void pte_threadDestroyCommon (pthread_t thread, unsigned char shouldThreadExit)
|
||||||
{
|
{
|
||||||
pte_thread_t * tp = (pte_thread_t *) thread;
|
|
||||||
pte_thread_t threadCopy;
|
pte_thread_t threadCopy;
|
||||||
|
pte_thread_t * tp = (pte_thread_t *) thread;
|
||||||
|
|
||||||
if (tp != NULL)
|
if (!tp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy thread state so that the thread can be atomically NULLed.
|
||||||
|
*/
|
||||||
|
memcpy (&threadCopy, tp, sizeof (threadCopy));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Thread ID structs are never freed. They're NULLed and reused.
|
||||||
|
* This also sets the thread to PThreadStateInitial (invalid).
|
||||||
|
*/
|
||||||
|
pte_threadReusePush (thread);
|
||||||
|
|
||||||
|
(void) pthread_mutex_destroy(&threadCopy.cancelLock);
|
||||||
|
(void) pthread_mutex_destroy(&threadCopy.threadLock);
|
||||||
|
|
||||||
|
if (threadCopy.threadId != 0)
|
||||||
{
|
{
|
||||||
/*
|
if (shouldThreadExit)
|
||||||
* Copy thread state so that the thread can be atomically NULLed.
|
pte_osThreadExitAndDelete(threadCopy.threadId);
|
||||||
*/
|
else
|
||||||
memcpy (&threadCopy, tp, sizeof (threadCopy));
|
pte_osThreadDelete(threadCopy.threadId);
|
||||||
|
|
||||||
/*
|
|
||||||
* Thread ID structs are never freed. They're NULLed and reused.
|
|
||||||
* This also sets the thread to PThreadStateInitial (invalid).
|
|
||||||
*/
|
|
||||||
pte_threadReusePush (thread);
|
|
||||||
|
|
||||||
(void) pthread_mutex_destroy(&threadCopy.cancelLock);
|
|
||||||
(void) pthread_mutex_destroy(&threadCopy.threadLock);
|
|
||||||
|
|
||||||
if (threadCopy.threadId != 0)
|
|
||||||
{
|
|
||||||
if (shouldThreadExit)
|
|
||||||
{
|
|
||||||
pte_osThreadExitAndDelete(threadCopy.threadId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pte_osThreadDelete(threadCopy.threadId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} /* pte_threadDestroy */
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pte_callUserDestroyRoutines (pthread_t thread)
|
pte_callUserDestroyRoutines (pthread_t thread)
|
||||||
@ -171,159 +159,130 @@ pte_callUserDestroyRoutines (pthread_t thread)
|
|||||||
* -------------------------------------------------------------------
|
* -------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ThreadKeyAssoc * assoc;
|
int assocsRemaining;
|
||||||
|
int iterations = 0;
|
||||||
|
ThreadKeyAssoc *assoc = NULL;
|
||||||
|
pte_thread_t *sp = (pte_thread_t *) thread;
|
||||||
|
|
||||||
if (thread != NULL)
|
if (!thread)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Run through all Thread<-->Key associations
|
||||||
|
* for the current thread.
|
||||||
|
*
|
||||||
|
* Do this process at most PTHREAD_DESTRUCTOR_ITERATIONS times.
|
||||||
|
*/
|
||||||
|
do
|
||||||
{
|
{
|
||||||
int assocsRemaining;
|
assocsRemaining = 0;
|
||||||
int iterations = 0;
|
iterations++;
|
||||||
pte_thread_t * sp = (pte_thread_t *) thread;
|
|
||||||
|
|
||||||
|
(void) pthread_mutex_lock(&(sp->threadLock));
|
||||||
/*
|
/*
|
||||||
* Run through all Thread<-->Key associations
|
* The pointer to the next assoc is stored in the thread struct so that
|
||||||
* for the current thread.
|
* the assoc destructor in pthread_key_delete can adjust it
|
||||||
*
|
* if it deletes this assoc. This can happen if we fail to acquire
|
||||||
* Do this process at most PTHREAD_DESTRUCTOR_ITERATIONS times.
|
* both locks below, and are forced to release all of our locks,
|
||||||
|
* leaving open the opportunity for pthread_key_delete to get in
|
||||||
|
* before us.
|
||||||
*/
|
*/
|
||||||
do
|
sp->nextAssoc = sp->keys;
|
||||||
|
(void) pthread_mutex_unlock(&(sp->threadLock));
|
||||||
|
|
||||||
|
for (;;)
|
||||||
{
|
{
|
||||||
assocsRemaining = 0;
|
void * value;
|
||||||
iterations++;
|
pthread_key_t k;
|
||||||
|
void (*destructor) (void *);
|
||||||
|
|
||||||
(void) pthread_mutex_lock(&(sp->threadLock));
|
|
||||||
/*
|
/*
|
||||||
* The pointer to the next assoc is stored in the thread struct so that
|
* First we need to serialise with pthread_key_delete by locking
|
||||||
* the assoc destructor in pthread_key_delete can adjust it
|
* both assoc guards, but in the reverse order to our convention,
|
||||||
* if it deletes this assoc. This can happen if we fail to acquire
|
* so we must be careful to avoid deadlock.
|
||||||
* both locks below, and are forced to release all of our locks,
|
|
||||||
* leaving open the opportunity for pthread_key_delete to get in
|
|
||||||
* before us.
|
|
||||||
*/
|
*/
|
||||||
sp->nextAssoc = sp->keys;
|
(void) pthread_mutex_lock(&(sp->threadLock));
|
||||||
(void) pthread_mutex_unlock(&(sp->threadLock));
|
|
||||||
|
|
||||||
for (;;)
|
if ((assoc = (ThreadKeyAssoc *)sp->nextAssoc) == NULL)
|
||||||
|
{
|
||||||
|
/* Finished */
|
||||||
|
pthread_mutex_unlock(&(sp->threadLock));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
void * value;
|
|
||||||
pthread_key_t k;
|
|
||||||
void (*destructor) (void *);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First we need to serialise with pthread_key_delete by locking
|
* assoc->key must be valid because assoc can't change or be
|
||||||
* both assoc guards, but in the reverse order to our convention,
|
* removed from our chain while we hold at least one lock. If
|
||||||
* so we must be careful to avoid deadlock.
|
* the assoc was on our key chain then the key has not been
|
||||||
|
* deleted yet.
|
||||||
|
*
|
||||||
|
* Now try to acquire the second lock without deadlocking.
|
||||||
|
* If we fail, we need to relinquish the first lock and the
|
||||||
|
* processor and then try to acquire them all again.
|
||||||
*/
|
*/
|
||||||
(void) pthread_mutex_lock(&(sp->threadLock));
|
if (pthread_mutex_trylock(&(assoc->key->keyLock)) == EBUSY)
|
||||||
|
|
||||||
if ((assoc = (ThreadKeyAssoc *)sp->nextAssoc) == NULL)
|
|
||||||
{
|
{
|
||||||
/* Finished */
|
|
||||||
pthread_mutex_unlock(&(sp->threadLock));
|
pthread_mutex_unlock(&(sp->threadLock));
|
||||||
break;
|
pte_osThreadSleep(1); // Ugly but necessary to avoid priority effects.
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* assoc->key must be valid because assoc can't change or be
|
* Go around again.
|
||||||
* removed from our chain while we hold at least one lock. If
|
* If pthread_key_delete has removed this assoc in the meantime,
|
||||||
* the assoc was on our key chain then the key has not been
|
* sp->nextAssoc will point to a new assoc.
|
||||||
* deleted yet.
|
|
||||||
*
|
|
||||||
* Now try to acquire the second lock without deadlocking.
|
|
||||||
* If we fail, we need to relinquish the first lock and the
|
|
||||||
* processor and then try to acquire them all again.
|
|
||||||
*/
|
*/
|
||||||
if (pthread_mutex_trylock(&(assoc->key->keyLock)) == EBUSY)
|
continue;
|
||||||
{
|
|
||||||
pthread_mutex_unlock(&(sp->threadLock));
|
|
||||||
pte_osThreadSleep(1); // Ugly but necessary to avoid priority effects.
|
|
||||||
/*
|
|
||||||
* Go around again.
|
|
||||||
* If pthread_key_delete has removed this assoc in the meantime,
|
|
||||||
* sp->nextAssoc will point to a new assoc.
|
|
||||||
*/
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We now hold both locks */
|
|
||||||
|
|
||||||
sp->nextAssoc = assoc->nextKey;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Key still active; pthread_key_delete
|
|
||||||
* will block on these same mutexes before
|
|
||||||
* it can release actual key; therefore,
|
|
||||||
* key is valid and we can call the destroy
|
|
||||||
* routine;
|
|
||||||
*/
|
|
||||||
k = assoc->key;
|
|
||||||
destructor = k->destructor;
|
|
||||||
value = pte_osTlsGetValue(k->key);
|
|
||||||
pte_osTlsSetValue (k->key, NULL);
|
|
||||||
|
|
||||||
// Every assoc->key exists and has a destructor
|
|
||||||
if (value != NULL && iterations <= PTHREAD_DESTRUCTOR_ITERATIONS)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Unlock both locks before the destructor runs.
|
|
||||||
* POSIX says pthread_key_delete can be run from destructors,
|
|
||||||
* and that probably includes with this key as target.
|
|
||||||
* pthread_setspecific can also be run from destructors and
|
|
||||||
* also needs to be able to access the assocs.
|
|
||||||
*/
|
|
||||||
(void) pthread_mutex_unlock(&(sp->threadLock));
|
|
||||||
(void) pthread_mutex_unlock(&(k->keyLock));
|
|
||||||
|
|
||||||
assocsRemaining++;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Run the caller's cleanup routine.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
destructor (value);
|
|
||||||
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Remove association from both the key and thread chains
|
|
||||||
* and reclaim it's memory resources.
|
|
||||||
*/
|
|
||||||
pte_tkAssocDestroy (assoc);
|
|
||||||
(void) pthread_mutex_unlock(&(sp->threadLock));
|
|
||||||
(void) pthread_mutex_unlock(&(k->keyLock));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We now hold both locks */
|
||||||
|
|
||||||
|
sp->nextAssoc = assoc->nextKey;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Key still active; pthread_key_delete
|
||||||
|
* will block on these same mutexes before
|
||||||
|
* it can release actual key; therefore,
|
||||||
|
* key is valid and we can call the destroy
|
||||||
|
* routine;
|
||||||
|
*/
|
||||||
|
k = assoc->key;
|
||||||
|
destructor = k->destructor;
|
||||||
|
value = pte_osTlsGetValue(k->key);
|
||||||
|
pte_osTlsSetValue (k->key, NULL);
|
||||||
|
|
||||||
|
// Every assoc->key exists and has a destructor
|
||||||
|
if (value && iterations <= PTHREAD_DESTRUCTOR_ITERATIONS)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Unlock both locks before the destructor runs.
|
||||||
|
* POSIX says pthread_key_delete can be run from destructors,
|
||||||
|
* and that probably includes with this key as target.
|
||||||
|
* pthread_setspecific can also be run from destructors and
|
||||||
|
* also needs to be able to access the assocs.
|
||||||
|
*/
|
||||||
|
(void) pthread_mutex_unlock(&(sp->threadLock));
|
||||||
|
(void) pthread_mutex_unlock(&(k->keyLock));
|
||||||
|
|
||||||
|
assocsRemaining++;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Run the caller's cleanup routine.
|
||||||
|
*/
|
||||||
|
destructor (value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Remove association from both the key and thread chains
|
||||||
|
* and reclaim it's memory resources.
|
||||||
|
*/
|
||||||
|
pte_tkAssocDestroy (assoc);
|
||||||
|
(void) pthread_mutex_unlock(&(sp->threadLock));
|
||||||
|
(void) pthread_mutex_unlock(&(k->keyLock));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (assocsRemaining);
|
}while (assocsRemaining);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pte_cancellable_wait (pte_osSemaphoreHandle semHandle, unsigned int* timeout)
|
int pte_cancellable_wait (pte_osSemaphoreHandle semHandle, unsigned int* timeout)
|
||||||
@ -334,7 +293,7 @@ int pte_cancellable_wait (pte_osSemaphoreHandle semHandle, unsigned int* timeout
|
|||||||
pthread_t self = pthread_self();
|
pthread_t self = pthread_self();
|
||||||
pte_thread_t *sp = (pte_thread_t *) self;
|
pte_thread_t *sp = (pte_thread_t *) self;
|
||||||
|
|
||||||
if (sp != NULL)
|
if (sp)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Get cancelEvent handle
|
* Get cancelEvent handle
|
||||||
@ -360,7 +319,7 @@ int pte_cancellable_wait (pte_osSemaphoreHandle semHandle, unsigned int* timeout
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PTE_OS_INTERRUPTED:
|
case PTE_OS_INTERRUPTED:
|
||||||
if (sp != NULL)
|
if (sp)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Should handle POSIX and implicit POSIX threads..
|
* Should handle POSIX and implicit POSIX threads..
|
||||||
@ -519,26 +478,18 @@ int pte_mutex_check_need_init (pthread_mutex_t * mutex)
|
|||||||
mtx = *mutex;
|
mtx = *mutex;
|
||||||
|
|
||||||
if (mtx == PTHREAD_MUTEX_INITIALIZER)
|
if (mtx == PTHREAD_MUTEX_INITIALIZER)
|
||||||
{
|
|
||||||
result = pthread_mutex_init (mutex, NULL);
|
result = pthread_mutex_init (mutex, NULL);
|
||||||
}
|
|
||||||
else if (mtx == PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
|
else if (mtx == PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
|
||||||
{
|
|
||||||
result = pthread_mutex_init (mutex, &pte_recursive_mutexattr);
|
result = pthread_mutex_init (mutex, &pte_recursive_mutexattr);
|
||||||
}
|
|
||||||
else if (mtx == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
|
else if (mtx == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
|
||||||
{
|
|
||||||
result = pthread_mutex_init (mutex, &pte_errorcheck_mutexattr);
|
result = pthread_mutex_init (mutex, &pte_errorcheck_mutexattr);
|
||||||
}
|
/*
|
||||||
|
* The mutex has been destroyed while we were waiting to
|
||||||
|
* initialise it, so the operation that caused the
|
||||||
|
* auto-initialisation should fail.
|
||||||
|
*/
|
||||||
else if (mtx == NULL)
|
else if (mtx == 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;
|
result = EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
pte_osMutexUnlock(pte_mutex_test_init_lock);
|
pte_osMutexUnlock(pte_mutex_test_init_lock);
|
||||||
|
|
||||||
@ -547,8 +498,8 @@ int pte_mutex_check_need_init (pthread_mutex_t * mutex)
|
|||||||
|
|
||||||
pthread_t pte_new (void)
|
pthread_t pte_new (void)
|
||||||
{
|
{
|
||||||
pthread_t nil = NULL;
|
pthread_t nil = NULL;
|
||||||
pte_thread_t * tp;
|
pte_thread_t * tp = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there's a reusable pthread_t then use it.
|
* If there's a reusable pthread_t then use it.
|
||||||
@ -588,7 +539,6 @@ unsigned int pte_relmillisecs (const struct timespec * abstime)
|
|||||||
const long long NANOSEC_PER_MILLISEC = 1000000;
|
const long long NANOSEC_PER_MILLISEC = 1000000;
|
||||||
const long long MILLISEC_PER_SEC = 1000;
|
const long long MILLISEC_PER_SEC = 1000;
|
||||||
unsigned int milliseconds;
|
unsigned int milliseconds;
|
||||||
long long tmpAbsMilliseconds;
|
|
||||||
long tmpCurrMilliseconds;
|
long tmpCurrMilliseconds;
|
||||||
struct timeb currSysTime;
|
struct timeb currSysTime;
|
||||||
|
|
||||||
@ -603,7 +553,7 @@ unsigned int pte_relmillisecs (const struct timespec * abstime)
|
|||||||
*
|
*
|
||||||
* Assume all integers are unsigned, i.e. cannot test if less than 0.
|
* Assume all integers are unsigned, i.e. cannot test if less than 0.
|
||||||
*/
|
*/
|
||||||
tmpAbsMilliseconds = (int64_t)abstime->tv_sec * MILLISEC_PER_SEC;
|
long long tmpAbsMilliseconds = (int64_t)abstime->tv_sec * MILLISEC_PER_SEC;
|
||||||
tmpAbsMilliseconds += ((int64_t)abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;
|
tmpAbsMilliseconds += ((int64_t)abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;
|
||||||
|
|
||||||
/* get current system time */
|
/* get current system time */
|
||||||
@ -665,7 +615,6 @@ pte_threadReusePop (void)
|
|||||||
{
|
{
|
||||||
pthread_t t = NULL;
|
pthread_t t = NULL;
|
||||||
|
|
||||||
|
|
||||||
pte_osMutexLock (pte_thread_reuse_lock);
|
pte_osMutexLock (pte_thread_reuse_lock);
|
||||||
|
|
||||||
if (PTE_THREAD_REUSE_EMPTY != pte_threadReuseTop)
|
if (PTE_THREAD_REUSE_EMPTY != pte_threadReuseTop)
|
||||||
@ -677,9 +626,7 @@ pte_threadReusePop (void)
|
|||||||
pte_threadReuseTop = tp->prevReuse;
|
pte_threadReuseTop = tp->prevReuse;
|
||||||
|
|
||||||
if (PTE_THREAD_REUSE_EMPTY == pte_threadReuseTop)
|
if (PTE_THREAD_REUSE_EMPTY == pte_threadReuseTop)
|
||||||
{
|
|
||||||
pte_threadReuseBottom = PTE_THREAD_REUSE_EMPTY;
|
pte_threadReuseBottom = PTE_THREAD_REUSE_EMPTY;
|
||||||
}
|
|
||||||
|
|
||||||
tp->prevReuse = NULL;
|
tp->prevReuse = NULL;
|
||||||
|
|
||||||
@ -859,7 +806,10 @@ int pte_threadStart (void *vthreadParms)
|
|||||||
pte_thread_t *sp = (pte_thread_t *) self;
|
pte_thread_t *sp = (pte_thread_t *) self;
|
||||||
start = threadParms->start;
|
start = threadParms->start;
|
||||||
arg = threadParms->arg;
|
arg = threadParms->arg;
|
||||||
// free (threadParms);
|
|
||||||
|
#if 0
|
||||||
|
free (threadParms);
|
||||||
|
#endif
|
||||||
|
|
||||||
pthread_setspecific (pte_selfThreadKey, sp);
|
pthread_setspecific (pte_selfThreadKey, sp);
|
||||||
|
|
||||||
@ -868,14 +818,11 @@ int pte_threadStart (void *vthreadParms)
|
|||||||
setjmp_rc = setjmp (sp->start_mark);
|
setjmp_rc = setjmp (sp->start_mark);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Run the caller's routine;
|
||||||
|
*/
|
||||||
if (0 == setjmp_rc)
|
if (0 == setjmp_rc)
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Run the caller's routine;
|
|
||||||
*/
|
|
||||||
sp->exitStatus = status = (*start) (arg);
|
sp->exitStatus = status = (*start) (arg);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (setjmp_rc)
|
switch (setjmp_rc)
|
||||||
@ -934,11 +881,9 @@ void pte_throw (unsigned int exception)
|
|||||||
pte_thread_t * sp = (pte_thread_t *) pthread_getspecific (pte_selfThreadKey);
|
pte_thread_t * sp = (pte_thread_t *) pthread_getspecific (pte_selfThreadKey);
|
||||||
|
|
||||||
|
|
||||||
|
/* Should never enter here */
|
||||||
if (exception != PTE_EPS_CANCEL && exception != PTE_EPS_EXIT)
|
if (exception != PTE_EPS_CANCEL && exception != PTE_EPS_EXIT)
|
||||||
{
|
|
||||||
/* Should never enter here */
|
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == sp || sp->implicit)
|
if (NULL == sp || sp->implicit)
|
||||||
{
|
{
|
||||||
@ -962,8 +907,9 @@ void pte_throw (unsigned int exception)
|
|||||||
|
|
||||||
pte_thread_detach_and_exit_np ();
|
pte_thread_detach_and_exit_np ();
|
||||||
|
|
||||||
// pte_osThreadExit((void*)exitCode);
|
#if 0
|
||||||
|
pte_osThreadExit((void*)exitCode);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
pte_pop_cleanup_all (1);
|
pte_pop_cleanup_all (1);
|
||||||
@ -1026,19 +972,17 @@ int pte_tkAssocCreate (pte_thread_t * sp, pthread_key_t key)
|
|||||||
assoc = (ThreadKeyAssoc *) calloc (1, sizeof (*assoc));
|
assoc = (ThreadKeyAssoc *) calloc (1, sizeof (*assoc));
|
||||||
|
|
||||||
if (assoc == NULL)
|
if (assoc == NULL)
|
||||||
{
|
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
assoc->thread = sp;
|
assoc->thread = sp;
|
||||||
assoc->key = key;
|
assoc->key = key;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register assoc with key
|
* Register assoc with key
|
||||||
*/
|
*/
|
||||||
assoc->prevThread = NULL;
|
assoc->prevThread = NULL;
|
||||||
assoc->nextThread = (ThreadKeyAssoc *) key->threads;
|
assoc->nextThread = (ThreadKeyAssoc *) key->threads;
|
||||||
if (assoc->nextThread != NULL)
|
if (assoc->nextThread)
|
||||||
assoc->nextThread->prevThread = assoc;
|
assoc->nextThread->prevThread = assoc;
|
||||||
key->threads = (void *) assoc;
|
key->threads = (void *) assoc;
|
||||||
|
|
||||||
@ -1047,7 +991,7 @@ int pte_tkAssocCreate (pte_thread_t * sp, pthread_key_t key)
|
|||||||
*/
|
*/
|
||||||
assoc->prevKey = NULL;
|
assoc->prevKey = NULL;
|
||||||
assoc->nextKey = (ThreadKeyAssoc *) sp->keys;
|
assoc->nextKey = (ThreadKeyAssoc *) sp->keys;
|
||||||
if (assoc->nextKey != NULL)
|
if (assoc->nextKey)
|
||||||
assoc->nextKey->prevKey = assoc;
|
assoc->nextKey->prevKey = assoc;
|
||||||
sp->keys = (void *) assoc;
|
sp->keys = (void *) assoc;
|
||||||
|
|
||||||
@ -1069,48 +1013,47 @@ void pte_tkAssocDestroy (ThreadKeyAssoc * assoc)
|
|||||||
* -------------------------------------------------------------------
|
* -------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
ThreadKeyAssoc *prev = NULL;
|
||||||
|
ThreadKeyAssoc *next = NULL;
|
||||||
/*
|
/*
|
||||||
* Both key->keyLock and thread->threadLock are locked on
|
* Both key->keyLock and thread->threadLock are locked on
|
||||||
* entry to this routine.
|
* entry to this routine.
|
||||||
*/
|
*/
|
||||||
if (assoc != NULL)
|
if (!assoc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Remove assoc from thread's keys chain */
|
||||||
|
prev = assoc->prevKey;
|
||||||
|
next = assoc->nextKey;
|
||||||
|
if (prev)
|
||||||
|
prev->nextKey = next;
|
||||||
|
if (next)
|
||||||
|
next->prevKey = prev;
|
||||||
|
|
||||||
|
/* We're at the head of the thread's keys chain */
|
||||||
|
if (assoc->thread->keys == assoc)
|
||||||
|
assoc->thread->keys = next;
|
||||||
|
|
||||||
|
if (assoc->thread->nextAssoc == assoc)
|
||||||
{
|
{
|
||||||
ThreadKeyAssoc * prev, * next;
|
/*
|
||||||
|
* Thread is exiting and we're deleting the assoc to be processed next.
|
||||||
/* Remove assoc from thread's keys chain */
|
* Hand thread the assoc after this one.
|
||||||
prev = assoc->prevKey;
|
*/
|
||||||
next = assoc->nextKey;
|
assoc->thread->nextAssoc = next;
|
||||||
if (prev != NULL)
|
|
||||||
prev->nextKey = next;
|
|
||||||
if (next != NULL)
|
|
||||||
next->prevKey = prev;
|
|
||||||
|
|
||||||
/* We're at the head of the thread's keys chain */
|
|
||||||
if (assoc->thread->keys == assoc)
|
|
||||||
assoc->thread->keys = next;
|
|
||||||
|
|
||||||
if (assoc->thread->nextAssoc == assoc)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Thread is exiting and we're deleting the assoc to be processed next.
|
|
||||||
* Hand thread the assoc after this one.
|
|
||||||
*/
|
|
||||||
assoc->thread->nextAssoc = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove assoc from key's threads chain */
|
|
||||||
prev = assoc->prevThread;
|
|
||||||
next = assoc->nextThread;
|
|
||||||
if (prev != NULL)
|
|
||||||
prev->nextThread = next;
|
|
||||||
if (next != NULL)
|
|
||||||
next->prevThread = prev;
|
|
||||||
|
|
||||||
/* We're at the head of the key's threads chain */
|
|
||||||
if (assoc->key->threads == assoc)
|
|
||||||
assoc->key->threads = next;
|
|
||||||
|
|
||||||
free (assoc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove assoc from key's threads chain */
|
||||||
|
prev = assoc->prevThread;
|
||||||
|
next = assoc->nextThread;
|
||||||
|
if (prev)
|
||||||
|
prev->nextThread = next;
|
||||||
|
if (next)
|
||||||
|
next->prevThread = prev;
|
||||||
|
|
||||||
|
/* We're at the head of the key's threads chain */
|
||||||
|
if (assoc->key->threads == assoc)
|
||||||
|
assoc->key->threads = next;
|
||||||
|
|
||||||
|
free (assoc);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user