about summary refs log tree commit diff
path: root/nptl/sysdeps/pthread/pthread.h
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-06-08 05:28:14 +0000
committerUlrich Drepper <drepper@redhat.com>2003-06-08 05:28:14 +0000
commit7726edc27354afe163f492c0e6a8d4354fddb494 (patch)
tree22a712872298767abf2b081d9f766a33cad8fa20 /nptl/sysdeps/pthread/pthread.h
parentede0f73aeabe62589f6ca19a6987f48aa0d06184 (diff)
downloadglibc-7726edc27354afe163f492c0e6a8d4354fddb494.tar.gz
glibc-7726edc27354afe163f492c0e6a8d4354fddb494.tar.xz
glibc-7726edc27354afe163f492c0e6a8d4354fddb494.zip
Update.
2003-06-07  Ulrich Drepper  <drepper@redhat.com>

	* cleanup_routine.c: New file.
	* Versions (libpthread) [GLIBC_2.3.3]: Add __pthread_cleanup_routine.
	* sysdeps/pthread/pthread.h: Add support for fully exception-based
	cleanup handling.
	* Makefile (libpthread-routines): Add cleanup_routine.
	Add more CFLAGS variables to compile with exceptions.  Add comments
	why which file needs unwind tables.
	(tests) [have-forced-unwind==yes]: Add tst-cancelx* and tst-cleanupx*
	tests.
	* tst-cancelx1.c: New file.
	* tst-cancelx2.c: New file.
	* tst-cancelx3.c: New file.
	* tst-cancelx4.c: New file.
	* tst-cancelx5.c: New file.
	* tst-cancelx6.c: New file.
	* tst-cancelx7.c: New file.
	* tst-cancelx8.c: New file.
	* tst-cancelx9.c: New file.
	* tst-cancelx10.c: New file.
	* tst-cancelx11.c: New file.
	* tst-cancelx12.c: New file.
	* tst-cancelx13.c: New file.
	* tst-cancelx14.c: New file.
	* tst-cancelx15.c: New file.
	* tst-cleanupx0.c: New file.
	* tst-cleanupx0.expect: New file.
	* tst-cleanupx1.c: New file.
	* tst-cleanupx2.c: New file.
	* tst-cleanupx3.c: New file.

	* tst-cleanup0.c: Make standard compliant.
	* tst-cleanup1.c: Likewise.

	* sysdeps/unix/sysv/linux/sem_timedwait.c: Add cancellation support.
	* sysdeps/unix/sysv/linux/sem_wait.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise.
	* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise.
	* sysdeps/i386/tcb-offsets.sym: Add RESULT, CANCELHANDLING, and
	CLEANUP_JMP_BUF.
	* sysdeps/x86_64/tcb-offsets.sym: Likewise.
	* tst-cancel12.c: New file.
	* tst-cancel13.c: New file.
	* tst-cancel14.c: New file.
	* tst-cancel15.c: New file.
	* Makefile (tests): Add tst-cancel12, tst-cancel13, tst-cancel14,
	and tst-cancel15.

	* tst-cancel1.c: Add some comments.

	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Compute relative
	timeout correctly.
Diffstat (limited to 'nptl/sysdeps/pthread/pthread.h')
-rw-r--r--nptl/sysdeps/pthread/pthread.h137
1 files changed, 128 insertions, 9 deletions
diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h
index c0375ae223..1f0a34baa2 100644
--- a/nptl/sysdeps/pthread/pthread.h
+++ b/nptl/sysdeps/pthread/pthread.h
@@ -419,14 +419,132 @@ typedef struct
 #endif
 
 
+/* Structure to hold the cleanup handler information.  */
+struct __pthread_cleanup_frame
+{
+  void (*__cancel_routine) (void *);
+  void *__cancel_arg;
+  int __do_it;
+  int __cancel_type;
+};
+
+#if defined __GNUC__ && defined __EXCEPTIONS
+# ifdef __cplusplus
+/* Class to handle cancellation handler invocation.  */
+class __pthread_cleanup_class
+{
+  void (*__cancel_routine) (void *);
+  void *__cancel_arg;
+  int __do_it;
+  int __cancel_type;
+
+ public:
+  __pthread_cleanup_class (void (*__fct) (void *), void *__arg)
+    : __cancel_routine (__fct), __cancel_arg (__arg), __do_it (1) { }
+  ~__pthread_cleanup_class () { if (__do_it) __cancel_routine (__cancel_arg); }
+  __setdoit (int __newval) { __do_it = __newval; }
+  __defer () { pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED,
+				      &__cancel_type);
+  __restore () const { pthread_setcanceltype (__cancel_type, 0);
+};
+
+/* Install a cleanup handler: ROUTINE will be called with arguments ARG
+   when the thread is canceled or calls pthread_exit.  ROUTINE will also
+   be called with arguments ARG when the matching pthread_cleanup_pop
+   is executed with non-zero EXECUTE argument.
+
+   pthread_cleanup_push and pthread_cleanup_pop are macros and must always
+   be used in matching pairs at the same nesting level of braces.  */
+#  define pthread_cleanup_push(routine, arg) \
+  do {									      \
+    __pthread_cleanup_class __clframe (routine, arg)
+
+/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
+   If EXECUTE is non-zero, the handler function is called. */
+#  define pthread_cleanup_pop(execute) \
+    __clframe.__setdoit (execute);					      \
+  } while (0)
+
+#  ifdef __USE_GNU
+/* Install a cleanup handler as pthread_cleanup_push does, but also
+   saves the current cancellation type and sets it to deferred
+   cancellation.  */
+#   define pthread_cleanup_push_defer_np(routine, arg) \
+  do {									      \
+    __pthread_cleanup_class __clframe (routine, arg);			      \
+    __clframe.__defer ()
+
+/* Remove a cleanup handler as pthread_cleanup_pop does, but also
+   restores the cancellation type that was in effect when the matching
+   pthread_cleanup_push_defer was called.  */
+#   define pthread_cleanup_pop_restore_np(execute) \
+    __clframe.__restore ();						      \
+    __clframe.__setdoit (execute);					      \
+  } while (0)
+#  endif
+# else
+/* Function called to call the cleanup handler.  As an extern inline
+   function the compiler is free to decide inlining the change when
+   needed or fall back on the copy which must exist somewhere
+   else.  */
+extern inline void
+__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame)
+{
+  if (__frame->__do_it)
+    __frame->__cancel_routine (__frame->__cancel_arg);
+}
+
 /* Install a cleanup handler: ROUTINE will be called with arguments ARG
-   when the thread is cancelled or calls pthread_exit.  ROUTINE will also
+   when the thread is canceled or calls pthread_exit.  ROUTINE will also
    be called with arguments ARG when the matching pthread_cleanup_pop
    is executed with non-zero EXECUTE argument.
 
    pthread_cleanup_push and pthread_cleanup_pop are macros and must always
    be used in matching pairs at the same nesting level of braces.  */
-#define pthread_cleanup_push(routine, arg) \
+#  define pthread_cleanup_push(routine, arg) \
+  do {									      \
+    struct __pthread_cleanup_frame __clframe				      \
+      __attribute__ ((__cleanup__ (__pthread_cleanup_routine)))		      \
+      = { .__cancel_routine = (routine), .__cancel_arg = (arg),	 	      \
+	  .__do_it = 1 };
+
+/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
+   If EXECUTE is non-zero, the handler function is called. */
+#  define pthread_cleanup_pop(execute) \
+    __clframe.__do_it = (execute);					      \
+  } while (0)
+
+#  ifdef __USE_GNU
+/* Install a cleanup handler as pthread_cleanup_push does, but also
+   saves the current cancellation type and sets it to deferred
+   cancellation.  */
+#   define pthread_cleanup_push_defer_np(routine, arg) \
+  do {									      \
+    struct __pthread_cleanup_frame __clframe				      \
+      __attribute__ ((__cleanup__ (__pthread_cleanup_routine)))		      \
+      = { .__cancel_routine = (routine), .__cancel_arg = (arg),		      \
+	  .__do_it = 1 };						      \
+    (void) pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED,		      \
+				  &__clframe.__cancel_type)
+
+/* Remove a cleanup handler as pthread_cleanup_pop does, but also
+   restores the cancellation type that was in effect when the matching
+   pthread_cleanup_push_defer was called.  */
+#   define pthread_cleanup_pop_restore_np(execute) \
+    (void) pthread_setcanceltype (__clframe.__cancel_type, NULL);	      \
+    __clframe.__do_it = (execute);					      \
+  } while (0)
+#  endif
+# endif
+#else
+/* Install a cleanup handler: ROUTINE will be called with arguments ARG
+   when the thread is canceled or calls pthread_exit.  ROUTINE will also
+   be called with arguments ARG when the matching pthread_cleanup_pop
+   is executed with non-zero EXECUTE argument.
+
+   pthread_cleanup_push and pthread_cleanup_pop are macros and must always
+   be used in matching pairs at the same nesting level of braces.  */
+# define pthread_cleanup_push(routine, arg) \
   do {									      \
     __pthread_unwind_buf_t __cancel_buf;				      \
     void (*__cancel_routine) (void *) = (routine);			      \
@@ -447,7 +565,7 @@ extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf)
 
 /* Remove a cleanup handler installed by the matching pthread_cleanup_push.
    If EXECUTE is non-zero, the handler function is called. */
-#define pthread_cleanup_pop(execute) \
+# define pthread_cleanup_pop(execute) \
     } while (0);							      \
     __pthread_unregister_cancel (&__cancel_buf);			      \
     if (execute)							      \
@@ -456,11 +574,11 @@ extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf)
 extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf)
   __cleanup_fct_attribute;
 
-#ifdef __USE_GNU
+# ifdef __USE_GNU
 /* Install a cleanup handler as pthread_cleanup_push does, but also
    saves the current cancellation type and sets it to deferred
    cancellation.  */
-# define pthread_cleanup_push_defer(routine, arg) \
+#  define pthread_cleanup_push_defer_np(routine, arg) \
   do {									      \
     __pthread_unwind_buf_t __cancel_buf;				      \
     void (*__cancel_routine) (void *) = (routine);			      \
@@ -482,7 +600,7 @@ extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf)
 /* Remove a cleanup handler as pthread_cleanup_pop does, but also
    restores the cancellation type that was in effect when the matching
    pthread_cleanup_push_defer was called.  */
-# define pthread_cleanup_pop_cleanup(execute) \
+#  define pthread_cleanup_pop_restore_np(execute) \
     } while (0);							      \
     __pthread_unregister_cancel_restore (&__cancel_buf);		      \
     if (execute)							      \
@@ -490,15 +608,16 @@ extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf)
   } while (0)
 extern void __pthread_unregister_cancel_restore (__pthread_unwind_buf_t *__buf)
   __cleanup_fct_attribute;
-#endif
+# endif
 
 /* Internal interface to initiate cleanup.  */
 extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
      __cleanup_fct_attribute __attribute ((__noreturn__))
-#ifndef SHARED
+# ifndef SHARED
      __attribute ((__weak__))
-#endif
+# endif
      ;
+#endif
 
 /* Function used in the macros.  */
 struct __jmp_buf_tag;