OSDN Git Service

* dcrt0.cc (dll_crt0_1): Move internal locale setting prior to potential
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / cygtls.h
1 /* cygtls.h
2
3    Copyright 2003, 2004, 2005, 2008, 2009 Red Hat, Inc.
4
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
7 details. */
8
9 #ifndef _CYGTLS_H
10 #define _CYGTLS_H
11
12 #include <signal.h>
13 #include <pwd.h>
14 #include <grp.h>
15 #include <time.h>
16 #define _NOMNTENT_FUNCS
17 #include <mntent.h>
18 #undef _NOMNTENT_FUNCS
19 #include <setjmp.h>
20 #include <exceptions.h>
21
22 #define CYGTLS_INITIALIZED 0xc763173f
23
24 #ifndef CYG_MAX_PATH
25 # define CYG_MAX_PATH 260
26 #endif
27
28 #ifndef UNLEN
29 # define UNLEN 256
30 #endif
31
32 #define TLS_STACK_SIZE 256
33
34 #include "cygthread.h"
35
36 #define TP_NUM_C_BUFS 10
37 #define TP_NUM_W_BUFS 10
38
39 #ifdef CYGTLS_HANDLE
40 #include "thread.h"
41 #endif
42
43 #pragma pack(push,4)
44 /* Defined here to support auto rebuild of tlsoffsets.h. */
45 class tls_pathbuf
46 {
47   int c_cnt;
48   int w_cnt;
49   char  *c_buf[TP_NUM_C_BUFS];
50   WCHAR *w_buf[TP_NUM_W_BUFS];
51
52 public:
53   void destroy ();
54   friend class tmp_pathbuf;
55   friend class _cygtls;
56 };
57
58 class unionent
59 {
60 public:
61   char *name;
62   char **list;
63   short port_proto_addrtype;
64   short h_len;
65   union
66   {
67     char *s_proto;
68     char **h_addr_list;
69   };
70   enum struct_type
71   {
72     t_hostent, t_protoent, t_servent
73   };
74 };
75
76 struct _local_storage
77 {
78   /*
79      Needed for the group functions
80    */
81   struct __group16 grp;
82   char *namearray[2];
83   int grp_pos;
84
85   /* console.cc */
86   unsigned rarg;
87
88   /* dlfcn.cc */
89   int dl_error;
90   char dl_buffer[256];
91
92   /* passwd.cc */
93   struct passwd res;
94   char pass[_PASSWORD_LEN];
95   int pw_pos;
96
97   /* path.cc */
98   struct mntent mntbuf;
99   int iteration;
100   unsigned available_drives;
101   char mnt_type[80];
102   char mnt_opts[80];
103   char mnt_fsname[CYG_MAX_PATH];
104   char mnt_dir[CYG_MAX_PATH];
105
106   /* select.cc */
107   struct {
108     HANDLE  sockevt;
109     int     max_w4;
110     LONG   *ser_num;                    // note: malloced
111     HANDLE *w4;                         // note: malloced
112   } select;
113
114   /* strerror */
115   char strerror_buf[sizeof ("Unknown error 4294967295")];
116
117   /* sysloc.cc */
118   char *process_ident;                  // note: malloced
119   int process_logopt;
120   int process_facility;
121   int process_logmask;
122
123   /* times.cc */
124   char timezone_buf[20];
125   struct tm _localtime_buf;
126
127   /* uinfo.cc */
128   char username[UNLEN + 1];
129
130   /* net.cc */
131   char *ntoa_buf;                       // note: malloced
132   char signamebuf[sizeof ("Unknown signal 4294967295   ")];
133
134   unionent *hostent_buf;                // note: malloced
135   unionent *protoent_buf;               // note: malloced
136   unionent *servent_buf;                // note: malloced
137
138   /* cygthread.cc */
139   char unknown_thread_name[30];
140
141   /* syscalls.cc */
142   int setmode_file;
143   int setmode_mode;
144
145   /* All functions requiring temporary path buffers. */
146   tls_pathbuf pathbufs;
147 };
148
149 typedef struct struct_waitq
150 {
151   int pid;
152   int options;
153   int status;
154   HANDLE ev;
155   void *rusage;                 /* pointer to potential rusage */
156   struct struct_waitq *next;
157   HANDLE thread_ev;
158 } waitq;
159
160 typedef struct
161 {
162   void *_myfault;
163   int _myfault_errno;
164   int _myfault_c_cnt;
165   int _myfault_w_cnt;
166 } san;
167
168 /* Changes to the below structure may require acompanying changes to the very
169    simple parser in the perl script 'gentls_offsets' (<<-- start parsing here).
170    The union in this structure is used to force alignment between the version
171    of the compiler used to generate tlsoffsets.h and the cygwin cross compiler.
172 */
173
174 /*gentls_offsets*/
175 #include "cygerrno.h"
176
177 extern "C" int __sjfault (jmp_buf);
178 extern "C" int __ljfault (jmp_buf, int);
179
180 /*gentls_offsets*/
181
182 typedef __uint32_t __stack_t;
183 struct _cygtls
184 {
185   void (*func) /*gentls_offsets*/(int)/*gentls_offsets*/;
186   exception_list el;
187   int saved_errno;
188   int sa_flags;
189   sigset_t oldmask;
190   sigset_t deltamask;
191   HANDLE event;
192   int *errno_addr;
193   sigset_t sigmask;
194   sigset_t sigwait_mask;
195   siginfo_t *sigwait_info;
196   struct ucontext thread_context;
197   DWORD thread_id;
198   unsigned threadkill;
199   siginfo_t infodata;
200   struct pthread *tid;
201   union
202   {
203     struct _reent local_clib;
204     char __dontuse[8 * ((sizeof(struct _reent) + 4) / 8)];
205   };
206   struct _local_storage locals;
207   class cygthread *_ctinfo;
208   san andreas;
209   waitq wq;
210   struct _cygtls *prev, *next;
211   int sig;
212   unsigned incyg;
213   unsigned spinning;
214   unsigned stacklock;
215   __stack_t *stackptr;
216   __stack_t stack[TLS_STACK_SIZE];
217   unsigned initialized;
218
219   /*gentls_offsets*/
220   static CRITICAL_SECTION protect_linked_list;
221   static void init ();
222   void init_thread (void *, DWORD (*) (void *, void *));
223   static void call (DWORD (*) (void *, void *), void *);
224   void call2 (DWORD (*) (void *, void *), void *, void *) __attribute__ ((regparm (3)));
225   static struct _cygtls *find_tls (int sig);
226   void remove (DWORD);
227   void push (__stack_t) __attribute__ ((regparm (2)));
228   __stack_t pop () __attribute__ ((regparm (1)));
229   __stack_t retaddr () {return stackptr[-1];}
230   bool isinitialized () const
231   {
232     return initialized == CYGTLS_INITIALIZED;
233   }
234   bool interrupt_now (CONTEXT *, int, void *, struct sigaction&)
235     __attribute__((regparm(3)));
236   void __stdcall interrupt_setup (int sig, void *handler,
237                                   struct sigaction& siga)
238     __attribute__((regparm(3)));
239
240   /* exception handling */
241   static int handle_exceptions (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void *);
242   bool inside_kernel (CONTEXT *);
243   void init_exception_handler (int (*) (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void*));
244   void signal_exit (int) __attribute__ ((noreturn, regparm(2)));
245   void copy_context (CONTEXT *) __attribute__ ((regparm(2)));
246   void signal_debugger (int) __attribute__ ((regparm(2)));
247
248 #ifdef CYGTLS_HANDLE
249   operator HANDLE () const {return tid->win32_obj_id;}
250 #endif
251   void set_siginfo (struct sigpacket *) __attribute__ ((regparm (3)));
252   void set_threadkill () {threadkill = true;}
253   void reset_threadkill () {threadkill = false;}
254   int call_signal_handler () __attribute__ ((regparm (1)));
255   void remove_wq (DWORD) __attribute__ ((regparm (1)));
256   void fixup_after_fork () __attribute__ ((regparm (1)));
257   void lock () __attribute__ ((regparm (1)));
258   void unlock () __attribute__ ((regparm (1)));
259   bool locked () __attribute__ ((regparm (1)));
260   void*& fault_guarded () {return andreas._myfault;}
261   void return_from_fault ()
262   {
263     if (andreas._myfault_errno)
264       set_errno (andreas._myfault_errno);
265     /* Restore tls_pathbuf counters in case of error. */
266     locals.pathbufs.c_cnt = andreas._myfault_c_cnt;
267     locals.pathbufs.w_cnt = andreas._myfault_w_cnt;
268     __ljfault ((int *) andreas._myfault, 1);
269   }
270   int setup_fault (jmp_buf j, san& old_j, int myerrno) __attribute__ ((always_inline))
271   {
272     old_j._myfault = andreas._myfault;
273     old_j._myfault_errno = andreas._myfault_errno;
274     old_j._myfault_c_cnt = andreas._myfault_c_cnt;
275     old_j._myfault_w_cnt = andreas._myfault_w_cnt;
276     andreas._myfault = (void *) j;
277     andreas._myfault_errno = myerrno;
278     /* Save tls_pathbuf counters. */
279     andreas._myfault_c_cnt = locals.pathbufs.c_cnt;
280     andreas._myfault_w_cnt = locals.pathbufs.w_cnt;
281     return __sjfault (j);
282   }
283   void reset_fault (san& old_j) __attribute__ ((always_inline))
284   {
285     andreas._myfault = old_j._myfault;
286     andreas._myfault_errno = old_j._myfault_errno;
287   }
288   /*gentls_offsets*/
289 };
290 #pragma pack(pop)
291
292 const int CYGTLS_PADSIZE = 12700;       /* FIXME: Find some way to autogenerate
293                                            this value */
294 /*gentls_offsets*/
295
296 extern char *_tlsbase __asm__ ("%fs:4");
297 extern char *_tlstop __asm__ ("%fs:8");
298 #define _my_tls (*((_cygtls *) (_tlsbase - CYGTLS_PADSIZE)))
299 extern _cygtls *_main_tls;
300 extern _cygtls *_sig_tls;
301
302 class myfault
303 {
304   jmp_buf buf;
305   san sebastian;
306 public:
307   ~myfault () __attribute__ ((always_inline)) { _my_tls.reset_fault (sebastian); }
308   inline int faulted (int myerrno = 0) __attribute__ ((always_inline))
309   {
310     return _my_tls.setup_fault (buf, sebastian, myerrno);
311   }
312 };
313
314 #define __getreent() (&_my_tls.local_clib)
315
316 #endif /*_CYGTLS_H*/ /*gentls_offsets*/