From 6946073e784471e1fc51fffd705b0cbc4d58e730 Mon Sep 17 00:00:00 2001
From: Christopher Faylor <me@cgf.cx>
Date: Sun, 8 Feb 2004 19:59:27 +0000
Subject: [PATCH] * localtime.cc (localtime_r): Call tzset. * Makefile.in: Make
 version.h/cygwin.din version check a warning since it is not foolproof. *
 cygheap.h (CYGHEAPSIZE): Bump size down. * cygtls.h (_threadinfo::stacklock):
 New element. (_threadinfo::pop): Make regparm. (_threadinfo::lock): New
 function. (_threadinfo::unlock): New function. * cygtls.cc
 (_threadinfo::push): Wait for a lock on the stack before performing the
 operation. (_threadinfo::pop): Move to another file. * cygwin.din: More SIGFE
 changes. * exceptions.cc (try_to_debug): Always display messages on console.
 (handle_exceptions): Unwind stack only when actually about to call sig_send.
 (setup_handler): Lock stack prior to performing any operations. * gendef
 (_sigfe): Ditto. (_sigbe): Ditto. (_threadinfo::pop): Ditto.  Move here. *
 gen_tlsoffsets: Generate positive offsets. * tlsoffsets.h: Regenerate.

---
 winsup/cygwin/ChangeLog      |  27 ++++++++
 winsup/cygwin/Makefile.in    |   3 +-
 winsup/cygwin/cygheap.h      |   2 +-
 winsup/cygwin/cygtls.cc      |  18 ++---
 winsup/cygwin/cygtls.h       |   5 +-
 winsup/cygwin/cygwin.din     |  25 ++++---
 winsup/cygwin/exceptions.cc  |  24 ++++---
 winsup/cygwin/gendef         |  78 +++++++++++++++------
 winsup/cygwin/gentls_offsets |   3 +
 winsup/cygwin/localtime.cc   |   1 +
 winsup/cygwin/tlsoffsets.h   | 128 ++++++++++++++++++++++++-----------
 11 files changed, 214 insertions(+), 100 deletions(-)

diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index befb8dd06..e3bd6e296 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,30 @@
+2004-02-08  Christopher Faylor  <cgf@redhat.com>
+
+	* localtime.cc (localtime_r): Call tzset.
+
+	* Makefile.in: Make version.h/cygwin.din version check a warning since
+	it is not foolproof.
+
+	* cygheap.h (CYGHEAPSIZE): Bump size down.
+
+	* cygtls.h (_threadinfo::stacklock): New element.
+	(_threadinfo::pop): Make regparm.
+	(_threadinfo::lock): New function.
+	(_threadinfo::unlock): New function.
+	* cygtls.cc (_threadinfo::push): Wait for a lock on the stack before
+	performing the operation.
+	(_threadinfo::pop): Move to another file.
+	* cygwin.din: More SIGFE changes.
+	* exceptions.cc (try_to_debug): Always display messages on console.
+	(handle_exceptions): Unwind stack only when actually about to call
+	sig_send.
+	(setup_handler): Lock stack prior to performing any operations.
+	* gendef (_sigfe): Ditto.
+	(_sigbe): Ditto.
+	(_threadinfo::pop): Ditto.  Move here.
+	* gen_tlsoffsets: Generate positive offsets.
+	* tlsoffsets.h: Regenerate.
+
 2004-02-06  Corinna Vinschen  <corinna@vinschen.de>
 
 	* cygserver.h (CYGWIN_SERVER_VERSION_API): Bump.
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index a208ebc27..54ae6e991 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -384,8 +384,7 @@ $(LIBGMON_A): $(GMON_OFILES) $(GMON_START)
 	$(AR) rcv $(LIBGMON_A) $(GMON_OFILES)
 
 $(API_VER): $(srcdir)/cygwin.din
-	@echo Error: Version info is older than DLL API!;\
-	false
+	@echo Error: Version info is older than DLL API!
 
 version.cc winver.o: winver_stamp
 	@ :
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index fd649af06..a5134cfde 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -272,7 +272,7 @@ struct init_cygheap
   void close_ctty ();
 };
 
-#define CYGHEAPSIZE (sizeof (init_cygheap) + (20000 * sizeof (fhandler_union)) + (64 * 1024 * 1024))
+#define CYGHEAPSIZE (sizeof (init_cygheap) + (20000 * sizeof (fhandler_union)) + (32 * 1024 * 1024))
 
 extern init_cygheap *cygheap;
 extern void *cygheap_max;
diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc
index a74412637..becde2d73 100644
--- a/winsup/cygwin/cygtls.cc
+++ b/winsup/cygwin/cygtls.cc
@@ -155,24 +155,14 @@ _threadinfo::remove (DWORD wait)
 void
 _threadinfo::push (__stack_t addr, bool exception)
 {
+  if (exception)
+    lock (true);
   *stackptr++ = (__stack_t) addr;
+  if (exception)
+    unlock ();
   set_state (exception);
 }
 
-__stack_t
-_threadinfo::pop ()
-{
-#ifdef DEBUGGING
-  assert (stackptr > stack);
-#endif
-  __stack_t res = *--stackptr;
-#ifdef DEBUGGING
-  *stackptr = 0;
-  debug_printf ("popped %p, stack %p, stackptr %p", res, stack, stackptr);
-#endif
-  return res;
-}
-
 #define BAD_IX ((size_t) -1)
 static size_t NO_COPY threadlist_ix = BAD_IX;
 
diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h
index e2f5f0b3a..c1525a45d 100644
--- a/winsup/cygwin/cygtls.h
+++ b/winsup/cygwin/cygtls.h
@@ -111,6 +111,7 @@ struct _threadinfo
   struct _threadinfo *prev, *next;
   __stack_t *stackptr;
   int sig;
+  unsigned stacklock;
   __stack_t stack[TLS_STACK_SIZE];
   unsigned padding[0];
 
@@ -123,7 +124,7 @@ struct _threadinfo
   static struct _threadinfo *find_tls (int sig);
   void remove (DWORD);
   void push (__stack_t, bool = false) __attribute__ ((regparm (3)));
-  __stack_t pop ();
+  __stack_t pop () __attribute__ ((regparm (1)));
   bool isinitialized () {return initialized == CYGTLS_INITIALIZED || initialized == CYGTLS_EXCEPTION;}
   void set_state (bool);
   void reset_exception ();
@@ -136,6 +137,8 @@ struct _threadinfo
   void set_siginfo (struct sigpacket *) __attribute__ ((regparm (3)));
   void set_threadkill () {threadkill = true;}
   void reset_threadkill () {threadkill = false;}
+  int lock (int wait) __attribute__ ((regparm (2)));
+  void unlock () __attribute__ ((regparm (1)));
   /*gentls_offsets*/
 };
 #pragma pack(pop)
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index 9f8553665..1a9e47a64 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -479,19 +479,19 @@ fdimf NOSIGFE
 fdopen SIGFE
 _fdopen = fdopen SIGFE
 _fdopen64 = fdopen64 SIGFE
-feof NOSIGFE
-_feof = feof NOSIGFE
+feof SIGFE
+_feof = feof SIGFE
 ferror NOSIGFE
 _ferror = ferror NOSIGFE
-fflush NOSIGFE
-_fflush = fflush NOSIGFE
+fflush SIGFE
+_fflush = fflush SIGFE
 ffs NOSIGFE
 _ffs = ffs NOSIGFE
 fgetc SIGFE
 _fgetc = fgetc SIGFE
-fgetpos NOSIGFE
-_fgetpos = fgetpos NOSIGFE
-_fgetpos64 = fgetpos64 NOSIGFE
+fgetpos SIGFE
+_fgetpos = fgetpos SIGFE
+_fgetpos64 = fgetpos64 SIGFE
 fgets SIGFE
 _fgets = fgets SIGFE
 fileno NOSIGFE
@@ -503,7 +503,6 @@ _finitef = finitef NOSIGFE
 fiprintf SIGFE
 _fiprintf = fiprintf SIGFE
 flock SIGFE
-flock SIGFE
 floor NOSIGFE
 _floor = floor NOSIGFE
 floorf NOSIGFE
@@ -559,11 +558,11 @@ fstatfs SIGFE
 _fstatfs = fstatfs SIGFE
 fsync SIGFE
 _fsync = fsync SIGFE
-ftell NOSIGFE
-_ftell = ftell NOSIGFE
-ftello NOSIGFE
-_ftello = ftello NOSIGFE
-_ftello64 = ftello64 NOSIGFE
+ftell SIGFE
+_ftell = ftell SIGFE
+ftello SIGFE
+_ftello = ftello SIGFE
+_ftello64 = ftello64 SIGFE
 ftime SIGFE
 _ftime = ftime SIGFE
 ftok SIGFE
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 4983a2ede..e90d093a2 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -361,8 +361,8 @@ try_to_debug (bool waitloop)
 	}
     }
 
-  small_printf ("*** starting debugger for pid %u\n",
-		cygwin_pid (GetCurrentProcessId ()));
+  console_printf ("*** starting debugger for pid %u\n",
+		  cygwin_pid (GetCurrentProcessId ()));
   BOOL dbg;
   dbg = CreateProcess (NULL,
 		       debugger_command,
@@ -380,17 +380,18 @@ try_to_debug (bool waitloop)
   else
     {
       if (!waitloop)
-	return 1;
+	return dbg;
       SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
       while (!being_debugged ())
 	Sleep (0);
       Sleep (2000);
-      small_printf ("*** continuing pid %u from debugger call\n",
-		    cygwin_pid (GetCurrentProcessId ()));
     }
 
+  console_printf ("*** continuing pid %u from debugger call (%d)\n",
+		  cygwin_pid (GetCurrentProcessId ()), dbg);
+
   SetThreadPriority (GetCurrentThread (), prio);
-  return 0;
+  return dbg;
 }
 
 /* Main exception handler. */
@@ -416,10 +417,6 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
   EXCEPTION_RECORD e = *e0;
   CONTEXT in = *in0;
 
-  extern DWORD ret_here[];
-  RtlUnwind (frame, ret_here, e0, 0);
-  __asm__ volatile (".equ _ret_here,.");
-
   siginfo_t si;
   /* Coerce win32 value to posix value.  */
   switch (e.ExceptionCode)
@@ -557,6 +554,10 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
       signal_exit (0x80 | si.si_signo);	// Flag signal + core dump
     }
 
+  extern DWORD ret_here[];
+  RtlUnwind (frame, ret_here, e0, 0);
+  __asm__ volatile (".equ _ret_here,.");
+
   si.si_addr = ebp;
   si.si_code = SI_KERNEL;
   si.si_errno = si.si_pid = si.si_uid = 0;
@@ -766,12 +767,15 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls)
       __stack_t *retaddr_on_stack = tls->stackptr - 1;
       if (retaddr_on_stack >= tls->stack)
 	{
+	  if (!tls->lock (false))
+	    continue;
 	  __stack_t retaddr = InterlockedExchange ((LONG *) retaddr_on_stack, 0);
 	  if (!retaddr)
 	    continue;
 	  tls->reset_exception ();
 	  tls->interrupt_setup (sig, handler, siga, retaddr);
 	  sigproc_printf ("interrupted known cygwin routine");
+	  tls->unlock ();
 	  interrupted = true;
 	  break;
 	}
diff --git a/winsup/cygwin/gendef b/winsup/cygwin/gendef
index d317eeacd..2457314b2 100755
--- a/winsup/cygwin/gendef
+++ b/winsup/cygwin/gendef
@@ -88,40 +88,79 @@ EOF
     if (!$main::first++) {
 	$res = <<EOF . longjmp () . $res;
 	.text
-	.global	__sigbe
-	.global	_sigreturn
-	.global	_sigdelayed
 
 	.stabs	"_sigfe:F(0,1)",36,0,0,__sigbe
 __sigfe:
 	pushl	%edx
-	movl	%fs:4,%eax
-	movl	\$4,%edx
-	xadd	%edx,$tls::stackptr(%eax)
-	leal	__sigbe,%eax
-	xchg	%eax,8(%esp)
-	movl	%eax,(%edx)
+	movl	%fs:4,%edx
+1:	movl	\$1,%eax
+	lock	cmpxchg %eax,$tls::stacklock(%edx)
+	jne	2f
+	xorl	%eax,%eax
+	call	_low_priority_sleep
+	jmp	1b
+2:	movl	\$4,%eax
+	xadd	%eax,$tls::stackptr(%edx)
+	decl	$tls::stacklock(%edx)
+	leal	__sigbe,%edx
+	xchg	%edx,8(%esp)
+	movl	%edx,(%eax)
 	popl	%edx
 	ret
 
+	.global	__sigbe
 	.stabs	"_sigbe:F(0,1)",36,0,0,__sigbe
 __sigbe:
-	pushl	%eax
 	pushl	%edx
-	movl	\$-4,%edx
-1:	movl	%fs:4,%eax
-	xadd	%edx,$tls::stackptr(%eax)
+	pushl	%eax
+	movl	%fs:4,%edx
+1:	movl	\$1,%eax
+	lock	cmpxchg %eax,$tls::stacklock(%edx)
+	jne	2f
 	xorl	%eax,%eax
-	lock    xchg %eax,-4(%edx)
-	testl	%eax,%eax
-	jnz	2f
 	call	_low_priority_sleep
-	xorl	%edx,%edx
 	jmp	1b
-2:	xchg	%eax,4(%esp)
-	popl	%edx
+2:	movl	\$-4,%eax
+	xadd	%eax,$tls::stackptr(%edx)
+	xchg	%edx,-4(%eax)
+	xchg	%edx,4(%esp)
+	popl	%eax
 	ret
 
+	.global	__ZN11_threadinfo3popEv
+__ZN11_threadinfo3popEv:
+1:	pushl	%ebx
+	movl	%eax,%edx
+	movl	\$-4,%ebx
+	xadd	%ebx,$tls::pstackptr(%edx)
+	xorl	%eax,%eax
+	xchg	%eax,-4(%ebx)
+	decl	$tls::pstacklock(%edx)
+	popl	%ebx
+	ret
+
+	.global	__ZN11_threadinfo4lockEi
+__ZN11_threadinfo4lockEi:
+	pushl	%ebx
+	movl	%eax,%ebx
+1:	movl	\$1,%eax
+	lock	cmpxchg %eax,$tls::pstacklock(%ebx)
+	jne	2f
+	cmpl	%edx,%edx
+	jz	2f
+	xorl	%eax,%eax
+	call	_low_priority_sleep
+	jmp	1b
+2:	xorl	\$1,%eax
+	popl	%ebx
+	ret
+
+	.global	__ZN11_threadinfo6unlockEv
+__ZN11_threadinfo6unlockEv:
+	decl	$tls::pstacklock(%eax)
+	ret
+
+	.global	_sigreturn
 	.stabs	"sigreturn:F(0,1)",36,0,0,_sigreturn
 _sigreturn:
 	addl	\$4,%esp			# Remove argument
@@ -147,6 +186,7 @@ _sigreturn:
 	popl	%ebp
 	jmp	__sigbe
 
+	.global	_sigdelayed
 	.stabs	"sigdelayed:F(0,1)",36,0,0,_sigdelayed
 _sigdelayed:
 	pushl	%ebp
diff --git a/winsup/cygwin/gentls_offsets b/winsup/cygwin/gentls_offsets
index 375b66840..c69488a36 100755
--- a/winsup/cygwin/gentls_offsets
+++ b/winsup/cygwin/gentls_offsets
@@ -50,14 +50,17 @@ main(int argc, char **argv)
   $struct foo[1];
 # define foo_end ((char *) (foo + 1))
 # define offset(f) (((char *) &(foo->f)) - foo_end)
+# define poffset(f) (((char *) &(foo->f)) - ((char *) foo))
 EOF
     print TMP 'puts ("//;# autogenerated:  Do not edit.\n");', "\n\n";
     for my $f (@fields) {
 	print TMP '  printf ("//; $tls::', $f, ' = %d;\n", ', "offset($f));\n";
+	print TMP '  printf ("//; $tls::p', $f, ' = %d;\n", ', "poffset($f));\n";
     }
     print TMP '  puts ("//; __DATA__\n");', "\n";
     for my $f (@fields) {
 	print TMP '  printf ("#define tls_', $f, ' (%d)\n", ', "offset($f));\n";
+	print TMP '  printf ("#define tls_p', $f, ' (%d)\n", ', "poffset($f));\n";
     }
 
     print TMP <<EOF;
diff --git a/winsup/cygwin/localtime.cc b/winsup/cygwin/localtime.cc
index 3a64d689c..548f9d2e1 100644
--- a/winsup/cygwin/localtime.cc
+++ b/winsup/cygwin/localtime.cc
@@ -1565,6 +1565,7 @@ localtime(const time_t *timep)
 extern "C" struct tm *
 localtime_r(const time_t *timep, struct tm *tm)
 {
+	tzset();
 	localsub(timep, 0L, tm);
 	return tm;
 }
diff --git a/winsup/cygwin/tlsoffsets.h b/winsup/cygwin/tlsoffsets.h
index 51034302b..e1da0395a 100644
--- a/winsup/cygwin/tlsoffsets.h
+++ b/winsup/cygwin/tlsoffsets.h
@@ -1,48 +1,96 @@
 //;# autogenerated:  Do not edit.
 
-//; $tls::func = -3736;
-//; $tls::saved_errno = -3732;
-//; $tls::sa_flags = -3728;
-//; $tls::oldmask = -3724;
-//; $tls::newmask = -3720;
-//; $tls::event = -3716;
-//; $tls::errno_addr = -3712;
-//; $tls::initialized = -3708;
-//; $tls::sigmask = -3704;
-//; $tls::sigwait_mask = -3700;
-//; $tls::sigwait_info = -3696;
-//; $tls::threadkill = -3692;
-//; $tls::infodata = -3688;
-//; $tls::tid = -3540;
-//; $tls::local_clib = -3536;
-//; $tls::locals = -2608;
-//; $tls::prev = -1040;
-//; $tls::next = -1036;
-//; $tls::stackptr = -1032;
-//; $tls::sig = -1028;
+//; $tls::func = -3740;
+//; $tls::pfunc = 0;
+//; $tls::saved_errno = -3736;
+//; $tls::psaved_errno = 4;
+//; $tls::sa_flags = -3732;
+//; $tls::psa_flags = 8;
+//; $tls::oldmask = -3728;
+//; $tls::poldmask = 12;
+//; $tls::newmask = -3724;
+//; $tls::pnewmask = 16;
+//; $tls::event = -3720;
+//; $tls::pevent = 20;
+//; $tls::errno_addr = -3716;
+//; $tls::perrno_addr = 24;
+//; $tls::initialized = -3712;
+//; $tls::pinitialized = 28;
+//; $tls::sigmask = -3708;
+//; $tls::psigmask = 32;
+//; $tls::sigwait_mask = -3704;
+//; $tls::psigwait_mask = 36;
+//; $tls::sigwait_info = -3700;
+//; $tls::psigwait_info = 40;
+//; $tls::threadkill = -3696;
+//; $tls::pthreadkill = 44;
+//; $tls::infodata = -3692;
+//; $tls::pinfodata = 48;
+//; $tls::tid = -3544;
+//; $tls::ptid = 196;
+//; $tls::local_clib = -3540;
+//; $tls::plocal_clib = 200;
+//; $tls::locals = -2612;
+//; $tls::plocals = 1128;
+//; $tls::prev = -1044;
+//; $tls::pprev = 2696;
+//; $tls::next = -1040;
+//; $tls::pnext = 2700;
+//; $tls::stackptr = -1036;
+//; $tls::pstackptr = 2704;
+//; $tls::sig = -1032;
+//; $tls::psig = 2708;
+//; $tls::stacklock = -1028;
+//; $tls::pstacklock = 2712;
 //; $tls::stack = -1024;
+//; $tls::pstack = 2716;
 //; $tls::padding = 0;
+//; $tls::ppadding = 3740;
 //; __DATA__
 
-#define tls_func (-3736)
-#define tls_saved_errno (-3732)
-#define tls_sa_flags (-3728)
-#define tls_oldmask (-3724)
-#define tls_newmask (-3720)
-#define tls_event (-3716)
-#define tls_errno_addr (-3712)
-#define tls_initialized (-3708)
-#define tls_sigmask (-3704)
-#define tls_sigwait_mask (-3700)
-#define tls_sigwait_info (-3696)
-#define tls_threadkill (-3692)
-#define tls_infodata (-3688)
-#define tls_tid (-3540)
-#define tls_local_clib (-3536)
-#define tls_locals (-2608)
-#define tls_prev (-1040)
-#define tls_next (-1036)
-#define tls_stackptr (-1032)
-#define tls_sig (-1028)
+#define tls_func (-3740)
+#define tls_pfunc (0)
+#define tls_saved_errno (-3736)
+#define tls_psaved_errno (4)
+#define tls_sa_flags (-3732)
+#define tls_psa_flags (8)
+#define tls_oldmask (-3728)
+#define tls_poldmask (12)
+#define tls_newmask (-3724)
+#define tls_pnewmask (16)
+#define tls_event (-3720)
+#define tls_pevent (20)
+#define tls_errno_addr (-3716)
+#define tls_perrno_addr (24)
+#define tls_initialized (-3712)
+#define tls_pinitialized (28)
+#define tls_sigmask (-3708)
+#define tls_psigmask (32)
+#define tls_sigwait_mask (-3704)
+#define tls_psigwait_mask (36)
+#define tls_sigwait_info (-3700)
+#define tls_psigwait_info (40)
+#define tls_threadkill (-3696)
+#define tls_pthreadkill (44)
+#define tls_infodata (-3692)
+#define tls_pinfodata (48)
+#define tls_tid (-3544)
+#define tls_ptid (196)
+#define tls_local_clib (-3540)
+#define tls_plocal_clib (200)
+#define tls_locals (-2612)
+#define tls_plocals (1128)
+#define tls_prev (-1044)
+#define tls_pprev (2696)
+#define tls_next (-1040)
+#define tls_pnext (2700)
+#define tls_stackptr (-1036)
+#define tls_pstackptr (2704)
+#define tls_sig (-1032)
+#define tls_psig (2708)
+#define tls_stacklock (-1028)
+#define tls_pstacklock (2712)
 #define tls_stack (-1024)
+#define tls_pstack (2716)
 #define tls_padding (0)
+#define tls_ppadding (3740)