fa924d58554c9f4be692ec8901816992f3f00edf
[sbcl.git] / src / runtime / x86-darwin-os.c
1
2
3 #ifdef LISP_FEATURE_SB_THREAD
4 #include <architecture/i386/table.h>
5 #include <i386/user_ldt.h>
6 #include <mach/mach_init.h>
7 #endif
8
9 #include "thread.h"
10 #include "x86-darwin-os.h"
11
12 #ifdef LISP_FEATURE_SB_THREAD
13
14 pthread_mutex_t modify_ldt_lock = PTHREAD_MUTEX_INITIALIZER;
15
16 void set_data_desc_size(data_desc_t* desc, unsigned long size)
17 {
18     desc->limit00 = (size - 1) & 0xffff;
19     desc->limit16 = ((size - 1) >> 16) &0xf;
20 }
21
22 void set_data_desc_addr(data_desc_t* desc, void* addr)
23 {
24     desc->base00 = (unsigned int)addr & 0xffff;
25     desc->base16 = ((unsigned int)addr & 0xff0000) >> 16;
26     desc->base24 = ((unsigned int)addr & 0xff000000) >> 24;
27 }
28
29 #endif
30
31 int arch_os_thread_init(struct thread *thread) {
32 #ifdef LISP_FEATURE_SB_THREAD
33     int n;
34     sel_t sel;
35
36     data_desc_t ldt_entry = { 0, 0, 0, DESC_DATA_WRITE,
37                               3, 1, 0, DESC_DATA_32B, DESC_GRAN_BYTE, 0 };
38
39     set_data_desc_addr(&ldt_entry, (unsigned long) thread);
40     set_data_desc_size(&ldt_entry, dynamic_values_bytes);
41
42     thread_mutex_lock(&modify_ldt_lock);
43     n = i386_set_ldt(LDT_AUTO_ALLOC, (union ldt_entry*) &ldt_entry, 1);
44
45     if (n < 0) {
46         perror("i386_set_ldt");
47         lose("unexpected i386_set_ldt(..) failure\n");
48     }
49     thread_mutex_unlock(&modify_ldt_lock);
50
51     FSHOW_SIGNAL((stderr, "/ TLS: Allocated LDT %x\n", n));
52     sel.index = n;
53     sel.rpl = USER_PRIV;
54     sel.ti = SEL_LDT;
55
56     __asm__ __volatile__ ("mov %0, %%fs" : : "r"(sel));
57
58     thread->tls_cookie=n;
59     pthread_setspecific(specials,thread);
60 #endif
61
62 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
63     stack_t sigstack;
64
65     /* Signal handlers are run on the control stack, so if it is exhausted
66      * we had better use an alternate stack for whatever signal tells us
67      * we've exhausted it */
68     sigstack.ss_sp=((void *) thread)+dynamic_values_bytes;
69     sigstack.ss_flags=0;
70     sigstack.ss_size = 32*SIGSTKSZ;
71     sigaltstack(&sigstack,0);
72 #endif
73     return 1;                  /* success */
74 }
75
76 int arch_os_thread_cleanup(struct thread *thread) {
77 #if defined(LISP_FEATURE_SB_THREAD)
78     int n = thread->tls_cookie;
79
80     /* Set the %%fs register back to 0 and free the the ldt
81      * by setting it to NULL.
82      */
83     FSHOW_SIGNAL((stderr, "/ TLS: Freeing LDT %x\n", n));
84
85     __asm__ __volatile__ ("mov %0, %%fs" : : "r"(0));
86     thread_mutex_lock(&modify_ldt_lock);
87     i386_set_ldt(n, NULL, 1);
88     thread_mutex_unlock(&modify_ldt_lock);
89 #endif
90     return 1;                  /* success */
91 }
92