(file) Return to atexit.c CVS log (file) (dir) Up to [OMI] / omi / pal

  1 krisbash 1.1 #include "palcommon.h"
  2              
  3              #if defined(USE_PAL_ATEXIT)
  4              # include <stdlib.h>
  5              # include <common.h>
  6              # include <pthread.h>
  7              
  8              typedef void (*AtexitFunc)();
  9              
 10              /* Array of at-exit functions */
 11              static AtexitFunc _funcs[PAL_ATEXIT_MAX];
 12              static size_t _nfuncs;
 13              
 14              /* Lock to synchronize access to _funcs and _nfuncs */
 15              
 16              static pthread_mutex_t _lock = PTHREAD_MUTEX_INITIALIZER;
 17              
 18              /* Used to detect re-entrancy errors */
 19              static int _nesting;
 20              static pthread_mutex_t _nestingLock = PTHREAD_MUTEX_INITIALIZER;
 21              
 22 krisbash 1.1 /* Non-zero once the system atexit() has been called */
 23              static int _initialized;
 24              
 25              static void _AtForkPrepare()
 26              {
 27                  /* Lock */
 28                  pthread_mutex_lock(&_lock);
 29                  pthread_mutex_lock(&_nestingLock);
 30              }
 31              
 32              static void _AtForkParent()
 33              {
 34                  /* Unlock */
 35                  pthread_mutex_unlock(&_lock);
 36                  pthread_mutex_unlock(&_nestingLock);
 37              }
 38              
 39              static void _AtForkChild()
 40              {
 41                  _initialized = 0;
 42                  /* Unlock */
 43 krisbash 1.1     pthread_mutex_unlock(&_lock);
 44                  pthread_mutex_unlock(&_nestingLock);
 45              }
 46              
 47              static void _atexitFunc()
 48              {
 49                  PAL_AtexitCall();
 50              }
 51              
 52              int PAL_Atexit(void (*func)())
 53              {
 54                  /* Disallow if currently executing PAL_AtexitCall() */
 55                  pthread_mutex_lock(&_nestingLock);
 56                  {
 57                      DEBUG_ASSERT(_nesting == 0);
 58              
 59                      if (_nesting)
 60                      {
 61                          pthread_mutex_unlock(&_nestingLock);
 62                          return -1;
 63                      }
 64 krisbash 1.1     }
 65                  pthread_mutex_unlock(&_nestingLock);
 66              
 67                  /* Install _atexitFunc() to be called on the first call */
 68                  if (_initialized == 0)
 69                  {
 70                      pthread_mutex_lock(&_lock);
 71                      {
 72                          if (_initialized == 0)
 73                          {
 74                              if (atexit(_atexitFunc) != 0)
 75                              {
 76                                  pthread_mutex_unlock(&_lock);
 77                                  return -1;
 78                              }
 79              
 80                              pthread_atfork(_AtForkPrepare, _AtForkParent, _AtForkChild);
 81                              _initialized = 1;
 82                          }
 83                      }
 84                      pthread_mutex_unlock(&_lock);
 85 krisbash 1.1     }
 86              
 87                  /* Add the function to the array of functions */
 88                  pthread_mutex_lock(&_lock);
 89                  {
 90                      if (_nfuncs == PAL_ATEXIT_MAX)
 91                      {
 92                          pthread_mutex_unlock(&_lock);
 93                          return -1;
 94                      }
 95              
 96                      _funcs[_nfuncs++] = func;
 97                  }
 98                  pthread_mutex_unlock(&_lock);
 99              
100                  return 0;
101              }
102              
103              int PAL_AtexitCall()
104              {
105                  /* Disallow if currently executing PAL_AtexitCall() */
106 krisbash 1.1     pthread_mutex_lock(&_nestingLock);
107                  {
108                      DEBUG_ASSERT(_nesting == 0);
109              
110                      if (_nesting)
111                      {
112                          pthread_mutex_unlock(&_nestingLock);
113                          return -1;
114                      }
115              
116                      _nesting = 1;
117                  }
118                  pthread_mutex_unlock(&_nestingLock);
119              
120                  /* Call all the functions and reset array to zero-size */
121                  pthread_mutex_lock(&_lock);
122                  {
123                      size_t i;
124              
125                      for (i = 0; i < _nfuncs; i++)
126                          (*_funcs[i])();
127 krisbash 1.1 
128                      _nfuncs = 0;
129                  }
130                  pthread_mutex_unlock(&_lock);
131              
132                  /* Reset _nesting to zero */
133                  pthread_mutex_lock(&_nestingLock);
134                  {
135                      _nesting = 0;
136                  }
137                  pthread_mutex_unlock(&_nestingLock);
138              
139                  return 0;
140              }
141              
142              #endif /* defined(USE_PAL_ATEXIT) */

ViewCVS 0.9.2