OLD | NEW |
| (Empty) |
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 /* | |
8 * Native Client support for thread local storage. | |
9 * | |
10 * This is a highly experimental hack which will work with glibc's ld.so. | |
11 * Note: it probably wont work for ARM as is but we have no way | |
12 * of testing this at this point. As we are lacking a dynamic loader | |
13 * for that platform. | |
14 */ | |
15 | |
16 #include <stdint.h> | |
17 | |
18 #include "native_client/src/untrusted/nacl/nacl_thread.h" | |
19 #include "native_client/src/untrusted/nacl/tls.h" | |
20 #include "native_client/src/untrusted/nacl/tls_params.h" | |
21 | |
22 /* | |
23 * These are part of ld.so's API and use a non-standard calling convention | |
24 */ | |
25 #define REGPARM(n) __attribute__((regparm(n))) | |
26 | |
27 extern REGPARM(2) void _dl_get_tls_static_info(int *static_tls_size, | |
28 int *static_tls_align); | |
29 extern void *_dl_allocate_tls (void *mem); | |
30 | |
31 /* | |
32 * In case there is some mismatch between the combined areas of | |
33 * glibc's and our pthread/tls code we add some safety margin on both ends | |
34 * of the combined area. | |
35 * This is probably not needed, especially since we believe that | |
36 * the part of the (glibc) tdb which is accessed by ld.so is smaller than | |
37 * our tdb. | |
38 * On the other hand, we have not tried this we a big code bases | |
39 * yet and if there were problems without the safty paddding | |
40 * those would be really hard to track down. So it seems prudent | |
41 * to leave them in for a while. | |
42 * | |
43 * TODO(robertm): set safety paddding to zero after we have tried | |
44 * this with big apps | |
45 */ | |
46 | |
47 #define SAFETY_PADDING 256 | |
48 | |
49 static size_t aligned_size(size_t size, size_t alignment) { | |
50 return (size + alignment - 1) & -alignment; | |
51 } | |
52 | |
53 static char *aligned_addr(void *start, size_t alignment) { | |
54 return (void *) aligned_size((size_t) start, alignment); | |
55 } | |
56 | |
57 /* | |
58 * this is ugly, but we need a way to communicate these from | |
59 * _dl_get_tls_static_info() to | |
60 * __nacl_tls_initialize_memory() | |
61 */ | |
62 static int tls_size; | |
63 static int tls_align; | |
64 | |
65 size_t __nacl_tls_combined_size(size_t tdb_size) { | |
66 _dl_get_tls_static_info (&tls_size, &tls_align); | |
67 /* | |
68 * Disregarding the SAFETY_PADDING we need enough space | |
69 * to align the tdb which is sort of in the middle of combined area | |
70 * hence the extra "tls_size - 1" | |
71 * TODO(robertm): this may need to be adapted for ARM | |
72 */ | |
73 return tls_size + tdb_size + (tls_size - 1) + 2 * SAFETY_PADDING; | |
74 } | |
75 | |
76 void *__nacl_tls_initialize_memory(void *combined_area, size_t tdb_size) { | |
77 if (__nacl_tp_tdb_offset(tdb_size) != 0) { | |
78 /* | |
79 * This needs more work for ARM. | |
80 * For now abort via null pointer dereference. | |
81 */ | |
82 while (1) *(volatile int *) 0; | |
83 } else { | |
84 void *tdb = aligned_addr(((char *) combined_area) + tls_size + | |
85 SAFETY_PADDING , tls_align); | |
86 return _dl_allocate_tls(tdb); | |
87 } | |
88 } | |
OLD | NEW |