6 #include <sys/syscall.h>
7 #include "../../config.h"
9 #define VG_STRINGIFZ(__str) #__str
10 #define VG_STRINGIFY(__str) VG_STRINGIFZ(__str)
12 extern void _exit_with_stack_teardown(void*, size_t);
14 /* Below code is modified version of android bionic
15 pthread_exit: when a detached thread exits: it munmaps
16 its stack and then exits. We cannot do that in C,
17 as we cannot touch the stack after the munmap
18 and before the exit. */
20 #if defined(VGP_x86_linux)
23 "\t.globl _exit_with_stack_teardown\n"
24 "\t.type _exit_with_stack_teardown,@function\n"
25 "_exit_with_stack_teardown:\n"
26 // We can trash registers because this function never returns.
27 "\tmov 4(%esp), %ebx\n" // stackBase
28 "\tmov 8(%esp), %ecx\n" // stackSize
29 "\tmov $"VG_STRINGIFY(__NR_munmap
)", %eax\n"
31 // If munmap failed, we ignore the failure and exit anyway.
33 "\tmov $0, %ebx\n" // status
34 "\tmovl $"VG_STRINGIFY(__NR_exit
)", %eax\n"
36 // The exit syscall does not return.
38 #elif defined(VGP_amd64_linux)
41 "\t.globl _exit_with_stack_teardown\n"
42 "\t.type _exit_with_stack_teardown,@function\n"
43 "_exit_with_stack_teardown:\n"
44 "\tmov $"VG_STRINGIFY(__NR_munmap
)", %eax\n"
46 // If munmap failed, we ignore the failure and exit anyway.
48 "\tmov $"VG_STRINGIFY(__NR_exit
)", %eax\n"
50 // The exit syscall does not return.
52 #elif defined(VGP_arm_linux)
55 "\t.globl _exit_with_stack_teardown\n"
56 "\t.type _exit_with_stack_teardown,%function\n"
57 "_exit_with_stack_teardown:\n"
58 "\tldr r7, ="VG_STRINGIFY(__NR_munmap
)"\n"
60 // If munmap failed, we ignore the failure and exit anyway.
63 "\tldr r7, ="VG_STRINGIFY(__NR_exit
)"\n"
65 // The exit syscall does not return.
68 void _exit_with_stack_teardown(void*stack
, size_t sz
)
70 // asm code not done for this platform.
71 // Do nothing, just return. The thread will exit spontaneously
76 static size_t sz
= 64 * 1024;
78 /* This one detaches, does its own thing. */
79 void* child_fn ( void* arg
)
82 r
= pthread_detach( pthread_self() ); assert(!r
);
83 _exit_with_stack_teardown(stack
, sz
);
87 /* Parent creates 1 child, that will detach, and exit after destroying
95 r
= pthread_attr_init(&attr
); assert(!r
);
96 # if !defined(VGO_darwin)
97 stack
= mmap(NULL
, sz
, PROT_READ
|PROT_WRITE
, MAP_PRIVATE
| MAP_ANONYMOUS
,
100 stack
= mmap(NULL
, sz
, PROT_READ
|PROT_WRITE
, MAP_PRIVATE
| MAP_ANON
,
103 assert(stack
!= (void *)-1);
104 r
= pthread_attr_setstack(&attr
, stack
, sz
);
105 r
= pthread_create(&child
, &attr
, child_fn
, NULL
); assert(!r
);