summaryrefslogtreecommitdiff
path: root/arch/sh/src/__set_thread_area.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2015-06-16 14:28:30 +0000
committerRich Felker <dalias@aerifal.cx>2015-06-16 14:38:41 +0000
commitf9d84554bae0fa17c9a1d724549c4408022228a5 (patch)
treee40d11d2c4af3c4bef11720664e92a288e6d37e4 /arch/sh/src/__set_thread_area.c
parent1b0cdc8700d29ef018bf226d74b2b58b23bce91c (diff)
downloadmusl-f9d84554bae0fa17c9a1d724549c4408022228a5.tar.gz
add support for sh2 interrupt-masking-based atomics to sh port
the sh2 target is being considered an ISA subset of sh3/sh4, in the sense that binaries built for sh2 are intended to be usable on later cpu models/kernels with mmu support. so rather than hard-coding sh2-specific atomics, the runtime atomic selection mechanisms that was already in place has been extended to add sh2 atomics. at this time, the sh2 atomics are not SMP-compatible; since the ISA lacks actual atomic operations, the new code instead masks interrupts for the duration of the atomic operation, producing an atomic result on single-core. this is only possible because the kernel/hardware does not impose protections against userspace doing so. additional changes will be needed to support future SMP systems. care has been taken to avoid producing significant additional code size in the case where it's known at compile-time that the target is not sh2 and does not need sh2-specific code.
Diffstat (limited to 'arch/sh/src/__set_thread_area.c')
-rw-r--r--arch/sh/src/__set_thread_area.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/arch/sh/src/__set_thread_area.c b/arch/sh/src/__set_thread_area.c
new file mode 100644
index 00000000..1d3e0225
--- /dev/null
+++ b/arch/sh/src/__set_thread_area.c
@@ -0,0 +1,34 @@
+#include "pthread_impl.h"
+#include "libc.h"
+#include "sh_atomic.h"
+#include <elf.h>
+
+/* Also perform sh-specific init */
+
+#define CPU_HAS_LLSC 0x0040
+
+__attribute__((__visibility__("hidden"))) unsigned __sh_atomic_model, __sh_nommu;
+
+int __set_thread_area(void *p)
+{
+ size_t *aux;
+ __asm__ __volatile__ ( "ldc %0, gbr" : : "r"(p) : "memory" );
+#ifndef __SH4A__
+ if (__hwcap & CPU_HAS_LLSC) {
+ __sh_atomic_model = SH_A_LLSC;
+ return 0;
+ }
+#if !defined(__SH3__) && !defined(__SH4__)
+ for (aux=libc.auxv; *aux; aux+=2) {
+ if (*aux != AT_PLATFORM) continue;
+ const char *s = (void *)aux[1];
+ if (s[0]!='s' || s[1]!='h' || s[2]!='2' || s[3]-'0'<10u) break;
+ __sh_atomic_model = SH_A_IMASK;
+ __sh_nommu = 1;
+ return 0;
+ }
+#endif
+ /* __sh_atomic_model = SH_A_GUSA; */ /* 0, default */
+#endif
+ return 0;
+}