Cygwin: cygtls: rename sig to current_sig
[newlib-cygwin.git] / winsup / cygwin / local_includes / cygtls.h
blob28bbe60f0f40df7f47d77d524afb767b04085f6d
1 /* cygtls.h
3 This software is a copyrighted work licensed under the terms of the
4 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
5 details. */
7 #pragma once
9 #include <signal.h>
10 #include <pwd.h>
11 #include <grp.h>
12 #include <time.h>
13 #define _NOMNTENT_FUNCS
14 #include <mntent.h>
15 #undef _NOMNTENT_FUNCS
16 #include <setjmp.h>
17 #include <ucontext.h>
19 #define CYGTLS_INITIALIZED 0xc763173f
21 #ifndef CYG_MAX_PATH
22 # define CYG_MAX_PATH 260
23 #endif
25 #ifndef UNLEN
26 # define UNLEN 256
27 #endif
29 #define TLS_STACK_SIZE 256
31 #include "cygthread.h"
33 #define TP_NUM_C_BUFS 50
34 #define TP_NUM_W_BUFS 50
36 #ifdef CYGTLS_HANDLE
37 #include "thread.h"
38 #endif
40 #pragma pack(push,8)
42 /* Defined here to support auto rebuild of tlsoffsets.h. */
43 class tls_pathbuf
45 /* Make sure that c_cnt and w_cnt are always the first two members of this
46 class, and never change the size (32 bit), unless you also change the
47 mov statements in sigbe! */
48 union
50 struct
52 uint32_t c_cnt;
53 uint32_t w_cnt;
55 uint64_t _counters;
57 HANDLE tls_heap;
58 char *c_buf[TP_NUM_C_BUFS];
59 WCHAR *w_buf[TP_NUM_W_BUFS];
61 public:
62 void clear () { memset (this, 0, sizeof *this); }
63 void create ();
64 void destroy ();
65 friend class tmp_pathbuf;
66 friend class san;
69 class unionent
71 public:
72 char *name;
73 char **list;
74 short port_proto_addrtype;
75 short h_len;
76 union
78 char *s_proto;
79 char **h_addr_list;
81 enum struct_type
83 t_hostent, t_protoent, t_servent
87 struct _local_storage
89 /* passwd.cc */
90 char pass[_PASSWORD_LEN];
92 /* dlfcn.cc */
93 int dl_error;
94 char dl_buffer[256];
96 /* path.cc */
97 struct mntent mntbuf;
98 int iteration;
99 unsigned available_drives;
100 char mnt_type[80];
101 char mnt_opts[80];
102 char mnt_fsname[CYG_MAX_PATH];
103 char mnt_dir[CYG_MAX_PATH];
105 /* select.cc */
106 struct {
107 HANDLE sockevt;
108 int max_w4;
109 LONG *ser_num; // note: malloced
110 HANDLE *w4; // note: malloced
111 } select;
113 /* strerror errno.cc */
114 char strerror_buf[sizeof ("Unknown error -2147483648")];
115 char strerror_r_buf[sizeof ("Unknown error -2147483648")];
117 /* times.cc */
118 char timezone_buf[20];
120 /* strsig.cc */
121 char signamebuf[sizeof ("Unknown signal 4294967295 ")];
123 /* net.cc */
124 char *ntoa_buf; // note: malloced
125 unionent *hostent_buf; // note: malloced
126 unionent *protoent_buf; // note: malloced
127 unionent *servent_buf; // note: malloced
129 /* cygthread.cc */
130 char unknown_thread_name[30];
132 /* syscalls.cc */
133 int setmode_file;
134 int setmode_mode;
136 /* thread.cc */
137 HANDLE cw_timer;
139 tls_pathbuf pathbufs;
140 char ttybuf[32];
143 typedef struct struct_waitq
145 int pid;
146 int options;
147 int status;
148 HANDLE ev;
149 void *rusage; /* pointer to potential rusage */
150 struct struct_waitq *next;
151 HANDLE thread_ev;
152 } waitq;
154 /* Changes to the below structure may require acompanying changes to the
155 gawk parser in the shell script 'gentls_offsets' */
157 extern "C" int __sjfault (jmp_buf);
158 extern "C" int __ljfault (jmp_buf, int);
160 typedef uintptr_t __tlsstack_t;
162 class _cygtls
164 public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */
165 /* offsetoff (class _cygtls, local_clib) *must* be 0. */
166 struct _reent local_clib;
167 struct _local_storage locals;
168 /**/
169 void (*func) (int, siginfo_t *, void *);
170 int saved_errno;
171 int sa_flags;
172 sigset_t oldmask;
173 sigset_t deltamask;
174 int *errno_addr;
175 sigset_t sigmask;
176 sigset_t sigwait_mask;
177 stack_t altstack;
178 siginfo_t *sigwait_info;
179 HANDLE signal_arrived;
180 bool will_wait_for_signal;
181 #if 0
182 long __align; /* Needed to align context to 16 byte. */
183 #endif
184 /* context MUST be aligned to 16 byte, otherwise RtlCaptureContext fails.
185 If you prepend cygtls members here, make sure context stays 16 byte
186 aligned. The gentls_offsets script checks for that now and fails
187 if the alignment is wrong. */
188 ucontext_t context;
189 DWORD thread_id;
190 siginfo_t infodata;
191 struct pthread *tid;
192 class cygthread *_ctinfo;
193 class san *andreas;
194 waitq wq;
195 int current_sig;
196 unsigned incyg;
197 unsigned spinning;
198 unsigned stacklock;
199 __tlsstack_t *stackptr;
200 __tlsstack_t stack[TLS_STACK_SIZE];
201 unsigned initialized;
203 public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */
204 void init_thread (void *, DWORD (*) (void *, void *));
205 static void call (DWORD (*) (void *, void *), void *);
206 void remove (DWORD);
207 void push (__tlsstack_t addr) {*stackptr++ = (__tlsstack_t) addr;}
208 __tlsstack_t pop ();
209 __tlsstack_t retaddr () {return stackptr[-1];}
210 bool isinitialized () const
212 return initialized == CYGTLS_INITIALIZED;
214 bool interrupt_now (CONTEXT *, siginfo_t&, void *, struct sigaction&);
215 void interrupt_setup (siginfo_t&, void *, struct sigaction&);
217 bool inside_kernel (CONTEXT *);
218 void signal_debugger (siginfo_t&);
220 #ifdef CYGTLS_HANDLE
221 operator HANDLE () const {return tid ? tid->win32_obj_id : NULL;}
222 #endif
223 int call_signal_handler ();
224 void remove_wq (DWORD);
225 void fixup_after_fork ();
226 void lock ();
227 void unlock ();
228 bool locked ();
229 HANDLE get_signal_arrived (bool wait_for_lock = true)
231 if (!signal_arrived)
233 if (wait_for_lock)
234 lock ();
235 if (!signal_arrived)
236 signal_arrived = CreateEvent (NULL, false, false, NULL);
237 if (wait_for_lock)
238 unlock ();
240 return signal_arrived;
242 void wait_signal_arrived (bool setit, HANDLE& h)
244 if (!setit)
245 will_wait_for_signal = false;
246 else
248 h = get_signal_arrived ();
249 will_wait_for_signal = true;
252 void set_signal_arrived ()
254 SetEvent (get_signal_arrived (false));
256 void reset_signal_arrived ()
258 if (signal_arrived)
259 ResetEvent (signal_arrived);
261 void unwait_signal_arrived ()
263 will_wait_for_signal = false;
265 void handle_SIGCONT ();
266 static void cleanup_early(struct _reent *);
267 private:
268 void call2 (DWORD (*) (void *, void *), void *, void *);
269 void remove_pending_sigs ();
271 #pragma pack(pop)
273 #include "cygerrno.h"
274 #include "ntdll.h"
276 #define _my_tls (*((_cygtls *) ((PBYTE) NtCurrentTeb()->Tib.StackBase \
277 - __CYGTLS_PADSIZE__)))
278 extern _cygtls *_main_tls;
279 extern _cygtls *_sig_tls;
281 class san
283 san *_clemente;
284 uint64_t _cnt;
285 public:
286 DWORD64 ret;
287 DWORD64 frame;
289 san (PVOID _ret) __attribute__ ((always_inline))
291 _clemente = _my_tls.andreas;
292 _my_tls.andreas = this;
293 _cnt = _my_tls.locals.pathbufs._counters;
294 /* myfault_altstack_handler needs the current stack pointer and the
295 address of the _except block to restore the context correctly.
296 See comment preceeding myfault_altstack_handler in exception.cc. */
297 ret = (DWORD64) _ret;
298 __asm__ volatile ("movq %%rsp,%0": "=o" (frame));
300 ~san () __attribute__ ((always_inline))
302 _my_tls.andreas = _clemente;
304 /* This is the first thing called in the __except handler. The attribute
305 "returns_twice" makes sure that GCC disregards any register value set
306 earlier in the function, so this call serves as a register barrier. */
307 void leave () __attribute__ ((returns_twice));
310 /* Exception handling macros. This is a handmade SEH try/except. */
311 #define __mem_barrier __asm__ __volatile__ ("" ::: "memory")
312 #define __try \
314 __label__ __l_try, __l_except, __l_endtry; \
315 __mem_barrier; \
316 san __sebastian (&&__l_except); \
317 __asm__ goto ("\n" \
318 " .seh_handler _ZN9exception7myfaultEP17_EXCEPTION_RECORDPvP8_CONTEXTP19_DISPATCHER_CONTEXT, @except \n" \
319 " .seh_handlerdata \n" \
320 " .long 1 \n" \
321 " .rva %l[__l_try],%l[__l_endtry],%l[__l_except],%l[__l_except] \n" \
322 " .seh_code \n" \
323 : : : : __l_try, __l_endtry, __l_except); \
325 __l_try: \
326 __mem_barrier;
328 #define __leave \
329 goto __l_endtry
331 #define __except(__errno) \
332 goto __l_endtry; \
335 __l_except: \
336 __mem_barrier; \
337 __sebastian.leave (); \
338 if (__errno) \
339 set_errno (__errno);
341 #define __endtry \
343 __l_endtry: \
344 __mem_barrier; \
347 class wait_signal_arrived
349 public:
350 wait_signal_arrived (bool setit, HANDLE& h) { _my_tls.wait_signal_arrived (setit, h); }
351 wait_signal_arrived (HANDLE& h) { _my_tls.wait_signal_arrived (true, h); }
353 operator int () const {return _my_tls.will_wait_for_signal;}
354 /* Do not reset the signal_arrived event just because we leave the scope of
355 this wait_signal_arrived object. This may lead to all sorts of races.
356 The only method actually resetting the signal_arrived event is
357 _cygtls::call_signal_handler. */
358 ~wait_signal_arrived () { _my_tls.unwait_signal_arrived (); }
360 /*gentls_offsets*/