IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 17390


Ignore:
Timestamp:
Apr 8, 2008, 4:15:02 AM (18 years ago)
Author:
eugene
Message:

fix locking / thread conflict problems

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Ohana/src/opihi/lib.shell/gprint.c

    r17069 r17390  
    2525     pointer is closed and set to NULL.  setting a new FILE results in the
    2626     IObuffer being freed and an already opened FILE to be flushed and closed.
     27
     28
     29  gprint & mutex:
     30
     31     gprintInit : init_stream_mutex
     32     gprintGetStream : init_stream_mutex
     33     gprintCloseFile : init_stream_mutex
     34
     35     gprintSetFileAllThreads : set_file_mutex
     36     (gprintSetFile -> gprintCloseFile)
     37
     38     gprintSetFileThisThread : set_file_mutex
     39     (gprintGetStream)
     40     (gprintSetFile -> gprintCloseFile)
     41
     42     we are safe from dead locks: init_stream_mutex can be wrapped by set_file_mutex, but
     43     not vice-versa
     44
    2745*/
    2846
    29 static gpStream *streams = NULL;
     47static gpStream **streams = NULL;
    3048static int Nstreams = 0;
    3149
    32 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
     50static pthread_mutex_t init_stream_mutex = PTHREAD_MUTEX_INITIALIZER;
    3351
    3452void gprintInit () {
     
    3856
    3957  /* need to use a mutex to prevent two threads from initing simultaneously */
    40   pthread_mutex_lock (&mutex);
    41 
     58  pthread_mutex_lock (&init_stream_mutex);
     59
     60  // streams is an array of pointers so we can add more streams without changing pointers
    4261  if (streams == NULL) {
    4362    Nstreams = 2;
    44     ALLOCATE (streams, gpStream, Nstreams);
     63    ALLOCATE (streams, gpStream *, Nstreams);
    4564  } else {
    4665    Nstreams += 2;
    47     REALLOCATE (streams, gpStream, Nstreams);
     66    REALLOCATE (streams, gpStream *, Nstreams);
    4867  }
    4968
     
    5271
    5372  N = Nstreams - 2;
    54   streams[N].dest = GP_LOG;
    55   streams[N].file = stdout;
    56   streams[N].name = strcreate ("stdout");
    57 
    58   ALLOCATE (streams[N].buffer, IOBuffer, 1);
    59   InitIOBuffer (streams[N].buffer, 64);
    60   streams[N].mode = GP_FILE;
    61   streams[N].thread = id;
     73  ALLOCATE (streams[N], gpStream, 1);
     74  streams[N][0].dest = GP_LOG;
     75  streams[N][0].file = stdout;
     76  streams[N][0].name = strcreate ("stdout");
     77
     78  ALLOCATE (streams[N][0].buffer, IOBuffer, 1);
     79  InitIOBuffer (streams[N][0].buffer, 64);
     80  streams[N][0].mode = GP_FILE;
     81  streams[N][0].thread = id;
    6282
    6383  N = Nstreams - 1;
    64   streams[N].dest = GP_ERR;
    65   streams[N].file = stderr;
    66   streams[N].name = strcreate ("stderr");
    67 
    68   ALLOCATE (streams[N].buffer, IOBuffer, 1);
    69   InitIOBuffer (streams[N].buffer, 64);
    70   streams[N].mode = GP_FILE;
    71   streams[N].thread = id;
    72 
    73   pthread_mutex_unlock (&mutex);
     84  ALLOCATE (streams[N], gpStream, 1);
     85  streams[N][0].dest = GP_ERR;
     86  streams[N][0].file = stderr;
     87  streams[N][0].name = strcreate ("stderr");
     88
     89  ALLOCATE (streams[N][0].buffer, IOBuffer, 1);
     90  InitIOBuffer (streams[N][0].buffer, 64);
     91  streams[N][0].mode = GP_FILE;
     92  streams[N][0].thread = id;
     93
     94  pthread_mutex_unlock (&init_stream_mutex);
    7495}
    7596
     
    7899  int i;
    79100  pthread_t id;
     101  gpStream *stream;
     102
     103  // need to wait for initialization to be finished before getting stream or the array
     104  // (streams[i]) may move
     105  pthread_mutex_lock (&init_stream_mutex);
    80106
    81107  id = pthread_self();
     
    83109  /* find the existing output stream which matches */
    84110  for (i = 0; i < Nstreams; i++) {
    85     if (streams[i].dest != dest) continue;
    86     if (!pthread_equal (streams[i].thread, id)) continue;
    87     return (&streams[i]);
    88   }
     111    if (streams[i][0].dest != dest) continue;
     112    if (!pthread_equal (streams[i][0].thread, id)) continue;
     113    stream = streams[i];
     114    pthread_mutex_unlock (&init_stream_mutex);
     115    return stream;
     116  }
     117  pthread_mutex_unlock (&init_stream_mutex);
    89118  fprintf (stderr, "programming error: gprintInit not called for thread\n");
    90119  abort ();
     
    115144  }
    116145
     146  // we cannot do the operation below while another thread is initing
     147  pthread_mutex_lock (&init_stream_mutex);
     148
    117149  // must we close the existing file? if still being used, then no
    118150  Nmatch = 0;
    119151  for (i = 0; i < Nstreams; i++) {
    120     if (stream == &streams[i]) continue;
    121     if (streams[i].file == stream[0].file) Nmatch ++;
    122   }
     152    if (stream == streams[i]) continue;
     153    if (streams[i][0].file == stream[0].file) Nmatch ++;
     154  }
     155  pthread_mutex_unlock (&init_stream_mutex);
     156
    123157  if (Nmatch == 0) {
    124158    fflush (stream[0].file);
     
    130164}
    131165
     166// this thread only operates on its own stream
    132167void gprintSetBuffer (gpDest dest) {
    133168
     
    145180}
    146181
     182// this thread only operates on its own stream
    147183IOBuffer *gprintGetBuffer (gpDest dest) {
    148184
     
    158194  int i;
    159195
    160   /* need to use a mutex to prevent two threads from initing simultaneously */
     196  // be sure we are not colliding with gprintSetFileThisThread
    161197  pthread_mutex_lock (&set_file_mutex);
    162198
    163199  for (i = 0; i < Nstreams; i++) {
    164     if (streams[i].dest != dest) continue;
    165     gprintSetFile (&streams[i], dest, filename);
     200    if (streams[i][0].dest != dest) continue;
     201    gprintSetFile (streams[i], dest, filename);
    166202  }
    167203
     
    170206}
    171207
     208// this thread only operates on its own stream
    172209void gprintSetFileThisThread (gpDest dest, char *filename) {
    173210
    174211  gpStream *stream;
    175   stream = gprintGetStream (dest);
    176 
    177   /* need to use a mutex to prevent two threads from initing simultaneously */
     212
     213  // be sure we are not colliding with gprintSetFileAllThreads
    178214  pthread_mutex_lock (&set_file_mutex);
    179215
     216  stream = gprintGetStream (dest);
    180217  gprintSetFile (stream, dest, filename);
    181218
     
    183220  return;
    184221}
    185 
    186222
    187223void gprintSetFile (gpStream *stream, gpDest dest, char *filename) {
     
    231267}
    232268
     269// this thread only operates on its own stream
    233270FILE *gprintGetFile (gpDest dest) {
    234271
     
    238275}
    239276
     277// this thread only operates on its own stream
    240278char *gprintGetName (gpDest dest) {
    241279
     
    251289  va_list argp; 
    252290
     291  // this thread only writes to its own stream
    253292  stream = gprintGetStream (dest);
    254293
     
    273312  gpStream *stream;
    274313
     314  // this thread only writes to its own stream
    275315  stream = gprintGetStream (dest);
    276316
Note: See TracChangeset for help on using the changeset viewer.