~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/thr_alarm.c

  • Committer: Brian Aker
  • Date: 2008-07-14 16:24:25 UTC
  • Revision ID: brian@tangent.org-20080714162425-juw3vw221gs9kysh
Cleanup around intptr_t

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
   along with this program; if not, write to the Free Software
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
 
#include "mysys_priv.h"
 
16
/* To avoid problems with alarms in debug code, we disable DBUG here */
 
17
#define FORCE_DBUG_OFF
 
18
#include <my_global.h>
17
19
 
18
20
#if !defined(DONT_USE_THR_ALARM)
19
21
#include <errno.h>
20
22
#include <my_pthread.h>
21
23
#include <signal.h>
22
24
#include <my_sys.h>
23
 
#include <mystrings/m_string.h>
 
25
#include <m_string.h>
24
26
#include <queues.h>
25
27
#include "thr_alarm.h"
26
28
 
32
34
#define ETIME ETIMEDOUT
33
35
#endif
34
36
 
35
 
uint32_t thr_client_alarm;
 
37
uint thr_client_alarm;
36
38
static int alarm_aborted=1;                     /* No alarm thread */
37
39
bool thr_alarm_inited= 0;
38
40
volatile bool alarm_thread_running= 0;
39
41
time_t next_alarm_expire_time= ~ (time_t) 0;
40
 
static RETSIGTYPE process_alarm_part2(int sig);
 
42
static sig_handler process_alarm_part2(int sig);
41
43
 
42
44
static pthread_mutex_t LOCK_alarm;
43
45
static pthread_cond_t COND_alarm;
44
46
static sigset_t full_signal_set;
45
47
static QUEUE alarm_queue;
46
 
static uint32_t max_used_alarms=0;
 
48
static uint max_used_alarms=0;
47
49
pthread_t alarm_thread;
48
50
 
49
51
#ifdef USE_ALARM_THREAD
53
55
#define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM)
54
56
#endif
55
57
 
56
 
static RETSIGTYPE thread_alarm(int sig __attribute__((unused)));
 
58
static sig_handler thread_alarm(int sig __attribute__((unused)));
57
59
 
58
 
static int compare_uint32_t(void *not_used __attribute__((unused)),
59
 
                         unsigned char *a_ptr,unsigned char* b_ptr)
 
60
static int compare_ulong(void *not_used __attribute__((unused)),
 
61
                         uchar *a_ptr,uchar* b_ptr)
60
62
{
61
 
  uint32_t a=*((uint32_t*) a_ptr),b= *((uint32_t*) b_ptr);
 
63
  ulong a=*((ulong*) a_ptr),b= *((ulong*) b_ptr);
62
64
  return (a < b) ? -1  : (a == b) ? 0 : 1;
63
65
}
64
66
 
65
 
void init_thr_alarm(uint32_t max_alarms)
 
67
void init_thr_alarm(uint max_alarms)
66
68
{
67
69
  sigset_t s;
 
70
  DBUG_ENTER("init_thr_alarm");
68
71
  alarm_aborted=0;
69
72
  next_alarm_expire_time= ~ (time_t) 0;
70
73
  init_queue(&alarm_queue,max_alarms+1,offsetof(ALARM,expire_time),0,
71
 
             compare_uint32_t,NULL);
 
74
             compare_ulong,NullS);
72
75
  sigfillset(&full_signal_set);                 /* Neaded to block signals */
73
76
  pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
74
77
  pthread_cond_init(&COND_alarm,NULL);
94
97
    pthread_attr_setstacksize(&thr_attr,8196);
95
98
 
96
99
    my_pthread_attr_setprio(&thr_attr,100);     /* Very high priority */
97
 
    pthread_create(&alarm_thread,&thr_attr,alarm_handler,NULL);
98
 
    pthread_attr_destroy(&thr_attr);
 
100
    VOID(pthread_create(&alarm_thread,&thr_attr,alarm_handler,NULL));
 
101
    VOID(pthread_attr_destroy(&thr_attr));
99
102
  }
100
103
#elif defined(USE_ONE_SIGNAL_HAND)
101
104
  pthread_sigmask(SIG_BLOCK, &s, NULL);         /* used with sigwait() */
108
111
  my_sigset(THR_SERVER_ALARM, process_alarm);
109
112
  pthread_sigmask(SIG_UNBLOCK, &s, NULL);
110
113
#endif /* USE_ALARM_THREAD */
111
 
  return;
 
114
  DBUG_VOID_RETURN;
112
115
}
113
116
 
114
117
 
115
 
void resize_thr_alarm(uint32_t max_alarms)
 
118
void resize_thr_alarm(uint max_alarms)
116
119
{
117
120
  pthread_mutex_lock(&LOCK_alarm);
118
121
  /*
144
147
    when the alarm has been given
145
148
*/
146
149
 
147
 
bool thr_alarm(thr_alarm_t *alrm, uint32_t sec, ALARM *alarm_data)
 
150
bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
148
151
{
149
152
  time_t now;
150
153
#ifndef USE_ONE_SIGNAL_HAND
152
155
#endif
153
156
  bool reschedule;
154
157
  struct st_my_thread_var *current_my_thread_var= my_thread_var;
 
158
  DBUG_ENTER("thr_alarm");
 
159
  DBUG_PRINT("enter",("thread: %s  sec: %d",my_thread_name(),sec));
155
160
 
156
161
  now= my_time(0);
157
162
#ifndef USE_ONE_SIGNAL_HAND
160
165
  pthread_mutex_lock(&LOCK_alarm);        /* Lock from threads & alarms */
161
166
  if (alarm_aborted > 0)
162
167
  {                                     /* No signal thread */
 
168
    DBUG_PRINT("info", ("alarm aborted"));
163
169
    *alrm= 0;                                   /* No alarm */
164
170
    pthread_mutex_unlock(&LOCK_alarm);
165
171
#ifndef USE_ONE_SIGNAL_HAND
166
172
    pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
167
173
#endif
168
 
    return(1);
 
174
    DBUG_RETURN(1);
169
175
  }
170
176
  if (alarm_aborted < 0)
171
177
    sec= 1;                                     /* Abort mode */
174
180
  {
175
181
    if (alarm_queue.elements == alarm_queue.max_elements)
176
182
    {
 
183
      DBUG_PRINT("info", ("alarm queue full"));
177
184
      fprintf(stderr,"Warning: thr_alarm queue is full\n");
178
185
      *alrm= 0;                                 /* No alarm */
179
186
      pthread_mutex_unlock(&LOCK_alarm);
180
187
#ifndef USE_ONE_SIGNAL_HAND
181
188
      pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
182
189
#endif
183
 
      return(1);
 
190
      DBUG_RETURN(1);
184
191
    }
185
192
    max_used_alarms=alarm_queue.elements+1;
186
193
  }
187
 
  reschedule= (uint32_t) next_alarm_expire_time > (uint32_t) now + sec;
 
194
  reschedule= (ulong) next_alarm_expire_time > (ulong) now + sec;
188
195
  if (!alarm_data)
189
196
  {
190
197
    if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME))))
191
198
    {
 
199
      DBUG_PRINT("info", ("failed my_malloc()"));
192
200
      *alrm= 0;                                 /* No alarm */
193
201
      pthread_mutex_unlock(&LOCK_alarm);
194
202
#ifndef USE_ONE_SIGNAL_HAND
195
203
      pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
196
204
#endif
197
 
      return(1);
 
205
      DBUG_RETURN(1);
198
206
    }
199
207
    alarm_data->malloced=1;
200
208
  }
204
212
  alarm_data->alarmed=0;
205
213
  alarm_data->thread=    current_my_thread_var->pthread_self;
206
214
  alarm_data->thread_id= current_my_thread_var->id;
207
 
  queue_insert(&alarm_queue,(unsigned char*) alarm_data);
 
215
  queue_insert(&alarm_queue,(uchar*) alarm_data);
208
216
 
209
217
  /* Reschedule alarm if the current one has more than sec left */
210
218
  if (reschedule)
211
219
  {
 
220
    DBUG_PRINT("info", ("reschedule"));
212
221
    if (pthread_equal(pthread_self(),alarm_thread))
213
222
    {
214
223
      alarm(sec);                               /* purecov: inspected */
222
231
  pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
223
232
#endif
224
233
  (*alrm)= &alarm_data->alarmed;
225
 
  return(0);
 
234
  DBUG_RETURN(0);
226
235
}
227
236
 
228
237
 
236
245
#ifndef USE_ONE_SIGNAL_HAND
237
246
  sigset_t old_mask;
238
247
#endif
239
 
  uint32_t i, found=0;
 
248
  uint i, found=0;
 
249
  DBUG_ENTER("thr_end_alarm");
240
250
 
241
251
#ifndef USE_ONE_SIGNAL_HAND
242
252
  pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
243
253
#endif
244
254
  pthread_mutex_lock(&LOCK_alarm);
245
255
 
246
 
  alarm_data= (ALARM*) ((unsigned char*) *alarmed - offsetof(ALARM,alarmed));
 
256
  alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed));
247
257
  for (i=0 ; i < alarm_queue.elements ; i++)
248
258
  {
249
259
    if ((ALARM*) queue_element(&alarm_queue,i) == alarm_data)
250
260
    {
251
261
      queue_remove(&alarm_queue,i),MYF(0);
252
262
      if (alarm_data->malloced)
253
 
        free((unsigned char*) alarm_data);
 
263
        my_free((uchar*) alarm_data,MYF(0));
254
264
      found++;
 
265
#ifdef DBUG_OFF
255
266
      break;
 
267
#endif
256
268
    }
257
269
  }
258
 
  assert(!*alarmed || found == 1);
 
270
  DBUG_ASSERT(!*alarmed || found == 1);
259
271
  if (!found)
260
272
  {
261
273
    if (*alarmed)
262
274
      fprintf(stderr,"Warning: Didn't find alarm 0x%lx in queue of %d alarms\n",
263
275
              (long) *alarmed, alarm_queue.elements);
 
276
    DBUG_PRINT("warning",("Didn't find alarm 0x%lx in queue\n",
 
277
                          (long) *alarmed));
264
278
  }
265
279
  pthread_mutex_unlock(&LOCK_alarm);
266
280
#ifndef USE_ONE_SIGNAL_HAND
267
281
  pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
268
282
#endif
269
 
  return;
 
283
  DBUG_VOID_RETURN;
270
284
}
271
285
 
272
286
/*
277
291
  every second.
278
292
*/
279
293
 
280
 
RETSIGTYPE process_alarm(int sig __attribute__((unused)))
 
294
sig_handler process_alarm(int sig __attribute__((unused)))
281
295
{
282
296
  sigset_t old_mask;
 
297
/*
 
298
  This must be first as we can't call DBUG inside an alarm for a normal thread
 
299
*/
283
300
 
284
301
  if (thd_lib_detected == THD_LIB_LT &&
285
302
      !pthread_equal(pthread_self(),alarm_thread))
287
304
#if defined(MAIN) && !defined(__bsdi__)
288
305
    printf("thread_alarm in process_alarm\n"); fflush(stdout);
289
306
#endif
290
 
#ifndef HAVE_BSD_SIGNALS
 
307
#ifdef DONT_REMEMBER_SIGNAL
291
308
    my_sigset(thr_client_alarm, process_alarm); /* int. thread system calls */
292
309
#endif
293
310
    return;
294
311
  }
295
312
 
 
313
  /*
 
314
    We have to do do the handling of the alarm in a sub function,
 
315
    because otherwise we would get problems with two threads calling
 
316
    DBUG_... functions at the same time (as two threads may call
 
317
    process_alarm() at the same time
 
318
  */
 
319
 
296
320
#ifndef USE_ALARM_THREAD
297
321
  pthread_sigmask(SIG_SETMASK,&full_signal_set,&old_mask);
298
322
  pthread_mutex_lock(&LOCK_alarm);
299
323
#endif
300
324
  process_alarm_part2(sig);
301
325
#ifndef USE_ALARM_THREAD
302
 
#if !defined(HAVE_BSD_SIGNALS) && !defined(USE_ONE_SIGNAL_HAND)
 
326
#if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND)
303
327
  my_sigset(THR_SERVER_ALARM,process_alarm);
304
328
#endif
305
329
  pthread_mutex_unlock(&LOCK_alarm);
309
333
}
310
334
 
311
335
 
312
 
static RETSIGTYPE process_alarm_part2(int sig __attribute__((unused)))
 
336
static sig_handler process_alarm_part2(int sig __attribute__((unused)))
313
337
{
314
338
  ALARM *alarm_data;
 
339
  DBUG_ENTER("process_alarm");
 
340
  DBUG_PRINT("info",("sig: %d  active alarms: %d",sig,alarm_queue.elements));
315
341
 
316
342
#if defined(MAIN)
317
343
  printf("process_alarm\n"); fflush(stdout);
320
346
  {
321
347
    if (alarm_aborted)
322
348
    {
323
 
      uint32_t i;
 
349
      uint i;
324
350
      for (i=0 ; i < alarm_queue.elements ;)
325
351
      {
326
352
        alarm_data=(ALARM*) queue_element(&alarm_queue,i);
343
369
    }
344
370
    else
345
371
    {
346
 
      uint32_t now=(uint32_t) my_time(0);
347
 
      uint32_t next=now+10-(now%10);
 
372
      ulong now=(ulong) my_time(0);
 
373
      ulong next=now+10-(now%10);
348
374
      while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now)
349
375
      {
350
376
        alarm_data->alarmed=1;                  /* Info to thread */
 
377
        DBUG_PRINT("info",("sending signal to waiting thread"));
351
378
        if (pthread_equal(alarm_data->thread,alarm_thread) ||
352
379
            pthread_kill(alarm_data->thread, thr_client_alarm))
353
380
        {
380
407
    */
381
408
    next_alarm_expire_time= ~(time_t) 0;
382
409
  }
383
 
  return;
 
410
  DBUG_VOID_RETURN;
384
411
}
385
412
 
386
413
 
401
428
 
402
429
void end_thr_alarm(bool free_structures)
403
430
{
 
431
  DBUG_ENTER("end_thr_alarm");
404
432
  if (alarm_aborted != 1)                       /* If memory not freed */
405
433
  {
406
434
    pthread_mutex_lock(&LOCK_alarm);
 
435
    DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements));
407
436
    alarm_aborted= -1;                          /* mark aborted */
408
437
    if (alarm_queue.elements || (alarm_thread_running && free_structures))
409
438
    {
416
445
    {
417
446
      struct timespec abstime;
418
447
 
419
 
      assert(!alarm_queue.elements);
 
448
      DBUG_ASSERT(!alarm_queue.elements);
420
449
 
421
450
      /* Wait until alarm thread dies */
422
451
      set_timespec(abstime, 10);                /* Wait up to 10 seconds */
438
467
    else
439
468
      pthread_mutex_unlock(&LOCK_alarm);
440
469
  }
441
 
  return;
 
470
  DBUG_VOID_RETURN;
442
471
}
443
472
 
444
473
 
448
477
 
449
478
void thr_alarm_kill(my_thread_id thread_id)
450
479
{
451
 
  uint32_t i;
 
480
  uint i;
452
481
  if (alarm_aborted)
453
482
    return;
454
483
  pthread_mutex_lock(&LOCK_alarm);
458
487
    {
459
488
      ALARM *tmp=(ALARM*) queue_remove(&alarm_queue,i);
460
489
      tmp->expire_time=0;
461
 
      queue_insert(&alarm_queue,(unsigned char*) tmp);
 
490
      queue_insert(&alarm_queue,(uchar*) tmp);
462
491
      reschedule_alarms();
463
492
      break;
464
493
    }
474
503
  info->max_used_alarms= max_used_alarms;
475
504
  if ((info->active_alarms=  alarm_queue.elements))
476
505
  {
477
 
    uint32_t now=(uint32_t) my_time(0);
 
506
    ulong now=(ulong) my_time(0);
478
507
    long time_diff;
479
508
    ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue);
480
509
    time_diff= (long) (alarm_data->expire_time - now);
481
 
    info->next_alarm_time= (uint32_t) (time_diff < 0 ? 0 : time_diff);
 
510
    info->next_alarm_time= (ulong) (time_diff < 0 ? 0 : time_diff);
482
511
  }
483
512
  pthread_mutex_unlock(&LOCK_alarm);
484
513
}
489
518
*/
490
519
 
491
520
 
492
 
static RETSIGTYPE thread_alarm(int sig)
 
521
static sig_handler thread_alarm(int sig)
493
522
{
494
523
#ifdef MAIN
495
524
  printf("thread_alarm\n"); fflush(stdout);
496
525
#endif
497
 
#ifndef HAVE_BSD_SIGNALS
 
526
#ifdef DONT_REMEMBER_SIGNAL
498
527
  my_sigset(sig,thread_alarm);          /* int. thread system calls */
499
528
#endif
500
529
}
522
551
  {
523
552
    if (alarm_queue.elements)
524
553
    {
525
 
      uint32_t sleep_time,now= my_time(0);
 
554
      ulong sleep_time,now= my_time(0);
526
555
      if (alarm_aborted)
527
556
        sleep_time=now+1;
528
557
      else
557
586
    }
558
587
    process_alarm(0);
559
588
  }
560
 
  memset(&alarm_thread, 0, sizeof(alarm_thread)); /* For easy debugging */
 
589
  bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */
561
590
  alarm_thread_running= 0;
562
591
  pthread_cond_signal(&COND_alarm);
563
592
  pthread_mutex_unlock(&LOCK_alarm);
578
607
 
579
608
static pthread_cond_t COND_thread_count;
580
609
static pthread_mutex_t LOCK_thread_count;
581
 
static uint32_t thread_count;
 
610
static uint thread_count;
582
611
 
583
612
#ifdef HPUX10
584
613
typedef int * fd_set_ptr;
625
654
      if (wait_time == 7)
626
655
      {                                         /* Simulate alarm-miss */
627
656
        fd_set readFDs;
628
 
        uint32_t max_connection=fileno(stdin);
 
657
        uint max_connection=fileno(stdin);
629
658
        FD_ZERO(&readFDs);
630
659
        FD_SET(max_connection,&readFDs);
631
660
        retry=0;
654
683
                break;
655
684
              continue;
656
685
            }
657
 
            getchar();                  /* Somebody was playing */
 
686
            VOID(getchar());                    /* Somebody was playing */
658
687
          }
659
688
        }
660
689
      }
666
695
  }
667
696
  pthread_mutex_lock(&LOCK_thread_count);
668
697
  thread_count--;
669
 
  pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */
 
698
  VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
670
699
  pthread_mutex_unlock(&LOCK_thread_count);
671
 
  free((unsigned char*) arg);
 
700
  free((uchar*) arg);
672
701
  return 0;
673
702
}
674
703
 
675
704
#ifdef USE_ONE_SIGNAL_HAND
676
 
static RETSIGTYPE print_signal_warning(int sig)
 
705
static sig_handler print_signal_warning(int sig)
677
706
{
678
707
  printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name());
679
708
  fflush(stdout);
680
 
#ifndef HAVE_BSD_SIGNALS
 
709
#ifdef DONT_REMEMBER_SIGNAL
681
710
  my_sigset(sig,print_signal_warning);          /* int. thread system calls */
682
711
#endif
683
712
  if (sig == SIGALRM)
695
724
  pthread_detach_this_thread();
696
725
  init_thr_alarm(10);                           /* Setup alarm handler */
697
726
  pthread_mutex_lock(&LOCK_thread_count);       /* Required by bsdi */
698
 
  pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */
 
727
  VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
699
728
  pthread_mutex_unlock(&LOCK_thread_count);
700
729
 
701
730
  sigemptyset(&set);                            /* Catch all signals */
714
743
#endif
715
744
  printf("server alarm: %d  thread alarm: %d\n",
716
745
         THR_SERVER_ALARM, thr_client_alarm);
 
746
  DBUG_PRINT("info",("Starting signal and alarm handling thread"));
717
747
  for(;;)
718
748
  {
719
749
    while ((error=my_sigwait(&set,&sig)) == EINTR)
762
792
  ALARM_INFO alarm_info;
763
793
  MY_INIT(argv[0]);
764
794
 
 
795
  if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#')
 
796
  {
 
797
    DBUG_PUSH(argv[1]+2);
 
798
  }
765
799
  pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
766
800
  pthread_cond_init(&COND_thread_count,NULL);
767
801
 
781
815
#ifdef NOT_USED
782
816
  sigemptyset(&set);
783
817
  sigaddset(&set, thr_client_alarm);
784
 
  pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0);
 
818
  VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0));
785
819
#endif
786
820
 
787
821
  pthread_attr_init(&thr_attr);
790
824
  pthread_attr_setstacksize(&thr_attr,65536L);
791
825
 
792
826
  /* Start signal thread and wait for it to start */
793
 
  pthread_mutex_lock(&LOCK_thread_count);
 
827
  VOID(pthread_mutex_lock(&LOCK_thread_count));
794
828
  pthread_create(&tid,&thr_attr,signal_hand,NULL);
795
 
  pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
796
 
  pthread_mutex_unlock(&LOCK_thread_count);
 
829
  VOID(pthread_cond_wait(&COND_thread_count,&LOCK_thread_count));
 
830
  VOID(pthread_mutex_unlock(&LOCK_thread_count));
 
831
  DBUG_PRINT("info",("signal thread created"));
797
832
 
798
833
  thr_setconcurrency(3);
799
834
  pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
820
855
         alarm_info.next_alarm_time);
821
856
  while (thread_count)
822
857
  {
823
 
    pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
 
858
    VOID(pthread_cond_wait(&COND_thread_count,&LOCK_thread_count));
824
859
    if (thread_count == 1)
825
860
    {
826
861
      printf("Calling end_thr_alarm. This should cancel the last thread\n");