[newlib-cygwin] Cygwin: Implement siglongjmp and sigsetjmp functions.

Corinna Vinschen corinna@sourceware.org
Tue Jul 21 15:31:00 GMT 2015


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=7c96ab0b434ea7d1f998841f39a5a704b84a87d2

commit 7c96ab0b434ea7d1f998841f39a5a704b84a87d2
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Tue Jul 21 17:31:02 2015 +0200

    Cygwin: Implement siglongjmp and sigsetjmp functions.
    
    	* libc/include/machine/setjmp.h (siglongjmp): Declare as function on
    	Cygwin.
    	(sigsetjmp): Ditto.
    	(_longjmp): Mark as noreturn function on Cygwin.
    
    	* common.din (siglongjmp): Export.
    	(sigsetjmp): Export.
    	* gendef: Change formatting of some comments.
    	(sigsetjmp): Implement.
    	(siglongjmp): Implement.
    	(__setjmpex): x86_64 only: Drop entry point.
    	(setjmp): x86_64 only: Store tls stackptr in Frame now, store MXCSR
    	and FPUCW registers in Spare, as MSVCRT does.
    	(longjmp): x86_64 only: Restore tls stackptr from Frame now, restore
    	MXCSR and FPUCW registers from Spare.
    	* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
    
    	* new-features.xml (ov-new2.2): Document sigsetjmp, siglongjmp.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 newlib/ChangeLog                       |   7 ++
 newlib/libc/include/machine/setjmp.h   |  11 ++-
 winsup/cygwin/ChangeLog                |  14 ++++
 winsup/cygwin/common.din               |   2 +
 winsup/cygwin/gendef                   | 120 +++++++++++++++++++++++++++------
 winsup/cygwin/include/cygwin/version.h |   3 +-
 winsup/cygwin/release/2.2.0            |   4 ++
 winsup/doc/ChangeLog                   |   4 ++
 winsup/doc/new-features.xml            |   8 +++
 9 files changed, 148 insertions(+), 25 deletions(-)

diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index 4131b6c..27f7395 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -1,3 +1,10 @@
+2015-07-21  Corinna Vinschen  <corinna@vinschen.de>
+
+	* libc/include/machine/setjmp.h (siglongjmp): Declare as function on
+	Cygwin.
+	(sigsetjmp): Ditto.
+	(_longjmp): Mark as noreturn function on Cygwin.
+
 2015-07-15  Wilco Dijkstra  <wdijkstr@arm.com>
 
 	* libc/machine/aarch64/memset.S (memset):
diff --git a/newlib/libc/include/machine/setjmp.h b/newlib/libc/include/machine/setjmp.h
index ec6644a..b25684d 100644
--- a/newlib/libc/include/machine/setjmp.h
+++ b/newlib/libc/include/machine/setjmp.h
@@ -381,6 +381,13 @@ typedef int sigjmp_buf[_JBLEN+1+(sizeof (sigset_t)/sizeof (int))];
 #define __SIGMASK_FUNC sigprocmask
 #endif
 
+#ifdef __CYGWIN__
+/* Per POSIX, siglongjmp has to be implemented as function.  Cygwin
+   provides functions for both, siglongjmp and sigsetjmp since 2.2.0. */
+extern void siglongjmp (sigjmp_buf, int) __attribute__ ((__noreturn__));
+extern int sigsetjmp (sigjmp_buf, int);
+#endif
+
 #if defined(__GNUC__)
 
 #define sigsetjmp(env, savemask) \
@@ -418,8 +425,8 @@ typedef int sigjmp_buf[_JBLEN+1+(sizeof (sigset_t)/sizeof (int))];
    are equivalent to sigsetjmp/siglongjmp when not saving the signal mask.
    New applications should use sigsetjmp/siglongjmp instead. */
 #ifdef __CYGWIN__
-extern void _longjmp(jmp_buf, int);
-extern int _setjmp(jmp_buf);
+extern void _longjmp (jmp_buf, int) __attribute__ ((__noreturn__));
+extern int _setjmp (jmp_buf);
 #else
 #define _setjmp(env)		sigsetjmp ((env), 0)
 #define _longjmp(env, val)	siglongjmp ((env), (val))
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 0d9df3b..2d8475b 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,17 @@
+2015-07-21  Corinna Vinschen  <corinna@vinschen.de>
+
+	* common.din (siglongjmp): Export.
+	(sigsetjmp): Export.
+	* gendef: Change formatting of some comments.
+	(sigsetjmp): Implement.
+	(siglongjmp): Implement.
+	(__setjmpex): x86_64 only: Drop entry point.
+	(setjmp): x86_64 only: Store tls stackptr in Frame now, store MXCSR
+	and FPUCW registers in Spare, as MSVCRT does.
+	(longjmp): x86_64 only: Restore tls stackptr from Frame now, restore
+	MXCSR and FPUCW registers from Spare.
+	* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
+
 2015-07-19  Corinna Vinschen  <corinna@vinschen.de>
 
 	* include/cygwin/signal.h (MINSIGSTKSZ): Define as 8K, unconditionally.
diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din
index e89a6bd..71a0c9b 100644
--- a/winsup/cygwin/common.din
+++ b/winsup/cygwin/common.din
@@ -1110,6 +1110,7 @@ sighold SIGFE
 sigignore SIGFE
 siginterrupt SIGFE
 sigismember SIGFE
+siglongjmp NOSIGFE
 signal SIGFE
 significand NOSIGFE
 significandf NOSIGFE
@@ -1119,6 +1120,7 @@ sigprocmask SIGFE
 sigqueue SIGFE
 sigrelse SIGFE
 sigset SIGFE
+sigsetjmp NOSIGFE
 sigsuspend SIGFE
 sigwait SIGFE
 sigwaitinfo SIGFE
diff --git a/winsup/cygwin/gendef b/winsup/cygwin/gendef
index 480f2d9..9868277 100755
--- a/winsup/cygwin/gendef
+++ b/winsup/cygwin/gendef
@@ -590,21 +590,32 @@ sub longjmp {
     if ($is64bit) {
 	return <<EOF;
 
-	.globl  setjmp
-	.seh_proc setjmp
-setjmp:
+	.globl	sigsetjmp
+	.seh_proc sigsetjmp
+sigsetjmp:
 	.seh_endprologue
-	leaq	8(%rsp),%rdx
-	jmp	__setjmpex
+	movl	%edx,0x100(%rcx)		# store savemask
+	testl	%edx,%edx			# savemask != 0?
+	je	setjmp				# no, skip fetching sigmask
+	pushq	%rcx
+	subq	\$0x20,%rsp
+	leaq	0x108(%rcx),%r8			# &sigjmp_buf.sigmask
+	xorq	%rdx,%rdx			# NULL
+	xorl	%ecx,%ecx			# SIG_SETMASK
+	call	pthread_sigmask
+	addq	\$0x20,%rsp
+	popq	%rcx
+	jmp	setjmp
 	.seh_endproc
 
-	.globl	__setjmpex
-	.seh_proc __setjmpex
-__setjmpex:
+	.globl  setjmp
+	.seh_proc setjmp
+setjmp:
 	.seh_endprologue
-	# We use the Windows jmp_buf layout.
-	# Store alternative stackptr in Spare.
-	movq	%rdx,(%rcx)
+	# We use the Windows jmp_buf layout with two small twists.
+	# - we store the tls stackptr in Frame, MSVCRT stores a second copy
+	#   of %rbp in Frame (twice? why?)
+	# - we just store %rsp as is, MSVCRT stores %rsp of the caller in Rsp
 	movq	%rbx,0x8(%rcx)
 	movq	%rsp,0x10(%rcx)
 	movq	%rbp,0x18(%rcx)
@@ -616,6 +627,8 @@ __setjmpex:
 	movq	%r15,0x48(%rcx)
 	movq	(%rsp),%r10
 	movq	%r10,0x50(%rcx)
+	stmxcsr	0x58(%rcx)
+	fnstcw	0x5c(%rcx)
 	# jmp_buf is potentially unaligned!
 	movdqu	%xmm6,0x60(%rcx)
 	movdqu	%xmm7,0x70(%rcx)
@@ -632,27 +645,47 @@ __setjmpex:
 	call	stabilize_sig_stack		# returns tls in r11
 	popq	%rcx
 	movq	$tls::stackptr(%r11),%r10
-	movq	%r10,0x58(%rcx)
+	movq	%r10,(%rcx)
 	decl	$tls::stacklock(%r11)
-	movl	\$0,%eax
+	xorl	%eax,%eax
 	ret
 	.seh_endproc
 
+	.globl	siglongjmp
+	.seh_proc siglongjmp
+siglongjmp:
+	pushq	%rcx
+	.seh_pushreg %rcx
+	.seh_endprologue
+	movl	%edx, %r12d
+	movl	0x100(%rcx),%r8d		# savemask
+	testl	%r8d,%r8d			# savemask != 0?
+	je	1f				# no, jmp to longjmp
+	xorq	%r8,%r8				# NULL
+	leaq    0x108(%rcx),%rdx		# &sigjmp_buf.sigmask
+	xorl	%ecx,%ecx			# SIG_SETMASK
+	subq	\$0x20,%rsp
+	call	pthread_sigmask
+	addq	\$0x20,%rsp
+	jmp	1f
+	.seh_endproc
+
 	.globl  longjmp
 	.seh_proc longjmp
 longjmp:
 	pushq	%rcx
 	.seh_pushreg %rcx
 	.seh_endprologue
-	movl	%edx,%r12d			# save return value (r12 is overwritten anyway)
+	movl	%edx,%r12d			# save return value
+1:
 	call	stabilize_sig_stack		# returns tls in r11
 	popq	%rcx
 	movl	%r12d,%eax			# restore return value
-	movq	0x58(%rcx),%r10			# get old signal stack
+	movq	(%rcx),%r10			# get old signal stack
 	movq	%r10,$tls::stackptr(%r11)	# restore
 	decl	$tls::stacklock(%r11)		# relinquish lock
 	xorl	%r10d,%r10d
-	movl	%r10d,$tls::incyg(%r11)		# we're definitely not in cygwin anymore
+	movl	%r10d,$tls::incyg(%r11)		# we're not in cygwin anymore
 	movq	0x8(%rcx),%rbx
 	movq	0x10(%rcx),%rsp
 	movq	0x18(%rcx),%rbp
@@ -664,6 +697,9 @@ longjmp:
 	movq	0x48(%rcx),%r15
 	movq	0x50(%rcx),%r10
 	movq	%r10,(%rsp)
+	ldmxcsr	0x58(%rcx)
+	fnclex
+	fldcw	0x5c(%rcx)
 	# jmp_buf is potentially unaligned!
 	movdqu	0x60(%rcx),%xmm6
 	movdqu	0x70(%rcx),%xmm7
@@ -684,12 +720,33 @@ EOF
     } else {
 	return <<EOF;
 
+	.globl	_sigsetjmp
+_sigsetjmp:
+	pushl   %ebp
+	movl    %esp,%ebp
+	pushl   %edi
+	movl	8(%ebp),%edi			# &sigjmp_buf
+	movl	12(%ebp),%eax			# savemask
+	movl	%eax,208(%edi)			# store savemask
+	testl	%eax,%eax			# savemask != 0?
+	je	1f				# no, skip fetching sigmask
+	subl	\$12,%esp
+	leal	212(%edi),%eax			# &sigjmp_buf.sigmask
+	movl	%eax,8(%esp)			# -> 3rd param "oldset"
+	xorl	%eax,%eax
+	movl	%eax,4(%esp)			# NULL -> 2nd param "set"
+	movl	%eax,(%esp)			# SIG_SETMASK -> 1st param "how"
+	call	_pthread_sigmask
+	addl	\$12,%esp
+	jmp	1f
+
 	.globl	_setjmp
 _setjmp:
 	pushl	%ebp
 	movl	%esp,%ebp
 	pushl	%edi
 	movl	8(%ebp),%edi
+1:
 	movl	%eax,0(%edi)
 	movl	%ebx,4(%edi)
 	movl	%ecx,8(%edi)
@@ -717,7 +774,7 @@ _setjmp:
 	fnstcw  48(%edi)
 	pushl	%ebx
 	call	stabilize_sig_stack
-	movl	$tls::stackptr(%ebx),%eax		# save stack pointer contents
+	movl	$tls::stackptr(%ebx),%eax	# save stack pointer contents
 	decl	$tls::stacklock(%ebx)
 	popl	%ebx
 	movl	%eax,52(%edi)
@@ -796,17 +853,36 @@ ___ljfault:
 	popfl
 	ret
 
+	.globl	_siglongjmp
+_siglongjmp:
+	pushl	%ebp
+	movl	%esp,%ebp
+	movl	8(%ebp),%edi			# &sigjmp_buf
+	movl	208(%edi),%eax			# load savemask
+	testl	%eax,%eax			# savemask != 0?
+	je	1f				# no, skip restoring sigmask
+	subl	\$12,%esp
+	leal	212(%edi),%eax			# &sigjmp_buf.sigmask
+	movl	%eax,4(%esp)			# -> 2nd param "set"
+	xorl	%eax,%eax
+	movl	%eax,8(%esp)			# NULL -> 3rd param "oldset"
+	movl	%eax,(%esp)			# SIG_SETMASK -> 1st param "how"
+	call	_pthread_sigmask
+	addl	\$12,%esp
+	jmp	1f
+
 	.globl	_longjmp
 _longjmp:
 	pushl	%ebp
 	movl	%esp,%ebp
-	movl	8(%ebp),%edi				# address of buffer
+	movl	8(%ebp),%edi			# &jmp_buf
+1:
 	call	stabilize_sig_stack
-	movl	52(%edi),%eax				# get old signal stack
-	movl	%eax,$tls::stackptr(%ebx)		# restore
-	decl	$tls::stacklock(%ebx)			# relinquish lock
+	movl	52(%edi),%eax			# get old signal stack
+	movl	%eax,$tls::stackptr(%ebx)	# restore
+	decl	$tls::stacklock(%ebx)		# relinquish lock
 	xorl	%eax,%eax
-	movl	%eax,$tls::incyg(%ebx)			# we're definitely not in cygwin anymore
+	movl	%eax,$tls::incyg(%ebx)		# we're not in cygwin anymore
 
 	movl	12(%ebp),%eax
 	testl	%eax,%eax
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index d909ec3..2c2d038 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -470,13 +470,14 @@ details. */
       286: Export cabsl, cimagl, creall, finitel, hypotl, sqrtl.
       287: Export issetugid.
       288: Export getcontext, makecontext, setcontext, swapcontext.
+      289: Export sigsetjmp, siglongjmp.
      */
 
      /* Note that we forgot to bump the api for ualarm, strtoll, strtoull,
 	sigaltstack, sethostname. */
 
 #define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 288
+#define CYGWIN_VERSION_API_MINOR 289
 
      /* There is also a compatibity version number associated with the
 	shared memory regions.  It is incremented when incompatible
diff --git a/winsup/cygwin/release/2.2.0 b/winsup/cygwin/release/2.2.0
index 4a8d923..2fab1f6 100644
--- a/winsup/cygwin/release/2.2.0
+++ b/winsup/cygwin/release/2.2.0
@@ -3,6 +3,10 @@ What's new:
 
 - New APIs: getcontext, setcontext, makecontext, swapcontext.
 
+- New functions: sigsetjmp, siglongjmp.
+  These were only available as macros up to now, but POSIX requires that
+  siglongjmp has to be available as function.
+
 
 What changed:
 -------------
diff --git a/winsup/doc/ChangeLog b/winsup/doc/ChangeLog
index a4c3036..e3eb26f 100644
--- a/winsup/doc/ChangeLog
+++ b/winsup/doc/ChangeLog
@@ -1,3 +1,7 @@
+2015-07-21  Corinna Vinschen  <corinna@vinschen.de>
+
+	* new-features.xml (ov-new2.2): Document sigsetjmp, siglongjmp.
+
 2015-07-17  Corinna Vinschen  <corinna@vinschen.de>
 
 	* new-features.xml (ov-new2.2): Add new section.  Document getcontext,
diff --git a/winsup/doc/new-features.xml b/winsup/doc/new-features.xml
index 85d6ec7..ed8d61d 100644
--- a/winsup/doc/new-features.xml
+++ b/winsup/doc/new-features.xml
@@ -12,6 +12,14 @@
 New APIs: getcontext, setcontext, makecontext, swapcontext.
 </para></listitem>
 
+<listitem><para>
+New functions: sigsetjmp, siglongjmp.
+</para>
+<para>
+These were only available as macros up to now, but POSIX requires that
+siglongjmp has to be available as function.
+</para></listitem>
+
 </itemizedlist>
 
 </sect2>



More information about the Cygwin-cvs mailing list