Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / native_client / tests / stack_alignment / stack_alignment_asm_test.c
1 /*
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.
5  */
6
7 #include <assert.h>
8 #include <sched.h>
9 #include <stdint.h>
10 #include <stdio.h>
11
12 #include "native_client/src/untrusted/nacl/nacl_irt.h"
13 #include "native_client/src/untrusted/pthread/pthread_internal.h"
14
15
16 /*
17  * This test checks that new threads are run with their stack pointer
18  * suitably aligned, as per architecture-specific ABI requirements.
19  */
20
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];
25
26 #if defined(__i386__)
27
28 __asm__(
29     ".pushsection .text, \"ax\", @progbits\n"
30     "ThreadStartWrapper:\n"
31     "push %esp\n"  /* Push argument */
32     "call ThreadStart\n"
33     ".popsection\n");
34
35 static const int kStackAlignment = 16;
36 static const int kStackPadBelowAlign = 4;
37
38 #elif defined(__x86_64__)
39
40 __asm__(
41     ".pushsection .text, \"ax\", @progbits\n"
42     "ThreadStartWrapper:\n"
43     "movl %esp, %edi\n"  /* Set argument */
44     "call ThreadStart\n"
45     ".popsection\n");
46
47 static const int kStackAlignment = 16;
48 static const int kStackPadBelowAlign = 8;
49
50 #elif defined(__arm__)
51
52 __asm__(
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 */
57     "bl ThreadStart\n"
58     ".popsection\n");
59
60 static const int kStackAlignment = 8;
61 static const int kStackPadBelowAlign = 0;
62
63 #elif defined(__mips__)
64
65 __asm__(
66     ".pushsection .text, \"ax\", @progbits\n"
67     ".set noreorder\n"
68     ".global ThreadStartWrapper\n"
69     "ThreadStartWrapper:\n"
70     "move $a0, $sp\n"  /* Set argument. */
71     "lui $t9, %hi(ThreadStart)\n"
72     "bal ThreadStart\n"
73     "addiu $t9, $t9, %lo(ThreadStart)\n"
74     ".set reorder\n"
75     ".popsection\n");
76
77 static const int kStackAlignment = 8;
78 static const int kStackPadBelowAlign = 0;
79
80 #else
81 # error Unsupported architecture
82 #endif
83
84 void ThreadStartWrapper(void);
85
86 void ThreadStart(char *stack_ptr) {
87   /*
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.
91    */
92   g_stack_ptr = stack_ptr;
93   __libnacl_irt_thread.thread_exit((int32_t *) &g_stack_in_use);
94 }
95
96 int main(void) {
97   __nc_initialize_interfaces();
98
99   int offset;
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);
103     g_stack_ptr = NULL;
104     g_stack_in_use = 1;
105     void *dummy_tls = &dummy_tls;
106     int rc = __libnacl_irt_thread.thread_create(ThreadStartWrapper, stack_top,
107                                                 dummy_tls);
108     assert(rc == 0);
109     /* Spin until the thread exits. */
110     while (g_stack_in_use) {
111       sched_yield();
112     }
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
116            == 0);
117   }
118
119   return 0;
120 }