2 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
12 #include "native_client/src/untrusted/nacl/nacl_irt.h"
13 #include "native_client/src/untrusted/pthread/pthread_internal.h"
17 * This test checks that new threads are run with their stack pointer
18 * suitably aligned, as per architecture-specific ABI requirements.
21 /* We use 'volatile' because we spin waiting for these variables to be set. */
22 static volatile int32_t g_stack_in_use;
23 static char *volatile g_stack_ptr;
24 static char stack[0x1000];
29 ".pushsection .text, \"ax\", @progbits\n"
30 "ThreadStartWrapper:\n"
31 "push %esp\n" /* Push argument */
35 static const int kStackAlignment = 16;
36 static const int kStackPadBelowAlign = 4;
38 #elif defined(__x86_64__)
41 ".pushsection .text, \"ax\", @progbits\n"
42 "ThreadStartWrapper:\n"
43 "movl %esp, %edi\n" /* Set argument */
47 static const int kStackAlignment = 16;
48 static const int kStackPadBelowAlign = 8;
50 #elif defined(__arm__)
53 ".pushsection .text, \"ax\", %progbits\n"
54 "ThreadStartWrapper:\n"
55 "mov r0, sp\n" /* Set argument */
56 "nop; nop\n" /* Padding to put the "bl" at the end of the bundle */
60 static const int kStackAlignment = 8;
61 static const int kStackPadBelowAlign = 0;
63 #elif defined(__mips__)
66 ".pushsection .text, \"ax\", @progbits\n"
68 ".global ThreadStartWrapper\n"
69 "ThreadStartWrapper:\n"
70 "move $a0, $sp\n" /* Set argument. */
71 "lui $t9, %hi(ThreadStart)\n"
73 "addiu $t9, $t9, %lo(ThreadStart)\n"
77 static const int kStackAlignment = 8;
78 static const int kStackPadBelowAlign = 0;
81 # error Unsupported architecture
84 void ThreadStartWrapper(void);
86 void ThreadStart(char *stack_ptr) {
88 * We do not have TLS set up in this thread, so we don't use libc
89 * functions like assert() here. Instead, we save stack_ptr and let
90 * the main thread check it.
92 g_stack_ptr = stack_ptr;
93 __libnacl_irt_thread.thread_exit((int32_t *) &g_stack_in_use);
97 __nc_initialize_interfaces();
100 for (offset = 0; offset <= 32; offset++) {
101 char *stack_top = stack + sizeof(stack) - offset;
102 printf("Checking offset %i: stack_top=%p...\n", offset, stack_top);
105 void *dummy_tls = &dummy_tls;
106 int rc = __libnacl_irt_thread.thread_create(ThreadStartWrapper, stack_top,
109 /* Spin until the thread exits. */
110 while (g_stack_in_use) {
113 printf("got g_stack_ptr=%p\n", g_stack_ptr);
114 assert(g_stack_ptr <= stack_top);
115 assert(((uintptr_t) g_stack_ptr + kStackPadBelowAlign) % kStackAlignment