Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/local_includes/cygtls.h')
-rw-r--r--winsup/cygwin/local_includes/cygtls.h354
1 files changed, 354 insertions, 0 deletions
diff --git a/winsup/cygwin/local_includes/cygtls.h b/winsup/cygwin/local_includes/cygtls.h
new file mode 100644
index 000000000..b265978f0
--- /dev/null
+++ b/winsup/cygwin/local_includes/cygtls.h
@@ -0,0 +1,354 @@
+/* cygtls.h
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#pragma once
+
+#include <signal.h>
+#include <pwd.h>
+#include <grp.h>
+#include <time.h>
+#define _NOMNTENT_FUNCS
+#include <mntent.h>
+#undef _NOMNTENT_FUNCS
+#include <setjmp.h>
+#include <ucontext.h>
+
+#define CYGTLS_INITIALIZED 0xc763173f
+
+#ifndef CYG_MAX_PATH
+# define CYG_MAX_PATH 260
+#endif
+
+#ifndef UNLEN
+# define UNLEN 256
+#endif
+
+#define TLS_STACK_SIZE 256
+
+#include "cygthread.h"
+
+#define TP_NUM_C_BUFS 50
+#define TP_NUM_W_BUFS 50
+
+#ifdef CYGTLS_HANDLE
+#include "thread.h"
+#endif
+
+#pragma pack(push,8)
+
+/* Defined here to support auto rebuild of tlsoffsets.h. */
+class tls_pathbuf
+{
+ /* Make sure that c_cnt and w_cnt are always the first two members of this
+ class, and never change the size (32 bit), unless you also change the
+ mov statements in sigbe! */
+ union
+ {
+ struct
+ {
+ uint32_t c_cnt;
+ uint32_t w_cnt;
+ };
+ uint64_t _counters;
+ };
+ char *c_buf[TP_NUM_C_BUFS];
+ WCHAR *w_buf[TP_NUM_W_BUFS];
+
+public:
+ void destroy ();
+ friend class tmp_pathbuf;
+ friend class san;
+};
+
+class unionent
+{
+public:
+ char *name;
+ char **list;
+ short port_proto_addrtype;
+ short h_len;
+ union
+ {
+ char *s_proto;
+ char **h_addr_list;
+ };
+ enum struct_type
+ {
+ t_hostent, t_protoent, t_servent
+ };
+};
+
+struct _local_storage
+{
+ /* passwd.cc */
+ char pass[_PASSWORD_LEN];
+
+ /* dlfcn.cc */
+ int dl_error;
+ char dl_buffer[256];
+
+ /* path.cc */
+ struct mntent mntbuf;
+ int iteration;
+ unsigned available_drives;
+ char mnt_type[80];
+ char mnt_opts[80];
+ char mnt_fsname[CYG_MAX_PATH];
+ char mnt_dir[CYG_MAX_PATH];
+
+ /* select.cc */
+ struct {
+ HANDLE sockevt;
+ int max_w4;
+ LONG *ser_num; // note: malloced
+ HANDLE *w4; // note: malloced
+ } select;
+
+ /* strerror errno.cc */
+ char strerror_buf[sizeof ("Unknown error -2147483648")];
+ char strerror_r_buf[sizeof ("Unknown error -2147483648")];
+
+ /* times.cc */
+ char timezone_buf[20];
+
+ /* strsig.cc */
+ char signamebuf[sizeof ("Unknown signal 4294967295 ")];
+
+ /* net.cc */
+ char *ntoa_buf; // note: malloced
+ unionent *hostent_buf; // note: malloced
+ unionent *protoent_buf; // note: malloced
+ unionent *servent_buf; // note: malloced
+
+ /* cygthread.cc */
+ char unknown_thread_name[30];
+
+ /* syscalls.cc */
+ int setmode_file;
+ int setmode_mode;
+
+ /* thread.cc */
+ HANDLE cw_timer;
+
+ tls_pathbuf pathbufs;
+ char ttybuf[32];
+};
+
+typedef struct struct_waitq
+{
+ int pid;
+ int options;
+ int status;
+ HANDLE ev;
+ void *rusage; /* pointer to potential rusage */
+ struct struct_waitq *next;
+ HANDLE thread_ev;
+} waitq;
+
+/* Changes to the below structure may require acompanying changes to the
+ gawk parser in the shell script 'gentls_offsets' */
+
+extern "C" int __sjfault (jmp_buf);
+extern "C" int __ljfault (jmp_buf, int);
+
+typedef uintptr_t __tlsstack_t;
+
+class _cygtls
+{
+public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */
+ /* offsetoff (class _cygtls, local_clib) *must* be 0. */
+ struct _reent local_clib;
+ struct _local_storage locals;
+ /**/
+ void (*func) (int, siginfo_t *, void *);
+ int saved_errno;
+ int sa_flags;
+ sigset_t oldmask;
+ sigset_t deltamask;
+ int *errno_addr;
+ sigset_t sigmask;
+ sigset_t sigwait_mask;
+ stack_t altstack;
+ siginfo_t *sigwait_info;
+ HANDLE signal_arrived;
+ bool will_wait_for_signal;
+ long __align; /* Needed to align context to 16 byte. */
+ /* context MUST be aligned to 16 byte, otherwise RtlCaptureContext fails.
+ If you prepend cygtls members here, make sure context stays 16 byte
+ aligned. */
+ ucontext_t context;
+ DWORD thread_id;
+ siginfo_t infodata;
+ struct pthread *tid;
+ class cygthread *_ctinfo;
+ class san *andreas;
+ waitq wq;
+ int sig;
+ unsigned incyg;
+ unsigned spinning;
+ unsigned stacklock;
+ __tlsstack_t *stackptr;
+ __tlsstack_t stack[TLS_STACK_SIZE];
+ unsigned initialized;
+
+public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */
+ void init_thread (void *, DWORD (*) (void *, void *));
+ static void call (DWORD (*) (void *, void *), void *);
+ void remove (DWORD);
+ void push (__tlsstack_t addr) {*stackptr++ = (__tlsstack_t) addr;}
+ __tlsstack_t pop ();
+ __tlsstack_t retaddr () {return stackptr[-1];}
+ bool isinitialized () const
+ {
+ return initialized == CYGTLS_INITIALIZED;
+ }
+ bool interrupt_now (CONTEXT *, siginfo_t&, void *, struct sigaction&);
+ void interrupt_setup (siginfo_t&, void *, struct sigaction&);
+
+ bool inside_kernel (CONTEXT *);
+ void signal_debugger (siginfo_t&);
+
+#ifdef CYGTLS_HANDLE
+ operator HANDLE () const {return tid ? tid->win32_obj_id : NULL;}
+#endif
+ int call_signal_handler ();
+ void remove_wq (DWORD);
+ void fixup_after_fork ();
+ void lock ();
+ void unlock ();
+ bool locked ();
+ HANDLE get_signal_arrived (bool wait_for_lock = true)
+ {
+ if (!signal_arrived)
+ {
+ if (wait_for_lock)
+ lock ();
+ if (!signal_arrived)
+ signal_arrived = CreateEvent (NULL, false, false, NULL);
+ if (wait_for_lock)
+ unlock ();
+ }
+ return signal_arrived;
+ }
+ void wait_signal_arrived (bool setit, HANDLE& h)
+ {
+ if (!setit)
+ will_wait_for_signal = false;
+ else
+ {
+ h = get_signal_arrived ();
+ will_wait_for_signal = true;
+ }
+ }
+ void set_signal_arrived ()
+ {
+ SetEvent (get_signal_arrived (false));
+ }
+ void reset_signal_arrived ()
+ {
+ if (signal_arrived)
+ ResetEvent (signal_arrived);
+ }
+ void unwait_signal_arrived ()
+ {
+ will_wait_for_signal = false;
+ }
+ void handle_SIGCONT ();
+ static void cleanup_early(struct _reent *);
+private:
+ void call2 (DWORD (*) (void *, void *), void *, void *);
+ void remove_pending_sigs ();
+};
+#pragma pack(pop)
+
+#include "cygerrno.h"
+#include "ntdll.h"
+
+#define _my_tls (*((_cygtls *) ((PBYTE) NtCurrentTeb()->Tib.StackBase \
+ - __CYGTLS_PADSIZE__)))
+extern _cygtls *_main_tls;
+extern _cygtls *_sig_tls;
+
+class san
+{
+ san *_clemente;
+ uint64_t _cnt;
+public:
+ DWORD64 ret;
+ DWORD64 frame;
+
+ san (PVOID _ret) __attribute__ ((always_inline))
+ {
+ _clemente = _my_tls.andreas;
+ _my_tls.andreas = this;
+ _cnt = _my_tls.locals.pathbufs._counters;
+ /* myfault_altstack_handler needs the current stack pointer and the
+ address of the _except block to restore the context correctly.
+ See comment preceeding myfault_altstack_handler in exception.cc. */
+ ret = (DWORD64) _ret;
+ __asm__ volatile ("movq %%rsp,%0": "=o" (frame));
+ }
+ ~san () __attribute__ ((always_inline))
+ {
+ _my_tls.andreas = _clemente;
+ }
+ /* This is the first thing called in the __except handler. The attribute
+ "returns_twice" makes sure that GCC disregards any register value set
+ earlier in the function, so this call serves as a register barrier. */
+ void leave () __attribute__ ((returns_twice));
+};
+
+/* Exception handling macros. This is a handmade SEH try/except. */
+#define __mem_barrier __asm__ __volatile__ ("" ::: "memory")
+#define __try \
+ { \
+ __label__ __l_try, __l_except, __l_endtry; \
+ __mem_barrier; \
+ san __sebastian (&&__l_except); \
+ __asm__ goto ("\n" \
+ " .seh_handler _ZN9exception7myfaultEP17_EXCEPTION_RECORDPvP8_CONTEXTP19_DISPATCHER_CONTEXT, @except \n" \
+ " .seh_handlerdata \n" \
+ " .long 1 \n" \
+ " .rva %l[__l_try],%l[__l_endtry],%l[__l_except],%l[__l_except] \n" \
+ " .seh_code \n" \
+ : : : : __l_try, __l_endtry, __l_except); \
+ { \
+ __l_try: \
+ __mem_barrier;
+
+#define __leave \
+ goto __l_endtry
+
+#define __except(__errno) \
+ goto __l_endtry; \
+ } \
+ { \
+ __l_except: \
+ __mem_barrier; \
+ __sebastian.leave (); \
+ if (__errno) \
+ set_errno (__errno);
+
+#define __endtry \
+ } \
+ __l_endtry: \
+ __mem_barrier; \
+ }
+
+class wait_signal_arrived
+{
+public:
+ wait_signal_arrived (bool setit, HANDLE& h) { _my_tls.wait_signal_arrived (setit, h); }
+ wait_signal_arrived (HANDLE& h) { _my_tls.wait_signal_arrived (true, h); }
+
+ operator int () const {return _my_tls.will_wait_for_signal;}
+ /* Do not reset the signal_arrived event just because we leave the scope of
+ this wait_signal_arrived object. This may lead to all sorts of races.
+ The only method actually resetting the signal_arrived event is
+ _cygtls::call_signal_handler. */
+ ~wait_signal_arrived () { _my_tls.unwait_signal_arrived (); }
+};
+/*gentls_offsets*/