]>
Commit | Line | Data |
---|---|---|
d4697bc9 | 1 | /* Copyright (C) 2005-2014 Free Software Foundation, Inc. |
7756ba9d DH |
2 | |
3 | This file is part of the GNU C Library. | |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public License as | |
7 | published by the Free Software Foundation; either version 2.1 of the | |
8 | License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
17 | <http://www.gnu.org/licenses/>. */ | |
18 | ||
19 | #ifndef _TLS_H | |
20 | # define _TLS_H 1 | |
21 | ||
22 | # include <dl-sysdep.h> | |
23 | ||
24 | #ifndef __ASSEMBLER__ | |
25 | # include <stdbool.h> | |
26 | # include <stddef.h> | |
27 | # include <stdint.h> | |
28 | ||
29 | /* Type for the dtv. */ | |
30 | typedef union dtv | |
31 | { | |
32 | size_t counter; | |
33 | struct | |
34 | { | |
35 | void *val; | |
36 | bool is_static; | |
37 | } pointer; | |
38 | } dtv_t; | |
39 | ||
40 | #else /* __ASSEMBLER__ */ | |
41 | # include <tcb-offsets.h> | |
42 | #endif /* __ASSEMBLER__ */ | |
43 | ||
44 | #ifndef __ASSEMBLER__ | |
45 | ||
46 | /* Get system call information. */ | |
47 | # include <sysdep.h> | |
48 | ||
49 | /* The TP points to the start of the thread blocks. */ | |
50 | # define TLS_DTV_AT_TP 1 | |
498a2233 | 51 | # define TLS_TCB_AT_TP 0 |
7756ba9d DH |
52 | |
53 | /* Get the thread descriptor definition. */ | |
54 | # include <nptl/descr.h> | |
55 | ||
56 | typedef struct | |
57 | { | |
58 | dtv_t *dtv; | |
59 | void *private; | |
60 | } tcbhead_t; | |
61 | ||
62 | static inline void *__microblaze_get_thread_area (void) | |
63 | { | |
64 | register void * volatile __microblaze_thread_area asm ("r21"); | |
65 | return (void *) __microblaze_thread_area; | |
66 | } | |
67 | ||
68 | # define READ_THREAD_POINTER() \ | |
69 | ({ __microblaze_get_thread_area(); }) | |
70 | ||
71 | /* This is the size of the initial TCB. */ | |
72 | # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) | |
73 | ||
74 | /* Alignment requirements for the initial TCB. */ | |
75 | # define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) | |
76 | ||
77 | /* This is the size of the TCB. */ | |
78 | # define TLS_TCB_SIZE sizeof (tcbhead_t) | |
79 | ||
80 | /* This is the size we need before TCB. */ | |
81 | # define TLS_PRE_TCB_SIZE sizeof (struct pthread) | |
82 | ||
83 | /* Alignment requirements for the TCB. */ | |
84 | # define TLS_TCB_ALIGN __alignof__ (struct pthread) | |
85 | ||
86 | /* Install the dtv pointer. The pointer passed is to the element with | |
87 | index -1 which contain the length. */ | |
88 | # define INSTALL_DTV(tcbp, dtvp) \ | |
89 | (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1) | |
90 | ||
91 | /* Install new dtv for current thread. */ | |
92 | # define INSTALL_NEW_DTV(dtv) \ | |
93 | (THREAD_DTV() = (dtv)) | |
94 | ||
95 | /* Return dtv of given thread descriptor. */ | |
96 | # define GET_DTV(tcbp) \ | |
97 | (((tcbhead_t *) (tcbp))->dtv) | |
98 | ||
99 | /* Code to initially initialize the thread pointer. | |
100 | r21 is reserved for thread pointer. */ | |
774f9285 | 101 | # define TLS_INIT_TP(tcbp) \ |
7756ba9d DH |
102 | ({ __asm __volatile ("or r21,r0,%0" : : "r" ((void *)tcbp)); 0; }) |
103 | ||
104 | /* Return the address of the dtv for the current thread. */ | |
105 | # define THREAD_DTV() \ | |
106 | (((tcbhead_t *) READ_THREAD_POINTER())->dtv) | |
107 | ||
108 | /* Return the thread descriptor for the current thread. */ | |
109 | # define THREAD_SELF \ | |
110 | (((struct pthread *) READ_THREAD_POINTER()) - 1) | |
111 | ||
112 | /* Magic for libthread_db to know how to do THREAD_SELF. */ | |
113 | # define DB_THREAD_SELF \ | |
114 | CONST_THREAD_AREA (32, sizeof (struct pthread)) | |
115 | ||
116 | /* Read member of the thread descriptor directly. */ | |
117 | # define THREAD_GETMEM(descr, member) (descr->member) | |
118 | ||
119 | /* Same as THREAD_GETMEM, but the member offset can be non-constant. */ | |
120 | # define THREAD_GETMEM_NC(descr, member, idx) \ | |
121 | (descr->member[idx]) | |
122 | ||
123 | /* Set member of the thread descriptor directly. */ | |
124 | # define THREAD_SETMEM(descr, member, value) \ | |
125 | (descr->member = (value)) | |
126 | ||
127 | /* Same as THREAD_SETMEM, but the member offset can be non-constant. */ | |
128 | # define THREAD_SETMEM_NC(descr, member, idx, value) \ | |
129 | (descr->member[idx] = (value)) | |
130 | ||
131 | /* Get and set the global scope generation counter in struct pthread. */ | |
132 | # define THREAD_GSCOPE_FLAG_UNUSED 0 | |
133 | # define THREAD_GSCOPE_FLAG_USED 1 | |
134 | # define THREAD_GSCOPE_FLAG_WAIT 2 | |
135 | # define THREAD_GSCOPE_RESET_FLAG() \ | |
136 | do \ | |
137 | { int __res \ | |
138 | = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ | |
139 | THREAD_GSCOPE_FLAG_UNUSED); \ | |
140 | if (__res == THREAD_GSCOPE_FLAG_WAIT) \ | |
141 | lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ | |
142 | } \ | |
143 | while (0) | |
144 | # define THREAD_GSCOPE_SET_FLAG() \ | |
145 | do \ | |
146 | { \ | |
147 | THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ | |
148 | atomic_write_barrier (); \ | |
149 | } \ | |
150 | while (0) | |
151 | # define THREAD_GSCOPE_WAIT() \ | |
152 | GL (dl_wait_lookup_done) () | |
153 | ||
154 | #endif /* __ASSEMBLER__ */ | |
155 | ||
156 | #endif /* tls.h. */ |