~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_pthread.c

  • Committer: Brian Aker
  • Date: 2008-06-28 05:26:20 UTC
  • Revision ID: brian@tangent.org-20080628052620-kglj1hb5cggw8h3r
Second pass on pthread cleanup

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 
26
26
uint thd_lib_detected= 0;
27
27
 
28
 
#ifndef my_pthread_getprio
29
 
int my_pthread_getprio(pthread_t thread_id)
30
 
{
31
 
#ifdef HAVE_PTHREAD_SETSCHEDPARAM
32
 
  struct sched_param tmp_sched_param;
33
 
  int policy;
34
 
  if (!pthread_getschedparam(thread_id,&policy,&tmp_sched_param))
35
 
  {
36
 
    return tmp_sched_param.sched_priority;
37
 
  }
38
 
#endif
39
 
  return -1;
40
 
}
41
 
#endif
42
 
 
43
 
#ifndef my_pthread_attr_setprio
44
 
void my_pthread_attr_setprio(pthread_attr_t *attr, int priority)
45
 
{
46
 
#ifdef HAVE_PTHREAD_SETSCHEDPARAM
47
 
  struct sched_param tmp_sched_param;
48
 
  bzero((char*) &tmp_sched_param,sizeof(tmp_sched_param));
49
 
  tmp_sched_param.sched_priority=priority;
50
 
  VOID(pthread_attr_setschedparam(attr,&tmp_sched_param));
51
 
#endif
52
 
}
53
 
#endif
54
 
 
55
 
/*
56
 
  Some functions for RTS threads, AIX, Siemens Unix and UnixWare 7
57
 
  (and DEC OSF/1 3.2 too)
58
 
*/
59
 
 
60
28
int my_pthread_create_detached=1;
61
29
 
62
 
#if defined(HAVE_NONPOSIX_SIGWAIT)
63
 
 
64
 
int my_sigwait(const sigset_t *set,int *sig)
65
 
{
66
 
  int signal=sigwait((sigset_t*) set);
67
 
  if (signal < 0)
68
 
    return errno;
69
 
  *sig=signal;
70
 
  return 0;
71
 
}
72
 
#endif
73
 
 
74
 
/* localtime_r for SCO 3.2V4.2 */
75
 
 
76
 
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
77
 
 
78
 
extern pthread_mutex_t LOCK_localtime_r;
79
 
 
80
 
#endif
81
 
 
82
 
#if !defined(HAVE_LOCALTIME_R)
83
 
struct tm *localtime_r(const time_t *clock, struct tm *res)
84
 
{
85
 
  struct tm *tmp;
86
 
  pthread_mutex_lock(&LOCK_localtime_r);
87
 
  tmp=localtime(clock);
88
 
  *res= *tmp;
89
 
  pthread_mutex_unlock(&LOCK_localtime_r);
90
 
  return res;
91
 
}
92
 
#endif
93
 
 
94
 
#if !defined(HAVE_GMTIME_R)
95
 
/* 
96
 
  Reentrant version of standard gmtime() function. 
97
 
  Needed on some systems which don't implement it.
98
 
*/
99
 
 
100
 
struct tm *gmtime_r(const time_t *clock, struct tm *res)
101
 
{
102
 
  struct tm *tmp;
103
 
  pthread_mutex_lock(&LOCK_localtime_r);
104
 
  tmp= gmtime(clock);
105
 
  *res= *tmp;
106
 
  pthread_mutex_unlock(&LOCK_localtime_r);
107
 
  return res;
108
 
}
109
 
#endif
110
 
 
111
 
/****************************************************************************
112
 
** Replacement of sigwait if the system doesn't have one (like BSDI 3.0)
113
 
**
114
 
** Note:
115
 
** This version of sigwait() is assumed to called in a loop so the signalmask
116
 
** is permanently modified to reflect the signal set. This is done to get
117
 
** a much faster implementation.
118
 
**
119
 
** This implementation isn't thread safe: It assumes that only one
120
 
** thread is using sigwait.
121
 
**
122
 
** If one later supplies a different signal mask, all old signals that
123
 
** was used before are unblocked and set to SIGDFL.
124
 
**
125
 
** Author: Gary Wisniewski <garyw@spidereye.com.au>, much modified by Monty
126
 
****************************************************************************/
127
 
 
128
 
#if !defined(HAVE_SIGWAIT) && !defined(sigwait) && !defined(HAVE_rts_threads) && !defined(HAVE_NONPOSIX_SIGWAIT)
129
 
 
130
 
#if !defined(DONT_USE_SIGSUSPEND)
131
 
 
132
 
static sigset_t sigwait_set,rev_sigwait_set,px_recd;
133
 
 
134
 
void px_handle_sig(int sig)
135
 
{
136
 
  sigaddset(&px_recd, sig);
137
 
}
138
 
 
139
 
 
140
 
void sigwait_setup(sigset_t *set)
141
 
{
142
 
  int i;
143
 
  struct sigaction sact,sact1;
144
 
  sigset_t unblock_mask;
145
 
 
146
 
  sact.sa_flags = 0;
147
 
  sact.sa_handler = px_handle_sig;
148
 
  memcpy_fixed(&sact.sa_mask,set,sizeof(*set)); /* handler isn't thread_safe */
149
 
  sigemptyset(&unblock_mask);
150
 
  pthread_sigmask(SIG_UNBLOCK,(sigset_t*) 0,&rev_sigwait_set);
151
 
 
152
 
  for (i = 1; i <= sizeof(sigwait_set)*8; i++)
153
 
  {
154
 
    if (sigismember(set,i))
155
 
    {
156
 
      sigdelset(&rev_sigwait_set,i);
157
 
      if (!sigismember(&sigwait_set,i))
158
 
        sigaction(i, &sact, (struct sigaction*) 0);
159
 
    }
160
 
    else
161
 
    {
162
 
      sigdelset(&px_recd,i);                    /* Don't handle this */
163
 
      if (sigismember(&sigwait_set,i))
164
 
      {                                         /* Remove the old handler */
165
 
        sigaddset(&unblock_mask,i);
166
 
        sigdelset(&rev_sigwait_set,i);
167
 
        sact1.sa_flags = 0;
168
 
        sact1.sa_handler = SIG_DFL;
169
 
        sigemptyset(&sact1.sa_mask);
170
 
        sigaction(i, &sact1, 0);
171
 
      }
172
 
    }
173
 
  }
174
 
  memcpy_fixed(&sigwait_set,set,sizeof(*set));
175
 
  pthread_sigmask(SIG_BLOCK,(sigset_t*) set,(sigset_t*) 0);
176
 
  pthread_sigmask(SIG_UNBLOCK,&unblock_mask,(sigset_t*) 0);
177
 
}
178
 
 
179
 
 
180
 
int sigwait(sigset_t *setp, int *sigp)
181
 
{
182
 
  if (memcmp(setp,&sigwait_set,sizeof(sigwait_set)))
183
 
    sigwait_setup(setp);                        /* Init or change of set */
184
 
 
185
 
  for (;;)
186
 
  {
187
 
    /*
188
 
      This is a fast, not 100% portable implementation to find the signal.
189
 
      Because the handler is blocked there should be at most 1 bit set, but
190
 
      the specification on this is somewhat shady so we use a set instead a
191
 
      single variable.
192
 
      */
193
 
 
194
 
    ulong *ptr= (ulong*) &px_recd;
195
 
    ulong *end=ptr+sizeof(px_recd)/sizeof(ulong);
196
 
 
197
 
    for ( ; ptr != end ; ptr++)
198
 
    {
199
 
      if (*ptr)
200
 
      {
201
 
        ulong set= *ptr;
202
 
        int found= (int) ((char*) ptr - (char*) &px_recd)*8+1;
203
 
        while (!(set & 1))
204
 
        {
205
 
          found++;
206
 
          set>>=1;
207
 
        }
208
 
        *sigp=found;
209
 
        sigdelset(&px_recd,found);
210
 
        return 0;
211
 
      }
212
 
    }
213
 
    sigsuspend(&rev_sigwait_set);
214
 
  }
215
 
  return 0;
216
 
}
217
 
#else  /* !DONT_USE_SIGSUSPEND */
218
 
 
219
 
/****************************************************************************
220
 
** Replacement of sigwait if the system doesn't have one (like BSDI 3.0)
221
 
**
222
 
** Note:
223
 
** This version of sigwait() is assumed to called in a loop so the signalmask
224
 
** is permanently modified to reflect the signal set. This is done to get
225
 
** a much faster implementation.
226
 
**
227
 
** This implementation uses a extra thread to handle the signals and one
228
 
** must always call sigwait() with the same signal mask!
229
 
**
230
 
** BSDI 3.0 NOTE:
231
 
**
232
 
** pthread_kill() doesn't work on a thread in a select() or sleep() loop?
233
 
** After adding the sleep to sigwait_thread, all signals are checked and
234
 
** delivered every second. This isn't that terrible performance vice, but
235
 
** someone should report this to BSDI and ask for a fix!
236
 
** Another problem is that when the sleep() ends, every select() in other
237
 
** threads are interrupted!
238
 
****************************************************************************/
239
 
 
240
 
static sigset_t pending_set;
241
 
static bool inited=0;
242
 
static pthread_cond_t  COND_sigwait;
243
 
static pthread_mutex_t LOCK_sigwait;
244
 
 
245
 
 
246
 
void sigwait_handle_sig(int sig)
247
 
{
248
 
  pthread_mutex_lock(&LOCK_sigwait);
249
 
  sigaddset(&pending_set, sig);
250
 
  VOID(pthread_cond_signal(&COND_sigwait)); /* inform sigwait() about signal */
251
 
  pthread_mutex_unlock(&LOCK_sigwait);
252
 
}
253
 
 
254
 
void *sigwait_thread(void *set_arg)
255
 
{
256
 
  sigset_t *set=(sigset_t*) set_arg;
257
 
 
258
 
  int i;
259
 
  struct sigaction sact;
260
 
  sact.sa_flags = 0;
261
 
  sact.sa_handler = sigwait_handle_sig;
262
 
  memcpy_fixed(&sact.sa_mask,set,sizeof(*set)); /* handler isn't thread_safe */
263
 
  sigemptyset(&pending_set);
264
 
 
265
 
  for (i = 1; i <= sizeof(pending_set)*8; i++)
266
 
  {
267
 
    if (sigismember(set,i))
268
 
    {
269
 
      sigaction(i, &sact, (struct sigaction*) 0);
270
 
    }
271
 
  }
272
 
  /* Ensure that init_thr_alarm() is called */
273
 
  DBUG_ASSERT(thr_client_alarm);
274
 
  sigaddset(set, thr_client_alarm);
275
 
  pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0);
276
 
  alarm_thread=pthread_self();                  /* For thr_alarm */
277
 
 
278
 
  for (;;)
279
 
  {                                             /* Wait for signals */
280
 
#ifdef HAVE_NOT_BROKEN_SELECT
281
 
    fd_set fd;
282
 
    FD_ZERO(&fd);
283
 
    select(0,&fd,0,0,0);
284
 
#else
285
 
    sleep(1);                                   /* Because of broken BSDI */
286
 
#endif
287
 
  }
288
 
}
289
 
 
290
 
 
291
 
int sigwait(sigset_t *setp, int *sigp)
292
 
{
293
 
  if (!inited)
294
 
  {
295
 
    pthread_attr_t thr_attr;
296
 
    pthread_t sigwait_thread_id;
297
 
    inited=1;
298
 
    sigemptyset(&pending_set);
299
 
    pthread_mutex_init(&LOCK_sigwait,MY_MUTEX_INIT_FAST);
300
 
    pthread_cond_init(&COND_sigwait,NULL);
301
 
 
302
 
    pthread_attr_init(&thr_attr);
303
 
    pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
304
 
    pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
305
 
    pthread_attr_setstacksize(&thr_attr,8196);
306
 
    my_pthread_attr_setprio(&thr_attr,100);     /* Very high priority */
307
 
    VOID(pthread_create(&sigwait_thread_id,&thr_attr,sigwait_thread,setp));
308
 
    VOID(pthread_attr_destroy(&thr_attr));
309
 
  }
310
 
 
311
 
  pthread_mutex_lock(&LOCK_sigwait);
312
 
  for (;;)
313
 
  {
314
 
    ulong *ptr= (ulong*) &pending_set;
315
 
    ulong *end=ptr+sizeof(pending_set)/sizeof(ulong);
316
 
 
317
 
    for ( ; ptr != end ; ptr++)
318
 
    {
319
 
      if (*ptr)
320
 
      {
321
 
        ulong set= *ptr;
322
 
        int found= (int) ((char*) ptr - (char*) &pending_set)*8+1;
323
 
        while (!(set & 1))
324
 
        {
325
 
          found++;
326
 
          set>>=1;
327
 
        }
328
 
        *sigp=found;
329
 
        sigdelset(&pending_set,found);
330
 
        pthread_mutex_unlock(&LOCK_sigwait);
331
 
        return 0;
332
 
      }
333
 
    }
334
 
    VOID(pthread_cond_wait(&COND_sigwait,&LOCK_sigwait));
335
 
  }
336
 
  return 0;
337
 
}
338
 
 
339
 
#endif /* DONT_USE_SIGSUSPEND */
340
 
#endif /* HAVE_SIGWAIT */
341
 
 
342
 
 
343
30
/****************************************************************************
344
31
 The following functions fixes that all pthread functions should work
345
32
 according to latest posix standard
359
46
#undef pthread_cond_timedwait
360
47
#undef pthread_cond_t
361
48
#undef pthread_attr_getstacksize
362
 
 
363
 
/* Some help functions */
364
 
 
365
 
int pthread_no_free(void *not_used __attribute__((unused)))
366
 
{
367
 
  return 0;
368
 
}
369
 
 
370
 
int pthread_dummy(int ret)
371
 
{
372
 
  return ret;
373
 
}
374
49
#endif /* THREAD */