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  if ((value = switch_core_hash_find(TIMEZONES_LIST.hash, tz_name)) == NULL) {
1388  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Timezone '%s' not found!\n", tz_name);
1389  }
1390 
1391  return value;
1392 }
1393 
1395 {
1396  switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL;
1397  unsigned total = 0;
1398 
1399  if (TIMEZONES_LIST.hash) {
1400  switch_core_hash_destroy(&TIMEZONES_LIST.hash);
1401  }
1402 
1403  if (TIMEZONES_LIST.pool) {
1404  switch_core_destroy_memory_pool(&TIMEZONES_LIST.pool);
1405  }
1406 
1407  memset(&TIMEZONES_LIST, 0, sizeof(TIMEZONES_LIST));
1408  switch_core_new_memory_pool(&TIMEZONES_LIST.pool);
1409  switch_core_hash_init(&TIMEZONES_LIST.hash);
1410 
1411  if ((xml = switch_xml_open_cfg("timezones.conf", &cfg, NULL))) {
1412  if ((x_lists = switch_xml_child(cfg, "timezones"))) {
1413  for (x_list = switch_xml_child(x_lists, "zone"); x_list; x_list = x_list->next) {
1414  const char *name = switch_xml_attr(x_list, "name");
1415  const char *value = switch_xml_attr(x_list, "value");
1416 
1417  if (zstr(name)) {
1418  continue;
1419  }
1420 
1421  if (zstr(value)) {
1422  continue;
1423  }
1424 
1425  switch_core_hash_insert(TIMEZONES_LIST.hash, name, switch_core_strdup(TIMEZONES_LIST.pool, value));
1426  total++;
1427  }
1428  }
1429 
1430  switch_xml_free(xml);
1431  }
1432 
1433  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Timezone %sloaded %d definitions\n", reload ? "re" : "", total);
1434 }
1435 
1436 static void event_handler(switch_event_t *event)
1437 {
1438  switch_mutex_lock(globals.mutex);
1441 }
1442 
1443 static void tztime(const time_t *const timep, const char *tzstring, struct tm *const tmp);
1444 
1446 {
1447  struct tm xtm = { 0 };
1448  const char *tz_name = tz;
1449  const char *tzdef;
1450  time_t timep;
1451 
1452  if (!thetime) {
1453  thetime = switch_micro_time_now();
1454  }
1455 
1456  timep = (thetime) / (int64_t) (1000000);
1457 
1458  if (!zstr(tz_name)) {
1459  tzdef = switch_lookup_timezone(tz_name);
1460  } else {
1461  /* We set the default timezone to GMT. */
1462  tzdef = "GMT";
1463  }
1464 
1465  if (tzdef) { /* The lookup of the zone may fail. */
1466  tztime(&timep, tzdef, &xtm);
1467  tm2switchtime(&xtm, tm);
1468  return SWITCH_STATUS_SUCCESS;
1469  }
1470 
1471  return SWITCH_STATUS_FALSE;
1472 
1473 }
1474 
1475 SWITCH_DECLARE(switch_status_t) switch_strftime_tz(const char *tz, const char *format, char *date, size_t len, switch_time_t thetime)
1476 {
1477  time_t timep;
1478 
1479  const char *tz_name = tz;
1480  const char *tzdef;
1481 
1482  switch_size_t retsize;
1483 
1484  struct tm tm = { 0 };
1485  switch_time_exp_t stm;
1486 
1487  if (!thetime) {
1488  thetime = switch_micro_time_now();
1489  }
1490 
1491  timep = (thetime) / (int64_t) (1000000);
1492 
1493  if (!zstr(tz_name)) {
1494  tzdef = switch_lookup_timezone(tz_name);
1495  } else {
1496  /* We set the default timezone to GMT. */
1497  tzdef = "GMT";
1498  }
1499 
1500  if (tzdef) { /* The lookup of the zone may fail. */
1501  tztime(&timep, tzdef, &tm);
1502  tm2switchtime(&tm, &stm);
1503  switch_strftime_nocheck(date, &retsize, len, zstr(format) ? "%Y-%m-%d %T" : format, &stm);
1504  if (!zstr_buf(date)) {
1505  return SWITCH_STATUS_SUCCESS;
1506  }
1507  }
1508  return SWITCH_STATUS_FALSE;
1509 }
1510 
1512 {
1513  switch_timer_interface_t *timer_interface;
1514  module_pool = pool;
1515 
1516 #ifdef WIN32
1517  timeBeginPeriod(1);
1518 
1519  InitializeCriticalSection(&timer_section);
1520 
1521  win32_init_timers(); /* Init timers for Windows, if we should use timeGetTime() or QueryPerformanceCounters() */
1522 #endif
1523 
1524  memset(&globals, 0, sizeof(globals));
1526 
1529  }
1531 
1532  /* connect my internal structure to the blank pointer passed to me */
1533  *module_interface = switch_loadable_module_create_module_interface(pool, modname);
1534  timer_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_TIMER_INTERFACE);
1535  timer_interface->interface_name = "soft";
1536  timer_interface->timer_init = timer_init;
1537  timer_interface->timer_next = timer_next;
1538  timer_interface->timer_step = timer_step;
1539  timer_interface->timer_sync = timer_sync;
1540  timer_interface->timer_check = timer_check;
1541  timer_interface->timer_destroy = timer_destroy;
1542 
1545  }
1546 
1549  }
1550 
1551  if (TFD) {
1553  }
1554 
1555 #ifdef WIN32
1557  MONO = 1;
1558 
1559  if (win32_use_qpc) {
1560  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Enabled Windows monotonic clock, using QueryPerformanceCounter()\n");
1561  } else {
1562  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Enabled Windows monotonic clock, using timeGetTime()\n");
1563  }
1564 
1565  runtime.initiated = switch_mono_micro_time_now(); /* Update mono_initiated, since now is the first time the real clock is enabled */
1566  }
1567 
1568  /* No need to calibrate clock in Win32, we will only sleep ms anyway, it's just not accurate enough */
1570 #endif
1571 
1573  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Calibrating timer, please wait...\n");
1575  } else {
1576  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clock calibration disabled.\n");
1577  }
1578 
1579  /* indicate that the module should continue to be loaded */
1580  return SWITCH_STATUS_SUCCESS;
1581 }
1582 
1584 {
1585  globals.use_cond_yield = 0;
1586 
1587  if (globals.RUNNING == 1) {
1588  switch_mutex_lock(globals.mutex);
1589  globals.RUNNING = -1;
1591 
1592  while (globals.RUNNING == -1) {
1593  do_sleep(10000);
1594  }
1595  }
1596 #if defined(WIN32)
1597  timeEndPeriod(1);
1598  win32_tick_time_since_start = -1; /* we are not initialized anymore */
1599  DeleteCriticalSection(&timer_section);
1600 #endif
1601 
1602  if (TIMEZONES_LIST.hash) {
1603  switch_core_hash_destroy(&TIMEZONES_LIST.hash);
1604  }
1605 
1606  if (TIMEZONES_LIST.pool) {
1607  switch_core_destroy_memory_pool(&TIMEZONES_LIST.pool);
1608  }
1609 
1610  if (NODE) {
1611  switch_event_unbind(&NODE);
1612  }
1613 
1614  return SWITCH_STATUS_SUCCESS;
1615 }
1616 
1617 
1618 
1619 
1620 /*
1621  * This file was originally written for NetBSD and is in the public domain,
1622  * so clarified as of 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
1623  *
1624  * Iw was modified by Massimo Cetra in order to be used with Callweaver and Freeswitch.
1625  */
1626 
1627 //#define TESTING_IT 1
1628 
1629 #include <stdlib.h>
1630 #include <stdio.h>
1631 #include <time.h>
1632 #include <string.h>
1633 #include <assert.h>
1634 
1635 
1636 #ifdef TESTING_IT
1637 #include <sys/time.h>
1638 #endif
1639 
1640 
1641 #ifndef TRUE
1642 #define TRUE 1
1643 #endif /* !defined TRUE */
1644 
1645 #ifndef FALSE
1646 #define FALSE 0
1647 #endif /* !defined FALSE */
1648 
1649 
1650 
1651 #ifndef TZ_MAX_TIMES
1652 /*
1653 ** The TZ_MAX_TIMES value below is enough to handle a bit more than a
1654 ** year's worth of solar time (corrected daily to the nearest second) or
1655 ** 138 years of Pacific Presidential Election time
1656 ** (where there are three time zone transitions every fourth year).
1657 */
1658 #define TZ_MAX_TIMES 370
1659 #endif /* !defined TZ_MAX_TIMES */
1660 
1661 #ifndef TZ_MAX_TYPES
1662 
1663 #ifndef NOSOLAR
1664 #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
1665 #endif /* !defined NOSOLAR */
1666 
1667 #ifdef NOSOLAR
1668 /*
1669 ** Must be at least 14 for Europe/Riga as of Jan 12 1995,
1670 ** as noted by Earl Chew <earl@hpato.aus.hp.com>.
1671 */
1672 #define TZ_MAX_TYPES 20 /* Maximum number of local time types */
1673 #endif /* !defined NOSOLAR */
1674 
1675 #endif /* !defined TZ_MAX_TYPES */
1676 
1677 #ifndef TZ_MAX_CHARS
1678 #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
1679  /* (limited by what unsigned chars can hold) */
1680 #endif /* !defined TZ_MAX_CHARS */
1681 
1682 #ifndef TZ_MAX_LEAPS
1683 #define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
1684 #endif /* !defined TZ_MAX_LEAPS */
1685 
1686 #ifdef TZNAME_MAX
1687 #define MY_TZNAME_MAX TZNAME_MAX
1688 #endif /* defined TZNAME_MAX */
1689 
1690 #ifndef TZNAME_MAX
1691 #define MY_TZNAME_MAX 255
1692 #endif /* !defined TZNAME_MAX */
1693 
1694 
1695 #define SECSPERMIN 60
1696 #define MINSPERHOUR 60
1697 #define HOURSPERDAY 24
1698 #define DAYSPERWEEK 7
1699 #define DAYSPERNYEAR 365
1700 #define DAYSPERLYEAR 366
1701 #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
1702 #define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
1703 #define MONSPERYEAR 12
1704 
1705 #define JULIAN_DAY 0 /* Jn - Julian day */
1706 #define DAY_OF_YEAR 1 /* n - day of year */
1707 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
1708 
1709 #define EPOCH_YEAR 1970
1710 #define EPOCH_WDAY TM_THURSDAY
1711 
1712 
1713 #ifndef TZ_MAX_TIMES
1714 /*
1715 ** The TZ_MAX_TIMES value below is enough to handle a bit more than a
1716 ** year's worth of solar time (corrected daily to the nearest second) or
1717 ** 138 years of Pacific Presidential Election time
1718 ** (where there are three time zone transitions every fourth year).
1719 */
1720 #define TZ_MAX_TIMES 370
1721 #endif /* !defined TZ_MAX_TIMES */
1722 
1723 #ifndef TZDEFRULES
1724 #define TZDEFRULES "posixrules"
1725 #endif /* !defined TZDEFRULES */
1726 
1727 /*
1728 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
1729 ** We default to US rules as of 1999-08-17.
1730 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
1731 ** implementation dependent; for historical reasons, US rules are a
1732 ** common default.
1733 */
1734 #ifndef TZDEFRULESTRING
1735 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
1736 #endif /* !defined TZDEFDST */
1737 
1738 /* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
1739 #define is_digit(c) ((unsigned)(c) - '0' <= 9)
1740 
1741 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
1742 
1743 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
1744 
1745 
1746 
1747 /*
1748 ** INITIALIZE(x)
1749 */
1750 
1751 #ifndef GNUC_or_lint
1752 #ifdef lint
1753 #define GNUC_or_lint
1754 #endif /* defined lint */
1755 #ifndef lint
1756 #ifdef __GNUC__
1757 #define GNUC_or_lint
1758 #endif /* defined __GNUC__ */
1759 #endif /* !defined lint */
1760 #endif /* !defined GNUC_or_lint */
1761 #ifdef WIN32
1762 #define GNUC_or_lint
1763 #endif
1764 
1765 #ifndef INITIALIZE
1766 #ifdef GNUC_or_lint
1767 #define INITIALIZE(x) ((x) = 0)
1768 #endif /* defined GNUC_or_lint */
1769 #ifndef GNUC_or_lint
1770 #define INITIALIZE(x)
1771 #endif /* !defined GNUC_or_lint */
1772 #endif /* !defined INITIALIZE */
1773 
1774 
1775 #define TM_SUNDAY 0
1776 #define TM_MONDAY 1
1777 #define TM_TUESDAY 2
1778 #define TM_WEDNESDAY 3
1779 #define TM_THURSDAY 4
1780 #define TM_FRIDAY 5
1781 #define TM_SATURDAY 6
1782 
1783 #define TM_JANUARY 0
1784 #define TM_FEBRUARY 1
1785 #define TM_MARCH 2
1786 #define TM_APRIL 3
1787 #define TM_MAY 4
1788 #define TM_JUNE 5
1789 #define TM_JULY 6
1790 #define TM_AUGUST 7
1791 #define TM_SEPTEMBER 8
1792 #define TM_OCTOBER 9
1793 #define TM_NOVEMBER 10
1794 #define TM_DECEMBER 11
1795 
1796 #define TM_YEAR_BASE 1900
1797 
1798 #define EPOCH_YEAR 1970
1799 #define EPOCH_WDAY TM_THURSDAY
1800 
1801 
1802 /* **************************************************************************
1803 
1804  ************************************************************************** */
1805 
1806 static const char gmt[] = "GMT";
1807 
1808 #define CHARS_DEF BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), (2 * (MY_TZNAME_MAX + 1)))
1809 
1810 struct rule {
1811  int r_type; /* type of rule--see below */
1812  int r_day; /* day number of rule */
1813  int r_week; /* week number of rule */
1814  int r_mon; /* month number of rule */
1815  long r_time; /* transition time of rule */
1816 };
1817 
1818 struct ttinfo { /* time type information */
1819  long tt_gmtoff; /* UTC offset in seconds */
1820  int tt_isdst; /* used to set tm_isdst */
1821  int tt_abbrind; /* abbreviation list index */
1822  int tt_ttisstd; /* TRUE if transition is std time */
1823  int tt_ttisgmt; /* TRUE if transition is UTC */
1824 };
1825 
1826 struct lsinfo { /* leap second information */
1827  time_t ls_trans; /* transition time */
1828  long ls_corr; /* correction to apply */
1829 };
1830 
1831 
1832 struct state {
1833  int leapcnt;
1834  int timecnt;
1835  int typecnt;
1836  int charcnt;
1837  time_t ats[TZ_MAX_TIMES];
1838  unsigned char types[TZ_MAX_TIMES];
1839  struct ttinfo ttis[TZ_MAX_TYPES];
1840  char chars[ /* LINTED constant */ CHARS_DEF];
1841  struct lsinfo lsis[TZ_MAX_LEAPS];
1842 };
1843 
1844 
1845 static const int mon_lengths[2][MONSPERYEAR] = {
1846  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
1847  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
1848 };
1849 
1850 static const int year_lengths[2] = {
1852 };
1853 
1854 
1855 /* **************************************************************************
1856 
1857  ************************************************************************** */
1858 
1859 
1860 /*
1861  Given a pointer into a time zone string, scan until a character that is not
1862  a valid character in a zone name is found. Return a pointer to that
1863  character.
1864 */
1865 
1866 static const char *getzname(register const char *strp)
1867 {
1868  register char c;
1869 
1870  while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && c != '+')
1871  ++strp;
1872  return strp;
1873 }
1874 
1875 
1876 /*
1877  Given a pointer into a time zone string, extract a number from that string.
1878  Check that the number is within a specified range; if it is not, return
1879  NULL.
1880  Otherwise, return a pointer to the first character not part of the number.
1881 */
1882 
1883 static const char *getnum(register const char *strp, int *const nump, const int min, const int max)
1884 {
1885  register char c;
1886  register int num;
1887 
1888  if (strp == NULL || !is_digit(c = *strp))
1889  return NULL;
1890  num = 0;
1891  do {
1892  num = num * 10 + (c - '0');
1893  if (num > max)
1894  return NULL; /* illegal value */
1895  c = *++strp;
1896  } while (is_digit(c));
1897  if (num < min)
1898  return NULL; /* illegal value */
1899  *nump = num;
1900  return strp;
1901 }
1902 
1903 /*
1904  Given a pointer into a time zone string, extract a number of seconds,
1905  in hh[:mm[:ss]] form, from the string.
1906  If any error occurs, return NULL.
1907  Otherwise, return a pointer to the first character not part of the number
1908  of seconds.
1909 */
1910 
1911 static const char *getsecs(register const char *strp, long *const secsp)
1912 {
1913  int num;
1914 
1915  /*
1916  ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
1917  ** "M10.4.6/26", which does not conform to Posix,
1918  ** but which specifies the equivalent of
1919  ** ``02:00 on the first Sunday on or after 23 Oct''.
1920  */
1921  strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
1922  if (strp == NULL)
1923  return NULL;
1924  *secsp = num * (long) SECSPERHOUR;
1925  if (*strp == ':') {
1926  ++strp;
1927  strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
1928  if (strp == NULL)
1929  return NULL;
1930  *secsp += num * SECSPERMIN;
1931  if (*strp == ':') {
1932  ++strp;
1933  /* `SECSPERMIN' allows for leap seconds. */
1934  strp = getnum(strp, &num, 0, SECSPERMIN);
1935  if (strp == NULL)
1936  return NULL;
1937  *secsp += num;
1938  }
1939  }
1940  return strp;
1941 }
1942 
1943 /*
1944  Given a pointer into a time zone string, extract an offset, in
1945  [+-]hh[:mm[:ss]] form, from the string.
1946  If any error occurs, return NULL.
1947  Otherwise, return a pointer to the first character not part of the time.
1948 */
1949 
1950 static const char *getoffset(register const char *strp, long *const offsetp)
1951 {
1952  register int neg = 0;
1953 
1954  if (*strp == '-') {
1955  neg = 1;
1956  ++strp;
1957  } else if (*strp == '+')
1958  ++strp;
1959  strp = getsecs(strp, offsetp);
1960  if (strp == NULL)
1961  return NULL; /* illegal time */
1962  if (neg)
1963  *offsetp = -*offsetp;
1964  return strp;
1965 }
1966 
1967 /*
1968  Given a pointer into a time zone string, extract a rule in the form
1969  date[/time]. See POSIX section 8 for the format of "date" and "time".
1970  If a valid rule is not found, return NULL.
1971  Otherwise, return a pointer to the first character not part of the rule.
1972 */
1973 
1974 static const char *getrule(const char *strp, register struct rule *const rulep)
1975 {
1976  if (*strp == 'J') {
1977  /*
1978  ** Julian day.
1979  */
1980  rulep->r_type = JULIAN_DAY;
1981  ++strp;
1982  strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
1983  } else if (*strp == 'M') {
1984  /*
1985  ** Month, week, day.
1986  */
1987  rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
1988  ++strp;
1989  strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
1990  if (strp == NULL)
1991  return NULL;
1992  if (*strp++ != '.')
1993  return NULL;
1994  strp = getnum(strp, &rulep->r_week, 1, 5);
1995  if (strp == NULL)
1996  return NULL;
1997  if (*strp++ != '.')
1998  return NULL;
1999  strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
2000  } else if (is_digit(*strp)) {
2001  /*
2002  ** Day of year.
2003  */
2004  rulep->r_type = DAY_OF_YEAR;
2005  strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
2006  } else
2007  return NULL; /* invalid format */
2008  if (strp == NULL)
2009  return NULL;
2010  if (*strp == '/') {
2011  /*
2012  ** Time specified.
2013  */
2014  ++strp;
2015  strp = getsecs(strp, &rulep->r_time);
2016  } else
2017  rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
2018  return strp;
2019 }
2020 
2021 
2022 /*
2023  Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
2024  year, a rule, and the offset from UTC at the time that rule takes effect,
2025  calculate the Epoch-relative time that rule takes effect.
2026 */
2027 
2028 static time_t transtime(const time_t janfirst, const int year, register const struct rule *const rulep, const long offset)
2029 {
2030  register int leapyear;
2031  register time_t value;
2032  register int i;
2033  int d, m1, yy0, yy1, yy2, dow;
2034 
2035  INITIALIZE(value);
2036  leapyear = isleap(year);
2037  switch (rulep->r_type) {
2038 
2039  case JULIAN_DAY:
2040  /*
2041  ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
2042  ** years.
2043  ** In non-leap years, or if the day number is 59 or less, just
2044  ** add SECSPERDAY times the day number-1 to the time of
2045  ** January 1, midnight, to get the day.
2046  */
2047  value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
2048  if (leapyear && rulep->r_day >= 60)
2049  value += SECSPERDAY;
2050  break;
2051 
2052  case DAY_OF_YEAR:
2053  /*
2054  ** n - day of year.
2055  ** Just add SECSPERDAY times the day number to the time of
2056  ** January 1, midnight, to get the day.
2057  */
2058  value = janfirst + rulep->r_day * SECSPERDAY;
2059  break;
2060 
2061  case MONTH_NTH_DAY_OF_WEEK:
2062  /*
2063  ** Mm.n.d - nth "dth day" of month m.
2064  */
2065  value = janfirst;
2066  for (i = 0; i < rulep->r_mon - 1; ++i)
2067  value += mon_lengths[leapyear][i] * SECSPERDAY;
2068 
2069  /*
2070  ** Use Zeller's Congruence to get day-of-week of first day of
2071  ** month.
2072  */
2073  m1 = (rulep->r_mon + 9) % 12 + 1;
2074  yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
2075  yy1 = yy0 / 100;
2076  yy2 = yy0 % 100;
2077  dow = ((26 * m1 - 2) / 10 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
2078  if (dow < 0)
2079  dow += DAYSPERWEEK;
2080 
2081  /*
2082  ** "dow" is the day-of-week of the first day of the month. Get
2083  ** the day-of-month (zero-origin) of the first "dow" day of the
2084  ** month.
2085  */
2086  d = rulep->r_day - dow;
2087  if (d < 0)
2088  d += DAYSPERWEEK;
2089  for (i = 1; i < rulep->r_week; ++i) {
2090  if (d + DAYSPERWEEK >= mon_lengths[leapyear][rulep->r_mon - 1])
2091  break;
2092  d += DAYSPERWEEK;
2093  }
2094 
2095  /*
2096  ** "d" is the day-of-month (zero-origin) of the day we want.
2097  */
2098  value += d * SECSPERDAY;
2099  break;
2100  }
2101 
2102  /*
2103  ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
2104  ** question. To get the Epoch-relative time of the specified local
2105  ** time on that day, add the transition time and the current offset
2106  ** from UTC.
2107  */
2108  return value + rulep->r_time + offset;
2109 }
2110 
2111 
2112 
2113 /*
2114  Given a POSIX section 8-style TZ string, fill in the rule tables as
2115  appropriate.
2116 */
2117 
2118 static int tzparse(const char *name, register struct state *const sp, const int lastditch)
2119 {
2120  const char *stdname;
2121  const char *dstname;
2122  size_t stdlen;
2123  size_t dstlen;
2124  long stdoffset;
2125  long dstoffset;
2126  register time_t *atp;
2127  register unsigned char *typep;
2128  register char *cp;
2129 
2130 
2131  INITIALIZE(dstname);
2132  stdname = name;
2133 
2134  if (lastditch) {
2135  stdlen = strlen(name); /* length of standard zone name */
2136  name += stdlen;
2137  if (stdlen >= sizeof sp->chars)
2138  stdlen = (sizeof sp->chars) - 1;
2139  stdoffset = 0;
2140  } else {
2141  name = getzname(name);
2142  stdlen = name - stdname;
2143  if (stdlen < 3)
2144  return -1;
2145  if (*name == '\0')
2146  return -1;
2147  name = getoffset(name, &stdoffset);
2148  if (name == NULL)
2149  return -1;
2150  }
2151 
2152  sp->leapcnt = 0; /* so, we're off a little */
2153 
2154  if (*name != '\0') {
2155  dstname = name;
2156  name = getzname(name);
2157  dstlen = name - dstname; /* length of DST zone name */
2158  if (dstlen < 3)
2159  return -1;
2160  if (*name != '\0' && *name != ',' && *name != ';') {
2161  name = getoffset(name, &dstoffset);
2162  if (name == NULL)
2163  return -1;
2164  } else
2165  dstoffset = stdoffset - SECSPERHOUR;
2166 
2167  /* Go parsing the daylight saving stuff */
2168  if (*name == ',' || *name == ';') {
2169  struct rule start;
2170  struct rule end;
2171  register int year;
2172  register time_t janfirst;
2173  time_t starttime;
2174  time_t endtime;
2175 
2176  ++name;
2177  if ((name = getrule(name, &start)) == NULL)
2178  return -1;
2179  if (*name++ != ',')
2180  return -1;
2181  if ((name = getrule(name, &end)) == NULL)
2182  return -1;
2183  if (*name != '\0')
2184  return -1;
2185 
2186  sp->typecnt = 2; /* standard time and DST */
2187 
2188  /*
2189  ** Two transitions per year, from EPOCH_YEAR to 2037.
2190  */
2191  sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
2192 
2193  if (sp->timecnt > TZ_MAX_TIMES)
2194  return -1;
2195 
2196  sp->ttis[0].tt_gmtoff = -dstoffset;
2197  sp->ttis[0].tt_isdst = 1;
2198  sp->ttis[0].tt_abbrind = (int) (stdlen + 1);
2199  sp->ttis[1].tt_gmtoff = -stdoffset;
2200  sp->ttis[1].tt_isdst = 0;
2201  sp->ttis[1].tt_abbrind = 0;
2202 
2203  atp = sp->ats;
2204  typep = sp->types;
2205  janfirst = 0;
2206 
2207  for (year = EPOCH_YEAR; year <= 2037; ++year) {
2208  starttime = transtime(janfirst, year, &start, stdoffset);
2209  endtime = transtime(janfirst, year, &end, dstoffset);
2210  if (starttime > endtime) {
2211  *atp++ = endtime;
2212  *typep++ = 1; /* DST ends */
2213  *atp++ = starttime;
2214  *typep++ = 0; /* DST begins */
2215  } else {
2216  *atp++ = starttime;
2217  *typep++ = 0; /* DST begins */
2218  *atp++ = endtime;
2219  *typep++ = 1; /* DST ends */
2220  }
2221 
2222  janfirst += year_lengths[isleap(year)] * SECSPERDAY;
2223  }
2224 
2225  } else {
2226  register long theirstdoffset;
2227  register long theirdstoffset;
2228  register long theiroffset;
2229  register int isdst;
2230  register int i;
2231  register int j;
2232 
2233  if (*name != '\0')
2234  return -1;
2235  /*
2236  Initial values of theirstdoffset and theirdstoffset.
2237  */
2238  theirstdoffset = 0;
2239  for (i = 0; i < sp->timecnt; ++i) {
2240  j = sp->types[i];
2241  if (!sp->ttis[j].tt_isdst) {
2242  theirstdoffset = -sp->ttis[j].tt_gmtoff;
2243  break;
2244  }
2245  }
2246  theirdstoffset = 0;
2247  for (i = 0; i < sp->timecnt; ++i) {
2248  j = sp->types[i];
2249  if (sp->ttis[j].tt_isdst) {
2250  theirdstoffset = -sp->ttis[j].tt_gmtoff;
2251  break;
2252  }
2253  }
2254  /*
2255  ** Initially we're assumed to be in standard time.
2256  */
2257  isdst = FALSE;
2258  /*
2259  ** Now juggle transition times and types
2260  ** tracking offsets as you do.
2261  */
2262  for (i = 0; i < sp->timecnt; ++i) {
2263  j = sp->types[i];
2264  sp->types[i] = (unsigned char) sp->ttis[j].tt_isdst;
2265  if (sp->ttis[j].tt_ttisgmt) {
2266  /* No adjustment to transition time */
2267  } else {
2268  /*
2269  ** If summer time is in effect, and the
2270  ** transition time was not specified as
2271  ** standard time, add the summer time
2272  ** offset to the transition time;
2273  ** otherwise, add the standard time
2274  ** offset to the transition time.
2275  */
2276  /*
2277  ** Transitions from DST to DDST
2278  ** will effectively disappear since
2279  ** POSIX provides for only one DST
2280  ** offset.
2281  */
2282  if (isdst && !sp->ttis[j].tt_ttisstd) {
2283  sp->ats[i] += dstoffset - theirdstoffset;
2284  } else {
2285  sp->ats[i] += stdoffset - theirstdoffset;
2286  }
2287  }
2288  theiroffset = -sp->ttis[j].tt_gmtoff;
2289  if (sp->ttis[j].tt_isdst)
2290  theirdstoffset = theiroffset;
2291  else
2292  theirstdoffset = theiroffset;
2293  }
2294  /*
2295  ** Finally, fill in ttis.
2296  ** ttisstd and ttisgmt need not be handled.
2297  */
2298  sp->ttis[0].tt_gmtoff = -stdoffset;
2299  sp->ttis[0].tt_isdst = FALSE;
2300  sp->ttis[0].tt_abbrind = 0;
2301  sp->ttis[1].tt_gmtoff = -dstoffset;
2302  sp->ttis[1].tt_isdst = TRUE;
2303  sp->ttis[1].tt_abbrind = (int) (stdlen + 1);
2304  sp->typecnt = 2;
2305  }
2306  } else {
2307  dstlen = 0;
2308  sp->typecnt = 1; /* only standard time */
2309  sp->timecnt = 0;
2310  sp->ttis[0].tt_gmtoff = -stdoffset;
2311  sp->ttis[0].tt_isdst = 0;
2312  sp->ttis[0].tt_abbrind = 0;
2313  }
2314 
2315  sp->charcnt = (int) (stdlen + 1);
2316  if (dstlen != 0)
2317  sp->charcnt += (int) (dstlen + 1);
2318  if ((size_t) sp->charcnt > sizeof sp->chars)
2319  return -1;
2320  cp = sp->chars;
2321  (void) strncpy(cp, stdname, stdlen);
2322  cp += stdlen;
2323  *cp++ = '\0';
2324  if (dstlen != 0) {
2325  (void) strncpy(cp, dstname, dstlen);
2326  *(cp + dstlen) = '\0';
2327  }
2328  return 0;
2329 }
2330 
2331 /* **************************************************************************
2332 
2333  ************************************************************************** */
2334 #if (_MSC_VER >= 1400) // VC8+
2335 #define switch_assert(expr) assert(expr);__analysis_assume( expr )
2336 #else
2337 #define switch_assert(expr) assert(expr)
2338 #endif
2339 
2340 static void timesub(const time_t *const timep, const long offset, register const struct state *const sp, register struct tm *const tmp)
2341 {
2342  register const struct lsinfo *lp;
2343  register long days;
2344  register time_t rem;
2345  register int y;
2346  register int yleap;
2347  register const int *ip;
2348  register long corr;
2349  register int hit;
2350  register int i;
2351 
2352  switch_assert(timep != NULL);
2353  switch_assert(sp != NULL);
2354  switch_assert(tmp != NULL);
2355 
2356  corr = 0;
2357  hit = 0;
2358  i = (sp == NULL) ? 0 : sp->leapcnt;
2359 
2360  while (--i >= 0) {
2361  lp = &sp->lsis[i];
2362  if (*timep >= lp->ls_trans) {
2363  if (*timep == lp->ls_trans) {
2364  hit = ((i == 0 && lp->ls_corr > 0) || (i > 0 && lp->ls_corr > sp->lsis[i - 1].ls_corr));
2365  if (hit)
2366  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) {
2367  ++hit;
2368  --i;
2369  }
2370  }
2371  corr = lp->ls_corr;
2372  break;
2373  }
2374  }
2375  days = (long) (*timep / SECSPERDAY);
2376  rem = *timep % SECSPERDAY;
2377 
2378 
2379 #ifdef mc68k
2380  /* If this is for CPU bugs workarounds, i would remove this anyway. Who would use it on an old mc68k ? */
2381  if (*timep == 0x80000000) {
2382  /*
2383  ** A 3B1 muffs the division on the most negative number.
2384  */
2385  days = -24855;
2386  rem = -11648;
2387  }
2388 #endif
2389 
2390  rem += (offset - corr);
2391  while (rem < 0) {
2392  rem += SECSPERDAY;
2393  --days;
2394  }
2395  while (rem >= SECSPERDAY) {
2396  rem -= SECSPERDAY;
2397  ++days;
2398  }
2399  tmp->tm_hour = (int) (rem / SECSPERHOUR);
2400  rem = rem % SECSPERHOUR;
2401  tmp->tm_min = (int) (rem / SECSPERMIN);
2402 
2403  /*
2404  ** A positive leap second requires a special
2405  ** representation. This uses "... ??:59:60" et seq.
2406  */
2407  tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
2408  tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
2409 
2410  if (tmp->tm_wday < 0)
2411  tmp->tm_wday += DAYSPERWEEK;
2412 
2413  y = EPOCH_YEAR;
2414 
2415 #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
2416 
2417  while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
2418  register int newy;
2419 
2420  newy = (int) (y + days / DAYSPERNYEAR);
2421  if (days < 0)
2422  --newy;
2423  days -= (newy - y) * DAYSPERNYEAR + LEAPS_THRU_END_OF(newy - 1) - LEAPS_THRU_END_OF(y - 1);
2424  y = newy;
2425  }
2426 
2427  tmp->tm_year = y - TM_YEAR_BASE;
2428  tmp->tm_yday = (int) days;
2429 
2430  ip = mon_lengths[yleap];
2431 
2432  for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
2433  days = days - (long) ip[tmp->tm_mon];
2434 
2435  tmp->tm_mday = (int) (days + 1);
2436  tmp->tm_isdst = 0;
2437 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
2438  tmp->tm_gmtoff = offset;
2439 #endif
2440 }
2441 
2442 /* **************************************************************************
2443 
2444  ************************************************************************** */
2445 
2446 static void tztime(const time_t *const timep, const char *tzstring, struct tm *const tmp)
2447 {
2448  struct state *tzptr, *sp;
2449  const time_t t = *timep;
2450  register int i;
2451  register const struct ttinfo *ttisp;
2452 
2453  if (tzstring == NULL)
2454  tzstring = gmt;
2455 
2456  tzptr = (struct state *) malloc(sizeof(struct state));
2457  sp = tzptr;
2458 
2459  if (tzptr != NULL) {
2460 
2461  memset(tzptr, 0, sizeof(struct state));
2462 
2463  (void) tzparse(tzstring, tzptr, FALSE);
2464 
2465  if (sp->timecnt == 0 || t < sp->ats[0]) {
2466  i = 0;
2467  while (sp->ttis[i].tt_isdst)
2468  if (++i >= sp->typecnt) {
2469  i = 0;
2470  break;
2471  }
2472  } else {
2473  for (i = 1; i < sp->timecnt; ++i)
2474  if (t < sp->ats[i])
2475  break;
2476  i = sp->types[i - 1]; // DST begin or DST end
2477  }
2478  ttisp = &sp->ttis[i];
2479 
2480  /*
2481  To get (wrong) behavior that's compatible with System V Release 2.0
2482  you'd replace the statement below with
2483  t += ttisp->tt_gmtoff;
2484  timesub(&t, 0L, sp, tmp);
2485  */
2486  if (tmp != NULL) { /* Just a check not to assert */
2487  timesub(&t, ttisp->tt_gmtoff, sp, tmp);
2488  tmp->tm_isdst = ttisp->tt_isdst;
2489 #if defined(HAVE_STRUCT_TM_TM_ZONE)
2490  tmp->tm_zone = &sp->chars[ttisp->tt_abbrind];
2491 #endif
2492  }
2493 
2494  free(tzptr);
2495  }
2496 
2497 }
2498 
2499 /* For Emacs:
2500  * Local Variables:
2501  * mode:c
2502  * indent-tabs-mode:t
2503  * tab-width:4
2504  * c-basic-offset:4
2505  * End:
2506  * For VIM:
2507  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
2508  */
#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:1705
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:1822
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:1815
#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:1950
time_t ats[TZ_MAX_TIMES]
Definition: switch_time.c:1837
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:1697
int charcnt
Definition: switch_time.c:1836
#define SECSPERMIN
Definition: switch_time.c:1695
switch_bool_t
Definition: switch_types.h:437
#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:1806
int leapcnt
Definition: switch_time.c:1833
#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:1658
#define TZ_MAX_TYPES
Definition: switch_time.c:1664
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:1583
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:1850
Abstract handler to a timer module.
int r_mon
Definition: switch_time.c:1814
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:1799
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:1813
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:1511
struct lsinfo lsis[TZ_MAX_LEAPS]
Definition: switch_time.c:1841
#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:2340
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:2028
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:1696
static int tzparse(const char *name, register struct state *const sp, const int lastditch)
Definition: switch_time.c:2118
#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:1475
uintptr_t switch_size_t
static const int mon_lengths[2][MONSPERYEAR]
Definition: switch_time.c:1845
int r_day
Definition: switch_time.c:1812
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:1642
int r_type
Definition: switch_time.c:1811
static int COND
Definition: switch_time.c:87
long ls_corr
Definition: switch_time.c:1828
static void tztime(const time_t *const timep, const char *tzstring, struct tm *const tmp)
Definition: switch_time.c:2446
#define INITIALIZE(x)
Definition: switch_time.c:1770
void switch_delete_profile_timer(switch_profile_timer_t **p)
Deletes profile timer.
long tt_gmtoff
Definition: switch_time.c:1819
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:1839
unsigned char types[TZ_MAX_TIMES]
Definition: switch_time.c:1838
struct fspr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
#define switch_assert(expr)
Definition: switch_time.c:2337
#define isleap(y)
Definition: switch_time.c:1743
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:1394
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:1739
static const char * getzname(register const char *strp)
Definition: switch_time.c:1866
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:1683
#define switch_core_hash_insert(_h, _k, _d)
Definition: switch_core.h:1479
#define SECSPERHOUR
Definition: switch_time.c:1701
int timecnt
Definition: switch_time.c:1834
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:1911
struct switch_session_manager session_manager
#define SECSPERDAY
Definition: switch_time.c:1702
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:1698
#define MONTH_NTH_DAY_OF_WEEK
Definition: switch_time.c:1707
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:1883
void switch_time_set_use_system_time(switch_bool_t enable)
Definition: switch_time.c:342
#define TM_YEAR_BASE
Definition: switch_time.c:1796
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:1808
uint64_t tick
Definition: switch_time.c:129
#define MONSPERYEAR
Definition: switch_time.c:1703
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
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:1840
int tt_abbrind
Definition: switch_time.c:1821
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:1798
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:1827
static void event_handler(switch_event_t *event)
Definition: switch_time.c:1436
switch_status_t switch_time_exp_tz_name(const char *tz, switch_time_exp_t *tm, switch_time_t thetime)
Definition: switch_time.c:1445
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:1820
switch_mutex_t * mutex
Definition: switch_time.c:106
int typecnt
Definition: switch_time.c:1835
int tt_ttisgmt
Definition: switch_time.c:1823
struct fspr_thread_rwlock_t switch_thread_rwlock_t
Definition: switch_apr.h:436
#define FALSE
Definition: switch_time.c:1646
#define DAYSPERNYEAR
Definition: switch_time.c:1699
#define DAYSPERLYEAR
Definition: switch_time.c:1700
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:1706
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:1974
switch_status_t switch_event_unbind(switch_event_node_t **node)
Unbind a bound event consumer.