bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Patch: Thread safe obstack


From: Herbert Euler
Subject: Patch: Thread safe obstack
Date: Sun, 26 Aug 2007 14:59:47 +0800

I have trouble using obstacks with my threaded server, since obstack's
error handling is not thread safe.  It provides a user defined
function `obstack_alloc_failed_handler' to signal errors when
allocation fails, and this function can call longjmp instead of
exiting.  But I can only call longjmp with a global jmp_buf, since
this function is called with no arguments.

Below is my patch to obstack to give it a chance calling the error
handling function with user provided data, so that obstack can be used
in a thread safe way.

Hope it useful.

Regards,
Guanpeng Xu




2007-08-26  Guanpeng Xu  <address@hidden>

       * lib/obstack.c (_obstack_newchunk): Call
       `obstack_alloc_failed_handler' with user data when thread safe
       required.
       (_obstack_begin, _obstack_begin_1): Likewise, and add an argument
       to thread safe version.
       (__attribute__): Add an argument to thread safe version.

       * lib/obstack.h (struct obstack): New member `user_data' for
       thread safe obstack.
       (obstack_alloc_failed_handler): Declared a different prototype for
       thread safe obstack.
       (set_obstack_user_data, obstack_user_data)
       (obstack_init_with_user_data): New macros for thread safe obstack.
       (obstack_init, obstack_begin, obstack_specify_allocation)
       (obstack_specify_allocation_with_arg): Created thread safe obstack
       version.



*** obstack.h.~1.33.~   Mon Jul 23 09:59:03 2007
--- obstack.h   Sun Aug 26 14:40:30 2007
***************
*** 160,165 ****
--- 160,171 ----
     void *tempptr;
   } temp;                      /* Temporary for some macros.  */
   int   alignment_mask;                /* Mask of alignment for each object. */
+ #ifdef OBSTACK_THREAD_SAFE
+   void *user_data;            /* The user data is for calling
+                                    obstack_alloc_failed_handler with
+                                    user-defined data, to make obstack
+                                    thread safe.  */
+ #endif /* OBSTACK_THREAD_SAFE */
   /* These prototypes vary based on `use_extra_arg', and we use
      casts to the prototypeless function type in all assignments,
      but having prototypes here quiets -Wstrict-prototypes.  */
***************
*** 179,189 ****
--- 185,203 ----
 /* Declare the external functions we use; they are in obstack.c.  */

 extern void _obstack_newchunk (struct obstack *, int);
+ #ifdef OBSTACK_THREAD_SAFE
+ extern int _obstack_begin (struct obstack *, int, int,
+                            void *(*) (long), void (*) (void *), void *);
+ extern int _obstack_begin_1 (struct obstack *, int, int,
+                            void *(*) (void *, long),
+                            void (*) (void *, void *), void *, void *);
+ #else
 extern int _obstack_begin (struct obstack *, int, int,
                            void *(*) (long), void (*) (void *));
 extern int _obstack_begin_1 (struct obstack *, int, int,
                             void *(*) (void *, long),
                             void (*) (void *, void *), void *);
+ #endif
 extern int _obstack_memory_used (struct obstack *);

 /* The default name of the function for freeing a chunk is 'obstack_free',
***************
*** 198,204 ****
--- 212,222 ----
    more memory.  This can be set to a user defined function which
    should either abort gracefully or use longjump - but shouldn't
    return.  The default action is to print a message and abort.  */
+ #ifdef OBSTACK_THREAD_SAFE
+ extern void (*obstack_alloc_failed_handler) (void *);
+ #else
 extern void (*obstack_alloc_failed_handler) (void);
+ #endif

 /* Exit value used when `print_and_abort' is used.  */
 extern int obstack_exit_failure;
***************
*** 222,227 ****
--- 240,282 ----
 #define obstack_alignment_mask(h) ((h)->alignment_mask)

 /* To prevent prototype warnings provide complete argument list.  */
+ #ifdef OBSTACK_THREAD_SAFE
+
+ #define set_obstack_user_data(h, ud) ((h)->user_data = (ud))
+
+ #define obstack_user_data(h) ((h)->user_data + 0)
+
+ #define obstack_init_with_user_data(h, user_data)               \
+   _obstack_begin ((h), 0, 0,                                    \
+                   (void *(*) (long)) obstack_chunk_alloc,       \
+                   (void (*) (void *)) obstack_chunk_free,       \
+                   (user_data))
+
+ #define obstack_init(h) obstack_init_with_user_data ((h), NULL)
+
+ /* The following three macros must be called with H that contains no
+    side effects.  */
+
+ #define obstack_begin(h, size)                                  \
+   _obstack_begin ((h), (size), 0,                               \
+                   (void *(*) (long)) obstack_chunk_alloc,       \
+                   (void (*) (void *)) obstack_chunk_free,       \
+                   (h)->user_data)
+
+ #define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+   _obstack_begin ((h), (size), (alignment),                             \
+                   (void *(*) (long)) (chunkfun),                        \
+                   (void (*) (void *)) (freefun),                        \
+                   (h)->user_data)
+
+ #define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
+   _obstack_begin_1 ((h), (size), (alignment),                           \
+                     (void *(*) (void *, long)) (chunkfun),              \
+                     (void (*) (void *, void *)) (freefun),              \
+                     (arg), (h)->user_data)
+
+ #else /* OBSTACK_THREAD_SAFE */
+
 #define obstack_init(h)                                                \
   _obstack_begin ((h), 0, 0,                                   \
                  (void *(*) (long)) obstack_chunk_alloc,       \
***************
*** 241,246 ****
--- 296,303 ----
   _obstack_begin_1 ((h), (size), (alignment),                          \
                    (void *(*) (void *, long)) (chunkfun),              \
                    (void (*) (void *, void *)) (freefun), (arg))
+
+ #endif /* OBSTACK_THREAD_SAFE */

 #define obstack_chunkfun(h, newchunkfun) \
((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
*** obstack.c.~1.35.~   Mon Jul 23 09:59:03 2007
--- obstack.c   Sun Aug 26 14:36:47 2007
***************
*** 90,97 ****
--- 90,102 ----
    abort gracefully or use longjump - but shouldn't return.  This
    variable by default points to the internal function
    `print_and_abort'.  */
+ #ifdef        OBSTACK_THREAD_SAFE
+ static void print_and_abort (void *);
+ void (*obstack_alloc_failed_handler) (void *) = print_and_abort;
+ #else
 static void print_and_abort (void);
 void (*obstack_alloc_failed_handler) (void) = print_and_abort;
+ #endif /* OBSTACK_THREAD_SAFE */

 /* Exit value used when `print_and_abort' is used.  */
 # include <stdlib.h>
*************** compat_symbol (libc, _obstack_compat, _o
*** 144,150 ****
 _obstack_begin (struct obstack *h,
                int size, int alignment,
                void *(*chunkfun) (long),
!               void (*freefun) (void *))
 {
   register struct _obstack_chunk *chunk; /* points to new chunk */

--- 149,159 ----
 _obstack_begin (struct obstack *h,
                int size, int alignment,
                void *(*chunkfun) (long),
!               void (*freefun) (void *)
! #ifdef OBSTACK_THREAD_SAFE
!                 , void *user_data
! #endif
!                 )
 {
   register struct _obstack_chunk *chunk; /* points to new chunk */

*************** _obstack_begin (struct obstack *h,
*** 172,181 ****
--- 181,197 ----
   h->chunk_size = size;
   h->alignment_mask = alignment - 1;
   h->use_extra_arg = 0;
+ #ifdef OBSTACK_THREAD_SAFE
+   set_obstack_user_data (h, user_data);
+ #endif

   chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
   if (!chunk)
+ #ifdef OBSTACK_THREAD_SAFE
+     (*obstack_alloc_failed_handler) (obstack_user_data (h));
+ #else
     (*obstack_alloc_failed_handler) ();
+ #endif
h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
                                               alignment - 1);
   h->chunk_limit = chunk->limit
*************** _obstack_begin (struct obstack *h,
*** 191,197 ****
 _obstack_begin_1 (struct obstack *h, int size, int alignment,
                  void *(*chunkfun) (void *, long),
                  void (*freefun) (void *, void *),
!                 void *arg)
 {
   register struct _obstack_chunk *chunk; /* points to new chunk */

--- 207,217 ----
 _obstack_begin_1 (struct obstack *h, int size, int alignment,
                  void *(*chunkfun) (void *, long),
                  void (*freefun) (void *, void *),
!                 void *arg
! #ifdef OBSTACK_THREAD_SAFE
!                   , void *user_data
! #endif
!                   )
 {
   register struct _obstack_chunk *chunk; /* points to new chunk */

*************** _obstack_begin_1 (struct obstack *h, int
*** 220,229 ****
--- 240,256 ----
   h->alignment_mask = alignment - 1;
   h->extra_arg = arg;
   h->use_extra_arg = 1;
+ #ifdef OBSTACK_THREAD_SAFE
+   set_obstack_user_data (h, user_data);
+ #endif

   chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
   if (!chunk)
+ #ifdef OBSTACK_THREAD_SAFE
+     (*obstack_alloc_failed_handler) (obstack_user_data (h));
+ #else
     (*obstack_alloc_failed_handler) ();
+ #endif
h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
                                               alignment - 1);
   h->chunk_limit = chunk->limit
*************** _obstack_newchunk (struct obstack *h, in
*** 260,266 ****
--- 287,297 ----
   /* Allocate and initialize the new chunk.  */
   new_chunk = CALL_CHUNKFUN (h, new_size);
   if (!new_chunk)
+ #ifdef OBSTACK_THREAD_SAFE
+     (*obstack_alloc_failed_handler) (obstack_user_data (h));
+ #else
     (*obstack_alloc_failed_handler) ();
+ #endif
   h->chunk = new_chunk;
   new_chunk->prev = old_chunk;
   new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
*************** _obstack_memory_used (struct obstack *h)
*** 413,419 ****

 static void
 __attribute__ ((noreturn))
! print_and_abort (void)
 {
   /* Don't change any of these strings.  Yes, it would be possible to add
      the newline to the string and use fputs or so.  But this must not
--- 444,456 ----

 static void
 __attribute__ ((noreturn))
! print_and_abort (
! #ifdef OBSTACK_THREAD_SAFE
!                  void *user_data
! #else
!                  void
! #endif
!                  )
 {
   /* Don't change any of these strings.  Yes, it would be possible to add
      the newline to the string and use fputs or so.  But this must not

_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today it's FREE! http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/





reply via email to

[Prev in Thread] Current Thread [Next in Thread]