12 #include <sys/socket.h>
13 #include <sys/utsname.h>
15 #include <sys/types.h>
21 #ifdef LISP_FEATURE_SB_THREAD
22 #include <sys/segment.h>
23 #include <sys/sysi86.h>
28 #ifdef LISP_FEATURE_SB_THREAD
29 pthread_mutex_t modify_ldt_lock
= PTHREAD_MUTEX_INITIALIZER
;
32 ldt_index_selector (int index
) {
33 return index
<< 3 | 7;
37 find_free_ldt_index () {
39 int usage
[65536/sizeof(int)];
43 memset(usage
, 0, sizeof(usage
));
45 fp
= fopen("/proc/self/ldt", "r");
48 lose("Couldn't open /proc/self/ldt");
51 while (fread(&ssd
, sizeof(ssd
), 1, fp
) == 1) {
52 int index
= ssd
.sel
>> 3;
54 lose("segment selector index too large: %d", index
);
57 usage
[index
/ sizeof(int)] |= 1 << (index
& (sizeof(int)-1));
62 /* Magic number 7 is the first LDT index that Solaris leaves free. */
63 for (i
= 7; i
< 65536; i
++) {
64 if (~usage
[i
/ sizeof(int)] & (1 << (i
& (sizeof(int)-1)))) {
69 lose("Couldn't find a free LDT index");
73 install_segment (unsigned long start
, unsigned long size
) {
76 thread_mutex_lock(&modify_ldt_lock
);
78 selector
= ldt_index_selector(find_free_ldt_index());
79 struct ssd ssd
= { selector
,
84 if (sysi86(SI86DSCR
, &ssd
) < 0) {
85 lose("Couldn't install segment for thread-local data");
88 thread_mutex_unlock(&modify_ldt_lock
);
94 int arch_os_thread_init(struct thread
*thread
) {
97 #ifdef LISP_FEATURE_SB_THREAD
98 int sel
= install_segment((unsigned long) thread
, dynamic_values_bytes
);
100 FSHOW_SIGNAL((stderr
, "/ TLS: Allocated LDT %x\n", sel
));
101 __asm__
__volatile__ ("mov %0, %%fs" : : "r"(sel
));
103 thread
->tls_cookie
= sel
;
104 pthread_setspecific(specials
,thread
);
107 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
108 /* Signal handlers are run on the control stack, so if it is exhausted
109 * we had better use an alternate stack for whatever signal tells us
110 * we've exhausted it */
111 sigstack
.ss_sp
=((void *) thread
)+dynamic_values_bytes
;
113 sigstack
.ss_size
= 32*SIGSTKSZ
;
114 sigaltstack(&sigstack
,0);
116 return 1; /* success */
119 int arch_os_thread_cleanup(struct thread
*thread
) {
120 #if defined(LISP_FEATURE_SB_THREAD)
121 int n
= thread
->tls_cookie
;
122 struct ssd
delete = { n
, 0, 0, 0, 0};
124 /* Set the %%fs register back to 0 and free the ldt by setting it
127 FSHOW_SIGNAL((stderr
, "/ TLS: Freeing LDT %x\n", n
));
129 __asm__
__volatile__ ("mov %0, %%fs" : : "r"(0));
131 thread_mutex_lock(&modify_ldt_lock
);
132 if (sysi86(SI86DSCR
, &delete) < 0) {
133 lose("Couldn't remove segment\n");
135 thread_mutex_unlock(&modify_ldt_lock
);
137 return 1; /* success */
140 os_context_register_t
*
141 os_context_register_addr(os_context_t
*context
, int offset
)
143 /* Solaris x86 holds %esp value in UESP */
145 case reg_EAX
: return &context
->uc_mcontext
.gregs
[11];
146 case reg_ECX
: return &context
->uc_mcontext
.gregs
[10];
147 case reg_EDX
: return &context
->uc_mcontext
.gregs
[9];
148 case reg_EBX
: return &context
->uc_mcontext
.gregs
[8];
149 case reg_ESP
: return &context
->uc_mcontext
.gregs
[17]; /* REG_UESP */
150 case reg_EBP
: return &context
->uc_mcontext
.gregs
[6];
151 case reg_ESI
: return &context
->uc_mcontext
.gregs
[5];
152 case reg_EDI
: return &context
->uc_mcontext
.gregs
[4];
155 return &context
->uc_mcontext
.gregs
[offset
];
158 os_context_register_t
*
159 os_context_pc_addr(os_context_t
*context
)
161 return &(context
->uc_mcontext
.gregs
[14]); /* REG_EIP */
164 os_context_register_t
*
165 os_context_sp_addr(os_context_t
*context
)
167 return &(context
->uc_mcontext
.gregs
[17]); /* REG_UESP */
171 os_context_sigmask_addr(os_context_t
*context
)
173 return &(context
->uc_sigmask
);
176 void os_flush_icache(os_vm_address_t address
, os_vm_size_t length
)
181 os_context_fp_control(os_context_t
*context
)
183 int *state
= context
->uc_mcontext
.fpregs
.fp_reg_set
.fpchip_state
.state
;
184 /* The STATE array is in the format used by the x86 instruction FNSAVE,
185 * so the FPU control word is in the first 16 bits */
186 int cw
= (state
[0] & 0xffff);
187 int sw
= context
->uc_mcontext
.fpregs
.fp_reg_set
.fpchip_state
.status
;
188 return (cw
^ 0x3f) | (sw
<< 16);