RTS API Documentation  1.10.11
switch_time.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Massimo Cetra <devel@navynet.it> - Timezone functionality
28  *
29  *
30  * softtimer.c -- Software Timer Module
31  *
32  */
33 
34 #include <switch.h>
35 #include <stdio.h>
36 #include "private/switch_apr_pvt.h"
38 
39 #ifdef HAVE_TIMERFD_CREATE
40 #include <sys/timerfd.h>
41 #endif
42 
43 //#if defined(DARWIN)
44 #define DISABLE_1MS_COND
45 //#endif
46 
47 #ifndef UINT32_MAX
48 #define UINT32_MAX 0xffffffff
49 #endif
50 
51 #define MAX_TICK UINT32_MAX - 1024
52 
53 #define MAX_ELEMENTS 3600
54 #define IDLE_SPEED 100
55 
56 /* In Windows, enable the montonic timer for better timer accuracy,
57  * GetSystemTimeAsFileTime does not update on timeBeginPeriod on these OS.
58  * Flag SCF_USE_WIN32_MONOTONIC must be enabled to activate it (start parameter -monotonic-clock).
59  */
60 
61 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
62 static int MONO = 1;
63 #else
64 static int MONO = 0;
65 #endif
66 
67 
68 static int SYSTEM_TIME = 0;
69 
70 /* clock_nanosleep works badly on some kernels but really well on others.
71  timerfd seems to work well as long as it exists so if you have timerfd we'll also enable clock_nanosleep by default.
72 */
73 #if defined(HAVE_TIMERFD_CREATE)
74 static int TFD = 2;
75 #if defined(HAVE_CLOCK_NANOSLEEP)
76 static int NANO = 1;
77 #else
78 static int NANO = 0;
79 #endif
80 #else
81 static int TFD = 0;
82 static int NANO = 0;
83 #endif
84 
85 static int OFFSET = 0;
86 
87 static int COND = 1;
88 
89 static int MATRIX = 1;
90 
91 #ifdef WIN32
92 static CRITICAL_SECTION timer_section;
93 static switch_time_t win32_tick_time_since_start = -1;
94 static DWORD win32_last_get_time_tick = 0;
95 
96 static uint8_t win32_use_qpc = 0;
97 static uint64_t win32_qpc_freq = 0;
98 #endif
99 
101 
102 static struct {
103  int32_t RUNNING;
104  int32_t STARTED;
105  int32_t use_cond_yield;
107  uint32_t timer_count;
108 } globals;
109 
110 #ifdef WIN32
111 #undef SWITCH_MOD_DECLARE_DATA
112 #define SWITCH_MOD_DECLARE_DATA __declspec(dllexport)
113 #endif
114 
115 SWITCH_MODULE_LOAD_FUNCTION(softtimer_load);
116 SWITCH_MODULE_SHUTDOWN_FUNCTION(softtimer_shutdown);
117 SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime);
118 SWITCH_MODULE_DEFINITION(CORE_SOFTTIMER_MODULE, softtimer_load, softtimer_shutdown, softtimer_runtime);
119 
123  uint32_t roll;
124  uint32_t ready;
125 };
127 
128 struct timer_matrix {
129  uint64_t tick;
130  uint32_t count;
131  uint32_t roll;
135 };
137 
139 
140 static switch_time_t time_now(int64_t offset);
141 
143 {
144 #if defined(WIN32)
145  SwitchToThread();
146 #else
147  sched_yield();
148 #endif
149 }
150 
152 {
153 #if defined(HAVE_CLOCK_NANOSLEEP) || defined(DARWIN)
154  struct timespec ts;
155 #endif
156 
157 #if defined(WIN32)
158  if (t < 1000) {
159  t = 1000;
160  }
161 #endif
162 
163 #if !defined(DARWIN)
164  if (t > 100000 || !NANO) {
165  fspr_sleep(t);
166  return;
167  }
168 #endif
169 
170 #if defined(HAVE_CLOCK_NANOSLEEP)
171  t -= OFFSET;
172  ts.tv_sec = t / 1000000;
173  ts.tv_nsec = ((t % 1000000) * 1000);
174  clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
175 
176 #elif defined(DARWIN)
177  t -= OFFSET;
178  ts.tv_sec = t / APR_USEC_PER_SEC;
179  ts.tv_nsec = (t % APR_USEC_PER_SEC) * 850;
180  nanosleep(&ts, NULL);
181 #else
182  fspr_sleep(t);
183 #endif
184 
185 #if defined(DARWIN)
186  sched_yield();
187 #endif
188 
189 }
190 
192 {
193  int x = 0;
194  switch_time_t start, stop, sum = 0;
195 
196  for (x = 0; x < reps; x++) {
197  start = switch_time_ref();
198  do_sleep(t);
199  stop = switch_time_ref();
200  sum += (stop - start);
201  }
202 
203  return sum / reps;
204 
205 }
206 
207 #define calc_step() if (step > 11) step -= 10; else if (step > 1) step--
209 {
210  int x;
211  switch_interval_time_t avg, val = 1000, want = 1000;
212  int over = 0, under = 0, good = 0, step = 50, diff = 0, retry = 0, lastgood = 0, one_k = 0;
213 
214 #ifdef HAVE_CLOCK_GETRES
215  struct timespec ts;
216  long res = 0;
217  clock_getres(CLOCK_MONOTONIC, &ts);
218  res = ts.tv_nsec / 1000;
219 
220 
221  if (res > 900 && res < 1100) {
222  one_k = 1;
223  }
224 
225  if (res > 1500) {
227  "Timer resolution of %ld microseconds detected!\n"
228  "Do you have your kernel timer frequency set to lower than 1,000Hz? "
229  "You may experience audio problems. Step MS %d\n", ts.tv_nsec / 1000, runtime.microseconds_per_tick / 1000);
230  do_sleep(5000000);
232  return;
233  }
234 #endif
235 
236  top:
237  val = 1000;
238  step = 50;
239  over = under = good = 0;
240  OFFSET = 0;
241 
242  for (x = 0; x < 100; x++) {
243  avg = average_time(val, 50);
244  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Test: %ld Average: %ld Step: %d\n", (long) val, (long) avg, step);
245 
246  diff = abs((int) (want - avg));
247  if (diff > 1500) {
249  "Abnormally large timer gap %d detected!\n"
250  "Do you have your kernel timer frequency set to lower than 1,000Hz? You may experience audio problems.\n", diff);
251  do_sleep(5000000);
253  return;
254  }
255 
256  if (diff <= 100) {
257  lastgood = (int) val;
258  }
259 
260  if (diff <= 2) {
261  under = over = 0;
262  lastgood = (int) val;
263  if (++good > 10) {
264  break;
265  }
266  } else if (avg > want) {
267  if (under) {
268  calc_step();
269  }
270  under = good = 0;
271  if ((val - step) < 0) {
272  if (++retry > 2)
273  break;
274  goto top;
275  }
276  val -= step;
277  over++;
278  } else if (avg < want) {
279  if (over) {
280  calc_step();
281  }
282  over = good = 0;
283  if ((val - step) < 0) {
284  if (++retry > 2)
285  break;
286  goto top;
287  }
288  val += step;
289  under++;
290  }
291  }
292 
293  if (good >= 10) {
294  OFFSET = (int) (want - val);
295  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Timer offset of %d calculated\n", OFFSET);
296  } else if (lastgood) {
297  OFFSET = (int) (want - lastgood);
298  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Timer offset of %d calculated (fallback)\n", OFFSET);
300  } else if (one_k) {
301  OFFSET = 900;
302  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Timer offset CANNOT BE DETECTED, forcing OFFSET to 900\n");
304  } else {
305  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Timer offset NOT calculated\n");
307  }
308 }
309 
310 
312 {
313  return (globals.RUNNING == 1 && runtime.timestamp) ? runtime.timestamp : switch_time_now();
314 }
315 
317 {
318  return time_now(-1);
319 }
320 
321 
323 {
324  time_t now = switch_micro_time_now() / APR_USEC_PER_SEC;
325  if (t) {
326  *t = now;
327  }
328  return now;
329 }
330 
332 {
333 #if (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)) || defined(WIN32)
334  MONO = enable ? 1 : 0;
336 #else
337  MONO = 0;
338 #endif
339 }
340 
341 
343 {
344  SYSTEM_TIME = enable;
345 }
346 
347 
349 {
350 #if defined(HAVE_TIMERFD_CREATE)
351  TFD = enable;
353 
354 #else
355  TFD = 0;
356 #endif
357 }
358 
359 
361 {
362  MATRIX = enable ? 1 : 0;
364 }
365 
367 {
368 #if defined(HAVE_CLOCK_NANOSLEEP)
369  NANO = enable ? 1 : 0;
370 #endif
371 }
372 
374 {
375  COND = enable ? 1 : 0;
376  if (COND) {
377  MATRIX = 1;
378  }
380 }
381 
383 {
385  int64_t elapsed = (now - timer->start);
386 
387  timer->tick = (elapsed / timer->interval) / 1000;
388  timer->samplecount = (uint32_t)(timer->tick * timer->samples);
389 
390  if (timer->interval == 1 && timer->samplecount == timer->last_samplecount) {
391  timer->samplecount++;
392  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Timer sync too often\n");
393  }
394  timer->last_samplecount = timer->samplecount;
395 
396 
397 
398  return SWITCH_STATUS_SUCCESS;
399 }
400 
401 
402 
403 /////////
404 #ifdef HAVE_TIMERFD_CREATE
405 
406 #define MAX_INTERVAL 2000 /* ms */
407 
408 struct interval_timer {
409  int fd;
410 };
411 typedef struct interval_timer interval_timer_t;
412 
413 static switch_status_t timerfd_start_interval(interval_timer_t *it, int interval)
414 {
415  struct itimerspec val;
416  int fd;
417  uint64_t exp;
418 
419  fd = timerfd_create(CLOCK_MONOTONIC, 0);
420 
421  if (fd < 0) {
422  return SWITCH_STATUS_GENERR;
423  }
424 
425  val.it_interval.tv_sec = interval / 1000;
426  val.it_interval.tv_nsec = (interval % 1000) * 1000000;
427  val.it_value.tv_sec = 0;
428  val.it_value.tv_nsec = 100000;
429 
430  if (timerfd_settime(fd, 0, &val, NULL) < 0) {
431  close(fd);
432  return SWITCH_STATUS_GENERR;
433  }
434 
435  if (read(fd, &exp, sizeof(exp)) < 0) {
436  close(fd);
437  return SWITCH_STATUS_GENERR;
438  }
439 
440  it->fd = fd;
441 
442  return SWITCH_STATUS_SUCCESS;
443 }
444 
445 static switch_status_t timerfd_stop_interval(interval_timer_t *it)
446 {
447  close(it->fd);
448  it->fd = -1;
449  return SWITCH_STATUS_SUCCESS;
450 }
451 
452 static switch_status_t _timerfd_init(switch_timer_t *timer)
453 {
454  interval_timer_t *it;
455  int rc;
456 
457  if (timer->interval < 1 || timer->interval > MAX_INTERVAL)
458  return SWITCH_STATUS_GENERR;
459 
460  it = switch_core_alloc(timer->memory_pool, sizeof(*it));
461 
462  if ((rc = timerfd_start_interval(it, timer->interval)) == SWITCH_STATUS_SUCCESS) {
463  timer->start = switch_micro_time_now();
464  timer->private_info = it;
465  }
466 
467  return rc;
468 }
469 
470 static switch_status_t _timerfd_step(switch_timer_t *timer)
471 {
472  timer->tick++;
473  timer->samplecount += timer->samples;
474 
475  return SWITCH_STATUS_SUCCESS;
476 }
477 
478 static switch_status_t _timerfd_next(switch_timer_t *timer)
479 {
480  interval_timer_t *it = timer->private_info;
481  uint64_t u64 = 0;
482 
483  if (!it) {
484  return SWITCH_STATUS_GENERR;
485  }
486 
487  if (read(it->fd, &u64, sizeof(u64)) < 0) {
488  return SWITCH_STATUS_GENERR;
489  } else {
490  timer->tick += u64;
491  timer->samplecount = timer->tick * timer->samples;
492  }
493 
494  return SWITCH_STATUS_SUCCESS;
495 }
496 
497 static switch_status_t _timerfd_check(switch_timer_t *timer, switch_bool_t step)
498 {
499  interval_timer_t *it = timer->private_info;
500  struct itimerspec val;
501  int diff;
502 
503  if (!it) {
504  return SWITCH_STATUS_GENERR;
505  }
506 
507  timerfd_gettime(it->fd, &val);
508  diff = val.it_interval.tv_nsec / 1000;
509 
510  if (diff > 0) {
511  /* still pending */
512  timer->diff = diff;
513  return SWITCH_STATUS_FALSE;
514  } else {
515  /* timer pending */
516  timer->diff = 0;
517  if (step) {
518  _timerfd_step(timer);
519  }
520  return SWITCH_STATUS_SUCCESS;
521  }
522 }
523 
524 static switch_status_t _timerfd_destroy(switch_timer_t *timer)
525 {
526  interval_timer_t *it = timer->private_info;
527  int rc = SWITCH_STATUS_GENERR;
528 
529  if (it) {
530  rc = timerfd_stop_interval(it);
531  }
532 
533  return rc;
534 }
535 
536 #endif
537 ////////
538 
539 
540 static switch_time_t time_now(int64_t offset)
541 {
542  switch_time_t now;
543 
544 #if (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)) || defined(WIN32)
545  if (MONO) {
546 #ifndef WIN32
547  struct timespec ts;
548  clock_gettime(offset ? CLOCK_MONOTONIC : CLOCK_REALTIME, &ts);
549  if (offset < 0) offset = 0;
550  now = ts.tv_sec * APR_USEC_PER_SEC + (ts.tv_nsec / 1000) + offset;
551 #else
552  if (offset == 0) {
553  return switch_time_now();
554  } else if (offset < 0) offset = 0;
555 
556 
557  if (win32_use_qpc) {
558  /* Use QueryPerformanceCounter */
559  uint64_t count = 0;
560  QueryPerformanceCounter((LARGE_INTEGER*)&count);
561  now = ((count * 1000000) / win32_qpc_freq) + offset;
562  } else {
563  /* Use good old timeGetTime() */
564  DWORD tick_now;
565  DWORD tick_diff;
566 
567  tick_now = timeGetTime();
568  if (win32_tick_time_since_start != -1) {
569  EnterCriticalSection(&timer_section);
570  /* just add diff (to make it work more than 50 days). */
571  tick_diff = tick_now - win32_last_get_time_tick;
572  win32_tick_time_since_start += tick_diff;
573 
574  win32_last_get_time_tick = tick_now;
575  now = (win32_tick_time_since_start * 1000) + offset;
576  LeaveCriticalSection(&timer_section);
577  } else {
578  /* If someone is calling us before timer is initialized,
579  * return the current tick + offset
580  */
581  now = (tick_now * 1000) + offset;
582  }
583  }
584 #endif
585  } else {
586 #endif
587  now = switch_time_now();
588 
589 #if (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)) || defined(WIN32)
590  }
591 #endif
592 
593  return now;
594 }
595 
597 {
598  if (SYSTEM_TIME) {
599  /* Return system time reference */
600  return time_now(0);
601  } else {
602  /* Return monotonic time reference (when available) */
604  }
605 }
606 
608 
610 {
611  runtime.time_sync++; /* Indicate that we are syncing time right now */
612 
614 
615  if (SYSTEM_TIME) {
617  runtime.offset = 0;
618  } else {
619  runtime.offset = runtime.reference - switch_mono_micro_time_now(); /* Get the offset between system time and the monotonic clock (when available) */
621  }
622 
623  if (runtime.reference - last_time > 1000000 || last_time == 0) {
624  if (SYSTEM_TIME) {
625  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Clock is already configured to always report system time.\n");
626  } else {
627  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Clock synchronized to system time.\n");
628  }
629  }
631 
632  runtime.time_sync++; /* Indicate that we are finished syncing time */
633 }
634 
636 {
637  do_sleep(t);
638 }
639 
641 {
642 
643  if (globals.RUNNING != 1 || t < 1000 || t >= 10000) {
644  do_sleep(t);
645  return;
646  }
647 #ifndef DISABLE_1MS_COND
648  if (globals.use_cond_yield == 1) {
650  return;
651  }
652 #endif
653 
654  do_sleep(t);
655 }
656 
657 
659 {
660  if (runtime.tipping_point && globals.timer_count >= runtime.tipping_point) {
661  switch_os_yield();
662  return;
663  }
664 #ifdef DISABLE_1MS_COND
665  do_sleep(1000);
666 #else
667  if (globals.RUNNING != 1 || !runtime.timestamp || globals.use_cond_yield != 1) {
668  do_sleep(1000);
669  return;
670  }
671  switch_mutex_lock(TIMER_MATRIX[1].mutex);
672  switch_thread_cond_wait(TIMER_MATRIX[1].cond, TIMER_MATRIX[1].mutex);
673  switch_mutex_unlock(TIMER_MATRIX[1].mutex);
674 #endif
675 }
676 
678 {
679  switch_time_t want;
680  if (!t)
681  return;
682 
683  if (globals.RUNNING != 1 || !runtime.timestamp || globals.use_cond_yield != 1) {
684  do_sleep(t);
685  return;
686  }
687  want = runtime.timestamp + t;
688  while (globals.RUNNING == 1 && globals.use_cond_yield == 1 && runtime.timestamp < want) {
689  switch_mutex_lock(TIMER_MATRIX[1].mutex);
690  if (runtime.timestamp < want) {
691  switch_thread_cond_wait(TIMER_MATRIX[1].cond, TIMER_MATRIX[1].mutex);
692  }
693  switch_mutex_unlock(TIMER_MATRIX[1].mutex);
694  }
695 
696 
697 }
698 
700 {
701  timer_private_t *private_info;
702  int sanity = 0;
703 
704  timer->start = switch_micro_time_now();
705 
706  if (timer->interval == 1) {
707  switch_mutex_lock(globals.mutex);
708  globals.timer_count++;
710  return SWITCH_STATUS_SUCCESS;
711  }
712 
713 #ifdef HAVE_TIMERFD_CREATE
714  if (TFD == 2) {
715  return _timerfd_init(timer);
716  }
717 #endif
718 
719  while (globals.STARTED == 0) {
720  do_sleep(100000);
721  if (++sanity == 300) {
722  abort();
723  }
724  }
725 
726  if (globals.RUNNING != 1 || !globals.mutex || timer->interval < 1) {
727  return SWITCH_STATUS_FALSE;
728  }
729 
730  if ((private_info = switch_core_alloc(timer->memory_pool, sizeof(*private_info)))) {
731  switch_mutex_lock(globals.mutex);
732  if (!TIMER_MATRIX[timer->interval].mutex) {
734  switch_thread_cond_create(&TIMER_MATRIX[timer->interval].cond, module_pool);
735  }
736  TIMER_MATRIX[timer->interval].count++;
738  timer->private_info = private_info;
739  private_info->start = private_info->reference = (switch_size_t)TIMER_MATRIX[timer->interval].tick;
740  private_info->start -= 2; /* switch_core_timer_init sets samplecount to samples, this makes first next() step once */
741  private_info->roll = TIMER_MATRIX[timer->interval].roll;
742  private_info->ready = 1;
743 
744  if (runtime.microseconds_per_tick > 10000 && (timer->interval % (int)(runtime.microseconds_per_tick / 1000)) != 0 && (timer->interval % 10) == 0) {
745  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Increasing global timer resolution to 10ms to handle interval %d\n", timer->interval);
747  }
748 
749  if (timer->interval > 0 && (timer->interval < (int)(runtime.microseconds_per_tick / 1000) || (timer->interval % 10) != 0)) {
750  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Increasing global timer resolution to 1ms to handle interval %d\n", timer->interval);
753  }
754 
755  switch_mutex_lock(globals.mutex);
756  globals.timer_count++;
757  if (runtime.tipping_point && globals.timer_count == (runtime.tipping_point + 1)) {
758  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Crossed tipping point of %u, shifting into high-gear.\n", runtime.tipping_point);
759  }
761 
762  return SWITCH_STATUS_SUCCESS;
763  }
764 
765  return SWITCH_STATUS_MEMERR;
766 }
767 
768 #define check_roll() if (private_info->roll < TIMER_MATRIX[timer->interval].roll) { \
769  private_info->roll++; \
770  private_info->reference = private_info->start = (switch_size_t)TIMER_MATRIX[timer->interval].tick; \
771  private_info->start--; /* Must have a diff */ \
772  } \
773 
774 
776 {
777  timer_private_t *private_info;
778  uint64_t samples;
779 
780  if (timer->interval == 1) {
781  return SWITCH_STATUS_FALSE;
782  }
783 
784 #ifdef HAVE_TIMERFD_CREATE
785  if (TFD == 2) {
786  return _timerfd_step(timer);
787  }
788 #endif
789 
790  private_info = timer->private_info;
791 
792  if (globals.RUNNING != 1 || private_info->ready == 0) {
793  return SWITCH_STATUS_FALSE;
794  }
795 
796  check_roll();
797  samples = (uint64_t)timer->samples * (private_info->reference - private_info->start);
798 
799  if (samples > UINT32_MAX) {
800  private_info->start = private_info->reference - 1; /* Must have a diff */
801  samples = timer->samples;
802  }
803 
804  timer->samplecount = (uint32_t) samples;
805  private_info->reference++;
806 
807  return SWITCH_STATUS_SUCCESS;
808 }
809 
811 {
812  timer_private_t *private_info;
813 
814  if (timer->interval == 1) {
815  return timer_generic_sync(timer);
816  }
817 
818 #ifdef HAVE_TIMERFD_CREATE
819  if (TFD == 2) {
820  return timer_generic_sync(timer);
821  }
822 #endif
823 
824  private_info = timer->private_info;
825 
826  if (globals.RUNNING != 1 || private_info->ready == 0) {
827  return SWITCH_STATUS_FALSE;
828  }
829 
830  /* sync the clock */
831  private_info->reference = (switch_size_t)(timer->tick = TIMER_MATRIX[timer->interval].tick);
832 
833  /* apply timestamp */
834  timer_step(timer);
835 
836  return SWITCH_STATUS_SUCCESS;
837 }
838 
839 
841 {
842  timer_private_t *private_info;
843 
844 #ifdef DISABLE_1MS_COND
845  int cond_index = timer->interval;
846 #else
847  int cond_index = 1;
848 #endif
849  int delta;
850 
851  if (timer->interval == 1) {
852  return SWITCH_STATUS_FALSE;
853  }
854 
855 #ifdef HAVE_TIMERFD_CREATE
856  if (TFD == 2) {
857  return _timerfd_next(timer);
858  }
859 #endif
860 
861  private_info = timer->private_info;
862 
863  delta = (int) (private_info->reference - TIMER_MATRIX[timer->interval].tick);
864 
865 
866 
867  /* sync up timer if it's not been called for a while otherwise it will return instantly several times until it catches up */
868  if (delta < -1) {
869  private_info->reference = (switch_size_t)(timer->tick = TIMER_MATRIX[timer->interval].tick);
870  }
871  timer_step(timer);
872 
873  if (!MATRIX) {
874  do_sleep(1000 * timer->interval);
875  goto end;
876  }
877 
878  while (globals.RUNNING == 1 && private_info->ready && TIMER_MATRIX[timer->interval].tick < private_info->reference) {
879  check_roll();
880 
881  switch_os_yield();
882 
883 
884  if (runtime.tipping_point && globals.timer_count >= runtime.tipping_point) {
885  globals.use_cond_yield = 0;
886  } else {
887  if (globals.use_cond_yield == 1) {
888  switch_mutex_lock(TIMER_MATRIX[cond_index].mutex);
889  if (TIMER_MATRIX[timer->interval].tick < private_info->reference) {
890  switch_thread_cond_wait(TIMER_MATRIX[cond_index].cond, TIMER_MATRIX[cond_index].mutex);
891  }
892  switch_mutex_unlock(TIMER_MATRIX[cond_index].mutex);
893  } else {
894  do_sleep(1000);
895  }
896  }
897  }
898 
899  end:
900  return globals.RUNNING == 1 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
901 }
902 
904 {
905  timer_private_t *private_info;
907 
908  if (timer->interval == 1) {
909  return SWITCH_STATUS_FALSE;
910  }
911 
912 #ifdef HAVE_TIMERFD_CREATE
913  if (TFD == 2) {
914  return _timerfd_check(timer, step);
915  }
916 #endif
917 
918  private_info = timer->private_info;
919 
920  if (globals.RUNNING != 1 || !private_info->ready) {
921  return SWITCH_STATUS_SUCCESS;
922  }
923 
924  check_roll();
925 
926  timer->tick = TIMER_MATRIX[timer->interval].tick;
927 
928  if (timer->tick < private_info->reference) {
929  timer->diff = (switch_size_t)(private_info->reference - timer->tick);
930  } else {
931  timer->diff = 0;
932  }
933 
934  if (timer->diff) {
935  status = SWITCH_STATUS_FALSE;
936  } else if (step) {
937  timer_step(timer);
938  }
939 
940 
941  return status;
942 }
943 
945 {
946  timer_private_t *private_info;
947 
948  if (timer->interval == 1) {
949  switch_mutex_lock(globals.mutex);
950  if (globals.timer_count) {
951  globals.timer_count--;
952  }
954  return SWITCH_STATUS_SUCCESS;
955  }
956 
957 #ifdef HAVE_TIMERFD_CREATE
958  if (TFD == 2) {
959  return _timerfd_destroy(timer);
960  }
961 #endif
962 
963  private_info = timer->private_info;
964 
965  if (timer->interval < MAX_ELEMENTS) {
966  switch_mutex_lock(globals.mutex);
967  TIMER_MATRIX[timer->interval].count--;
968  if (TIMER_MATRIX[timer->interval].count == 0) {
969  TIMER_MATRIX[timer->interval].tick = 0;
970  }
972  }
973  if (private_info) {
974  private_info->ready = 0;
975  }
976 
977  switch_mutex_lock(globals.mutex);
978  if (globals.timer_count) {
979  globals.timer_count--;
980  if (runtime.tipping_point && globals.timer_count == (runtime.tipping_point - 1)) {
981  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Fell Below tipping point of %u, shifting into low-gear.\n", runtime.tipping_point);
982  }
983  }
985 
986  return SWITCH_STATUS_SUCCESS;
987 }
988 
989 static void win32_init_timers(void)
990 {
991 #ifdef WIN32
992  OSVERSIONINFOEX version_info; /* Used to fetch current OS version from Windows */
993 
994  EnterCriticalSection(&timer_section);
995 
996  ZeroMemory(&version_info, sizeof(OSVERSIONINFOEX));
997  version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
998 
999  /* Check if we should use timeGetTime() (pre-Vista) or QueryPerformanceCounter() (Vista and later) */
1000 
1001  if (GetVersionEx((OSVERSIONINFO*) &version_info)) {
1002  if (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT && version_info.dwMajorVersion >= 6) {
1003  if (QueryPerformanceFrequency((LARGE_INTEGER*)&win32_qpc_freq) && win32_qpc_freq > 0) {
1004  /* At least Vista, and QueryPerformanceFrequency() suceeded, enable qpc */
1005  win32_use_qpc = 1;
1006  } else {
1007  /* At least Vista, but QueryPerformanceFrequency() failed, disable qpc */
1008  win32_use_qpc = 0;
1009  }
1010  } else {
1011  /* Older then Vista, disable qpc */
1012  win32_use_qpc = 0;
1013  }
1014  } else {
1015  /* Unknown version - we want at least Vista, disable qpc */
1016  win32_use_qpc = 0;
1017  }
1018 
1019  if (win32_use_qpc) {
1020  uint64_t count = 0;
1021 
1022  if (!QueryPerformanceCounter((LARGE_INTEGER*)&count) || count == 0) {
1023  /* Call to QueryPerformanceCounter() failed, disable qpc again */
1024  win32_use_qpc = 0;
1025  }
1026  }
1027 
1028  if (!win32_use_qpc) {
1029  /* This will enable timeGetTime() instead, qpc init failed */
1030  win32_last_get_time_tick = timeGetTime();
1031  win32_tick_time_since_start = win32_last_get_time_tick;
1032  }
1033 
1034  LeaveCriticalSection(&timer_section);
1035 #endif
1036 }
1037 
1039 {
1040  switch_time_t too_late = runtime.microseconds_per_tick * 1000;
1041  uint32_t current_ms = 0;
1042  uint32_t x, tick = 0, sps_interval_ticks = 0;
1043  switch_time_t ts = 0, last = 0;
1044  int fwd_errs = 0, rev_errs = 0;
1045  int profile_tick = 0;
1046  int tfd = -1;
1047  uint32_t time_sync;
1048 
1049 #ifdef HAVE_TIMERFD_CREATE
1050  int last_MICROSECONDS_PER_TICK = runtime.microseconds_per_tick;
1051 
1052  struct itimerspec spec = { { 0 } };
1053 
1054  if (MONO && TFD) {
1055  tfd = timerfd_create(CLOCK_MONOTONIC, 0);
1056 
1057  if (tfd > -1) {
1058  spec.it_interval.tv_sec = 0;
1059  spec.it_interval.tv_nsec = runtime.microseconds_per_tick * 1000;
1060  spec.it_value.tv_sec = 0;
1061  spec.it_value.tv_nsec = 100000;
1062 
1063  if (timerfd_settime(tfd, 0, &spec, NULL)) {
1064  close(tfd);
1065  tfd = -1;
1066  }
1067  }
1068 
1069  if (tfd > -1) MATRIX = 0;
1070  }
1071 #else
1072  tfd = -1;
1073 #endif
1074 
1077 
1078  if (runtime.timer_affinity > -1) {
1080  }
1081 
1082  switch_time_sync();
1083 
1084  globals.STARTED = globals.RUNNING = 1;
1088 
1089  if (MONO) {
1090  int loops;
1091  for (loops = 0; loops < 3; loops++) {
1092  ts = switch_time_ref();
1093  /* if it returns the same value every time it won't be of much use. */
1094  if (ts == last) {
1095  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Broken MONOTONIC Clock Detected!, Support Disabled.\n");
1096  MONO = 0;
1097  NANO = 0;
1100  break;
1101  }
1103  last = ts;
1104  }
1105  }
1106 
1107  last = 0;
1108  fwd_errs = rev_errs = 0;
1109 
1110 #ifndef DISABLE_1MS_COND
1111  if (!NANO) {
1113  switch_thread_cond_create(&TIMER_MATRIX[1].cond, module_pool);
1114  }
1115 #endif
1116 
1117 
1118  switch_time_sync();
1119  time_sync = runtime.time_sync;
1120 
1121  globals.use_cond_yield = COND;
1122  globals.RUNNING = 1;
1123 
1124  while (globals.RUNNING == 1) {
1125 
1126 #ifdef HAVE_TIMERFD_CREATE
1127  if (last_MICROSECONDS_PER_TICK != runtime.microseconds_per_tick) {
1128  spec.it_interval.tv_nsec = runtime.microseconds_per_tick * 1000;
1129  timerfd_settime(tfd, 0, &spec, NULL);
1130  }
1131 
1132  last_MICROSECONDS_PER_TICK = runtime.microseconds_per_tick;
1133 #endif
1134 
1136 
1137  while (((ts = time_now(runtime.offset)) + 100) < runtime.reference) {
1138  if (ts < last) {
1139  if (MONO) {
1141 
1142  if (time_sync == runtime.time_sync) { /* Only resync if not in the middle of switch_time_sync() already */
1143  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Virtual Migration Detected! Syncing Clock\n");
1144  win32_init_timers(); /* Make sure to reinit timers on WIN32 */
1145  switch_time_sync();
1146  time_sync = runtime.time_sync;
1147  }
1148  } else {
1149  int64_t diff = (int64_t) (ts - last);
1150  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Reverse Clock Skew Detected!\n");
1152  current_ms = 0;
1153  tick = 0;
1154  runtime.initiated += diff;
1155  rev_errs++;
1156  }
1157 
1158  if (!MONO || time_sync == runtime.time_sync) {
1159 #if defined(HAVE_CLOCK_NANOSLEEP)
1161  "If you see this message many times try setting the param enable-clock-nanosleep to true in switch.conf.xml or consider a nicer machine to run me on.\n");
1162 #else
1164  "If you see this message many times consider a nicer machine to run me on.\n");
1165 #endif
1166  }
1167  } else {
1168  rev_errs = 0;
1169  }
1170 
1171  if (runtime.tipping_point && globals.timer_count >= runtime.tipping_point) {
1172  switch_os_yield();
1173  } else {
1174  if (tfd > -1 && globals.RUNNING == 1) {
1175  uint64_t exp;
1176  read(tfd, &exp, sizeof(exp));
1177  (void)exp;
1178  } else {
1179  switch_time_t timediff = runtime.reference - ts;
1180 
1181  if (runtime.microseconds_per_tick < timediff) {
1182  /* Only sleep for runtime.microseconds_per_tick if this value is lower then the actual time diff we need to sleep */
1184  } else {
1185 #ifdef WIN32
1186  /* Windows only sleeps in ms precision, try to round the usec value as good as possible */
1187  do_sleep((switch_interval_time_t)floor((timediff / 1000.0) + 0.5) * 1000);
1188 #else
1189  do_sleep(timediff);
1190 #endif
1191  }
1192  }
1193  }
1194 
1195  last = ts;
1196  }
1197 
1198  if (ts > (runtime.reference + too_late)) {
1199  if (MONO) {
1201 
1202  if (time_sync == runtime.time_sync) { /* Only resync if not in the middle of switch_time_sync() already */
1203  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Virtual Migration Detected! Syncing Clock\n");
1204  win32_init_timers(); /* Make sure to reinit timers on WIN32 */
1205  switch_time_sync();
1206  time_sync = runtime.time_sync;
1207  }
1208  } else {
1210  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Forward Clock Skew Detected!\n");
1211  fwd_errs++;
1213  current_ms = 0;
1214  tick = 0;
1215  runtime.initiated += diff;
1216  }
1217  } else {
1218  fwd_errs = 0;
1219  }
1220 
1221  if (fwd_errs > 9 || rev_errs > 9) {
1222  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Auto Re-Syncing clock.\n");
1223  switch_time_sync();
1224  time_sync = runtime.time_sync;
1225  fwd_errs = rev_errs = 0;
1226  }
1227 
1228  runtime.timestamp = ts;
1229  current_ms += (runtime.microseconds_per_tick / 1000);
1230  tick++;
1231 
1232  if (time_sync < runtime.time_sync) {
1233  time_sync++; /* Only step once for each loop, we want to make sure to keep this thread safe */
1234  }
1235 
1236  if (tick >= (1000000 / runtime.microseconds_per_tick)) {
1237  if (++profile_tick == 1) {
1239  profile_tick = 0;
1240  }
1241 
1242  if (runtime.sps <= 0) {
1243  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Over Session Rate of %d!\n", runtime.sps_total);
1244  }
1245 
1246  /* These two mutexes must be held in exact order: session_hash_mutex and then throttle_mutex. See switch_core_session_request_uuid() */
1250 
1251  if (sps_interval_ticks >= 300) {
1253  sps_interval_ticks = 0;
1254  /* This line is protected by runtime.session_hash_mutex */
1256  }
1257 
1258  sps_interval_ticks++;
1259 
1262  }
1263 
1264  if (runtime.sps_last > runtime.sps_peak) {
1266  }
1270  tick = 0;
1271  }
1272 #ifndef DISABLE_1MS_COND
1273  TIMER_MATRIX[1].tick++;
1274  if (switch_mutex_trylock(TIMER_MATRIX[1].mutex) == SWITCH_STATUS_SUCCESS) {
1275  switch_thread_cond_broadcast(TIMER_MATRIX[1].cond);
1276  switch_mutex_unlock(TIMER_MATRIX[1].mutex);
1277  }
1278  if (TIMER_MATRIX[1].tick == MAX_TICK) {
1279  TIMER_MATRIX[1].tick = 0;
1280  TIMER_MATRIX[1].roll++;
1281  }
1282 #endif
1283 
1284 
1285  if (MATRIX && (current_ms % (runtime.microseconds_per_tick / 1000)) == 0) {
1286  for (x = (runtime.microseconds_per_tick / 1000); x <= MAX_ELEMENTS; x += (runtime.microseconds_per_tick / 1000)) {
1287  if ((current_ms % x) == 0) {
1288  if (TIMER_MATRIX[x].count) {
1289  TIMER_MATRIX[x].tick++;
1290 #ifdef DISABLE_1MS_COND
1291 
1292  if (TIMER_MATRIX[x].mutex && switch_mutex_trylock(TIMER_MATRIX[x].mutex) == SWITCH_STATUS_SUCCESS) {
1293  switch_thread_cond_broadcast(TIMER_MATRIX[x].cond);
1294  switch_mutex_unlock(TIMER_MATRIX[x].mutex);
1295  }
1296 #endif
1297  if (TIMER_MATRIX[x].tick == MAX_TICK) {
1298  TIMER_MATRIX[x].tick = 0;
1299  TIMER_MATRIX[x].roll++;
1300  }
1301  }
1302  }
1303  }
1304  }
1305 
1306  if (current_ms == MAX_ELEMENTS) {
1307  current_ms = 0;
1308  }
1309  }
1310 
1311  globals.use_cond_yield = 0;
1312 
1313  for (x = (runtime.microseconds_per_tick / 1000); x <= MAX_ELEMENTS; x += (runtime.microseconds_per_tick / 1000)) {
1314  if (TIMER_MATRIX[x].mutex && switch_mutex_trylock(TIMER_MATRIX[x].mutex) == SWITCH_STATUS_SUCCESS) {
1315  switch_thread_cond_broadcast(TIMER_MATRIX[x].cond);
1316  switch_mutex_unlock(TIMER_MATRIX[x].mutex);
1317  }
1318  }
1319 
1320  if (tfd > -1) {
1321  close(tfd);
1322  }
1323 
1324 
1325  switch_mutex_lock(globals.mutex);
1326  globals.RUNNING = 0;
1328 
1330 
1331  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Soft timer thread exiting.\n");
1332 
1333  return SWITCH_STATUS_TERM;
1334 }
1335 
1336 /*
1337  This converts a struct tm to a switch_time_exp_t
1338  We have to use UNIX structures to do our exams
1339  and use switch_* functions for the output.
1340 */
1341 
1342 static void tm2switchtime(struct tm *tm, switch_time_exp_t *xt)
1343 {
1344 
1345  if (!xt || !tm) {
1346  return;
1347  }
1348  memset(xt, 0, sizeof(*xt));
1349 
1350  xt->tm_sec = tm->tm_sec;
1351  xt->tm_min = tm->tm_min;
1352  xt->tm_hour = tm->tm_hour;
1353  xt->tm_mday = tm->tm_mday;
1354  xt->tm_mon = tm->tm_mon;
1355  xt->tm_year = tm->tm_year;
1356  xt->tm_wday = tm->tm_wday;
1357  xt->tm_yday = tm->tm_yday;
1358  xt->tm_isdst = tm->tm_isdst;
1359 
1360 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
1361  xt->tm_gmtoff = tm->tm_gmtoff;
1362 #endif
1363 
1364  return;
1365 }
1366 
1367 /* **************************************************************************
1368  LOADING OF THE XML DATA - HASH TABLE & MEMORY POOL MANAGEMENT
1369  ************************************************************************** */
1370 
1371 typedef struct {
1375 
1377 static switch_event_node_t *NODE = NULL;
1378 
1379 SWITCH_DECLARE(const char *) switch_lookup_timezone(const char *tz_name)
1380 {
1381  char *value = NULL;
1382 
1383  if (zstr(tz_name) || !TIMEZONES_LIST.hash) {
1384  return NULL;
1385  }
1386 
1387  switch_mutex_lock(globals.mutex);
1388  if ((value = switch_core_hash_find(TIMEZONES_LIST.hash, tz_name)) == NULL) {
1389  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Timezone '%s' not found!\n", tz_name);
1390  }
1391 
1393 
1394  return value;
1395 }
1396 
1398 {
1399  switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL;
1400  unsigned total = 0;
1401 
1402  if (TIMEZONES_LIST.hash) {
1403  switch_core_hash_destroy(&TIMEZONES_LIST.hash);
1404  }
1405 
1406  if (TIMEZONES_LIST.pool) {
1407  switch_core_destroy_memory_pool(&TIMEZONES_LIST.pool);
1408  }
1409 
1410  memset(&TIMEZONES_LIST, 0, sizeof(TIMEZONES_LIST));
1411  switch_core_new_memory_pool(&TIMEZONES_LIST.pool);
1412  switch_core_hash_init(&TIMEZONES_LIST.hash);
1413 
1414  if ((xml = switch_xml_open_cfg("timezones.conf", &cfg, NULL))) {
1415  if ((x_lists = switch_xml_child(cfg, "timezones"))) {
1416  for (x_list = switch_xml_child(x_lists, "zone"); x_list; x_list = x_list->next) {
1417  const char *name = switch_xml_attr(x_list, "name");
1418  const char *value = switch_xml_attr(x_list, "value");
1419 
1420  if (zstr(name)) {
1421  continue;
1422  }
1423 
1424  if (zstr(value)) {
1425  continue;
1426  }
1427 
1428  switch_core_hash_insert(TIMEZONES_LIST.hash, name, switch_core_strdup(TIMEZONES_LIST.pool, value));
1429  total++;
1430  }
1431  }
1432 
1433  switch_xml_free(xml);
1434  }
1435 
1436  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Timezone %sloaded %d definitions\n", reload ? "re" : "", total);
1437 }
1438 
1439 static void event_handler(switch_event_t *event)
1440 {
1441  switch_mutex_lock(globals.mutex);
1444 }
1445 
1446 static void tztime(const time_t *const timep, const char *tzstring, struct tm *const tmp);
1447 
1449 {
1450  struct tm xtm = { 0 };
1451  const char *tz_name = tz;
1452  const char *tzdef;
1453  time_t timep;
1454 
1455  if (!thetime) {
1456  thetime = switch_micro_time_now();
1457  }
1458 
1459  timep = (thetime) / (int64_t) (1000000);
1460 
1461  if (!zstr(tz_name)) {
1462  tzdef = switch_lookup_timezone(tz_name);
1463  } else {
1464  /* We set the default timezone to GMT. */
1465  tzdef = "GMT";
1466  }
1467 
1468  if (tzdef) { /* The lookup of the zone may fail. */
1469  tztime(&timep, tzdef, &xtm);
1470  tm2switchtime(&xtm, tm);
1471  return SWITCH_STATUS_SUCCESS;
1472  }
1473 
1474  return SWITCH_STATUS_FALSE;
1475 
1476 }
1477 
1478 SWITCH_DECLARE(switch_status_t) switch_strftime_tz(const char *tz, const char *format, char *date, size_t len, switch_time_t thetime)
1479 {
1480  time_t timep;
1481 
1482  const char *tz_name = tz;
1483  const char *tzdef;
1484 
1485  switch_size_t retsize;
1486 
1487  struct tm tm = { 0 };
1488  switch_time_exp_t stm;
1489 
1490  if (!thetime) {
1491  thetime = switch_micro_time_now();
1492  }
1493 
1494  timep = (thetime) / (int64_t) (1000000);
1495 
1496  if (!zstr(tz_name)) {
1497  tzdef = switch_lookup_timezone(tz_name);
1498  } else {
1499  /* We set the default timezone to GMT. */
1500  tzdef = "GMT";
1501  }
1502 
1503  if (tzdef) { /* The lookup of the zone may fail. */
1504  tztime(&timep, tzdef, &tm);
1505  tm2switchtime(&tm, &stm);
1506  switch_strftime_nocheck(date, &retsize, len, zstr(format) ? "%Y-%m-%d %T" : format, &stm);
1507  if (!zstr_buf(date)) {
1508  return SWITCH_STATUS_SUCCESS;
1509  }
1510  }
1511  return SWITCH_STATUS_FALSE;
1512 }
1513 
1515 {
1516  switch_timer_interface_t *timer_interface;
1517  module_pool = pool;
1518 
1519 #ifdef WIN32
1520  timeBeginPeriod(1);
1521 
1522  InitializeCriticalSection(&timer_section);
1523 
1524  win32_init_timers(); /* Init timers for Windows, if we should use timeGetTime() or QueryPerformanceCounters() */
1525 #endif
1526 
1527  memset(&globals, 0, sizeof(globals));
1529 
1532  }
1534 
1535  /* connect my internal structure to the blank pointer passed to me */
1536  *module_interface = switch_loadable_module_create_module_interface(pool, modname);
1537  timer_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_TIMER_INTERFACE);
1538  timer_interface->interface_name = "soft";
1539  timer_interface->timer_init = timer_init;
1540  timer_interface->timer_next = timer_next;
1541  timer_interface->timer_step = timer_step;
1542  timer_interface->timer_sync = timer_sync;
1543  timer_interface->timer_check = timer_check;
1544  timer_interface->timer_destroy = timer_destroy;
1545 
1548  }
1549 
1552  }
1553 
1554  if (TFD) {
1556  }
1557 
1558 #ifdef WIN32
1560  MONO = 1;
1561 
1562  if (win32_use_qpc) {
1563  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Enabled Windows monotonic clock, using QueryPerformanceCounter()\n");
1564  } else {
1565  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Enabled Windows monotonic clock, using timeGetTime()\n");
1566  }
1567 
1568  runtime.initiated = switch_mono_micro_time_now(); /* Update mono_initiated, since now is the first time the real clock is enabled */
1569  }
1570 
1571  /* No need to calibrate clock in Win32, we will only sleep ms anyway, it's just not accurate enough */
1573 #endif
1574 
1576  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Calibrating timer, please wait...\n");
1578  } else {
1579  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clock calibration disabled.\n");
1580  }
1581 
1582  /* indicate that the module should continue to be loaded */
1583  return SWITCH_STATUS_SUCCESS;
1584 }
1585 
1587 {
1588  globals.use_cond_yield = 0;
1589 
1590  if (globals.RUNNING == 1) {
1591  switch_mutex_lock(globals.mutex);
1592  globals.RUNNING = -1;
1594 
1595  while (globals.RUNNING == -1) {
1596  do_sleep(10000);
1597  }
1598  }
1599 #if defined(WIN32)
1600  timeEndPeriod(1);
1601  win32_tick_time_since_start = -1; /* we are not initialized anymore */
1602  DeleteCriticalSection(&timer_section);
1603 #endif
1604 
1605  if (NODE) {
1606  switch_event_unbind(&NODE);
1607  }
1608 
1609  switch_mutex_lock(globals.mutex);
1610  if (TIMEZONES_LIST.hash) {
1611  switch_core_hash_destroy(&TIMEZONES_LIST.hash);
1612  }
1613 
1615 
1616  if (TIMEZONES_LIST.pool) {
1617  switch_core_destroy_memory_pool(&TIMEZONES_LIST.pool);
1618  }
1619 
1620  return SWITCH_STATUS_SUCCESS;
1621 }
1622 
1623 
1624 
1625 
1626 /*
1627  * This file was originally written for NetBSD and is in the public domain,
1628  * so clarified as of 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
1629  *
1630  * Iw was modified by Massimo Cetra in order to be used with Callweaver and Freeswitch.
1631  */
1632 
1633 //#define TESTING_IT 1
1634 
1635 #include <stdlib.h>
1636 #include <stdio.h>
1637 #include <time.h>
1638 #include <string.h>
1639 #include <assert.h>
1640 
1641 
1642 #ifdef TESTING_IT
1643 #include <sys/time.h>
1644 #endif
1645 
1646 
1647 #ifndef TRUE
1648 #define TRUE 1
1649 #endif /* !defined TRUE */
1650 
1651 #ifndef FALSE
1652 #define FALSE 0
1653 #endif /* !defined FALSE */
1654 
1655 
1656 
1657 #ifndef TZ_MAX_TIMES
1658 /*
1659 ** The TZ_MAX_TIMES value below is enough to handle a bit more than a
1660 ** year's worth of solar time (corrected daily to the nearest second) or
1661 ** 138 years of Pacific Presidential Election time
1662 ** (where there are three time zone transitions every fourth year).
1663 */
1664 #define TZ_MAX_TIMES 370
1665 #endif /* !defined TZ_MAX_TIMES */
1666 
1667 #ifndef TZ_MAX_TYPES
1668 
1669 #ifndef NOSOLAR
1670 #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
1671 #endif /* !defined NOSOLAR */
1672 
1673 #ifdef NOSOLAR
1674 /*
1675 ** Must be at least 14 for Europe/Riga as of Jan 12 1995,
1676 ** as noted by Earl Chew <earl@hpato.aus.hp.com>.
1677 */
1678 #define TZ_MAX_TYPES 20 /* Maximum number of local time types */
1679 #endif /* !defined NOSOLAR */
1680 
1681 #endif /* !defined TZ_MAX_TYPES */
1682 
1683 #ifndef TZ_MAX_CHARS
1684 #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
1685  /* (limited by what unsigned chars can hold) */
1686 #endif /* !defined TZ_MAX_CHARS */
1687 
1688 #ifndef TZ_MAX_LEAPS
1689 #define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
1690 #endif /* !defined TZ_MAX_LEAPS */
1691 
1692 #ifdef TZNAME_MAX
1693 #define MY_TZNAME_MAX TZNAME_MAX
1694 #endif /* defined TZNAME_MAX */
1695 
1696 #ifndef TZNAME_MAX
1697 #define MY_TZNAME_MAX 255
1698 #endif /* !defined TZNAME_MAX */
1699 
1700 
1701 #define SECSPERMIN 60
1702 #define MINSPERHOUR 60
1703 #define HOURSPERDAY 24
1704 #define DAYSPERWEEK 7
1705 #define DAYSPERNYEAR 365
1706 #define DAYSPERLYEAR 366
1707 #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
1708 #define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
1709 #define MONSPERYEAR 12
1710 
1711 #define JULIAN_DAY 0 /* Jn - Julian day */
1712 #define DAY_OF_YEAR 1 /* n - day of year */
1713 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
1714 
1715 #define EPOCH_YEAR 1970
1716 #define EPOCH_WDAY TM_THURSDAY
1717 
1718 
1719 #ifndef TZ_MAX_TIMES
1720 /*
1721 ** The TZ_MAX_TIMES value below is enough to handle a bit more than a
1722 ** year's worth of solar time (corrected daily to the nearest second) or
1723 ** 138 years of Pacific Presidential Election time
1724 ** (where there are three time zone transitions every fourth year).
1725 */
1726 #define TZ_MAX_TIMES 370
1727 #endif /* !defined TZ_MAX_TIMES */
1728 
1729 #ifndef TZDEFRULES
1730 #define TZDEFRULES "posixrules"
1731 #endif /* !defined TZDEFRULES */
1732 
1733 /*
1734 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
1735 ** We default to US rules as of 1999-08-17.
1736 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
1737 ** implementation dependent; for historical reasons, US rules are a
1738 ** common default.
1739 */
1740 #ifndef TZDEFRULESTRING
1741 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
1742 #endif /* !defined TZDEFDST */
1743 
1744 /* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
1745 #define is_digit(c) ((unsigned)(c) - '0' <= 9)
1746 
1747 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
1748 
1749 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
1750 
1751 
1752 
1753 /*
1754 ** INITIALIZE(x)
1755 */
1756 
1757 #ifndef GNUC_or_lint
1758 #ifdef lint
1759 #define GNUC_or_lint
1760 #endif /* defined lint */
1761 #ifndef lint
1762 #ifdef __GNUC__
1763 #define GNUC_or_lint
1764 #endif /* defined __GNUC__ */
1765 #endif /* !defined lint */
1766 #endif /* !defined GNUC_or_lint */
1767 #ifdef WIN32
1768 #define GNUC_or_lint
1769 #endif
1770 
1771 #ifndef INITIALIZE
1772 #ifdef GNUC_or_lint
1773 #define INITIALIZE(x) ((x) = 0)
1774 #endif /* defined GNUC_or_lint */
1775 #ifndef GNUC_or_lint
1776 #define INITIALIZE(x)
1777 #endif /* !defined GNUC_or_lint */
1778 #endif /* !defined INITIALIZE */
1779 
1780 
1781 #define TM_SUNDAY 0
1782 #define TM_MONDAY 1
1783 #define TM_TUESDAY 2
1784 #define TM_WEDNESDAY 3
1785 #define TM_THURSDAY 4
1786 #define TM_FRIDAY 5
1787 #define TM_SATURDAY 6
1788 
1789 #define TM_JANUARY 0
1790 #define TM_FEBRUARY 1
1791 #define TM_MARCH 2
1792 #define TM_APRIL 3
1793 #define TM_MAY 4
1794 #define TM_JUNE 5
1795 #define TM_JULY 6
1796 #define TM_AUGUST 7
1797 #define TM_SEPTEMBER 8
1798 #define TM_OCTOBER 9
1799 #define TM_NOVEMBER 10
1800 #define TM_DECEMBER 11
1801 
1802 #define TM_YEAR_BASE 1900
1803 
1804 #define EPOCH_YEAR 1970
1805 #define EPOCH_WDAY TM_THURSDAY
1806 
1807 
1808 /* **************************************************************************
1809 
1810  ************************************************************************** */
1811 
1812 static const char gmt[] = "GMT";
1813 
1814 #define CHARS_DEF BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), (2 * (MY_TZNAME_MAX + 1)))
1815 
1816 struct rule {
1817  int r_type; /* type of rule--see below */
1818  int r_day; /* day number of rule */
1819  int r_week; /* week number of rule */
1820  int r_mon; /* month number of rule */
1821  long r_time; /* transition time of rule */
1822 };
1823 
1824 struct ttinfo { /* time type information */
1825  long tt_gmtoff; /* UTC offset in seconds */
1826  int tt_isdst; /* used to set tm_isdst */
1827  int tt_abbrind; /* abbreviation list index */
1828  int tt_ttisstd; /* TRUE if transition is std time */
1829  int tt_ttisgmt; /* TRUE if transition is UTC */
1830 };
1831 
1832 struct lsinfo { /* leap second information */
1833  time_t ls_trans; /* transition time */
1834  long ls_corr; /* correction to apply */
1835 };
1836 
1837 
1838 struct state {
1839  int leapcnt;
1840  int timecnt;
1841  int typecnt;
1842  int charcnt;
1843  time_t ats[TZ_MAX_TIMES];
1844  unsigned char types[TZ_MAX_TIMES];
1845  struct ttinfo ttis[TZ_MAX_TYPES];
1846  char chars[ /* LINTED constant */ CHARS_DEF];
1847  struct lsinfo lsis[TZ_MAX_LEAPS];
1848 };
1849 
1850 
1851 static const int mon_lengths[2][MONSPERYEAR] = {
1852  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
1853  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
1854 };
1855 
1856 static const int year_lengths[2] = {
1858 };
1859 
1860 
1861 /* **************************************************************************
1862 
1863  ************************************************************************** */
1864 
1865 
1866 /*
1867  Given a pointer into a time zone string, scan until a character that is not
1868  a valid character in a zone name is found. Return a pointer to that
1869  character.
1870 */
1871 
1872 static const char *getzname(register const char *strp)
1873 {
1874  register char c;
1875 
1876  while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && c != '+')
1877  ++strp;
1878  return strp;
1879 }
1880 
1881 
1882 /*
1883  Given a pointer into a time zone string, extract a number from that string.
1884  Check that the number is within a specified range; if it is not, return
1885  NULL.
1886  Otherwise, return a pointer to the first character not part of the number.
1887 */
1888 
1889 static const char *getnum(register const char *strp, int *const nump, const int min, const int max)
1890 {
1891  register char c;
1892  register int num;
1893 
1894  if (strp == NULL || !is_digit(c = *strp))
1895  return NULL;
1896  num = 0;
1897  do {
1898  num = num * 10 + (c - '0');
1899  if (num > max)
1900  return NULL; /* illegal value */
1901  c = *++strp;
1902  } while (is_digit(c));
1903  if (num < min)
1904  return NULL; /* illegal value */
1905  *nump = num;
1906  return strp;
1907 }
1908 
1909 /*
1910  Given a pointer into a time zone string, extract a number of seconds,
1911  in hh[:mm[:ss]] form, from the string.
1912  If any error occurs, return NULL.
1913  Otherwise, return a pointer to the first character not part of the number
1914  of seconds.
1915 */
1916 
1917 static const char *getsecs(register const char *strp, long *const secsp)
1918 {
1919  int num;
1920 
1921  /*
1922  ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
1923  ** "M10.4.6/26", which does not conform to Posix,
1924  ** but which specifies the equivalent of
1925  ** ``02:00 on the first Sunday on or after 23 Oct''.
1926  */
1927  strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
1928  if (strp == NULL)
1929  return NULL;
1930  *secsp = num * (long) SECSPERHOUR;
1931  if (*strp == ':') {
1932  ++strp;
1933  strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
1934  if (strp == NULL)
1935  return NULL;
1936  *secsp += num * SECSPERMIN;
1937  if (*strp == ':') {
1938  ++strp;
1939  /* `SECSPERMIN' allows for leap seconds. */
1940  strp = getnum(strp, &num, 0, SECSPERMIN);
1941  if (strp == NULL)
1942  return NULL;
1943  *secsp += num;
1944  }
1945  }
1946  return strp;
1947 }
1948 
1949 /*
1950  Given a pointer into a time zone string, extract an offset, in
1951  [+-]hh[:mm[:ss]] form, from the string.
1952  If any error occurs, return NULL.
1953  Otherwise, return a pointer to the first character not part of the time.
1954 */
1955 
1956 static const char *getoffset(register const char *strp, long *const offsetp)
1957 {
1958  register int neg = 0;
1959 
1960  if (*strp == '-') {
1961  neg = 1;
1962  ++strp;
1963  } else if (*strp == '+')
1964  ++strp;
1965  strp = getsecs(strp, offsetp);
1966  if (strp == NULL)
1967  return NULL; /* illegal time */
1968  if (neg)
1969  *offsetp = -*offsetp;
1970  return strp;
1971 }
1972 
1973 /*
1974  Given a pointer into a time zone string, extract a rule in the form
1975  date[/time]. See POSIX section 8 for the format of "date" and "time".
1976  If a valid rule is not found, return NULL.
1977  Otherwise, return a pointer to the first character not part of the rule.
1978 */
1979 
1980 static const char *getrule(const char *strp, register struct rule *const rulep)
1981 {
1982  if (*strp == 'J') {
1983  /*
1984  ** Julian day.
1985  */
1986  rulep->r_type = JULIAN_DAY;
1987  ++strp;
1988  strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
1989  } else if (*strp == 'M') {
1990  /*
1991  ** Month, week, day.
1992  */
1993  rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
1994  ++strp;
1995  strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
1996  if (strp == NULL)
1997  return NULL;
1998  if (*strp++ != '.')
1999  return NULL;
2000  strp = getnum(strp, &rulep->r_week, 1, 5);
2001  if (strp == NULL)
2002  return NULL;
2003  if (*strp++ != '.')
2004  return NULL;
2005  strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
2006  } else if (is_digit(*strp)) {
2007  /*
2008  ** Day of year.
2009  */
2010  rulep->r_type = DAY_OF_YEAR;
2011  strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
2012  } else
2013  return NULL; /* invalid format */
2014  if (strp == NULL)
2015  return NULL;
2016  if (*strp == '/') {
2017  /*
2018  ** Time specified.
2019  */
2020  ++strp;
2021  strp = getsecs(strp, &rulep->r_time);
2022  } else
2023  rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
2024  return strp;
2025 }
2026 
2027 
2028 /*
2029  Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
2030  year, a rule, and the offset from UTC at the time that rule takes effect,
2031  calculate the Epoch-relative time that rule takes effect.
2032 */
2033 
2034 static time_t transtime(const time_t janfirst, const int year, register const struct rule *const rulep, const long offset)
2035 {
2036  register int leapyear;
2037  register time_t value;
2038  register int i;
2039  int d, m1, yy0, yy1, yy2, dow;
2040 
2041  INITIALIZE(value);
2042  leapyear = isleap(year);
2043  switch (rulep->r_type) {
2044 
2045  case JULIAN_DAY:
2046  /*
2047  ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
2048  ** years.
2049  ** In non-leap years, or if the day number is 59 or less, just
2050  ** add SECSPERDAY times the day number-1 to the time of
2051  ** January 1, midnight, to get the day.
2052  */
2053  value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
2054  if (leapyear && rulep->r_day >= 60)
2055  value += SECSPERDAY;
2056  break;
2057 
2058  case DAY_OF_YEAR:
2059  /*
2060  ** n - day of year.
2061  ** Just add SECSPERDAY times the day number to the time of
2062  ** January 1, midnight, to get the day.
2063  */
2064  value = janfirst + rulep->r_day * SECSPERDAY;
2065  break;
2066 
2067  case MONTH_NTH_DAY_OF_WEEK:
2068  /*
2069  ** Mm.n.d - nth "dth day" of month m.
2070  */
2071  value = janfirst;
2072  for (i = 0; i < rulep->r_mon - 1; ++i)
2073  value += mon_lengths[leapyear][i] * SECSPERDAY;
2074 
2075  /*
2076  ** Use Zeller's Congruence to get day-of-week of first day of
2077  ** month.
2078  */
2079  m1 = (rulep->r_mon + 9) % 12 + 1;
2080  yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
2081  yy1 = yy0 / 100;
2082  yy2 = yy0 % 100;
2083  dow = ((26 * m1 - 2) / 10 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
2084  if (dow < 0)
2085  dow += DAYSPERWEEK;
2086 
2087  /*
2088  ** "dow" is the day-of-week of the first day of the month. Get
2089  ** the day-of-month (zero-origin) of the first "dow" day of the
2090  ** month.
2091  */
2092  d = rulep->r_day - dow;
2093  if (d < 0)
2094  d += DAYSPERWEEK;
2095  for (i = 1; i < rulep->r_week; ++i) {
2096  if (d + DAYSPERWEEK >= mon_lengths[leapyear][rulep->r_mon - 1])
2097  break;
2098  d += DAYSPERWEEK;
2099  }
2100 
2101  /*
2102  ** "d" is the day-of-month (zero-origin) of the day we want.
2103  */
2104  value += d * SECSPERDAY;
2105  break;
2106  }
2107 
2108  /*
2109  ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
2110  ** question. To get the Epoch-relative time of the specified local
2111  ** time on that day, add the transition time and the current offset
2112  ** from UTC.
2113  */
2114  return value + rulep->r_time + offset;
2115 }
2116 
2117 
2118 
2119 /*
2120  Given a POSIX section 8-style TZ string, fill in the rule tables as
2121  appropriate.
2122 */
2123 
2124 static int tzparse(const char *name, register struct state *const sp, const int lastditch)
2125 {
2126  const char *stdname;
2127  const char *dstname;
2128  size_t stdlen;
2129  size_t dstlen;
2130  long stdoffset;
2131  long dstoffset;
2132  register time_t *atp;
2133  register unsigned char *typep;
2134  register char *cp;
2135 
2136 
2137  INITIALIZE(dstname);
2138  stdname = name;
2139 
2140  if (lastditch) {
2141  stdlen = strlen(name); /* length of standard zone name */
2142  name += stdlen;
2143  if (stdlen >= sizeof sp->chars)
2144  stdlen = (sizeof sp->chars) - 1;
2145  stdoffset = 0;
2146  } else {
2147  name = getzname(name);
2148  stdlen = name - stdname;
2149  if (stdlen < 3)
2150  return -1;
2151  if (*name == '\0')
2152  return -1;
2153  name = getoffset(name, &stdoffset);
2154  if (name == NULL)
2155  return -1;
2156  }
2157 
2158  sp->leapcnt = 0; /* so, we're off a little */
2159 
2160  if (*name != '\0') {
2161  dstname = name;
2162  name = getzname(name);
2163  dstlen = name - dstname; /* length of DST zone name */
2164  if (dstlen < 3)
2165  return -1;
2166  if (*name != '\0' && *name != ',' && *name != ';') {
2167  name = getoffset(name, &dstoffset);
2168  if (name == NULL)
2169  return -1;
2170  } else
2171  dstoffset = stdoffset - SECSPERHOUR;
2172 
2173  /* Go parsing the daylight saving stuff */
2174  if (*name == ',' || *name == ';') {
2175  struct rule start;
2176  struct rule end;
2177  register int year;
2178  register time_t janfirst;
2179  time_t starttime;
2180  time_t endtime;
2181 
2182  ++name;
2183  if ((name = getrule(name, &start)) == NULL)
2184  return -1;
2185  if (*name++ != ',')
2186  return -1;
2187  if ((name = getrule(name, &end)) == NULL)
2188  return -1;
2189  if (*name != '\0')
2190  return -1;
2191 
2192  sp->typecnt = 2; /* standard time and DST */
2193 
2194  /*
2195  ** Two transitions per year, from EPOCH_YEAR to 2037.
2196  */
2197  sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
2198 
2199  if (sp->timecnt > TZ_MAX_TIMES)
2200  return -1;
2201 
2202  sp->ttis[0].tt_gmtoff = -dstoffset;
2203  sp->ttis[0].tt_isdst = 1;
2204  sp->ttis[0].tt_abbrind = (int) (stdlen + 1);
2205  sp->ttis[1].tt_gmtoff = -stdoffset;
2206  sp->ttis[1].tt_isdst = 0;
2207  sp->ttis[1].tt_abbrind = 0;
2208 
2209  atp = sp->ats;
2210  typep = sp->types;
2211  janfirst = 0;
2212 
2213  for (year = EPOCH_YEAR; year <= 2037; ++year) {
2214  starttime = transtime(janfirst, year, &start, stdoffset);
2215  endtime = transtime(janfirst, year, &end, dstoffset);
2216  if (starttime > endtime) {
2217  *atp++ = endtime;
2218  *typep++ = 1; /* DST ends */
2219  *atp++ = starttime;
2220  *typep++ = 0; /* DST begins */
2221  } else {
2222  *atp++ = starttime;
2223  *typep++ = 0; /* DST begins */
2224  *atp++ = endtime;
2225  *typep++ = 1; /* DST ends */
2226  }
2227 
2228  janfirst += year_lengths[isleap(year)] * SECSPERDAY;
2229  }
2230 
2231  } else {
2232  register long theirstdoffset;
2233  register long theirdstoffset;
2234  register long theiroffset;
2235  register int isdst;
2236  register int i;
2237  register int j;
2238 
2239  if (*name != '\0')
2240  return -1;
2241  /*
2242  Initial values of theirstdoffset and theirdstoffset.
2243  */
2244  theirstdoffset = 0;
2245  for (i = 0; i < sp->timecnt; ++i) {
2246  j = sp->types[i];
2247  if (!sp->ttis[j].tt_isdst) {
2248  theirstdoffset = -sp->ttis[j].tt_gmtoff;
2249  break;
2250  }
2251  }
2252  theirdstoffset = 0;
2253  for (i = 0; i < sp->timecnt; ++i) {
2254  j = sp->types[i];
2255  if (sp->ttis[j].tt_isdst) {
2256  theirdstoffset = -sp->ttis[j].tt_gmtoff;
2257  break;
2258  }
2259  }
2260  /*
2261  ** Initially we're assumed to be in standard time.
2262  */
2263  isdst = FALSE;
2264  /*
2265  ** Now juggle transition times and types
2266  ** tracking offsets as you do.
2267  */
2268  for (i = 0; i < sp->timecnt; ++i) {
2269  j = sp->types[i];
2270  sp->types[i] = (unsigned char) sp->ttis[j].tt_isdst;
2271  if (sp->ttis[j].tt_ttisgmt) {
2272  /* No adjustment to transition time */
2273  } else {
2274  /*
2275  ** If summer time is in effect, and the
2276  ** transition time was not specified as
2277  ** standard time, add the summer time
2278  ** offset to the transition time;
2279  ** otherwise, add the standard time
2280  ** offset to the transition time.
2281  */
2282  /*
2283  ** Transitions from DST to DDST
2284  ** will effectively disappear since
2285  ** POSIX provides for only one DST
2286  ** offset.
2287  */
2288  if (isdst && !sp->ttis[j].tt_ttisstd) {
2289  sp->ats[i] += dstoffset - theirdstoffset;
2290  } else {
2291  sp->ats[i] += stdoffset - theirstdoffset;
2292  }
2293  }
2294  theiroffset = -sp->ttis[j].tt_gmtoff;
2295  if (sp->ttis[j].tt_isdst)
2296  theirdstoffset = theiroffset;
2297  else
2298  theirstdoffset = theiroffset;
2299  }
2300  /*
2301  ** Finally, fill in ttis.
2302  ** ttisstd and ttisgmt need not be handled.
2303  */
2304  sp->ttis[0].tt_gmtoff = -stdoffset;
2305  sp->ttis[0].tt_isdst = FALSE;
2306  sp->ttis[0].tt_abbrind = 0;
2307  sp->ttis[1].tt_gmtoff = -dstoffset;
2308  sp->ttis[1].tt_isdst = TRUE;
2309  sp->ttis[1].tt_abbrind = (int) (stdlen + 1);
2310  sp->typecnt = 2;
2311  }
2312  } else {
2313  dstlen = 0;
2314  sp->typecnt = 1; /* only standard time */
2315  sp->timecnt = 0;
2316  sp->ttis[0].tt_gmtoff = -stdoffset;
2317  sp->ttis[0].tt_isdst = 0;
2318  sp->ttis[0].tt_abbrind = 0;
2319  }
2320 
2321  sp->charcnt = (int) (stdlen + 1);
2322  if (dstlen != 0)
2323  sp->charcnt += (int) (dstlen + 1);
2324  if ((size_t) sp->charcnt > sizeof sp->chars)
2325  return -1;
2326  cp = sp->chars;
2327  (void) strncpy(cp, stdname, stdlen);
2328  cp += stdlen;
2329  *cp++ = '\0';
2330  if (dstlen != 0) {
2331  (void) strncpy(cp, dstname, dstlen);
2332  *(cp + dstlen) = '\0';
2333  }
2334  return 0;
2335 }
2336 
2337 /* **************************************************************************
2338 
2339  ************************************************************************** */
2340 #if (_MSC_VER >= 1400) // VC8+
2341 #define switch_assert(expr) assert(expr);__analysis_assume( expr )
2342 #else
2343 #define switch_assert(expr) assert(expr)
2344 #endif
2345 
2346 static void timesub(const time_t *const timep, const long offset, register const struct state *const sp, register struct tm *const tmp)
2347 {
2348  register const struct lsinfo *lp;
2349  register long days;
2350  register time_t rem;
2351  register int y;
2352  register int yleap;
2353  register const int *ip;
2354  register long corr;
2355  register int hit;
2356  register int i;
2357 
2358  switch_assert(timep != NULL);
2359  switch_assert(sp != NULL);
2360  switch_assert(tmp != NULL);
2361 
2362  corr = 0;
2363  hit = 0;
2364  i = (sp == NULL) ? 0 : sp->leapcnt;
2365 
2366  while (--i >= 0) {
2367  lp = &sp->lsis[i];
2368  if (*timep >= lp->ls_trans) {
2369  if (*timep == lp->ls_trans) {
2370  hit = ((i == 0 && lp->ls_corr > 0) || (i > 0 && lp->ls_corr > sp->lsis[i - 1].ls_corr));
2371  if (hit)
2372  while (i > 0 && sp->lsis[i].ls_trans == sp->lsis[i - 1].ls_trans + 1 && sp->lsis[i].ls_corr == sp->lsis[i - 1].ls_corr + 1) {
2373  ++hit;
2374  --i;
2375  }
2376  }
2377  corr = lp->ls_corr;
2378  break;
2379  }
2380  }
2381  days = (long) (*timep / SECSPERDAY);
2382  rem = *timep % SECSPERDAY;
2383 
2384 
2385 #ifdef mc68k
2386  /* If this is for CPU bugs workarounds, i would remove this anyway. Who would use it on an old mc68k ? */
2387  if (*timep == 0x80000000) {
2388  /*
2389  ** A 3B1 muffs the division on the most negative number.
2390  */
2391  days = -24855;
2392  rem = -11648;
2393  }
2394 #endif
2395 
2396  rem += (offset - corr);
2397  while (rem < 0) {
2398  rem += SECSPERDAY;
2399  --days;
2400  }
2401  while (rem >= SECSPERDAY) {
2402  rem -= SECSPERDAY;
2403  ++days;
2404  }
2405  tmp->tm_hour = (int) (rem / SECSPERHOUR);
2406  rem = rem % SECSPERHOUR;
2407  tmp->tm_min = (int) (rem / SECSPERMIN);
2408 
2409  /*
2410  ** A positive leap second requires a special
2411  ** representation. This uses "... ??:59:60" et seq.
2412  */
2413  tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
2414  tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
2415 
2416  if (tmp->tm_wday < 0)
2417  tmp->tm_wday += DAYSPERWEEK;
2418 
2419  y = EPOCH_YEAR;
2420 
2421 #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
2422 
2423  while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
2424  register int newy;
2425 
2426  newy = (int) (y + days / DAYSPERNYEAR);
2427  if (days < 0)
2428  --newy;
2429  days -= (newy - y) * DAYSPERNYEAR + LEAPS_THRU_END_OF(newy - 1) - LEAPS_THRU_END_OF(y - 1);
2430  y = newy;
2431  }
2432 
2433  tmp->tm_year = y - TM_YEAR_BASE;
2434  tmp->tm_yday = (int) days;
2435 
2436  ip = mon_lengths[yleap];
2437 
2438  for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
2439  days = days - (long) ip[tmp->tm_mon];
2440 
2441  tmp->tm_mday = (int) (days + 1);
2442  tmp->tm_isdst = 0;
2443 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
2444  tmp->tm_gmtoff = offset;
2445 #endif
2446 }
2447 
2448 /* **************************************************************************
2449 
2450  ************************************************************************** */
2451 
2452 static void tztime(const time_t *const timep, const char *tzstring, struct tm *const tmp)
2453 {
2454  struct state *tzptr, *sp;
2455  const time_t t = *timep;
2456  register int i;
2457  register const struct ttinfo *ttisp;
2458 
2459  if (tzstring == NULL)
2460  tzstring = gmt;
2461 
2462  tzptr = (struct state *) malloc(sizeof(struct state));
2463  sp = tzptr;
2464 
2465  if (tzptr != NULL) {
2466 
2467  memset(tzptr, 0, sizeof(struct state));
2468 
2469  (void) tzparse(tzstring, tzptr, FALSE);
2470 
2471  if (sp->timecnt == 0 || t < sp->ats[0]) {
2472  i = 0;
2473  while (sp->ttis[i].tt_isdst)
2474  if (++i >= sp->typecnt) {
2475  i = 0;
2476  break;
2477  }
2478  } else {
2479  for (i = 1; i < sp->timecnt; ++i)
2480  if (t < sp->ats[i])
2481  break;
2482  i = sp->types[i - 1]; // DST begin or DST end
2483  }
2484  ttisp = &sp->ttis[i];
2485 
2486  /*
2487  To get (wrong) behavior that's compatible with System V Release 2.0
2488  you'd replace the statement below with
2489  t += ttisp->tt_gmtoff;
2490  timesub(&t, 0L, sp, tmp);
2491  */
2492  if (tmp != NULL) { /* Just a check not to assert */
2493  timesub(&t, ttisp->tt_gmtoff, sp, tmp);
2494  tmp->tm_isdst = ttisp->tt_isdst;
2495 #if defined(HAVE_STRUCT_TM_TM_ZONE)
2496  tmp->tm_zone = &sp->chars[ttisp->tt_abbrind];
2497 #endif
2498  }
2499 
2500  free(tzptr);
2501  }
2502 
2503 }
2504 
2505 /* For Emacs:
2506  * Local Variables:
2507  * mode:c
2508  * indent-tabs-mode:t
2509  * tab-width:4
2510  * c-basic-offset:4
2511  * End:
2512  * For VIM:
2513  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
2514  */
#define check_roll()
Definition: switch_time.c:768
int32_t use_cond_yield
Definition: switch_time.c:105
switch_status_t(* timer_sync)(switch_timer_t *)
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:311
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
void switch_time_sync(void)
Definition: switch_time.c:609
#define JULIAN_DAY
Definition: switch_time.c:1711
static switch_status_t timer_sync(switch_timer_t *timer)
Definition: switch_time.c:810
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
static switch_status_t timer_init(switch_timer_t *timer)
Definition: switch_time.c:699
static switch_status_t timer_step(switch_timer_t *timer)
Definition: switch_time.c:775
switch_status_t switch_thread_cond_create(switch_thread_cond_t **cond, switch_memory_pool_t *pool)
Definition: switch_apr.c:373
int32_t STARTED
Definition: switch_time.c:104
SWITCH_MODULE_DEFINITION(CORE_SOFTTIMER_MODULE, softtimer_load, softtimer_shutdown, softtimer_runtime)
switch_status_t switch_event_bind_removable(const char *id, switch_event_types_t event, const char *subclass_name, switch_event_callback_t callback, void *user_data, switch_event_node_t **node)
Bind an event callback to a specific event.
#define SWITCH_CHANNEL_LOG
switch_time_t initiated
switch_status_t switch_mutex_trylock(switch_mutex_t *lock)
Definition: switch_apr.c:318
switch_status_t switch_core_hash_destroy(_Inout_ switch_hash_t **hash)
Destroy an existing hash table.
int tt_ttisstd
Definition: switch_time.c:1828
void * switch_core_hash_find(_In_ switch_hash_t *hash, _In_z_ const char *key)
Retrieve data from a given hash.
static switch_time_t time_now(int64_t offset)
Definition: switch_time.c:540
const char * switch_xml_attr(_In_opt_ switch_xml_t xml, _In_opt_z_ const char *attr)
returns the value of the requested tag attribute, or NULL if not found
static void tm2switchtime(struct tm *tm, switch_time_exp_t *xt)
Definition: switch_time.c:1342
#define switch_core_hash_init(_hash)
Definition: switch_core.h:1431
void switch_os_yield(void)
Definition: switch_time.c:142
static timer_matrix_t TIMER_MATRIX[MAX_ELEMENTS+1]
Definition: switch_time.c:138
long r_time
Definition: switch_time.c:1821
#define MAX_ELEMENTS
Definition: switch_time.c:53
void switch_time_set_nanosleep(switch_bool_t enable)
Definition: switch_time.c:366
int32_t timer_affinity
static const char * getoffset(register const char *strp, long *const offsetp)
Definition: switch_time.c:1956
time_t ats[TZ_MAX_TIMES]
Definition: switch_time.c:1843
void switch_sleep(switch_interval_time_t t)
Definition: switch_time.c:640
uint32_t timer_count
Definition: switch_time.c:107
#define HOURSPERDAY
Definition: switch_time.c:1703
int charcnt
Definition: switch_time.c:1842
#define SECSPERMIN
Definition: switch_time.c:1701
switch_bool_t
Definition: switch_types.h:441
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:733
static const char gmt[]
Definition: switch_time.c:1812
int leapcnt
Definition: switch_time.c:1839
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
switch_memory_pool_t * pool
Representation of an event.
Definition: switch_event.h:80
#define TZ_MAX_TIMES
Definition: switch_time.c:1664
#define TZ_MAX_TYPES
Definition: switch_time.c:1670
const char *const const char *const const cJSON *const value
void switch_cond_yield(switch_interval_time_t t)
Definition: switch_time.c:677
SWITCH_MODULE_SHUTDOWN_FUNCTION(softtimer_shutdown)
Definition: switch_time.c:1586
static int TFD
Definition: switch_time.c:81
static switch_timezones_list_t TIMEZONES_LIST
Definition: switch_time.c:1376
static struct @9 globals
#define MAX_TICK
Definition: switch_time.c:51
SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
Definition: switch_time.c:1038
A representation of an XML tree.
Definition: switch_xml.h:79
static switch_memory_pool_t * module_pool
Definition: switch_time.c:100
switch_mutex_t * throttle_mutex
switch_status_t switch_thread_cond_wait(switch_thread_cond_t *cond, switch_mutex_t *mutex)
Definition: switch_apr.c:378
A table of functions that a timer module implements.
char const int const cJSON_bool format
Definition: switch_cJSON.h:153
A node to store binded events.
Definition: switch_event.c:48
switch_status_t switch_strftime_nocheck(char *s, switch_size_t *retsize, switch_size_t max, const char *format, switch_time_exp_t *tm)
Definition: switch_apr.c:202
void switch_time_set_timerfd(int enable)
Definition: switch_time.c:348
static const int year_lengths[2]
Definition: switch_time.c:1856
Abstract handler to a timer module.
int r_mon
Definition: switch_time.c:1820
struct switch_runtime runtime
Definition: switch_core.c:86
uint32_t microseconds_per_tick
static switch_interval_time_t average_time(switch_interval_time_t t, int reps)
Definition: switch_time.c:191
switch_status_t(* timer_init)(switch_timer_t *)
static switch_status_t timer_destroy(switch_timer_t *timer)
Definition: switch_time.c:944
#define EPOCH_WDAY
Definition: switch_time.c:1805
switch_status_t switch_core_thread_set_cpu_affinity(int cpu)
Definition: switch_core.c:1763
#define zstr(x)
Definition: switch_utils.h:314
static switch_status_t timer_next(switch_timer_t *timer)
Definition: switch_time.c:840
int r_week
Definition: switch_time.c:1819
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
SWITCH_MODULE_LOAD_FUNCTION(softtimer_load)
Definition: switch_time.c:1514
struct lsinfo lsis[TZ_MAX_LEAPS]
Definition: switch_time.c:1847
#define switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
Definition: switch_utils.h:724
void switch_micro_sleep(switch_interval_time_t t)
Definition: switch_time.c:635
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
static int MONO
Definition: switch_time.c:64
int64_t switch_time_t
Definition: switch_apr.h:188
int32_t sessions_peak_fivemin
switch_xml_t next
Definition: switch_xml.h:91
if((uint32_t)(unpack->cur - unpack->buf) > unpack->buflen)
static void timesub(const time_t *const timep, const long offset, register const struct state *const sp, register struct tm *const tmp)
Definition: switch_time.c:2346
void switch_time_set_matrix(switch_bool_t enable)
Definition: switch_time.c:360
static time_t transtime(const time_t janfirst, const int year, register const struct rule *const rulep, const long offset)
Definition: switch_time.c:2034
switch_bool_t switch_get_system_idle_time(switch_profile_timer_t *p, double *idle_percentage)
provides the percentage of idle system time
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
switch_memory_pool_t * memory_pool
switch_memory_pool_t * pool
Definition: switch_time.c:1372
switch_status_t(* timer_check)(switch_timer_t *, switch_bool_t)
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:684
switch_status_t(* timer_destroy)(switch_timer_t *)
switch_size_t start
Definition: switch_time.c:122
uint32_t roll
Definition: switch_time.c:131
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:293
#define MINSPERHOUR
Definition: switch_time.c:1702
static int tzparse(const char *name, register struct state *const sp, const int lastditch)
Definition: switch_time.c:2124
#define UINT32_MAX
Definition: switch_time.c:48
switch_status_t switch_strftime_tz(const char *tz, const char *format, char *date, size_t len, switch_time_t thetime)
Definition: switch_time.c:1478
uintptr_t switch_size_t
static const int mon_lengths[2][MONSPERYEAR]
Definition: switch_time.c:1851
int r_day
Definition: switch_time.c:1818
static int OFFSET
Definition: switch_time.c:85
switch_mutex_t * session_hash_mutex
void switch_cond_next(void)
Definition: switch_time.c:658
switch_size_t reference
Definition: switch_time.c:121
int64_t switch_interval_time_t
Definition: switch_apr.h:191
#define zstr_buf(s)
Definition: switch_utils.h:318
#define TRUE
Definition: switch_time.c:1648
int r_type
Definition: switch_time.c:1817
static int COND
Definition: switch_time.c:87
long ls_corr
Definition: switch_time.c:1834
static void tztime(const time_t *const timep, const char *tzstring, struct tm *const tmp)
Definition: switch_time.c:2452
#define INITIALIZE(x)
Definition: switch_time.c:1776
void switch_delete_profile_timer(switch_profile_timer_t **p)
Deletes profile timer.
long tt_gmtoff
Definition: switch_time.c:1825
uint32_t count
Definition: switch_time.c:130
static switch_status_t timer_check(switch_timer_t *timer, switch_bool_t step)
Definition: switch_time.c:903
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: switch_time.c:1845
unsigned char types[TZ_MAX_TIMES]
Definition: switch_time.c:1844
struct fspr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
#define switch_assert(expr)
Definition: switch_time.c:2343
#define isleap(y)
Definition: switch_time.c:1749
switch_profile_timer_t * switch_new_profile_timer(void)
create a new profile timer
static switch_event_node_t * NODE
Definition: switch_time.c:1377
const char * switch_lookup_timezone(const char *tz_name)
Definition: switch_time.c:1379
char * ip
Definition: switch_msrp.c:60
void switch_load_timezones(switch_bool_t reload)
Definition: switch_time.c:1397
switch_time_t timestamp
void switch_time_set_monotonic(switch_bool_t enable)
Definition: switch_time.c:331
uint32_t ready
Definition: switch_time.c:124
switch_status_t
Common return values.
switch_xml_t switch_xml_open_cfg(_In_z_ const char *file_path, _Out_ switch_xml_t *node, _In_opt_ switch_event_t *params)
open a config in the core registry
switch_status_t(* timer_step)(switch_timer_t *)
#define is_digit(c)
Definition: switch_time.c:1745
static const char * getzname(register const char *strp)
Definition: switch_time.c:1872
switch_loadable_module_interface_t * switch_loadable_module_create_module_interface(switch_memory_pool_t *pool, const char *name)
switch_thread_cond_t * cond
Definition: switch_time.c:133
#define TZ_MAX_LEAPS
Definition: switch_time.c:1689
#define switch_core_hash_insert(_h, _k, _d)
Definition: switch_core.h:1479
#define SECSPERHOUR
Definition: switch_time.c:1707
int timecnt
Definition: switch_time.c:1840
switch_hash_t * hash
Definition: switch_time.c:1373
static switch_status_t timer_generic_sync(switch_timer_t *timer)
Definition: switch_time.c:382
void switch_time_calibrate_clock(void)
Definition: switch_time.c:208
Main Library Header.
static const char * getsecs(register const char *strp, long *const secsp)
Definition: switch_time.c:1917
struct switch_session_manager session_manager
#define SECSPERDAY
Definition: switch_time.c:1708
uint32_t tipping_point
#define LEAPS_THRU_END_OF(y)
int32_t sps_peak_fivemin
switch_mutex_t * mutex
Definition: switch_time.c:132
#define SWITCH_DECLARE(type)
static int NANO
Definition: switch_time.c:82
struct fspr_thread_cond_t switch_thread_cond_t
Definition: switch_apr.h:463
#define DAYSPERWEEK
Definition: switch_time.c:1704
#define MONTH_NTH_DAY_OF_WEEK
Definition: switch_time.c:1713
switch_time_t switch_mono_micro_time_now(void)
Definition: switch_time.c:316
switch_xml_t switch_xml_child(_In_ switch_xml_t xml, _In_z_ const char *name)
returns the first child tag (one level deeper) with the given name or NULL \ if not found ...
static const char * getnum(register const char *strp, int *const nump, const int min, const int max)
Definition: switch_time.c:1889
void switch_time_set_use_system_time(switch_bool_t enable)
Definition: switch_time.c:342
#define TM_YEAR_BASE
Definition: switch_time.c:1802
void switch_time_set_cond_yield(switch_bool_t enable)
Definition: switch_time.c:373
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:322
#define CHARS_DEF
Definition: switch_time.c:1814
uint64_t tick
Definition: switch_time.c:129
#define MONSPERYEAR
Definition: switch_time.c:1709
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
switch_memory_pool_t * memory_pool
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
int32_t RUNNING
Definition: switch_time.c:103
char chars[CHARS_DEF]
Definition: switch_time.c:1846
int tt_abbrind
Definition: switch_time.c:1827
static switch_time_t last_time
Definition: switch_time.c:607
while(unpack->bits_cur<=SWITCH_BITS_PER_BYTE)
int count
Definition: switch_cJSON.h:204
struct fspr_pool_t switch_memory_pool_t
#define calc_step()
Definition: switch_time.c:207
uint32_t roll
Definition: switch_time.c:123
const char *const name
Definition: switch_cJSON.h:250
#define EPOCH_YEAR
Definition: switch_time.c:1804
static void do_sleep(switch_interval_time_t t)
Definition: switch_time.c:151
switch_status_t switch_thread_cond_broadcast(switch_thread_cond_t *cond)
Definition: switch_apr.c:399
time_t ls_trans
Definition: switch_time.c:1833
static void event_handler(switch_event_t *event)
Definition: switch_time.c:1439
switch_status_t switch_time_exp_tz_name(const char *tz, switch_time_exp_t *tm, switch_time_t thetime)
Definition: switch_time.c:1448
static int SYSTEM_TIME
Definition: switch_time.c:68
switch_thread_rwlock_t * rwlock
Definition: switch_time.c:134
static void win32_init_timers(void)
Definition: switch_time.c:989
switch_time_t switch_time_now(void)
Definition: switch_apr.c:325
int tt_isdst
Definition: switch_time.c:1826
switch_mutex_t * mutex
Definition: switch_time.c:106
int typecnt
Definition: switch_time.c:1841
int tt_ttisgmt
Definition: switch_time.c:1829
struct fspr_thread_rwlock_t switch_thread_rwlock_t
Definition: switch_apr.h:436
#define FALSE
Definition: switch_time.c:1652
#define DAYSPERNYEAR
Definition: switch_time.c:1705
#define DAYSPERLYEAR
Definition: switch_time.c:1706
memset(buf, 0, buflen)
switch_status_t(* timer_next)(switch_timer_t *)
static int MATRIX
Definition: switch_time.c:89
#define DAY_OF_YEAR
Definition: switch_time.c:1712
switch_profile_timer_t * profile_timer
switch_time_t reference
void * switch_loadable_module_create_interface(switch_loadable_module_interface_t *mod, switch_module_interface_name_t iname)
switch_time_t switch_time_ref(void)
Definition: switch_time.c:596
static const char * getrule(const char *strp, register struct rule *const rulep)
Definition: switch_time.c:1980
switch_status_t switch_event_unbind(switch_event_node_t **node)
Unbind a bound event consumer.