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