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