aboutsummaryrefslogtreecommitdiff
path: root/src/Platform/Posix/Tss.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Platform/Posix/Tss.c')
-rw-r--r--src/Platform/Posix/Tss.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/Platform/Posix/Tss.c b/src/Platform/Posix/Tss.c
new file mode 100644
index 0000000..a16d653
--- /dev/null
+++ b/src/Platform/Posix/Tss.c
@@ -0,0 +1,97 @@
+#include "Thread.h"
+
+#include <BH/Thread.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static int tssCleanupLock = 0;
+static int tssCleanupSize = 0;
+static BH_GenericCallback tssCleanupData[BH_MAX_TSS];
+
+static int tssLock = 0;
+static int tssReady = 0;
+static pthread_key_t tssKey;
+
+
+static void BH_TssKeyCleanup(void *data)
+{
+ int i;
+
+ /* Lock cleanup table and call cleanups */
+ BH_SpinlockLock(&tssCleanupLock);
+ for (i = 0; i < tssCleanupSize; i++)
+ tssCleanupData[i](((void **)data)[i]);
+ BH_SpinlockUnlock(&tssCleanupLock);
+
+ free(data);
+}
+
+
+static void **BH_TssDataFetch(void)
+{
+ void **result;
+
+ /* Get or setup TSS data */
+ BH_SpinlockLock(&tssLock);
+ if (!tssReady)
+ {
+ if (pthread_key_create(&tssKey, BH_TssKeyCleanup))
+ abort();
+ tssReady = 1;
+ }
+ BH_SpinlockUnlock(&tssLock);
+
+ /* Get or setup TSS data */
+ result = pthread_getspecific(tssKey);
+ if (!result)
+ {
+ result = malloc(sizeof(void *) * BH_MAX_TSS);
+ if (!result)
+ abort();
+
+ memset(result, 0, sizeof(sizeof(void *) * BH_MAX_TSS));
+ if (pthread_setspecific(tssKey, result))
+ abort();
+ }
+
+ return result;
+}
+
+
+void BH_TssCleanup(void)
+{
+ BH_TssKeyCleanup(BH_TssDataFetch());
+}
+
+
+int BH_TssCreate(BH_GenericCallback callback)
+{
+ int result;
+
+ /* Lock info and set up cleanup function */
+ BH_SpinlockLock(&tssCleanupLock);
+ if (tssCleanupSize < BH_MAX_TSS)
+ {
+ tssCleanupData[tssCleanupSize] = callback;
+ result = tssCleanupSize++;
+ }
+ else
+ result = BH_ERROR;
+ BH_SpinlockUnlock(&tssCleanupLock);
+
+ return result;
+}
+
+
+void *BH_TssRead(int index)
+{
+ return BH_TssDataFetch()[index];
+}
+
+
+void BH_TssWrite(int index,
+ void *value)
+{
+ BH_TssDataFetch()[index] = value;
+}