Around 17 o'clock on Feb 21, David Dawes wrote:
> The attached patch attempts to implement the second approach, and from
> some limited testing it works OK for the two cases handled so far (where
> setjmp is available directly as a function, and the glibc 2.[01] case
> where it's a macro defined as above).
I think you're on the right track -- create a macro which invokes
different functions depending on the underlying libc. I think we can do
it with smaller changes, and no magic GCC pragmas. See attached.
Alternatively, we could admit that this is all very OS dependent and
#include <stdjmp.h> in the application, then all we need do is add
SYMFUNC's for the actual underlying function names in xf86sym.c (and not
for the ones not present on the system) and things should work as expected.
Modules built for another OS would fail to resolve the expected symbol and
crash as soon as setjmp was invoked.
-keith
Index: programs/Xserver/hw/xfree86/loader/xf86sym.c
===================================================================
RCS file: /home/x-cvs/xc/programs/Xserver/hw/xfree86/loader/xf86sym.c,v
retrieving revision 1.224
diff -u -r1.224 xf86sym.c
--- programs/Xserver/hw/xfree86/loader/xf86sym.c 9 Feb 2003 00:18:18 -0000
1.224
+++ programs/Xserver/hw/xfree86/loader/xf86sym.c 22 Feb 2003 02:58:20 -0000
@@ -26,6 +26,7 @@
#define INCLUDE_DEPRECATED 1
#include <fcntl.h>
+#include <setjmp.h>
#include "sym.h"
#include "misc.h"
#include "mi.h"
@@ -61,6 +62,11 @@
#endif
#include "compiler.h"
+#if defined(setjmp) && \
+ defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
+#define HAS_GLIBC_SIGSETJMP 1
+#endif
+
#ifdef __FreeBSD__
/* XXX used in drmOpen(). This should change to use a less os-specific
* method. */
@@ -887,8 +893,18 @@
SYMFUNC(xf86shmat)
SYMFUNC(xf86shmdt)
SYMFUNC(xf86shmctl)
- SYMFUNC(xf86setjmp)
- SYMFUNC(xf86longjmp)
+ SYMFUNC(xf86setjmp_has_1_arg)
+ SYMFUNC(xf86setjmp_has_2_args)
+#ifdef HAS_GLIBC_SIGSETJMP
+ SYMFUNC(xf86setjmp_1_arg)
+ SYMFUNCALIAS("xf86setjmp_2_args",__sigsetjmp)
+#else
+ SYMFUNCALIAS("xf86setjmp_1_arg",setjmp)
+ SYMFUNC(xf86setjmp_2_args)
+#endif
+ SYMFUNC(xf86setjmp_arg_2)
+ SYMFUNC(xf86setjmp_unknown_args)
+ SYMFUNCALIAS("xf86longjmp",longjmp)
#ifdef XF86DRI
/* These may have more general uses, but
for now, they are only used by the DRI.
Index: programs/Xserver/hw/xfree86/os-support/xf86_ansic.h
===================================================================
RCS file: /home/x-cvs/xc/programs/Xserver/hw/xfree86/os-support/xf86_ansic.h,v
retrieving revision 3.48
diff -u -r3.48 xf86_ansic.h
--- programs/Xserver/hw/xfree86/os-support/xf86_ansic.h 31 Dec 2001 18:13:37 -0000
3.48
+++ programs/Xserver/hw/xfree86/os-support/xf86_ansic.h 22 Feb 2003 02:11:06 -0000
@@ -305,7 +305,24 @@
extern char * xf86shmat(int id, char *addr, int xf86shmflg);
extern int xf86shmdt(char *addr);
extern int xf86shmctl(int id, int xf86cmd, pointer buf);
-extern int xf86setjmp(xf86jmp_buf env);
+
+/*
+ * Pre 2.2 GLIBC setjmp takes an extra (int) argument to
+ * a magic function
+ */
+#define xf86setjmp(e) (xf86setjmp_has_1_arg() ? \
+ xf86setjmp_1_arg(e): \
+ xf86setjmp_has_2_args() ? \
+ xf86setjmp_2_args(e,xf86setjmp_arg_2()) : \
+ xf86setjmp_unknown_args ())
+
+extern int xf86setjmp_has_1_arg(void);
+extern int xf86setjmp_has_2_args(void);
+extern int xf86setjmp_1_arg(xf86jmp_buf env);
+extern int xf86setjmp_2_args(xf86jmp_buf env, int arg2);
+extern int xf86setjmp_arg_2(void);
+extern int xf86setjmp_unknown_args(void);
+
extern void xf86longjmp(xf86jmp_buf env, int val);
#else /* XFree86LOADER || NEED_XF86_PROTOTYPES */
Index: programs/Xserver/hw/xfree86/os-support/xf86_libc.h
===================================================================
RCS file: /home/x-cvs/xc/programs/Xserver/hw/xfree86/os-support/xf86_libc.h,v
retrieving revision 3.54
diff -u -r3.54 xf86_libc.h
--- programs/Xserver/hw/xfree86/os-support/xf86_libc.h 19 Sep 2002 13:22:02 -0000
3.54
+++ programs/Xserver/hw/xfree86/os-support/xf86_libc.h 20 Feb 2003 06:51:17 -0000
@@ -71,7 +71,7 @@
typedef int xf86key_t;
/* setjmp/longjmp */
-typedef int xf86jmp_buf[20];
+typedef int xf86jmp_buf[1024];
/* for setvbuf */
#define XF86_IONBF 1
Index: programs/Xserver/hw/xfree86/os-support/shared/libc_wrapper.c
===================================================================
RCS file: /home/x-cvs/xc/programs/Xserver/hw/xfree86/os-support/shared/libc_wrapper.c,v
retrieving revision 1.86
diff -u -r1.86 libc_wrapper.c
--- programs/Xserver/hw/xfree86/os-support/shared/libc_wrapper.c 31 May 2002
18:46:02 -0000 1.86
+++ programs/Xserver/hw/xfree86/os-support/shared/libc_wrapper.c 22 Feb 2003
02:11:07 -0000
@@ -165,6 +165,14 @@
#endif
#include <setjmp.h>
+#if defined(setjmp) && \
+ defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
+#define SETJMP_ARG_2 0
+#define SETJMP_ARGS 2
+#else
+#define SETJMP_ARGS 1
+#endif
+
#if 0
#define SETBUF_RETURNS_INT
#endif
@@ -1945,15 +1953,43 @@
}
#endif /* HAVE_SYSV_IPC */
-int
-xf86setjmp(xf86jmp_buf xf86env)
+int xf86setjmp_has_1_arg(void)
{
- return setjmp((void *)xf86env);
+ return SETJMP_ARGS == 1;
}
-void
-xf86longjmp(xf86jmp_buf xf86env, int val)
+int xf86setjmp_has_2_args(void)
+{
+ return SETJMP_ARGS == 2;
+}
+
+#if SETJMP_ARGS != 1
+int xf86setjmp_1_arg(xf86jmp_buf env)
{
- longjmp((void *)xf86env, val);
+ FatalError ("setjmp: called with one arg instead of %d\n", SETJMP_ARGS);
+ return 0;
}
+#endif
+#if SETJMP_ARGS != 2
+int xf86setjmp_2_args(xf86jmp_buf env, int arg2)
+{
+ FatalError ("setjmp: called with two args instead of %d\n", SETJMP_ARGS);
+ return 0;
+}
+#endif
+
+int xf86setjmp_arg_2(void)
+{
+#ifdef SETJMP_ARG_2
+ return SETJMP_ARG_2;
+#else
+ FatalError ("setjmp: has no second argument\n");
+ return 0;
+#endif
+}
+
+int xf86setjmp_unknown_args(void)
+{
+ FatalError ("setjmp: should be called with %d args\n", SETJMP_ARGS);
+}