4 #include "genesis/sbcl.h"
13 #include <sys/types.h>
19 #ifdef LISP_FEATURE_SB_THREAD
20 #include <sys/segment.h>
21 #include <sys/sysi86.h>
26 #ifdef LISP_FEATURE_SB_THREAD
27 pthread_mutex_t modify_ldt_lock
= PTHREAD_MUTEX_INITIALIZER
;
30 ldt_index_selector (int index
) {
31 return index
<< 3 | 7;
35 find_free_ldt_index () {
37 int usage
[65536/sizeof(int)];
41 memset(usage
, 0, sizeof(usage
));
43 fp
= fopen("/proc/self/ldt", "r");
46 lose("Couldn't open /proc/self/ldt");
49 while (fread(&ssd
, sizeof(ssd
), 1, fp
) == 1) {
50 int index
= ssd
.sel
>> 3;
52 lose("segment selector index too large: %d", index
);
55 usage
[index
/ sizeof(int)] |= 1 << (index
& (sizeof(int)-1));
60 /* Magic number 7 is the first LDT index that Solaris leaves free. */
61 for (i
= 7; i
< 65536; i
++) {
62 if (~usage
[i
/ sizeof(int)] & (1 << (i
& (sizeof(int)-1)))) {
67 lose("Couldn't find a free LDT index");
71 install_segment (unsigned long start
, unsigned long size
) {
74 ignore_value(mutex_acquire(&modify_ldt_lock
));
76 selector
= ldt_index_selector(find_free_ldt_index());
77 struct ssd ssd
= { selector
,
82 if (sysi86(SI86DSCR
, &ssd
) < 0) {
83 lose("Couldn't install segment for thread-local data");
86 ignore_value(mutex_release(&modify_ldt_lock
));
92 int arch_os_thread_init(struct thread
*thread
) {
95 #ifdef LISP_FEATURE_SB_THREAD
96 int sel
= install_segment((unsigned long) thread
, dynamic_values_bytes
);
98 __asm__
__volatile__ ("mov %0, %%fs" : : "r"(sel
));
100 thread
->tls_cookie
= sel
;
103 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
104 /* Signal handlers are run on the control stack, so if it is exhausted
105 * we had better use an alternate stack for whatever signal tells us
106 * we've exhausted it */
107 sigstack
.ss_sp
= calc_altstack_base(thread
);
108 sigstack
.ss_flags
= 0;
109 sigstack
.ss_size
= calc_altstack_size(thread
);
110 if (sigaltstack(&sigstack
,0)<0)
111 lose("Cannot sigaltstack: %s",strerror(errno
));
113 return 1; /* success */
116 int arch_os_thread_cleanup(struct thread
*thread
) {
117 #if defined(LISP_FEATURE_SB_THREAD)
118 int n
= thread
->tls_cookie
;
119 struct ssd
delete = { n
, 0, 0, 0, 0};
121 /* Set the %%fs register back to 0 and free the ldt by setting it
124 __asm__
__volatile__ ("mov %0, %%fs" : : "r"(0));
126 ignore_value(mutex_acquire(&modify_ldt_lock
));
127 if (sysi86(SI86DSCR
, &delete) < 0) {
128 lose("Couldn't remove segment");
130 ignore_value(mutex_release(&modify_ldt_lock
));
132 return 1; /* success */
135 os_context_register_t
*
136 os_context_register_addr(os_context_t
*context
, int offset
)
138 /* Solaris x86 holds %esp value in UESP */
140 case reg_EAX
: return &context
->uc_mcontext
.gregs
[11];
141 case reg_ECX
: return &context
->uc_mcontext
.gregs
[10];
142 case reg_EDX
: return &context
->uc_mcontext
.gregs
[9];
143 case reg_EBX
: return &context
->uc_mcontext
.gregs
[8];
144 case reg_ESP
: return &context
->uc_mcontext
.gregs
[17]; /* REG_UESP */
145 case reg_EBP
: return &context
->uc_mcontext
.gregs
[6];
146 case reg_ESI
: return &context
->uc_mcontext
.gregs
[5];
147 case reg_EDI
: return &context
->uc_mcontext
.gregs
[4];
150 return &context
->uc_mcontext
.gregs
[offset
];
153 os_context_register_t
*
154 os_context_sp_addr(os_context_t
*context
)
156 return &(context
->uc_mcontext
.gregs
[17]); /* REG_UESP */
160 os_context_sigmask_addr(os_context_t
*context
)
162 return &(context
->uc_sigmask
);
165 void os_flush_icache(os_vm_address_t address
, os_vm_size_t length
)
170 os_context_fp_control(os_context_t
*context
)
172 int *state
= context
->uc_mcontext
.fpregs
.fp_reg_set
.fpchip_state
.state
;
173 /* The STATE array is in the format used by the x86 instruction FNSAVE,
174 * so the FPU control word is in the first 16 bits */
175 int cw
= (state
[0] & 0xffff);
176 int sw
= context
->uc_mcontext
.fpregs
.fp_reg_set
.fpchip_state
.status
;
177 return (cw
^ 0x3f) | (sw
<< 16);