~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 22:40:46 UTC
  • Revision ID: brian@tangent.org-20080714224046-x183907w9wp1txwv
Removed sql_manager. Ever heard of just setting up the OS to sync when you
want it to?

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
 
28
30
#include <sys/select.h>                         /* AIX needs this for fd_set */
29
31
#endif
30
32
 
31
 
#if TIME_WITH_SYS_TIME
32
 
# include <sys/time.h>
33
 
# include <time.h>
34
 
#else
35
 
# if HAVE_SYS_TIME_H
36
 
#  include <sys/time.h>
37
 
# else
38
 
#  include <time.h>
39
 
# endif
40
 
#endif  
41
 
 
42
 
 
43
33
#ifndef ETIME
44
34
#define ETIME ETIMEDOUT
45
35
#endif
46
36
 
47
 
uint32_t thr_client_alarm;
 
37
uint thr_client_alarm;
48
38
static int alarm_aborted=1;                     /* No alarm thread */
49
39
bool thr_alarm_inited= 0;
50
40
volatile bool alarm_thread_running= 0;
51
41
time_t next_alarm_expire_time= ~ (time_t) 0;
52
 
static RETSIGTYPE process_alarm_part2(int sig);
 
42
static sig_handler process_alarm_part2(int sig);
53
43
 
54
44
static pthread_mutex_t LOCK_alarm;
55
45
static pthread_cond_t COND_alarm;
56
46
static sigset_t full_signal_set;
57
47
static QUEUE alarm_queue;
58
 
static uint32_t max_used_alarms=0;
 
48
static uint max_used_alarms=0;
59
49
pthread_t alarm_thread;
60
50
 
61
51
#ifdef USE_ALARM_THREAD
65
55
#define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM)
66
56
#endif
67
57
 
68
 
static RETSIGTYPE thread_alarm(int sig __attribute__((unused)));
 
58
static sig_handler thread_alarm(int sig __attribute__((unused)));
69
59
 
70
 
static int compare_uint32_t(void *not_used __attribute__((unused)),
71
 
                         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)
72
62
{
73
 
  uint32_t a=*((uint32_t*) a_ptr),b= *((uint32_t*) b_ptr);
 
63
  ulong a=*((ulong*) a_ptr),b= *((ulong*) b_ptr);
74
64
  return (a < b) ? -1  : (a == b) ? 0 : 1;
75
65
}
76
66
 
77
 
void init_thr_alarm(uint32_t max_alarms)
 
67
void init_thr_alarm(uint max_alarms)
78
68
{
79
69
  sigset_t s;
 
70
  DBUG_ENTER("init_thr_alarm");
80
71
  alarm_aborted=0;
81
72
  next_alarm_expire_time= ~ (time_t) 0;
82
73
  init_queue(&alarm_queue,max_alarms+1,offsetof(ALARM,expire_time),0,
83
 
             compare_uint32_t,NULL);
 
74
             compare_ulong,NullS);
84
75
  sigfillset(&full_signal_set);                 /* Neaded to block signals */
85
76
  pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
86
77
  pthread_cond_init(&COND_alarm,NULL);
106
97
    pthread_attr_setstacksize(&thr_attr,8196);
107
98
 
108
99
    my_pthread_attr_setprio(&thr_attr,100);     /* Very high priority */
109
 
    pthread_create(&alarm_thread,&thr_attr,alarm_handler,NULL);
110
 
    pthread_attr_destroy(&thr_attr);
 
100
    VOID(pthread_create(&alarm_thread,&thr_attr,alarm_handler,NULL));
 
101
    VOID(pthread_attr_destroy(&thr_attr));
111
102
  }
112
103
#elif defined(USE_ONE_SIGNAL_HAND)
113
104
  pthread_sigmask(SIG_BLOCK, &s, NULL);         /* used with sigwait() */
120
111
  my_sigset(THR_SERVER_ALARM, process_alarm);
121
112
  pthread_sigmask(SIG_UNBLOCK, &s, NULL);
122
113
#endif /* USE_ALARM_THREAD */
123
 
  return;
 
114
  DBUG_VOID_RETURN;
124
115
}
125
116
 
126
117
 
127
 
void resize_thr_alarm(uint32_t max_alarms)
 
118
void resize_thr_alarm(uint max_alarms)
128
119
{
129
120
  pthread_mutex_lock(&LOCK_alarm);
130
121
  /*
156
147
    when the alarm has been given
157
148
*/
158
149
 
159
 
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)
160
151
{
161
152
  time_t now;
162
153
#ifndef USE_ONE_SIGNAL_HAND
164
155
#endif
165
156
  bool reschedule;
166
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));
167
160
 
168
161
  now= my_time(0);
169
162
#ifndef USE_ONE_SIGNAL_HAND
172
165
  pthread_mutex_lock(&LOCK_alarm);        /* Lock from threads & alarms */
173
166
  if (alarm_aborted > 0)
174
167
  {                                     /* No signal thread */
 
168
    DBUG_PRINT("info", ("alarm aborted"));
175
169
    *alrm= 0;                                   /* No alarm */
176
170
    pthread_mutex_unlock(&LOCK_alarm);
177
171
#ifndef USE_ONE_SIGNAL_HAND
178
172
    pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
179
173
#endif
180
 
    return(1);
 
174
    DBUG_RETURN(1);
181
175
  }
182
176
  if (alarm_aborted < 0)
183
177
    sec= 1;                                     /* Abort mode */
186
180
  {
187
181
    if (alarm_queue.elements == alarm_queue.max_elements)
188
182
    {
 
183
      DBUG_PRINT("info", ("alarm queue full"));
189
184
      fprintf(stderr,"Warning: thr_alarm queue is full\n");
190
185
      *alrm= 0;                                 /* No alarm */
191
186
      pthread_mutex_unlock(&LOCK_alarm);
192
187
#ifndef USE_ONE_SIGNAL_HAND
193
188
      pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
194
189
#endif
195
 
      return(1);
 
190
      DBUG_RETURN(1);
196
191
    }
197
192
    max_used_alarms=alarm_queue.elements+1;
198
193
  }
199
 
  reschedule= (uint32_t) next_alarm_expire_time > (uint32_t) now + sec;
 
194
  reschedule= (ulong) next_alarm_expire_time > (ulong) now + sec;
200
195
  if (!alarm_data)
201
196
  {
202
197
    if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME))))
203
198
    {
 
199
      DBUG_PRINT("info", ("failed my_malloc()"));
204
200
      *alrm= 0;                                 /* No alarm */
205
201
      pthread_mutex_unlock(&LOCK_alarm);
206
202
#ifndef USE_ONE_SIGNAL_HAND
207
203
      pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
208
204
#endif
209
 
      return(1);
 
205
      DBUG_RETURN(1);
210
206
    }
211
207
    alarm_data->malloced=1;
212
208
  }
216
212
  alarm_data->alarmed=0;
217
213
  alarm_data->thread=    current_my_thread_var->pthread_self;
218
214
  alarm_data->thread_id= current_my_thread_var->id;
219
 
  queue_insert(&alarm_queue,(unsigned char*) alarm_data);
 
215
  queue_insert(&alarm_queue,(uchar*) alarm_data);
220
216
 
221
217
  /* Reschedule alarm if the current one has more than sec left */
222
218
  if (reschedule)
223
219
  {
 
220
    DBUG_PRINT("info", ("reschedule"));
224
221
    if (pthread_equal(pthread_self(),alarm_thread))
225
222
    {
226
223
      alarm(sec);                               /* purecov: inspected */
234
231
  pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
235
232
#endif
236
233
  (*alrm)= &alarm_data->alarmed;
237
 
  return(0);
 
234
  DBUG_RETURN(0);
238
235
}
239
236
 
240
237
 
248
245
#ifndef USE_ONE_SIGNAL_HAND
249
246
  sigset_t old_mask;
250
247
#endif
251
 
  uint32_t i, found=0;
 
248
  uint i, found=0;
 
249
  DBUG_ENTER("thr_end_alarm");
252
250
 
253
251
#ifndef USE_ONE_SIGNAL_HAND
254
252
  pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
255
253
#endif
256
254
  pthread_mutex_lock(&LOCK_alarm);
257
255
 
258
 
  alarm_data= (ALARM*) ((unsigned char*) *alarmed - offsetof(ALARM,alarmed));
 
256
  alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed));
259
257
  for (i=0 ; i < alarm_queue.elements ; i++)
260
258
  {
261
259
    if ((ALARM*) queue_element(&alarm_queue,i) == alarm_data)
262
260
    {
263
261
      queue_remove(&alarm_queue,i),MYF(0);
264
262
      if (alarm_data->malloced)
265
 
        free((unsigned char*) alarm_data);
 
263
        my_free((uchar*) alarm_data,MYF(0));
266
264
      found++;
 
265
#ifdef DBUG_OFF
267
266
      break;
 
267
#endif
268
268
    }
269
269
  }
270
 
  assert(!*alarmed || found == 1);
 
270
  DBUG_ASSERT(!*alarmed || found == 1);
271
271
  if (!found)
272
272
  {
273
273
    if (*alarmed)
274
274
      fprintf(stderr,"Warning: Didn't find alarm 0x%lx in queue of %d alarms\n",
275
275
              (long) *alarmed, alarm_queue.elements);
 
276
    DBUG_PRINT("warning",("Didn't find alarm 0x%lx in queue\n",
 
277
                          (long) *alarmed));
276
278
  }
277
279
  pthread_mutex_unlock(&LOCK_alarm);
278
280
#ifndef USE_ONE_SIGNAL_HAND
279
281
  pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
280
282
#endif
281
 
  return;
 
283
  DBUG_VOID_RETURN;
282
284
}
283
285
 
284
286
/*
289
291
  every second.
290
292
*/
291
293
 
292
 
RETSIGTYPE process_alarm(int sig __attribute__((unused)))
 
294
sig_handler process_alarm(int sig __attribute__((unused)))
293
295
{
294
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
*/
295
300
 
296
301
  if (thd_lib_detected == THD_LIB_LT &&
297
302
      !pthread_equal(pthread_self(),alarm_thread))
299
304
#if defined(MAIN) && !defined(__bsdi__)
300
305
    printf("thread_alarm in process_alarm\n"); fflush(stdout);
301
306
#endif
302
 
#ifndef HAVE_BSD_SIGNALS
 
307
#ifdef DONT_REMEMBER_SIGNAL
303
308
    my_sigset(thr_client_alarm, process_alarm); /* int. thread system calls */
304
309
#endif
305
310
    return;
306
311
  }
307
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
 
308
320
#ifndef USE_ALARM_THREAD
309
321
  pthread_sigmask(SIG_SETMASK,&full_signal_set,&old_mask);
310
322
  pthread_mutex_lock(&LOCK_alarm);
311
323
#endif
312
324
  process_alarm_part2(sig);
313
325
#ifndef USE_ALARM_THREAD
314
 
#if !defined(HAVE_BSD_SIGNALS) && !defined(USE_ONE_SIGNAL_HAND)
 
326
#if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND)
315
327
  my_sigset(THR_SERVER_ALARM,process_alarm);
316
328
#endif
317
329
  pthread_mutex_unlock(&LOCK_alarm);
321
333
}
322
334
 
323
335
 
324
 
static RETSIGTYPE process_alarm_part2(int sig __attribute__((unused)))
 
336
static sig_handler process_alarm_part2(int sig __attribute__((unused)))
325
337
{
326
338
  ALARM *alarm_data;
 
339
  DBUG_ENTER("process_alarm");
 
340
  DBUG_PRINT("info",("sig: %d  active alarms: %d",sig,alarm_queue.elements));
327
341
 
328
342
#if defined(MAIN)
329
343
  printf("process_alarm\n"); fflush(stdout);
332
346
  {
333
347
    if (alarm_aborted)
334
348
    {
335
 
      uint32_t i;
 
349
      uint i;
336
350
      for (i=0 ; i < alarm_queue.elements ;)
337
351
      {
338
352
        alarm_data=(ALARM*) queue_element(&alarm_queue,i);
355
369
    }
356
370
    else
357
371
    {
358
 
      uint32_t now=(uint32_t) my_time(0);
359
 
      uint32_t next=now+10-(now%10);
 
372
      ulong now=(ulong) my_time(0);
 
373
      ulong next=now+10-(now%10);
360
374
      while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now)
361
375
      {
362
376
        alarm_data->alarmed=1;                  /* Info to thread */
 
377
        DBUG_PRINT("info",("sending signal to waiting thread"));
363
378
        if (pthread_equal(alarm_data->thread,alarm_thread) ||
364
379
            pthread_kill(alarm_data->thread, thr_client_alarm))
365
380
        {
392
407
    */
393
408
    next_alarm_expire_time= ~(time_t) 0;
394
409
  }
395
 
  return;
 
410
  DBUG_VOID_RETURN;
396
411
}
397
412
 
398
413
 
413
428
 
414
429
void end_thr_alarm(bool free_structures)
415
430
{
 
431
  DBUG_ENTER("end_thr_alarm");
416
432
  if (alarm_aborted != 1)                       /* If memory not freed */
417
433
  {
418
434
    pthread_mutex_lock(&LOCK_alarm);
 
435
    DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements));
419
436
    alarm_aborted= -1;                          /* mark aborted */
420
437
    if (alarm_queue.elements || (alarm_thread_running && free_structures))
421
438
    {
428
445
    {
429
446
      struct timespec abstime;
430
447
 
431
 
      assert(!alarm_queue.elements);
 
448
      DBUG_ASSERT(!alarm_queue.elements);
432
449
 
433
450
      /* Wait until alarm thread dies */
434
451
      set_timespec(abstime, 10);                /* Wait up to 10 seconds */
450
467
    else
451
468
      pthread_mutex_unlock(&LOCK_alarm);
452
469
  }
453
 
  return;
 
470
  DBUG_VOID_RETURN;
454
471
}
455
472
 
456
473
 
460
477
 
461
478
void thr_alarm_kill(my_thread_id thread_id)
462
479
{
463
 
  uint32_t i;
 
480
  uint i;
464
481
  if (alarm_aborted)
465
482
    return;
466
483
  pthread_mutex_lock(&LOCK_alarm);
470
487
    {
471
488
      ALARM *tmp=(ALARM*) queue_remove(&alarm_queue,i);
472
489
      tmp->expire_time=0;
473
 
      queue_insert(&alarm_queue,(unsigned char*) tmp);
 
490
      queue_insert(&alarm_queue,(uchar*) tmp);
474
491
      reschedule_alarms();
475
492
      break;
476
493
    }
486
503
  info->max_used_alarms= max_used_alarms;
487
504
  if ((info->active_alarms=  alarm_queue.elements))
488
505
  {
489
 
    uint32_t now=(uint32_t) my_time(0);
 
506
    ulong now=(ulong) my_time(0);
490
507
    long time_diff;
491
508
    ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue);
492
509
    time_diff= (long) (alarm_data->expire_time - now);
493
 
    info->next_alarm_time= (uint32_t) (time_diff < 0 ? 0 : time_diff);
 
510
    info->next_alarm_time= (ulong) (time_diff < 0 ? 0 : time_diff);
494
511
  }
495
512
  pthread_mutex_unlock(&LOCK_alarm);
496
513
}
501
518
*/
502
519
 
503
520
 
504
 
static RETSIGTYPE thread_alarm(int sig)
 
521
static sig_handler thread_alarm(int sig)
505
522
{
506
523
#ifdef MAIN
507
524
  printf("thread_alarm\n"); fflush(stdout);
508
525
#endif
509
 
#ifndef HAVE_BSD_SIGNALS
 
526
#ifdef DONT_REMEMBER_SIGNAL
510
527
  my_sigset(sig,thread_alarm);          /* int. thread system calls */
511
528
#endif
512
529
}
534
551
  {
535
552
    if (alarm_queue.elements)
536
553
    {
537
 
      uint32_t sleep_time,now= my_time(0);
 
554
      ulong sleep_time,now= my_time(0);
538
555
      if (alarm_aborted)
539
556
        sleep_time=now+1;
540
557
      else
569
586
    }
570
587
    process_alarm(0);
571
588
  }
572
 
  memset(&alarm_thread, 0, sizeof(alarm_thread)); /* For easy debugging */
 
589
  bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */
573
590
  alarm_thread_running= 0;
574
591
  pthread_cond_signal(&COND_alarm);
575
592
  pthread_mutex_unlock(&LOCK_alarm);
590
607
 
591
608
static pthread_cond_t COND_thread_count;
592
609
static pthread_mutex_t LOCK_thread_count;
593
 
static uint32_t thread_count;
 
610
static uint thread_count;
594
611
 
595
612
#ifdef HPUX10
596
613
typedef int * fd_set_ptr;
637
654
      if (wait_time == 7)
638
655
      {                                         /* Simulate alarm-miss */
639
656
        fd_set readFDs;
640
 
        uint32_t max_connection=fileno(stdin);
 
657
        uint max_connection=fileno(stdin);
641
658
        FD_ZERO(&readFDs);
642
659
        FD_SET(max_connection,&readFDs);
643
660
        retry=0;
666
683
                break;
667
684
              continue;
668
685
            }
669
 
            getchar();                  /* Somebody was playing */
 
686
            VOID(getchar());                    /* Somebody was playing */
670
687
          }
671
688
        }
672
689
      }
678
695
  }
679
696
  pthread_mutex_lock(&LOCK_thread_count);
680
697
  thread_count--;
681
 
  pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */
 
698
  VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
682
699
  pthread_mutex_unlock(&LOCK_thread_count);
683
 
  free((unsigned char*) arg);
 
700
  free((uchar*) arg);
684
701
  return 0;
685
702
}
686
703
 
687
704
#ifdef USE_ONE_SIGNAL_HAND
688
 
static RETSIGTYPE print_signal_warning(int sig)
 
705
static sig_handler print_signal_warning(int sig)
689
706
{
690
707
  printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name());
691
708
  fflush(stdout);
692
 
#ifndef HAVE_BSD_SIGNALS
 
709
#ifdef DONT_REMEMBER_SIGNAL
693
710
  my_sigset(sig,print_signal_warning);          /* int. thread system calls */
694
711
#endif
695
712
  if (sig == SIGALRM)
707
724
  pthread_detach_this_thread();
708
725
  init_thr_alarm(10);                           /* Setup alarm handler */
709
726
  pthread_mutex_lock(&LOCK_thread_count);       /* Required by bsdi */
710
 
  pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */
 
727
  VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
711
728
  pthread_mutex_unlock(&LOCK_thread_count);
712
729
 
713
730
  sigemptyset(&set);                            /* Catch all signals */
726
743
#endif
727
744
  printf("server alarm: %d  thread alarm: %d\n",
728
745
         THR_SERVER_ALARM, thr_client_alarm);
 
746
  DBUG_PRINT("info",("Starting signal and alarm handling thread"));
729
747
  for(;;)
730
748
  {
731
749
    while ((error=my_sigwait(&set,&sig)) == EINTR)
774
792
  ALARM_INFO alarm_info;
775
793
  MY_INIT(argv[0]);
776
794
 
 
795
  if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#')
 
796
  {
 
797
    DBUG_PUSH(argv[1]+2);
 
798
  }
777
799
  pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
778
800
  pthread_cond_init(&COND_thread_count,NULL);
779
801
 
793
815
#ifdef NOT_USED
794
816
  sigemptyset(&set);
795
817
  sigaddset(&set, thr_client_alarm);
796
 
  pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0);
 
818
  VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0));
797
819
#endif
798
820
 
799
821
  pthread_attr_init(&thr_attr);
802
824
  pthread_attr_setstacksize(&thr_attr,65536L);
803
825
 
804
826
  /* Start signal thread and wait for it to start */
805
 
  pthread_mutex_lock(&LOCK_thread_count);
 
827
  VOID(pthread_mutex_lock(&LOCK_thread_count));
806
828
  pthread_create(&tid,&thr_attr,signal_hand,NULL);
807
 
  pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
808
 
  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"));
809
832
 
810
833
  thr_setconcurrency(3);
811
834
  pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
832
855
         alarm_info.next_alarm_time);
833
856
  while (thread_count)
834
857
  {
835
 
    pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
 
858
    VOID(pthread_cond_wait(&COND_thread_count,&LOCK_thread_count));
836
859
    if (thread_count == 1)
837
860
    {
838
861
      printf("Calling end_thr_alarm. This should cancel the last thread\n");