(really) Bug 477630 - Include ucontext.h rather than sys/ucontext.h in Solaris sources
[valgrind.git] / memcheck / tests / solaris / thr_daemon_exit_standalone.c
blob791cc363a7cbafe9bd189f77024cd53e16a48787
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. */
4 #include <sys/lwp.h>
5 #include <sys/mman.h>
6 #include <sys/regset.h>
7 #include <sys/syscall.h>
8 #include <ucontext.h>
10 #if defined(__amd64) || defined(__i386)
11 #include <sys/segments.h>
12 #endif
14 extern void bzero(void *ptr, size_t n);
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"
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"
41 #else
42 # error "Unknown platform"
43 #endif
45 static void sleep(unsigned int sec) {
46 timespec_t ts;
47 ts.tv_sec = (time_t)sec;
48 ts.tv_nsec = 0;
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"
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"
68 : [TS] "g" (&ts), [SYSNO] "n" (SYS_nanosleep)
69 : "rax", "rdx", "rdi", "rsi", "cc", "memory");
70 #else
71 # error "Unknown platform"
72 #endif
75 static void lwp_exit(void) {
76 #if defined(VGP_x86_solaris)
77 __asm__ __volatile__ (
78 "movl %[SYSNO], %%eax\n"
79 "int $0x91\n"
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"
88 : [SYSNO] "n" (SYS_lwp_exit)
89 : "rax", "rdx", "cc", "memory");
90 #else
91 # error "Unknown platform"
92 #endif
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;
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
136 return address;
138 #undef STACK_FLAGS
139 #undef STACK_PROT
141 static void thread_func(void) {
142 sleep(10000);
145 #define LWP_FLAGS (LWP_SUSPENDED | LWP_DETACHED | LWP_DAEMON)
146 static id_t lwp_create(void *stack) {
147 id_t tid;
149 ucontext_t ucontext;
150 bzero(&ucontext, sizeof(ucontext));
151 ucontext.uc_flags = UC_CPU;
153 #if defined(VGP_x86_solaris)
154 __asm__ __volatile__ (
155 "mov %%ss, %[STACK_SEG]\n"
156 : [STACK_SEG] "=r" (ucontext.uc_mcontext.gregs[SS])
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
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
201 return tid;
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"
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"
222 : [TID] "r" (tid), [SYSNO] "n" (SYS_lwp_continue)
223 : "rax", "rdx", "rdi", "cc", "memory");
224 #else
225 # error "Unknown platform"
226 #endif
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 */