summaryrefslogtreecommitdiffhomepage
path: root/arch/nt32/pthread_arch.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/nt32/pthread_arch.h')
-rw-r--r--arch/nt32/pthread_arch.h74
1 files changed, 74 insertions, 0 deletions
diff --git a/arch/nt32/pthread_arch.h b/arch/nt32/pthread_arch.h
new file mode 100644
index 0000000..d5f2553
--- /dev/null
+++ b/arch/nt32/pthread_arch.h
@@ -0,0 +1,74 @@
+#include <stddef.h>
+
+#define TP_ADJ(p) (p)
+#define CANCEL_REG_IP 16
+
+extern uintptr_t __teb_sys_idx;
+extern uintptr_t __teb_libc_idx;
+
+struct __os_tib {
+ void * exception_list;
+ void * stack_base;
+ void * stack_limit;
+};
+
+static __inline__ void * __os_get_teb_address(void)
+{
+ void * ptrRet;
+ __asm__ __volatile__ (
+ "mov %%fs:0x18, %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+
+static inline void __pthread_convert(void)
+{
+ /* (third-party thread support) */
+ __asm__ __volatile__ (
+ "push %eax\n\t"
+ "mov ___psx_vtbl,%eax\n\t"
+ "call *(%eax)\n\t"
+ "pop %eax\n\t"
+ );
+}
+
+
+static inline struct pthread ** __psx_tlca(void)
+{
+ struct pthread ** ptlca;
+ struct __os_tib * tib;
+ void ** slots;
+ void *** xslots;
+ uintptr_t sys_idx;
+
+ tib = __os_get_teb_address();
+ sys_idx = __teb_sys_idx;
+
+ if (sys_idx < 64) {
+ slots = (void **)((uintptr_t)tib + 0xa40);
+ ptlca = (struct pthread **)(slots[sys_idx]);
+ } else {
+ xslots = (void ***)((uintptr_t)tib + 0xbc0);
+ slots = *xslots;
+ ptlca = (struct pthread **)(slots[sys_idx - 64]);
+ }
+
+ return ptlca;
+}
+
+
+static inline struct pthread * __pthread_self(void)
+{
+ struct pthread ** ptlca;
+
+ ptlca = __psx_tlca();
+ if (ptlca) return *ptlca;
+
+ /* (third-party thread) */
+ __pthread_convert();
+ ptlca = __psx_tlca();
+ return *ptlca;
+}
+