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