Home | History | Annotate | Download | only in solaris
      1 /* Tests that the process can exit even if daemon thread is still running.
      2    This test does *not* use any libc; it interfaces only with kernel. */
      3 
      4 #include <sys/lwp.h>
      5 #include <sys/mman.h>
      6 #include <sys/regset.h>
      7 #include <sys/syscall.h>
      8 #include <sys/ucontext.h>
      9 
     10 #if defined(__amd64) || defined(__i386)
     11 #include <sys/segments.h>
     12 #endif
     13 
     14 extern void bzero(void *ptr, size_t n);
     15 
     16 #if defined(VGP_x86_solaris)
     17 asm("\n"
     18 ".text\n"
     19 ".globl bzero\n"
     20 "bzero:\n"
     21 "   push %edi\n"
     22 "   movl $0, %eax\n"
     23 "   movl 12(%esp), %ecx\n"
     24 "   movl 8(%esp), %edi\n"
     25 "   rep  stosb\n"
     26 "   pop  %edi\n"
     27 "   ret\n"
     28 );
     29 #elif defined(VGP_amd64_solaris)
     30 asm("\n"
     31 ".text\n"
     32 ".globl bzero\n"
     33 "bzero:\n"
     34 "   push %rdi\n"
     35 "   movq %rsi, %rcx\n"
     36 "   movq $0, %rax\n"
     37 "   rep  stosb\n"
     38 "   pop  %rdi\n"
     39 "   ret\n"
     40 );
     41 #else
     42 #  error "Unknown platform"
     43 #endif
     44 
     45 static void sleep(unsigned int sec) {
     46    timespec_t ts;
     47    ts.tv_sec = (time_t)sec;
     48    ts.tv_nsec = 0;
     49 
     50 #if defined(VGP_x86_solaris)
     51    __asm__ __volatile__ (
     52       "pushl $0\n"
     53       "pushl %[TS]\n"
     54       "pushl $0xdeadbeef\n"
     55       "movl  %[SYSNO], %%eax\n"
     56       "int   $0x91\n"
     57       "addl  $12, %%esp\n"
     58       :
     59       : [TS] "g" (&ts), [SYSNO] "n" (SYS_nanosleep)
     60       : "eax", "edx", "cc", "memory");
     61 #elif defined(VGP_amd64_solaris)
     62    __asm__ __volatile__ (
     63       "movq %[SYSNO], %%rax\n"
     64       "movq %[TS], %%rdi\n"
     65       "movq $0, %%rsi\n"
     66       "syscall\n"
     67       :
     68       : [TS] "g" (&ts), [SYSNO] "n" (SYS_nanosleep)
     69       : "rax", "rdx", "rdi", "rsi", "cc", "memory");
     70 #else
     71 #  error "Unknown platform"
     72 #endif
     73 }
     74 
     75 static void lwp_exit(void) {
     76 #if defined(VGP_x86_solaris)
     77    __asm__ __volatile__ (
     78       "movl %[SYSNO], %%eax\n"
     79       "int  $0x91\n"
     80       :
     81       : [SYSNO] "n" (SYS_lwp_exit)
     82       : "eax", "edx", "cc", "memory");
     83 #elif defined(VGP_amd64_solaris)
     84    __asm__ __volatile__ (
     85       "movq %[SYSNO], %%rax\n"
     86       "syscall\n"
     87       :
     88       : [SYSNO] "n" (SYS_lwp_exit)
     89       : "rax", "rdx", "cc", "memory");
     90 #else
     91 #  error "Unknown platform"
     92 #endif
     93 }
     94 
     95 #define STACK_FLAGS (MAP_PRIVATE | MAP_NORESERVE | MAP_ANON)
     96 #define STACK_PROT  (PROT_READ | PROT_WRITE)
     97 static void *allocate_stack(size_t stacksize) {
     98    void *address = NULL;
     99 
    100 #if defined(VGP_x86_solaris)
    101    __asm__ __volatile__ (
    102       "pushl $0\n"
    103       "pushl $-1\n"
    104       "pushl %[FLAGS]\n"
    105       "pushl %[PROT]\n"
    106       "pushl %[SIZE]\n"
    107       "pushl $0\n"
    108       "pushl $0xdeadbeef\n"
    109       "movl  %[SYSNO], %%eax\n"
    110       "int   $0x91\n"
    111       "addl  $28, %%esp\n"
    112       "movl %%eax, %[ADDRESS]\n"
    113       : [ADDRESS] "=r" (address)
    114       : [FLAGS] "n" (STACK_FLAGS), [PROT] "n" (STACK_PROT),
    115         [SIZE] "g" (stacksize), [SYSNO] "n" (SYS_mmap)
    116       : "eax", "edx", "cc", "memory");
    117 #elif defined(VGP_amd64_solaris)
    118    __asm__ __volatile__ (
    119       "movq %[SYSNO], %%rax\n"
    120       "movq $0, %%rdi\n"
    121       "movq %[SIZE], %%rsi\n"
    122       "movq %[PROT], %%rdx\n"
    123       "movq %[FLAGS], %%r10\n"
    124       "movq $-1, %%r8\n"
    125       "movq $0, %%r9\n"
    126       "syscall\n"
    127       "movq %%rax, %[ADDRESS]\n"
    128       : [ADDRESS] "=r" (address)
    129       : [FLAGS] "n" (STACK_FLAGS), [PROT] "n" (STACK_PROT),
    130         [SIZE] "g" (stacksize), [SYSNO] "n" (SYS_mmap)
    131       : "rax", "rdx", "rdi", "rsi", "r10", "r8", "r9", "cc", "memory");
    132 #else
    133 #  error "Unknown platform"
    134 #endif
    135 
    136    return address;
    137 }
    138 #undef STACK_FLAGS
    139 #undef STACK_PROT
    140 
    141 static void thread_func(void) {
    142    sleep(10000);
    143 }
    144 
    145 #define LWP_FLAGS (LWP_SUSPENDED | LWP_DETACHED | LWP_DAEMON)
    146 static id_t lwp_create(void *stack) {
    147    id_t tid;
    148 
    149    ucontext_t ucontext;
    150    bzero(&ucontext, sizeof(ucontext));
    151    ucontext.uc_flags = UC_CPU;
    152 
    153 #if defined(VGP_x86_solaris)
    154    __asm__ __volatile__ (
    155       "mov %%ss, %[STACK_SEG]\n"
    156       : [STACK_SEG] "=r" (ucontext.uc_mcontext.gregs[SS])
    157       :
    158       :);
    159    ucontext.uc_mcontext.gregs[EIP] = (greg_t) thread_func;
    160    ucontext.uc_mcontext.gregs[UESP] = (greg_t) stack;
    161    ucontext.uc_mcontext.gregs[EBP] = (greg_t) stack;
    162 #elif defined(VGP_amd64_solaris)
    163    ucontext.uc_mcontext.gregs[REG_SS] = UDS_SEL;
    164    ucontext.uc_mcontext.gregs[REG_RIP] = (greg_t) thread_func;
    165    ucontext.uc_mcontext.gregs[REG_RSP] = (greg_t) stack;
    166    ucontext.uc_mcontext.gregs[REG_RBP] = (greg_t) stack;
    167 #else
    168 #  error "Unknown platform"
    169 #endif
    170 
    171 #if defined(VGP_x86_solaris)
    172    __asm__ __volatile__ (
    173       "pushl $0\n"
    174       "pushl %[FLAGS]\n"
    175       "pushl %[UCONTEXT]\n"
    176       "pushl $0xdeadbeef\n"
    177       "movl  %[SYSNO], %%eax\n"
    178       "int   $0x91\n"
    179       "addl  $16, %%esp\n"
    180       "movl %%eax, %[TID]\n"
    181       : [TID] "=r" (tid)
    182       : [FLAGS] "n" (LWP_FLAGS), [UCONTEXT] "g" (&ucontext),
    183         [SYSNO] "n" (SYS_lwp_create)
    184       : "eax", "edx", "cc", "memory");
    185 #elif defined(VGP_amd64_solaris)
    186    __asm__ __volatile__ (
    187       "movq %[SYSNO], %%rax\n"
    188       "movq %[UCONTEXT], %%rdi\n"
    189       "movq %[FLAGS], %%rsi\n"
    190       "movq $0, %%rdx\n"
    191       "syscall\n"
    192       "movl %%eax, %[TID]\n"
    193       : [TID] "=r" (tid)
    194       : [FLAGS] "n" (LWP_FLAGS), [UCONTEXT] "g" (&ucontext),
    195         [SYSNO] "n" (SYS_lwp_create)
    196       : "rax", "rdx", "rdi", "rsi", "cc", "memory");
    197 #else
    198 #  error "Unknown platform"
    199 #endif
    200 
    201    return tid;
    202 }
    203 
    204 static void lwp_continue(id_t tid) {
    205 #if defined(VGP_x86_solaris)
    206    __asm__ __volatile__ (
    207       "pushl %[TID]\n"
    208       "pushl $0xdeadbeef\n"
    209       "movl  %[SYSNO], %%eax\n"
    210       "int   $0x91\n"
    211       "addl  $8, %%esp\n"
    212       :
    213       : [TID] "m" (tid), [SYSNO] "n" (SYS_lwp_continue)
    214       : "eax", "edx", "cc", "memory");
    215 #elif defined(VGP_amd64_solaris)
    216    __asm__ __volatile__ (
    217       "movq %[SYSNO], %%rax\n"
    218       "xor %%rdi, %%rdi\n"
    219       "movl %[TID], %%edi\n"
    220       "syscall\n"
    221       :
    222       : [TID] "r" (tid), [SYSNO] "n" (SYS_lwp_continue)
    223       : "rax", "rdx", "rdi", "cc", "memory");
    224 #else
    225 #  error "Unknown platform"
    226 #endif
    227 }
    228 
    229 #define STACK_SIZE 16384
    230 void _start(void) {
    231    void *stack = allocate_stack(STACK_SIZE);
    232    id_t tid = lwp_create((char *) stack + STACK_SIZE);
    233    lwp_continue(tid);
    234    sleep(5);
    235    lwp_exit();
    236    return; /* not reached */
    237 }
    238 
    239