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
);
106 # ifdef LISP_FEATURE_SB_SAFEPOINT
107 thread
->selfptr
= thread
;
111 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
112 /* Signal handlers are run on the control stack, so if it is exhausted
113 * we had better use an alternate stack for whatever signal tells us
114 * we've exhausted it */
115 sigstack
.ss_sp
=((void *) thread
)+dynamic_values_bytes
;
117 sigstack
.ss_size
= 32*SIGSTKSZ
;
118 sigaltstack(&sigstack
,0);
120 return 1; /* success */
123 int arch_os_thread_cleanup(struct thread
*thread
) {
124 #if defined(LISP_FEATURE_SB_THREAD)
125 int n
= thread
->tls_cookie
;
126 struct ssd
delete = { n
, 0, 0, 0, 0};
128 /* Set the %%fs register back to 0 and free the ldt by setting it
131 FSHOW_SIGNAL((stderr
, "/ TLS: Freeing LDT %x\n", n
));
133 __asm__
__volatile__ ("mov %0, %%fs" : : "r"(0));
135 thread_mutex_lock(&modify_ldt_lock
);
136 if (sysi86(SI86DSCR
, &delete) < 0) {
137 lose("Couldn't remove segment\n");
139 thread_mutex_unlock(&modify_ldt_lock
);
141 return 1; /* success */
144 os_context_register_t
*
145 os_context_register_addr(os_context_t
*context
, int offset
)
147 /* Solaris x86 holds %esp value in UESP */
149 case reg_EAX
: return &context
->uc_mcontext
.gregs
[11];
150 case reg_ECX
: return &context
->uc_mcontext
.gregs
[10];
151 case reg_EDX
: return &context
->uc_mcontext
.gregs
[9];
152 case reg_EBX
: return &context
->uc_mcontext
.gregs
[8];
153 case reg_ESP
: return &context
->uc_mcontext
.gregs
[17]; /* REG_UESP */
154 case reg_EBP
: return &context
->uc_mcontext
.gregs
[6];
155 case reg_ESI
: return &context
->uc_mcontext
.gregs
[5];
156 case reg_EDI
: return &context
->uc_mcontext
.gregs
[4];
159 return &context
->uc_mcontext
.gregs
[offset
];
162 os_context_register_t
*
163 os_context_pc_addr(os_context_t
*context
)
165 return &(context
->uc_mcontext
.gregs
[14]); /* REG_EIP */
168 os_context_register_t
*
169 os_context_sp_addr(os_context_t
*context
)
171 return &(context
->uc_mcontext
.gregs
[17]); /* REG_UESP */
175 os_context_sigmask_addr(os_context_t
*context
)
177 return &(context
->uc_sigmask
);
180 void os_flush_icache(os_vm_address_t address
, os_vm_size_t length
)
185 os_context_fp_control(os_context_t
*context
)
187 int *state
= context
->uc_mcontext
.fpregs
.fp_reg_set
.fpchip_state
.state
;
188 /* The STATE array is in the format used by the x86 instruction FNSAVE,
189 * so the FPU control word is in the first 16 bits */
190 int cw
= (state
[0] & 0xffff);
191 int sw
= context
->uc_mcontext
.fpregs
.fp_reg_set
.fpchip_state
.status
;
192 return (cw
^ 0x3f) | (sw
<< 16);