X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fx86-64-linux-os.c;h=e012289022eec477d7f0e3e9a6e8b23e2e75b3cd;hb=35ab27e7aab71c94aa6be12da15603c7fd87fca8;hp=c9968137911f1123c3baf6fdb9a9b33085d276b5;hpb=78fa16bf55be44cc16845be84d98023e83fb14bc;p=sbcl.git diff --git a/src/runtime/x86-64-linux-os.c b/src/runtime/x86-64-linux-os.c index c996813..e012289 100644 --- a/src/runtime/x86-64-linux-os.c +++ b/src/runtime/x86-64-linux-os.c @@ -1,6 +1,6 @@ /* - * The x86 Linux incarnation of arch-dependent OS-dependent routines. - * See also "linux-os.c". + * The x86-64 Linux incarnation of arch-dependent OS-dependent + * routines. See also "linux-os.c". */ /* @@ -14,6 +14,8 @@ * files for more information. */ +#define _GNU_SOURCE /* for REG_RAX etc. from sys/ucontext */ + #include #include #include @@ -22,10 +24,7 @@ #include #include -#define __USE_GNU #include -#undef __USE_GNU - #include "./signal.h" #include "os.h" @@ -48,67 +47,19 @@ #include #include #include -#include "thread.h" /* dynamic_values_bytes */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define user_desc modify_ldt_ldt_s -#endif - -_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount ); +#include "thread.h" /* dynamic_values_bytes */ #include "validate.h" size_t os_vm_page_size; -u32 local_ldt_copy[LDT_ENTRIES*LDT_ENTRY_SIZE/sizeof(u32)]; - -/* This is never actually called, but it's great for calling from gdb when - * users have thread-related problems that maintainers can't duplicate */ - -void debug_get_ldt() -{ - int n=modify_ldt (0, local_ldt_copy, sizeof local_ldt_copy); - printf("%d bytes in ldt: print/x local_ldt_copy\n", n); -} - -lispobj modify_ldt_lock; /* protect all calls to modify_ldt */ - int arch_os_thread_init(struct thread *thread) { stack_t sigstack; #ifdef LISP_FEATURE_SB_THREAD - /* this must be called from a function that has an exclusive lock - * on all_threads - */ - struct user_desc ldt_entry = { - 1, 0, 0, /* index, address, length filled in later */ - 1, MODIFY_LDT_CONTENTS_DATA, 0, 0, 0, 1 - }; - int n; - get_spinlock(&modify_ldt_lock,thread); - n=modify_ldt(0,local_ldt_copy,sizeof local_ldt_copy); - /* get next free ldt entry */ - - if(n) { - u32 *p; - for(n=0,p=local_ldt_copy;*p;p+=LDT_ENTRY_SIZE/sizeof(u32)) - n++; - } - ldt_entry.entry_number=n; - ldt_entry.base_addr=(unsigned long) thread; - ldt_entry.limit=dynamic_values_bytes; - ldt_entry.limit_in_pages=0; - if (modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0) { - modify_ldt_lock=0; - /* modify_ldt call failed: something magical is not happening */ - return -1; - } - __asm__ __volatile__ ("movw %w0, %%fs" : : "q" - ((n << 3) /* selector number */ - + (1 << 2) /* TI set = LDT */ - + 3)); /* privilege level */ - thread->tls_cookie=n; - modify_ldt_lock=0; - - if(n<0) return 0; +#ifdef LISP_FEATURE_GCC_TLS + current_thread = thread; +#else + pthread_setspecific(specials,thread); +#endif #endif #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK /* Signal handlers are run on the control stack, so if it is exhausted @@ -117,35 +68,18 @@ int arch_os_thread_init(struct thread *thread) { sigstack.ss_sp=((void *) thread)+dynamic_values_bytes; sigstack.ss_flags=0; sigstack.ss_size = 32*SIGSTKSZ; - sigaltstack(&sigstack,0); + if(sigaltstack(&sigstack,0)<0) { + lose("Cannot sigaltstack: %s\n",strerror(errno)); + } #endif return 1; } -struct thread *debug_get_fs() { - register u32 fs; - __asm__ __volatile__ ("movl %%fs,%0" : "=r" (fs) : ); - return fs; -} - /* free any arch/os-specific resources used by thread, which is now * defunct. Not called on live threads */ int arch_os_thread_cleanup(struct thread *thread) { - struct user_desc ldt_entry = { - 0, 0, 0, - 0, MODIFY_LDT_CONTENTS_DATA, 0, 0, 0, 0 - }; - - ldt_entry.entry_number=thread->tls_cookie; - get_spinlock(&modify_ldt_lock,thread); - if (modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0) { - modify_ldt_lock=0; - /* modify_ldt call failed: something magical is not happening */ - return 0; - } - modify_ldt_lock=0; return 1; } @@ -156,25 +90,25 @@ os_context_register_addr(os_context_t *context, int offset) #define RCASE(name) case reg_ ## name: return &context->uc_mcontext.gregs[REG_ ## name]; switch(offset) { RCASE(RAX) - RCASE(RCX) - RCASE(RDX) - RCASE(RBX) - RCASE(RSP) - RCASE(RBP) - RCASE(RSI) - RCASE(RDI) - RCASE(R8) - RCASE(R9) - RCASE(R10) - RCASE(R11) - RCASE(R12) - RCASE(R13) - RCASE(R14) - RCASE(R15) - default: - if(offsetuc_mcontext.gregs[offset/2+4]; - else return 0; + RCASE(RCX) + RCASE(RDX) + RCASE(RBX) + RCASE(RSP) + RCASE(RBP) + RCASE(RSI) + RCASE(RDI) + RCASE(R8) + RCASE(R9) + RCASE(R10) + RCASE(R11) + RCASE(R12) + RCASE(R13) + RCASE(R14) + RCASE(R15) + default: + if(offsetuc_mcontext.gregs[offset/2+4]; + else return 0; } return &context->uc_mcontext.gregs[offset]; } @@ -187,7 +121,7 @@ os_context_pc_addr(os_context_t *context) os_context_register_t * os_context_sp_addr(os_context_t *context) -{ +{ return &context->uc_mcontext.gregs[REG_RSP]; } @@ -200,12 +134,11 @@ os_context_fp_addr(os_context_t *context) unsigned long os_context_fp_control(os_context_t *context) { -#if 0 - return ((((context->uc_mcontext.fpregs->cw) & 0xffff) ^ 0x3f) | - (((context->uc_mcontext.fpregs->sw) & 0xffff) << 16)); -#else - return 0; -#endif + /* return the x87 exception flags ored in with the sse2 + * control+status flags */ + unsigned int result = (context->uc_mcontext.fpregs->swd & 0x3F) | context->uc_mcontext.fpregs->mxcsr; + /* flip exception mask bits */ + return result ^ (0x3F << 7); } sigset_t * @@ -217,9 +150,13 @@ os_context_sigmask_addr(os_context_t *context) void os_restore_fp_control(os_context_t *context) { -#if 0 - asm ("fldcw %0" : : "m" (context->uc_mcontext.fpregs->cw)); -#endif + if (context->uc_mcontext.fpregs) { + /* reset exception flags and restore control flags on SSE2 FPU */ + unsigned int temp = (context->uc_mcontext.fpregs->mxcsr) & ~0x3F; + asm ("ldmxcsr %0" : : "m" (temp)); + /* same for x87 FPU. */ + asm ("fldcw %0" : : "m" (context->uc_mcontext.fpregs->cwd)); + } } void