summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Chisnall <dchisnall@pathscale.com>2011-11-24 17:17:26 +0000
committerDavid Chisnall <dchisnall@pathscale.com>2011-11-24 17:17:26 +0000
commit8931d9e5180830a5433d16ae6b3ad8dd9e629512 (patch)
treedf0c27b502ea5e999dd6aee617dfc9e2f78317fd /src
parentc7d66e279e31c0523bcb8bc5b1dd5c98260f0848 (diff)
downloadlibcxxrt-8931d9e5180830a5433d16ae6b3ad8dd9e629512.tar.gz
libcxxrt-8931d9e5180830a5433d16ae6b3ad8dd9e629512.tar.bz2
libcxxrt-8931d9e5180830a5433d16ae6b3ad8dd9e629512.tar.xz
Make all pthread symbols weak and test before calling any of them. This should allow us to work on platforms like GNU/Linux that don't export pthread stubs in libc.
Diffstat (limited to 'src')
-rw-r--r--src/exception.cc58
1 files changed, 51 insertions, 7 deletions
diff --git a/src/exception.cc b/src/exception.cc
index 0896354..2da7454 100644
--- a/src/exception.cc
+++ b/src/exception.cc
@@ -8,6 +8,17 @@
#include "dwarf_eh.h"
#include "cxxabi.h"
+#pragma weak pthread_key_create
+#pragma weak pthread_setspecific
+#pragma weak pthread_getspecific
+#pragma weak pthread_once
+#pragma weak pthread_once
+#pragma weak pthread_cond_signal
+#pragma weak pthread_cond_wait
+#pragma weak pthread_mutex_lock
+#pragma weak pthread_mutex_unlock
+
+
using namespace ABI_NAMESPACE;
/**
@@ -303,6 +314,13 @@ static __cxa_thread_info singleThreadInfo;
*/
static void init_key(void)
{
+ if ((0 == pthread_key_create) ||
+ (0 == pthread_setspecific) ||
+ (0 == pthread_getspecific))
+ {
+ fakeTLS = true;
+ return;
+ }
pthread_key_create(&eh_key, thread_cleanup);
pthread_setspecific(eh_key, (void*)0x42);
fakeTLS = (pthread_getspecific(eh_key) != (void*)0x42);
@@ -314,7 +332,7 @@ static void init_key(void)
*/
static __cxa_thread_info *thread_info()
{
- if (pthread_once(&once_control, init_key))
+ if ((0 == pthread_once) || pthread_once(&once_control, init_key))
{
fakeTLS = true;
}
@@ -385,7 +403,10 @@ static char *emergency_malloc(size_t size)
// Only 4 emergency buffers allowed per thread!
if (info->emergencyBuffersHeld > 3) { return 0; }
- pthread_mutex_lock(&emergency_malloc_lock);
+ if (pthread_mutex_lock)
+ {
+ pthread_mutex_lock(&emergency_malloc_lock);
+ }
int buffer = -1;
while (buffer < 0)
{
@@ -396,7 +417,10 @@ static char *emergency_malloc(size_t size)
void *m = calloc(1, size);
if (0 != m)
{
- pthread_mutex_unlock(&emergency_malloc_lock);
+ if (pthread_mutex_unlock)
+ {
+ pthread_mutex_unlock(&emergency_malloc_lock);
+ }
return (char*)m;
}
for (int i=0 ; i<16 ; i++)
@@ -413,10 +437,24 @@ static char *emergency_malloc(size_t size)
// of the emergency buffers.
if (buffer < 0)
{
+ // If we don't have pthread_cond_wait, then there is only one
+ // thread and it's already used all of the emergency buffers, so we
+ // have no alternative but to die. Calling abort() instead of
+ // terminate, because terminate can throw exceptions, which can
+ // bring us back here and infinite loop.
+ if (!pthread_cond_wait)
+ {
+ fputs("Terminating while out of memory trying to throw an exception",
+ stderr);
+ abort();
+ }
pthread_cond_wait(&emergency_malloc_wait, &emergency_malloc_lock);
}
}
- pthread_mutex_unlock(&emergency_malloc_lock);
+ if (pthread_mutex_unlock)
+ {
+ pthread_mutex_unlock(&emergency_malloc_lock);
+ }
info->emergencyBuffersHeld++;
return emergency_buffer + (1024 * buffer);
}
@@ -449,13 +487,19 @@ static void emergency_malloc_free(char *ptr)
memset((void*)ptr, 0, 1024);
// Signal the condition variable to wake up any threads that are blocking
// waiting for some space in the emergency buffer
- pthread_mutex_lock(&emergency_malloc_lock);
+ if (pthread_mutex_lock)
+ {
+ pthread_mutex_lock(&emergency_malloc_lock);
+ }
// In theory, we don't need to do this with the lock held. In practice,
// our array of bools will probably be updated using 32-bit or 64-bit
// memory operations, so this update may clobber adjacent values.
buffer_allocated[buffer] = false;
- pthread_cond_signal(&emergency_malloc_wait);
- pthread_mutex_unlock(&emergency_malloc_lock);
+ if (pthread_cond_signal && pthread_mutex_unlock)
+ {
+ pthread_cond_signal(&emergency_malloc_wait);
+ pthread_mutex_unlock(&emergency_malloc_lock);
+ }
}
static char *alloc_or_die(size_t size)