#include <switch.h>#include <stdio.h>#include "private/switch_core_pvt.h"#include <stdlib.h>#include <time.h>#include <string.h>#include <assert.h>Include dependency graph for switch_time.c:
Go to the source code of this file.
Data Structures | |
| struct | timer_private |
| struct | timer_matrix |
| struct | switch_timezones_list_t |
| struct | rule |
| struct | ttinfo |
| struct | lsinfo |
| struct | state |
Defines | |
| #define | DISABLE_1MS_COND |
| #define | UINT32_MAX 0xffffffff |
| #define | MAX_TICK UINT32_MAX - 1024 |
| #define | MAX_ELEMENTS 3600 |
| #define | IDLE_SPEED 100 |
| #define | calc_step() if (step > 11) step -= 10; else if (step > 1) step-- |
| #define | check_roll() |
| #define | TRUE 1 |
| #define | FALSE 0 |
| #define | TZ_MAX_TIMES 370 |
| #define | TZ_MAX_TYPES 256 |
| #define | TZ_MAX_CHARS 50 |
| #define | TZ_MAX_LEAPS 50 |
| #define | MY_TZNAME_MAX 255 |
| #define | SECSPERMIN 60 |
| #define | MINSPERHOUR 60 |
| #define | HOURSPERDAY 24 |
| #define | DAYSPERWEEK 7 |
| #define | DAYSPERNYEAR 365 |
| #define | DAYSPERLYEAR 366 |
| #define | SECSPERHOUR (SECSPERMIN * MINSPERHOUR) |
| #define | SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) |
| #define | MONSPERYEAR 12 |
| #define | JULIAN_DAY 0 |
| #define | DAY_OF_YEAR 1 |
| #define | MONTH_NTH_DAY_OF_WEEK 2 |
| #define | EPOCH_YEAR 1970 |
| #define | EPOCH_WDAY TM_THURSDAY |
| #define | TZDEFRULES "posixrules" |
| #define | TZDEFRULESTRING ",M4.1.0,M10.5.0" |
| #define | is_digit(c) ((unsigned)(c) - '0' <= 9) |
| #define | BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) |
| #define | isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) |
| #define | INITIALIZE(x) |
| #define | TM_SUNDAY 0 |
| #define | TM_MONDAY 1 |
| #define | TM_TUESDAY 2 |
| #define | TM_WEDNESDAY 3 |
| #define | TM_THURSDAY 4 |
| #define | TM_FRIDAY 5 |
| #define | TM_SATURDAY 6 |
| #define | TM_JANUARY 0 |
| #define | TM_FEBRUARY 1 |
| #define | TM_MARCH 2 |
| #define | TM_APRIL 3 |
| #define | TM_MAY 4 |
| #define | TM_JUNE 5 |
| #define | TM_JULY 6 |
| #define | TM_AUGUST 7 |
| #define | TM_SEPTEMBER 8 |
| #define | TM_OCTOBER 9 |
| #define | TM_NOVEMBER 10 |
| #define | TM_DECEMBER 11 |
| #define | TM_YEAR_BASE 1900 |
| #define | EPOCH_YEAR 1970 |
| #define | EPOCH_WDAY TM_THURSDAY |
| #define | CHARS_DEF BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), (2 * (MY_TZNAME_MAX + 1))) |
| #define | switch_assert(expr) assert(expr) |
| #define | LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) |
Typedefs | |
| typedef timer_private | timer_private_t |
| typedef timer_matrix | timer_matrix_t |
Functions | |
| SWITCH_MODULE_LOAD_FUNCTION (softtimer_load) | |
| SWITCH_MODULE_SHUTDOWN_FUNCTION (softtimer_shutdown) | |
| SWITCH_MODULE_RUNTIME_FUNCTION (softtimer_runtime) | |
| SWITCH_MODULE_DEFINITION (CORE_SOFTTIMER_MODULE, softtimer_load, softtimer_shutdown, softtimer_runtime) | |
| void | switch_os_yield (void) |
| static void | do_sleep (switch_interval_time_t t) |
| static switch_interval_time_t | average_time (switch_interval_time_t t, int reps) |
| void | switch_time_calibrate_clock (void) |
| switch_time_t | switch_micro_time_now (void) |
| Get the current epoch time in microseconds. | |
| time_t | switch_epoch_time_now (time_t *t) |
| Get the current epoch time. | |
| void | switch_time_set_monotonic (switch_bool_t enable) |
| void | switch_time_set_timerfd (switch_bool_t enable) |
| void | switch_time_set_matrix (switch_bool_t enable) |
| void | switch_time_set_nanosleep (switch_bool_t enable) |
| void | switch_time_set_cond_yield (switch_bool_t enable) |
| static switch_time_t | time_now (int64_t offset) |
| switch_time_t | switch_time_ref (void) |
| void | switch_time_sync (void) |
| void | switch_micro_sleep (switch_interval_time_t t) |
| void | switch_sleep (switch_interval_time_t t) |
| void | switch_cond_next (void) |
| void | switch_cond_yield (switch_interval_time_t t) |
| static switch_status_t | timer_init (switch_timer_t *timer) |
| static switch_status_t | timer_step (switch_timer_t *timer) |
| static switch_status_t | timer_sync (switch_timer_t *timer) |
| static switch_status_t | timer_next (switch_timer_t *timer) |
| static switch_status_t | timer_check (switch_timer_t *timer, switch_bool_t step) |
| static switch_status_t | timer_destroy (switch_timer_t *timer) |
| static void | win32_init_timers (void) |
| static void | tm2switchtime (struct tm *tm, switch_time_exp_t *xt) |
| const char * | switch_lookup_timezone (const char *tz_name) |
| void | switch_load_timezones (switch_bool_t reload) |
| static void | event_handler (switch_event_t *event) |
| static void | tztime (const time_t *const timep, const char *tzstring, struct tm *const tmp) |
| switch_status_t | switch_time_exp_tz_name (const char *tz, switch_time_exp_t *tm, switch_time_t thetime) |
| switch_status_t | switch_strftime_tz (const char *tz, const char *format, char *date, size_t len, switch_time_t thetime) |
| static const char * | getzname (register const char *strp) |
| static const char * | getnum (register const char *strp, int *const nump, const int min, const int max) |
| static const char * | getsecs (register const char *strp, long *const secsp) |
| static const char * | getoffset (register const char *strp, long *const offsetp) |
| static const char * | getrule (const char *strp, register struct rule *const rulep) |
| static time_t | transtime (const time_t janfirst, const int year, register const struct rule *const rulep, const long offset) |
| static int | tzparse (const char *name, register struct state *const sp, const int lastditch) |
| static void | timesub (const time_t *const timep, const long offset, register const struct state *const sp, register struct tm *const tmp) |
Variables | |
| static int | MONO = 0 |
| static int | TFD = 0 |
| static int | NANO = 0 |
| static int | OFFSET = 0 |
| static int | COND = 1 |
| static int | MATRIX = 1 |
| static switch_memory_pool_t * | module_pool = NULL |
| struct { | |
| int32_t RUNNING | |
| int32_t STARTED | |
| int32_t use_cond_yield | |
| switch_mutex_t * mutex | |
| uint32_t timer_count | |
| } | globals |
| static timer_matrix_t | TIMER_MATRIX [MAX_ELEMENTS+1] |
| static switch_time_t | last_time = 0 |
| static switch_timezones_list_t | TIMEZONES_LIST = { 0 } |
| static switch_event_node_t * | NODE = NULL |
| static const char | gmt [] = "GMT" |
| static const int | mon_lengths [2][MONSPERYEAR] |
| static const int | year_lengths [2] |
| #define BIGGEST | ( | a, | |||
| b | ) | (((a) > (b)) ? (a) : (b)) |
Definition at line 1431 of file switch_time.c.
| #define calc_step | ( | ) | if (step > 11) step -= 10; else if (step > 1) step-- |
| #define CHARS_DEF BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), (2 * (MY_TZNAME_MAX + 1))) |
Definition at line 1498 of file switch_time.c.
| #define check_roll | ( | ) |
Value:
if (private_info->roll < TIMER_MATRIX[timer->interval].roll) { \ private_info->roll++; \ private_info->reference = private_info->start = TIMER_MATRIX[timer->interval].tick; \ private_info->start--; /* Must have a diff */ \ } \
Definition at line 562 of file switch_time.c.
Referenced by timer_check(), timer_next(), and timer_step().
| #define DAY_OF_YEAR 1 |
| #define DAYSPERLYEAR 366 |
| #define DAYSPERNYEAR 365 |
| #define DAYSPERWEEK 7 |
Definition at line 1388 of file switch_time.c.
Referenced by getrule(), getsecs(), timesub(), and transtime().
| #define DISABLE_1MS_COND |
Definition at line 50 of file switch_time.c.
| #define EPOCH_WDAY TM_THURSDAY |
Definition at line 1489 of file switch_time.c.
| #define EPOCH_WDAY TM_THURSDAY |
| #define EPOCH_YEAR 1970 |
Definition at line 1488 of file switch_time.c.
| #define EPOCH_YEAR 1970 |
| #define FALSE 0 |
Definition at line 1336 of file switch_time.c.
| #define HOURSPERDAY 24 |
| #define IDLE_SPEED 100 |
Definition at line 60 of file switch_time.c.
| #define INITIALIZE | ( | x | ) |
| #define is_digit | ( | c | ) | ((unsigned)(c) - '0' <= 9) |
| #define isleap | ( | y | ) | (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) |
| #define JULIAN_DAY 0 |
| #define LEAPS_THRU_END_OF | ( | y | ) | ((y) / 4 - (y) / 100 + (y) / 400) |
Referenced by timesub().
| #define MAX_ELEMENTS 3600 |
Definition at line 59 of file switch_time.c.
Referenced by SWITCH_MODULE_RUNTIME_FUNCTION(), and timer_destroy().
| #define MAX_TICK UINT32_MAX - 1024 |
| #define MINSPERHOUR 60 |
| #define MONSPERYEAR 12 |
| #define MONTH_NTH_DAY_OF_WEEK 2 |
| #define MY_TZNAME_MAX 255 |
Definition at line 1381 of file switch_time.c.
| #define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) |
| #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) |
| #define SECSPERMIN 60 |
| #define switch_assert | ( | expr | ) | assert(expr) |
Definition at line 2028 of file switch_time.c.
| #define TM_APRIL 3 |
Definition at line 1476 of file switch_time.c.
| #define TM_AUGUST 7 |
Definition at line 1480 of file switch_time.c.
| #define TM_DECEMBER 11 |
Definition at line 1484 of file switch_time.c.
| #define TM_FEBRUARY 1 |
Definition at line 1474 of file switch_time.c.
| #define TM_FRIDAY 5 |
Definition at line 1470 of file switch_time.c.
| #define TM_JANUARY 0 |
Definition at line 1473 of file switch_time.c.
| #define TM_JULY 6 |
Definition at line 1479 of file switch_time.c.
| #define TM_JUNE 5 |
Definition at line 1478 of file switch_time.c.
| #define TM_MARCH 2 |
Definition at line 1475 of file switch_time.c.
| #define TM_MAY 4 |
Definition at line 1477 of file switch_time.c.
| #define TM_MONDAY 1 |
Definition at line 1466 of file switch_time.c.
| #define TM_NOVEMBER 10 |
Definition at line 1483 of file switch_time.c.
| #define TM_OCTOBER 9 |
Definition at line 1482 of file switch_time.c.
| #define TM_SATURDAY 6 |
Definition at line 1471 of file switch_time.c.
| #define TM_SEPTEMBER 8 |
Definition at line 1481 of file switch_time.c.
| #define TM_SUNDAY 0 |
Definition at line 1465 of file switch_time.c.
| #define TM_THURSDAY 4 |
Definition at line 1469 of file switch_time.c.
| #define TM_TUESDAY 2 |
Definition at line 1467 of file switch_time.c.
| #define TM_WEDNESDAY 3 |
Definition at line 1468 of file switch_time.c.
| #define TM_YEAR_BASE 1900 |
| #define TRUE 1 |
Definition at line 1332 of file switch_time.c.
| #define TZ_MAX_CHARS 50 |
Definition at line 1368 of file switch_time.c.
| #define TZ_MAX_LEAPS 50 |
Definition at line 1373 of file switch_time.c.
| #define TZ_MAX_TIMES 370 |
| #define TZ_MAX_TYPES 256 |
Definition at line 1354 of file switch_time.c.
| #define TZDEFRULES "posixrules" |
Definition at line 1414 of file switch_time.c.
| #define TZDEFRULESTRING ",M4.1.0,M10.5.0" |
Definition at line 1425 of file switch_time.c.
| #define UINT32_MAX 0xffffffff |
| typedef struct timer_matrix timer_matrix_t |
Definition at line 139 of file switch_time.c.
| typedef struct timer_private timer_private_t |
Definition at line 129 of file switch_time.c.
| static switch_interval_time_t average_time | ( | switch_interval_time_t | t, | |
| int | reps | |||
| ) | [static] |
Definition at line 191 of file switch_time.c.
References do_sleep(), and switch_time_ref().
Referenced by switch_time_calibrate_clock().
00192 { 00193 int x = 0; 00194 switch_time_t start, stop, sum = 0; 00195 00196 for (x = 0; x < reps; x++) { 00197 start = switch_time_ref(); 00198 do_sleep(t); 00199 stop = switch_time_ref(); 00200 sum += (stop - start); 00201 } 00202 00203 return sum / reps; 00204 00205 }
| static void do_sleep | ( | switch_interval_time_t | t | ) | [static] |
Definition at line 152 of file switch_time.c.
Referenced by average_time(), switch_cond_next(), switch_cond_yield(), switch_core_sql_thread(), switch_micro_sleep(), SWITCH_MODULE_RUNTIME_FUNCTION(), SWITCH_MODULE_SHUTDOWN_FUNCTION(), switch_sleep(), switch_time_calibrate_clock(), timer_init(), and timer_next().
00153 { 00154 #if defined(HAVE_CLOCK_NANOSLEEP) || defined(DARWIN) 00155 struct timespec ts; 00156 #endif 00157 00158 #if defined(WIN32) 00159 if (t < 1000) { 00160 t = 1000; 00161 } 00162 #endif 00163 00164 #if !defined(DARWIN) 00165 if (t > 100000 || !NANO) { 00166 apr_sleep(t); 00167 return; 00168 } 00169 #endif 00170 00171 #if defined(HAVE_CLOCK_NANOSLEEP) 00172 t -= OFFSET; 00173 ts.tv_sec = t / 1000000; 00174 ts.tv_nsec = ((t % 1000000) * 1000); 00175 clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); 00176 00177 #elif defined(DARWIN) 00178 ts.tv_sec = t / APR_USEC_PER_SEC; 00179 ts.tv_nsec = (t % APR_USEC_PER_SEC) * 1000; 00180 nanosleep(&ts, NULL); 00181 #else 00182 apr_sleep(t); 00183 #endif 00184 00185 #if defined(DARWIN) 00186 sched_yield(); 00187 #endif 00188 00189 }
| static void event_handler | ( | switch_event_t * | event | ) | [static] |
Definition at line 1126 of file switch_time.c.
References globals, switch_load_timezones(), switch_mutex_lock(), and switch_mutex_unlock().
01127 { 01128 switch_mutex_lock(globals.mutex); 01129 switch_load_timezones(1); 01130 switch_mutex_unlock(globals.mutex); 01131 }
| static const char* getnum | ( | register const char * | strp, | |
| int *const | nump, | |||
| const int | min, | |||
| const int | max | |||
| ) | [static] |
Definition at line 1573 of file switch_time.c.
References is_digit.
Referenced by getrule(), and getsecs().
01574 { 01575 register char c; 01576 register int num; 01577 01578 if (strp == NULL || !is_digit(c = *strp)) 01579 return NULL; 01580 num = 0; 01581 do { 01582 num = num * 10 + (c - '0'); 01583 if (num > max) 01584 return NULL; /* illegal value */ 01585 c = *++strp; 01586 } while (is_digit(c)); 01587 if (num < min) 01588 return NULL; /* illegal value */ 01589 *nump = num; 01590 return strp; 01591 }
| static const char* getoffset | ( | register const char * | strp, | |
| long *const | offsetp | |||
| ) | [static] |
Definition at line 1640 of file switch_time.c.
References getsecs().
Referenced by tzparse().
01641 { 01642 register int neg = 0; 01643 01644 if (*strp == '-') { 01645 neg = 1; 01646 ++strp; 01647 } else if (*strp == '+') 01648 ++strp; 01649 strp = getsecs(strp, offsetp); 01650 if (strp == NULL) 01651 return NULL; /* illegal time */ 01652 if (neg) 01653 *offsetp = -*offsetp; 01654 return strp; 01655 }
| static const char* getrule | ( | const char * | strp, | |
| register struct rule *const | rulep | |||
| ) | [static] |
Definition at line 1664 of file switch_time.c.
References DAY_OF_YEAR, DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, getnum(), getsecs(), is_digit, JULIAN_DAY, MONSPERYEAR, MONTH_NTH_DAY_OF_WEEK, and SECSPERHOUR.
Referenced by tzparse().
01665 { 01666 if (*strp == 'J') { 01667 /* 01668 ** Julian day. 01669 */ 01670 rulep->r_type = JULIAN_DAY; 01671 ++strp; 01672 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); 01673 } else if (*strp == 'M') { 01674 /* 01675 ** Month, week, day. 01676 */ 01677 rulep->r_type = MONTH_NTH_DAY_OF_WEEK; 01678 ++strp; 01679 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); 01680 if (strp == NULL) 01681 return NULL; 01682 if (*strp++ != '.') 01683 return NULL; 01684 strp = getnum(strp, &rulep->r_week, 1, 5); 01685 if (strp == NULL) 01686 return NULL; 01687 if (*strp++ != '.') 01688 return NULL; 01689 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); 01690 } else if (is_digit(*strp)) { 01691 /* 01692 ** Day of year. 01693 */ 01694 rulep->r_type = DAY_OF_YEAR; 01695 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); 01696 } else 01697 return NULL; /* invalid format */ 01698 if (strp == NULL) 01699 return NULL; 01700 if (*strp == '/') { 01701 /* 01702 ** Time specified. 01703 */ 01704 ++strp; 01705 strp = getsecs(strp, &rulep->r_time); 01706 } else 01707 rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ 01708 return strp; 01709 }
| static const char* getsecs | ( | register const char * | strp, | |
| long *const | secsp | |||
| ) | [static] |
Definition at line 1601 of file switch_time.c.
References DAYSPERWEEK, getnum(), HOURSPERDAY, MINSPERHOUR, SECSPERHOUR, and SECSPERMIN.
Referenced by getoffset(), and getrule().
01602 { 01603 int num; 01604 01605 /* 01606 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like 01607 ** "M10.4.6/26", which does not conform to Posix, 01608 ** but which specifies the equivalent of 01609 ** ``02:00 on the first Sunday on or after 23 Oct''. 01610 */ 01611 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); 01612 if (strp == NULL) 01613 return NULL; 01614 *secsp = num * (long) SECSPERHOUR; 01615 if (*strp == ':') { 01616 ++strp; 01617 strp = getnum(strp, &num, 0, MINSPERHOUR - 1); 01618 if (strp == NULL) 01619 return NULL; 01620 *secsp += num * SECSPERMIN; 01621 if (*strp == ':') { 01622 ++strp; 01623 /* `SECSPERMIN' allows for leap seconds. */ 01624 strp = getnum(strp, &num, 0, SECSPERMIN); 01625 if (strp == NULL) 01626 return NULL; 01627 *secsp += num; 01628 } 01629 } 01630 return strp; 01631 }
| static const char* getzname | ( | register const char * | strp | ) | [static] |
Definition at line 1556 of file switch_time.c.
References is_digit.
Referenced by tzparse().
01557 { 01558 register char c; 01559 01560 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && c != '+') 01561 ++strp; 01562 return strp; 01563 }
| void switch_load_timezones | ( | switch_bool_t | reload | ) |
Definition at line 1084 of file switch_time.c.
References switch_timezones_list_t::hash, switch_xml::next, switch_timezones_list_t::pool, SWITCH_CHANNEL_LOG, switch_core_destroy_memory_pool, switch_core_hash_destroy(), switch_core_hash_init, switch_core_hash_insert(), switch_core_new_memory_pool, switch_core_strdup, SWITCH_LOG_INFO, switch_log_printf(), switch_xml_attr(), switch_xml_child(), switch_xml_free(), switch_xml_open_cfg(), TIMEZONES_LIST, and zstr.
Referenced by event_handler(), and SWITCH_MODULE_LOAD_FUNCTION().
01085 { 01086 switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL; 01087 unsigned total = 0; 01088 01089 if (TIMEZONES_LIST.hash) { 01090 switch_core_hash_destroy(&TIMEZONES_LIST.hash); 01091 } 01092 01093 if (TIMEZONES_LIST.pool) { 01094 switch_core_destroy_memory_pool(&TIMEZONES_LIST.pool); 01095 } 01096 01097 memset(&TIMEZONES_LIST, 0, sizeof(TIMEZONES_LIST)); 01098 switch_core_new_memory_pool(&TIMEZONES_LIST.pool); 01099 switch_core_hash_init(&TIMEZONES_LIST.hash, TIMEZONES_LIST.pool); 01100 01101 if ((xml = switch_xml_open_cfg("timezones.conf", &cfg, NULL))) { 01102 if ((x_lists = switch_xml_child(cfg, "timezones"))) { 01103 for (x_list = switch_xml_child(x_lists, "zone"); x_list; x_list = x_list->next) { 01104 const char *name = switch_xml_attr(x_list, "name"); 01105 const char *value = switch_xml_attr(x_list, "value"); 01106 01107 if (zstr(name)) { 01108 continue; 01109 } 01110 01111 if (zstr(value)) { 01112 continue; 01113 } 01114 01115 switch_core_hash_insert(TIMEZONES_LIST.hash, name, switch_core_strdup(TIMEZONES_LIST.pool, value)); 01116 total++; 01117 } 01118 } 01119 01120 switch_xml_free(xml); 01121 } 01122 01123 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Timezone %sloaded %d definitions\n", reload ? "re" : "", total); 01124 }
| const char* switch_lookup_timezone | ( | const char * | tz_name | ) |
Definition at line 1073 of file switch_time.c.
References switch_timezones_list_t::hash, SWITCH_CHANNEL_LOG, switch_core_hash_find(), SWITCH_LOG_ERROR, switch_log_printf(), and TIMEZONES_LIST.
Referenced by switch_strftime_tz(), and switch_time_exp_tz_name().
01074 { 01075 char *value = NULL; 01076 01077 if (tz_name && (value = switch_core_hash_find(TIMEZONES_LIST.hash, tz_name)) == NULL) { 01078 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Timezone '%s' not found!\n", tz_name); 01079 } 01080 01081 return value; 01082 }
| SWITCH_MODULE_DEFINITION | ( | CORE_SOFTTIMER_MODULE | , | |
| softtimer_load | , | |||
| softtimer_shutdown | , | |||
| softtimer_runtime | ||||
| ) |
| SWITCH_MODULE_LOAD_FUNCTION | ( | softtimer_load | ) |
Definition at line 1203 of file switch_time.c.
References event_handler(), globals, switch_timer_interface::interface_name, module_pool, MONO, NODE, pool, runtime, SCF_CALIBRATE_CLOCK, SCF_USE_CLOCK_RT, SCF_USE_HEAVY_TIMING, SCF_USE_WIN32_MONOTONIC, SWITCH_CHANNEL_LOG, switch_clear_flag, switch_event_bind_removable(), SWITCH_EVENT_RELOADXML, SWITCH_FALSE, switch_load_timezones(), switch_loadable_module_create_interface(), switch_loadable_module_create_module_interface(), SWITCH_LOG_CONSOLE, SWITCH_LOG_ERROR, SWITCH_LOG_NOTICE, switch_log_printf(), switch_mutex_init(), SWITCH_MUTEX_NESTED, SWITCH_STATUS_SUCCESS, switch_test_flag, switch_time_calibrate_clock(), switch_time_set_cond_yield(), switch_time_set_nanosleep(), SWITCH_TIMER_INTERFACE, TFD, timer_check(), switch_timer_interface::timer_check, timer_destroy(), switch_timer_interface::timer_destroy, timer_init(), switch_timer_interface::timer_init, timer_next(), switch_timer_interface::timer_next, timer_step(), switch_timer_interface::timer_step, timer_sync(), switch_timer_interface::timer_sync, and win32_init_timers().
01204 { 01205 switch_timer_interface_t *timer_interface; 01206 module_pool = pool; 01207 01208 #ifdef WIN32 01209 timeBeginPeriod(1); 01210 01211 InitializeCriticalSection(&timer_section); 01212 01213 win32_init_timers(); /* Init timers for Windows, if we should use timeGetTime() or QueryPerformanceCounters() */ 01214 #endif 01215 01216 memset(&globals, 0, sizeof(globals)); 01217 switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool); 01218 01219 if ((switch_event_bind_removable(modname, SWITCH_EVENT_RELOADXML, NULL, event_handler, NULL, &NODE) != SWITCH_STATUS_SUCCESS)) { 01220 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); 01221 } 01222 switch_load_timezones(0); 01223 01224 /* connect my internal structure to the blank pointer passed to me */ 01225 *module_interface = switch_loadable_module_create_module_interface(pool, modname); 01226 timer_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_TIMER_INTERFACE); 01227 timer_interface->interface_name = "soft"; 01228 timer_interface->timer_init = timer_init; 01229 timer_interface->timer_next = timer_next; 01230 timer_interface->timer_step = timer_step; 01231 timer_interface->timer_sync = timer_sync; 01232 timer_interface->timer_check = timer_check; 01233 timer_interface->timer_destroy = timer_destroy; 01234 01235 if (!switch_test_flag((&runtime), SCF_USE_CLOCK_RT)) { 01236 switch_time_set_nanosleep(SWITCH_FALSE); 01237 } 01238 01239 if (switch_test_flag((&runtime), SCF_USE_HEAVY_TIMING)) { 01240 switch_time_set_cond_yield(SWITCH_FALSE); 01241 } 01242 01243 if (TFD) { 01244 switch_clear_flag((&runtime), SCF_CALIBRATE_CLOCK); 01245 } 01246 01247 #ifdef WIN32 01248 if (switch_test_flag((&runtime), SCF_USE_WIN32_MONOTONIC)) { 01249 MONO = 1; 01250 01251 if (win32_use_qpc) { 01252 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Enabled Windows monotonic clock, using QueryPerformanceCounter()\n"); 01253 } else { 01254 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Enabled Windows monotonic clock, using timeGetTime()\n"); 01255 } 01256 } 01257 01258 /* No need to calibrate clock in Win32, we will only sleep ms anyway, it's just not accurate enough */ 01259 switch_clear_flag((&runtime), SCF_CALIBRATE_CLOCK); 01260 #endif 01261 01262 if (switch_test_flag((&runtime), SCF_CALIBRATE_CLOCK)) { 01263 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Calibrating timer, please wait...\n"); 01264 switch_time_calibrate_clock(); 01265 } else { 01266 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clock calibration disabled.\n"); 01267 } 01268 01269 /* indicate that the module should continue to be loaded */ 01270 return SWITCH_STATUS_SUCCESS; 01271 }
| SWITCH_MODULE_RUNTIME_FUNCTION | ( | softtimer_runtime | ) |
Definition at line 760 of file switch_time.c.
References COND, cond, do_sleep(), globals, switch_runtime::initiated, MATRIX, MAX_ELEMENTS, MAX_TICK, switch_runtime::microseconds_per_tick, module_pool, MONO, mutex, NANO, switch_runtime::offset, switch_runtime::profile_time, switch_runtime::profile_timer, switch_runtime::reference, timer_matrix::roll, runtime, switch_runtime::sps, switch_runtime::sps_last, switch_runtime::sps_total, SWITCH_CHANNEL_LOG, switch_core_thread_set_cpu_affinity(), switch_delete_profile_timer(), switch_get_system_idle_time(), SWITCH_LOG_CONSOLE, SWITCH_LOG_CRIT, switch_log_printf(), switch_mutex_init(), switch_mutex_lock(), SWITCH_MUTEX_NESTED, switch_mutex_trylock(), switch_mutex_unlock(), switch_new_profile_timer(), switch_os_yield(), SWITCH_STATUS_SUCCESS, SWITCH_STATUS_TERM, switch_thread_cond_broadcast(), switch_thread_cond_create(), switch_time_now(), switch_time_sync(), TFD, TFD_TIMER_ABSTIME, switch_runtime::throttle_mutex, timer_matrix::tick, time_now(), switch_runtime::time_sync, switch_runtime::timer_affinity, TIMER_MATRIX, timerfd_create(), timerfd_settime(), switch_runtime::timestamp, switch_runtime::tipping_point, and win32_init_timers().
00761 { 00762 switch_time_t too_late = runtime.microseconds_per_tick * 1000; 00763 uint32_t current_ms = 0; 00764 uint32_t x, tick = 0; 00765 switch_time_t ts = 0, last = 0; 00766 int fwd_errs = 0, rev_errs = 0; 00767 int profile_tick = 0; 00768 int tfd = -1; 00769 uint32_t time_sync = runtime.time_sync; 00770 00771 #ifdef HAVE_TIMERFD_CREATE 00772 int last_MICROSECONDS_PER_TICK = runtime.microseconds_per_tick; 00773 00774 struct itimerspec spec = { { 0 } }; 00775 00776 if (MONO && TFD) { 00777 tfd = timerfd_create(CLOCK_MONOTONIC, 0); 00778 00779 if (tfd > -1) { 00780 spec.it_interval.tv_sec = 0; 00781 spec.it_interval.tv_nsec = runtime.microseconds_per_tick * 1000; 00782 spec.it_value.tv_sec = spec.it_interval.tv_sec; 00783 spec.it_value.tv_nsec = spec.it_interval.tv_nsec; 00784 00785 if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &spec, NULL)) { 00786 close(tfd); 00787 tfd = -1; 00788 } 00789 } 00790 } 00791 #else 00792 tfd = -1; 00793 #endif 00794 00795 runtime.profile_timer = switch_new_profile_timer(); 00796 switch_get_system_idle_time(runtime.profile_timer, &runtime.profile_time); 00797 00798 if (runtime.timer_affinity > -1) { 00799 switch_core_thread_set_cpu_affinity(runtime.timer_affinity); 00800 } 00801 00802 switch_time_sync(); 00803 time_sync = runtime.time_sync; 00804 00805 globals.STARTED = globals.RUNNING = 1; 00806 switch_mutex_lock(runtime.throttle_mutex); 00807 runtime.sps = runtime.sps_total; 00808 switch_mutex_unlock(runtime.throttle_mutex); 00809 00810 if (MONO) { 00811 int loops; 00812 for (loops = 0; loops < 3; loops++) { 00813 ts = time_now(0); 00814 /* if it returns the same value every time it won't be of much use. */ 00815 if (ts == last) { 00816 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Broken MONOTONIC Clock Detected!, Support Disabled.\n"); 00817 MONO = 0; 00818 NANO = 0; 00819 runtime.reference = switch_time_now(); 00820 runtime.initiated = runtime.reference; 00821 break; 00822 } 00823 do_sleep(runtime.microseconds_per_tick); 00824 last = ts; 00825 } 00826 } 00827 00828 ts = 0; 00829 last = 0; 00830 fwd_errs = rev_errs = 0; 00831 00832 #ifndef DISABLE_1MS_COND 00833 if (!NANO) { 00834 switch_mutex_init(&TIMER_MATRIX[1].mutex, SWITCH_MUTEX_NESTED, module_pool); 00835 switch_thread_cond_create(&TIMER_MATRIX[1].cond, module_pool); 00836 } 00837 #endif 00838 00839 00840 switch_time_sync(); 00841 time_sync = runtime.time_sync; 00842 00843 globals.use_cond_yield = COND; 00844 globals.RUNNING = 1; 00845 00846 while (globals.RUNNING == 1) { 00847 00848 #ifdef HAVE_TIMERFD_CREATE 00849 if (last_MICROSECONDS_PER_TICK != runtime.microseconds_per_tick) { 00850 spec.it_interval.tv_nsec = runtime.microseconds_per_tick * 1000; 00851 timerfd_settime(tfd, TFD_TIMER_ABSTIME, &spec, NULL); 00852 } 00853 00854 last_MICROSECONDS_PER_TICK = runtime.microseconds_per_tick; 00855 #endif 00856 00857 runtime.reference += runtime.microseconds_per_tick; 00858 00859 while (((ts = time_now(runtime.offset)) + 100) < runtime.reference) { 00860 if (ts < last) { 00861 if (MONO) { 00862 if (time_sync == runtime.time_sync) { /* Only resync if not in the middle of switch_time_sync() already */ 00863 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Virtual Migration Detected! Syncing Clock\n"); 00864 win32_init_timers(); /* Make sure to reinit timers on WIN32 */ 00865 switch_time_sync(); 00866 time_sync = runtime.time_sync; 00867 } 00868 } else { 00869 int64_t diff = (int64_t) (ts - last); 00870 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Reverse Clock Skew Detected!\n"); 00871 runtime.reference = switch_time_now(); 00872 current_ms = 0; 00873 tick = 0; 00874 runtime.initiated += diff; 00875 rev_errs++; 00876 } 00877 00878 if (!MONO || time_sync == runtime.time_sync) { 00879 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, 00880 "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. I AM *FREE* afterall.\n"); 00881 } 00882 } else { 00883 rev_errs = 0; 00884 } 00885 00886 if (runtime.tipping_point && globals.timer_count >= runtime.tipping_point) { 00887 switch_os_yield(); 00888 } else { 00889 if (tfd > -1 && globals.RUNNING == 1) { 00890 uint64_t exp; 00891 int r; 00892 r = read(tfd, &exp, sizeof(exp)); 00893 r++; 00894 } else { 00895 switch_time_t timediff = runtime.reference - ts; 00896 00897 if (runtime.microseconds_per_tick < timediff) { 00898 /* Only sleep for runtime.microseconds_per_tick if this value is lower then the actual time diff we need to sleep */ 00899 do_sleep(runtime.microseconds_per_tick); 00900 } else { 00901 #ifdef WIN32 00902 /* Windows only sleeps in ms precision, try to round the usec value as good as possible */ 00903 do_sleep((switch_interval_time_t)floor((timediff / 1000.0) + 0.5) * 1000); 00904 #else 00905 do_sleep(timediff); 00906 #endif 00907 } 00908 } 00909 } 00910 00911 last = ts; 00912 } 00913 00914 if (ts > (runtime.reference + too_late)) { 00915 if (MONO) { 00916 if (time_sync == runtime.time_sync) { /* Only resync if not in the middle of switch_time_sync() already */ 00917 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Virtual Migration Detected! Syncing Clock\n"); 00918 win32_init_timers(); /* Make sure to reinit timers on WIN32 */ 00919 switch_time_sync(); 00920 time_sync = runtime.time_sync; 00921 } 00922 } else { 00923 switch_time_t diff = ts - runtime.reference - runtime.microseconds_per_tick; 00924 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Forward Clock Skew Detected!\n"); 00925 fwd_errs++; 00926 runtime.reference = switch_time_now(); 00927 current_ms = 0; 00928 tick = 0; 00929 runtime.initiated += diff; 00930 } 00931 } else { 00932 fwd_errs = 0; 00933 } 00934 00935 if (fwd_errs > 9 || rev_errs > 9) { 00936 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Auto Re-Syncing clock.\n"); 00937 switch_time_sync(); 00938 time_sync = runtime.time_sync; 00939 fwd_errs = rev_errs = 0; 00940 } 00941 00942 runtime.timestamp = ts; 00943 current_ms += (runtime.microseconds_per_tick / 1000); 00944 tick += (runtime.microseconds_per_tick / 1000); 00945 00946 if (time_sync < runtime.time_sync) { 00947 time_sync++; /* Only step once for each loop, we want to make sure to keep this thread safe */ 00948 } 00949 00950 if (tick >= (1000000 / runtime.microseconds_per_tick)) { 00951 if (++profile_tick == 1) { 00952 switch_get_system_idle_time(runtime.profile_timer, &runtime.profile_time); 00953 profile_tick = 0; 00954 } 00955 00956 if (runtime.sps <= 0) { 00957 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Over Session Rate of %d!\n", runtime.sps_total); 00958 } 00959 switch_mutex_lock(runtime.throttle_mutex); 00960 runtime.sps_last = runtime.sps_total - runtime.sps; 00961 runtime.sps = runtime.sps_total; 00962 switch_mutex_unlock(runtime.throttle_mutex); 00963 tick = 0; 00964 } 00965 #ifndef DISABLE_1MS_COND 00966 TIMER_MATRIX[1].tick++; 00967 if (switch_mutex_trylock(TIMER_MATRIX[1].mutex) == SWITCH_STATUS_SUCCESS) { 00968 switch_thread_cond_broadcast(TIMER_MATRIX[1].cond); 00969 switch_mutex_unlock(TIMER_MATRIX[1].mutex); 00970 } 00971 if (TIMER_MATRIX[1].tick == MAX_TICK) { 00972 TIMER_MATRIX[1].tick = 0; 00973 TIMER_MATRIX[1].roll++; 00974 } 00975 #endif 00976 00977 00978 if (MATRIX && (current_ms % (runtime.microseconds_per_tick / 1000)) == 0) { 00979 for (x = (runtime.microseconds_per_tick / 1000); x <= MAX_ELEMENTS; x += (runtime.microseconds_per_tick / 1000)) { 00980 if ((current_ms % x) == 0) { 00981 if (TIMER_MATRIX[x].count) { 00982 TIMER_MATRIX[x].tick++; 00983 #ifdef DISABLE_1MS_COND 00984 00985 if (TIMER_MATRIX[x].mutex && switch_mutex_trylock(TIMER_MATRIX[x].mutex) == SWITCH_STATUS_SUCCESS) { 00986 switch_thread_cond_broadcast(TIMER_MATRIX[x].cond); 00987 switch_mutex_unlock(TIMER_MATRIX[x].mutex); 00988 } 00989 #endif 00990 if (TIMER_MATRIX[x].tick == MAX_TICK) { 00991 TIMER_MATRIX[x].tick = 0; 00992 TIMER_MATRIX[x].roll++; 00993 } 00994 } 00995 } 00996 } 00997 } 00998 00999 if (current_ms == MAX_ELEMENTS) { 01000 current_ms = 0; 01001 } 01002 } 01003 01004 globals.use_cond_yield = 0; 01005 01006 for (x = (runtime.microseconds_per_tick / 1000); x <= MAX_ELEMENTS; x += (runtime.microseconds_per_tick / 1000)) { 01007 if (TIMER_MATRIX[x].mutex && switch_mutex_trylock(TIMER_MATRIX[x].mutex) == SWITCH_STATUS_SUCCESS) { 01008 switch_thread_cond_broadcast(TIMER_MATRIX[x].cond); 01009 switch_mutex_unlock(TIMER_MATRIX[x].mutex); 01010 } 01011 } 01012 01013 if (tfd > -1) { 01014 close(tfd); 01015 tfd = -1; 01016 } 01017 01018 01019 switch_mutex_lock(globals.mutex); 01020 globals.RUNNING = 0; 01021 switch_mutex_unlock(globals.mutex); 01022 01023 switch_delete_profile_timer(&runtime.profile_timer); 01024 01025 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Soft timer thread exiting.\n"); 01026 01027 return SWITCH_STATUS_TERM; 01028 }
| SWITCH_MODULE_SHUTDOWN_FUNCTION | ( | softtimer_shutdown | ) |
Definition at line 1273 of file switch_time.c.
References do_sleep(), globals, switch_timezones_list_t::hash, NODE, switch_timezones_list_t::pool, switch_core_destroy_memory_pool, switch_core_hash_destroy(), switch_event_unbind(), switch_mutex_lock(), switch_mutex_unlock(), SWITCH_STATUS_SUCCESS, and TIMEZONES_LIST.
01274 { 01275 globals.use_cond_yield = 0; 01276 01277 if (globals.RUNNING == 1) { 01278 switch_mutex_lock(globals.mutex); 01279 globals.RUNNING = -1; 01280 switch_mutex_unlock(globals.mutex); 01281 01282 while (globals.RUNNING == -1) { 01283 do_sleep(10000); 01284 } 01285 } 01286 #if defined(WIN32) 01287 timeEndPeriod(1); 01288 win32_tick_time_since_start = -1; /* we are not initialized anymore */ 01289 DeleteCriticalSection(&timer_section); 01290 #endif 01291 01292 if (TIMEZONES_LIST.hash) { 01293 switch_core_hash_destroy(&TIMEZONES_LIST.hash); 01294 } 01295 01296 if (TIMEZONES_LIST.pool) { 01297 switch_core_destroy_memory_pool(&TIMEZONES_LIST.pool); 01298 } 01299 01300 if (NODE) { 01301 switch_event_unbind(&NODE); 01302 } 01303 01304 return SWITCH_STATUS_SUCCESS; 01305 }
| void switch_os_yield | ( | void | ) |
Definition at line 143 of file switch_time.c.
Referenced by switch_cond_next(), SWITCH_MODULE_RUNTIME_FUNCTION(), and timer_next().
00144 { 00145 #if defined(WIN32) 00146 SwitchToThread(); 00147 #else 00148 sched_yield(); 00149 #endif 00150 }
| static switch_time_t time_now | ( | int64_t | offset | ) | [static] |
Definition at line 371 of file switch_time.c.
References MONO, and switch_time_now().
Referenced by SWITCH_MODULE_RUNTIME_FUNCTION(), switch_time_ref(), and switch_time_sync().
00372 { 00373 switch_time_t now; 00374 00375 #if (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)) || defined(WIN32) 00376 if (MONO) { 00377 #ifndef WIN32 00378 struct timespec ts; 00379 clock_gettime(CLOCK_MONOTONIC, &ts); 00380 now = ts.tv_sec * APR_USEC_PER_SEC + (ts.tv_nsec / 1000) + offset; 00381 #else 00382 if (win32_use_qpc) { 00383 /* Use QueryPerformanceCounter */ 00384 uint64_t count = 0; 00385 QueryPerformanceCounter((LARGE_INTEGER*)&count); 00386 now = ((count * 1000000) / win32_qpc_freq) + offset; 00387 } else { 00388 /* Use good old timeGetTime() */ 00389 DWORD tick_now; 00390 DWORD tick_diff; 00391 00392 tick_now = timeGetTime(); 00393 if (win32_tick_time_since_start != -1) { 00394 EnterCriticalSection(&timer_section); 00395 /* just add diff (to make it work more than 50 days). */ 00396 tick_diff = tick_now - win32_last_get_time_tick; 00397 win32_tick_time_since_start += tick_diff; 00398 00399 win32_last_get_time_tick = tick_now; 00400 now = (win32_tick_time_since_start * 1000) + offset; 00401 LeaveCriticalSection(&timer_section); 00402 } else { 00403 /* If someone is calling us before timer is initialized, 00404 * return the current tick + offset 00405 */ 00406 now = (tick_now * 1000) + offset; 00407 } 00408 } 00409 #endif 00410 } else { 00411 #endif 00412 now = switch_time_now(); 00413 00414 #if (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)) || defined(WIN32) 00415 } 00416 #endif 00417 00418 return now; 00419 }
| static switch_status_t timer_check | ( | switch_timer_t * | timer, | |
| switch_bool_t | step | |||
| ) | [static] |
Definition at line 655 of file switch_time.c.
References check_roll, switch_timer::diff, globals, switch_timer::interval, switch_timer::private_info, timer_private::ready, timer_private::reference, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, timer_matrix::tick, switch_timer::tick, TIMER_MATRIX, and timer_step().
Referenced by rtp_common_read(), and SWITCH_MODULE_LOAD_FUNCTION().
00656 { 00657 timer_private_t *private_info = timer->private_info; 00658 switch_status_t status = SWITCH_STATUS_SUCCESS; 00659 00660 if (globals.RUNNING != 1 || !private_info->ready) { 00661 return SWITCH_STATUS_SUCCESS; 00662 } 00663 00664 check_roll(); 00665 00666 timer->tick = TIMER_MATRIX[timer->interval].tick; 00667 00668 if (timer->tick < private_info->reference) { 00669 timer->diff = private_info->reference - timer->tick; 00670 } else { 00671 timer->diff = 0; 00672 } 00673 00674 if (timer->diff) { 00675 status = SWITCH_STATUS_FALSE; 00676 } else if (step) { 00677 timer_step(timer); 00678 } 00679 00680 00681 return status; 00682 }
| static switch_status_t timer_destroy | ( | switch_timer_t * | timer | ) | [static] |
Definition at line 684 of file switch_time.c.
References timer_matrix::count, globals, switch_timer::interval, MAX_ELEMENTS, switch_timer::private_info, timer_private::ready, runtime, SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, switch_log_printf(), switch_mutex_lock(), switch_mutex_unlock(), SWITCH_STATUS_SUCCESS, timer_matrix::tick, TIMER_MATRIX, and switch_runtime::tipping_point.
Referenced by SWITCH_MODULE_LOAD_FUNCTION().
00685 { 00686 timer_private_t *private_info = timer->private_info; 00687 if (timer->interval < MAX_ELEMENTS) { 00688 switch_mutex_lock(globals.mutex); 00689 TIMER_MATRIX[timer->interval].count--; 00690 if (TIMER_MATRIX[timer->interval].count == 0) { 00691 TIMER_MATRIX[timer->interval].tick = 0; 00692 } 00693 switch_mutex_unlock(globals.mutex); 00694 } 00695 if (private_info) { 00696 private_info->ready = 0; 00697 } 00698 00699 switch_mutex_lock(globals.mutex); 00700 if (globals.timer_count) { 00701 globals.timer_count--; 00702 if (runtime.tipping_point && globals.timer_count == (runtime.tipping_point - 1)) { 00703 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Fell Below tipping point of %u, shifting into low-gear.\n", runtime.tipping_point); 00704 } 00705 } 00706 switch_mutex_unlock(globals.mutex); 00707 00708 return SWITCH_STATUS_SUCCESS; 00709 }
| static switch_status_t timer_init | ( | switch_timer_t * | timer | ) | [static] |
Definition at line 508 of file switch_time.c.
References timer_matrix::count, do_sleep(), globals, switch_timer::interval, switch_timer::memory_pool, switch_runtime::microseconds_per_tick, module_pool, switch_timer::private_info, timer_matrix::roll, runtime, SWITCH_CHANNEL_LOG, switch_core_alloc, SWITCH_LOG_NOTICE, switch_log_printf(), SWITCH_LOG_WARNING, switch_mutex_init(), switch_mutex_lock(), SWITCH_MUTEX_NESTED, switch_mutex_unlock(), SWITCH_STATUS_FALSE, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, switch_thread_cond_create(), switch_time_sync(), timer_matrix::tick, TIMER_MATRIX, and switch_runtime::tipping_point.
Referenced by SWITCH_MODULE_LOAD_FUNCTION().
00509 { 00510 timer_private_t *private_info; 00511 int sanity = 0; 00512 00513 while (globals.STARTED == 0) { 00514 do_sleep(100000); 00515 if (++sanity == 300) { 00516 abort(); 00517 } 00518 } 00519 00520 if (globals.RUNNING != 1 || !globals.mutex || timer->interval < 1) { 00521 return SWITCH_STATUS_FALSE; 00522 } 00523 00524 if ((private_info = switch_core_alloc(timer->memory_pool, sizeof(*private_info)))) { 00525 switch_mutex_lock(globals.mutex); 00526 if (!TIMER_MATRIX[timer->interval].mutex) { 00527 switch_mutex_init(&TIMER_MATRIX[timer->interval].mutex, SWITCH_MUTEX_NESTED, module_pool); 00528 switch_thread_cond_create(&TIMER_MATRIX[timer->interval].cond, module_pool); 00529 } 00530 TIMER_MATRIX[timer->interval].count++; 00531 switch_mutex_unlock(globals.mutex); 00532 timer->private_info = private_info; 00533 private_info->start = private_info->reference = TIMER_MATRIX[timer->interval].tick; 00534 private_info->start -= 2; /* switch_core_timer_init sets samplecount to samples, this makes first next() step once */ 00535 private_info->roll = TIMER_MATRIX[timer->interval].roll; 00536 private_info->ready = 1; 00537 00538 if ((timer->interval == 10 || timer->interval == 30) && runtime.microseconds_per_tick > 10000) { 00539 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Increasing global timer resolution to 10ms to handle interval %d\n", timer->interval); 00540 runtime.microseconds_per_tick = 10000; 00541 } 00542 00543 if (timer->interval > 0 && (timer->interval < (int)(runtime.microseconds_per_tick / 1000) || (timer->interval % 10) != 0)) { 00544 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Increasing global timer resolution to 1ms to handle interval %d\n", timer->interval); 00545 runtime.microseconds_per_tick = 1000; 00546 switch_time_sync(); 00547 } 00548 00549 switch_mutex_lock(globals.mutex); 00550 globals.timer_count++; 00551 if (runtime.tipping_point && globals.timer_count == (runtime.tipping_point + 1)) { 00552 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Crossed tipping point of %u, shifting into high-gear.\n", runtime.tipping_point); 00553 } 00554 switch_mutex_unlock(globals.mutex); 00555 00556 return SWITCH_STATUS_SUCCESS; 00557 } 00558 00559 return SWITCH_STATUS_MEMERR; 00560 }
| static switch_status_t timer_next | ( | switch_timer_t * | timer | ) | [static] |
Definition at line 610 of file switch_time.c.
References check_roll, cond, do_sleep(), globals, switch_timer::interval, MATRIX, mutex, switch_timer::private_info, timer_private::ready, timer_private::reference, runtime, switch_mutex_lock(), switch_mutex_unlock(), switch_os_yield(), SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_thread_cond_wait(), timer_matrix::tick, switch_timer::tick, TIMER_MATRIX, timer_step(), and switch_runtime::tipping_point.
Referenced by SWITCH_MODULE_LOAD_FUNCTION().
00611 { 00612 timer_private_t *private_info = timer->private_info; 00613 00614 #ifdef DISABLE_1MS_COND 00615 int cond_index = timer->interval; 00616 #else 00617 int cond_index = 1; 00618 #endif 00619 int delta = (int) (private_info->reference - TIMER_MATRIX[timer->interval].tick); 00620 00621 /* sync up timer if it's not been called for a while otherwise it will return instantly several times until it catches up */ 00622 if (delta < -1) { 00623 private_info->reference = timer->tick = TIMER_MATRIX[timer->interval].tick; 00624 } 00625 timer_step(timer); 00626 00627 if (!MATRIX) { 00628 do_sleep(1000 * timer->interval); 00629 goto end; 00630 } 00631 00632 while (globals.RUNNING == 1 && private_info->ready && TIMER_MATRIX[timer->interval].tick < private_info->reference) { 00633 check_roll(); 00634 00635 if (runtime.tipping_point && globals.timer_count >= runtime.tipping_point) { 00636 switch_os_yield(); 00637 globals.use_cond_yield = 0; 00638 } else { 00639 if (globals.use_cond_yield == 1) { 00640 switch_mutex_lock(TIMER_MATRIX[cond_index].mutex); 00641 if (TIMER_MATRIX[timer->interval].tick < private_info->reference) { 00642 switch_thread_cond_wait(TIMER_MATRIX[cond_index].cond, TIMER_MATRIX[cond_index].mutex); 00643 } 00644 switch_mutex_unlock(TIMER_MATRIX[cond_index].mutex); 00645 } else { 00646 do_sleep(1000); 00647 } 00648 } 00649 } 00650 00651 end: 00652 return globals.RUNNING == 1 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; 00653 }
| static switch_status_t timer_step | ( | switch_timer_t * | timer | ) | [static] |
Definition at line 569 of file switch_time.c.
References check_roll, globals, switch_timer::private_info, timer_private::ready, timer_private::reference, switch_timer::samplecount, switch_timer::samples, timer_private::start, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and UINT32_MAX.
Referenced by SWITCH_MODULE_LOAD_FUNCTION(), timer_check(), timer_next(), and timer_sync().
00570 { 00571 timer_private_t *private_info = timer->private_info; 00572 uint64_t samples; 00573 00574 if (globals.RUNNING != 1 || private_info->ready == 0) { 00575 return SWITCH_STATUS_FALSE; 00576 } 00577 00578 check_roll(); 00579 samples = timer->samples * (private_info->reference - private_info->start); 00580 00581 if (samples > UINT32_MAX) { 00582 private_info->start = private_info->reference - 1; /* Must have a diff */ 00583 samples = timer->samples; 00584 } 00585 00586 timer->samplecount = (uint32_t) samples; 00587 private_info->reference++; 00588 00589 return SWITCH_STATUS_SUCCESS; 00590 }
| static switch_status_t timer_sync | ( | switch_timer_t * | timer | ) | [static] |
Definition at line 592 of file switch_time.c.
References globals, switch_timer::interval, switch_timer::private_info, timer_private::ready, timer_private::reference, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, timer_matrix::tick, switch_timer::tick, TIMER_MATRIX, and timer_step().
Referenced by SWITCH_MODULE_LOAD_FUNCTION().
00593 { 00594 timer_private_t *private_info = timer->private_info; 00595 00596 if (globals.RUNNING != 1 || private_info->ready == 0) { 00597 return SWITCH_STATUS_FALSE; 00598 } 00599 00600 /* sync the clock */ 00601 private_info->reference = timer->tick = TIMER_MATRIX[timer->interval].tick; 00602 00603 /* apply timestamp */ 00604 timer_step(timer); 00605 00606 return SWITCH_STATUS_SUCCESS; 00607 }
| static void timesub | ( | const time_t *const | timep, | |
| const long | offset, | |||
| register const struct state *const | sp, | |||
| register struct tm *const | tmp | |||
| ) | [static] |
Definition at line 2031 of file switch_time.c.
References DAYSPERNYEAR, DAYSPERWEEK, EPOCH_WDAY, EPOCH_YEAR, isleap, LEAPS_THRU_END_OF, lsinfo::ls_corr, lsinfo::ls_trans, mon_lengths, SECSPERDAY, SECSPERHOUR, SECSPERMIN, switch_assert, TM_YEAR_BASE, and year_lengths.
Referenced by tztime().
02032 { 02033 register const struct lsinfo *lp; 02034 register long days; 02035 register time_t rem; 02036 register int y; 02037 register int yleap; 02038 register const int *ip; 02039 register long corr; 02040 register int hit; 02041 register int i; 02042 02043 switch_assert(timep != NULL); 02044 switch_assert(sp != NULL); 02045 switch_assert(tmp != NULL); 02046 02047 corr = 0; 02048 hit = 0; 02049 i = (sp == NULL) ? 0 : sp->leapcnt; 02050 02051 while (--i >= 0) { 02052 lp = &sp->lsis[i]; 02053 if (*timep >= lp->ls_trans) { 02054 if (*timep == lp->ls_trans) { 02055 hit = ((i == 0 && lp->ls_corr > 0) || (i > 0 && lp->ls_corr > sp->lsis[i - 1].ls_corr)); 02056 if (hit) 02057 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) { 02058 ++hit; 02059 --i; 02060 } 02061 } 02062 corr = lp->ls_corr; 02063 break; 02064 } 02065 } 02066 days = (long) (*timep / SECSPERDAY); 02067 rem = *timep % SECSPERDAY; 02068 02069 02070 #ifdef mc68k 02071 /* If this is for CPU bugs workarounds, i would remove this anyway. Who would use it on an old mc68k ? */ 02072 if (*timep == 0x80000000) { 02073 /* 02074 ** A 3B1 muffs the division on the most negative number. 02075 */ 02076 days = -24855; 02077 rem = -11648; 02078 } 02079 #endif 02080 02081 rem += (offset - corr); 02082 while (rem < 0) { 02083 rem += SECSPERDAY; 02084 --days; 02085 } 02086 while (rem >= SECSPERDAY) { 02087 rem -= SECSPERDAY; 02088 ++days; 02089 } 02090 tmp->tm_hour = (int) (rem / SECSPERHOUR); 02091 rem = rem % SECSPERHOUR; 02092 tmp->tm_min = (int) (rem / SECSPERMIN); 02093 02094 /* 02095 ** A positive leap second requires a special 02096 ** representation. This uses "... ??:59:60" et seq. 02097 */ 02098 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; 02099 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); 02100 02101 if (tmp->tm_wday < 0) 02102 tmp->tm_wday += DAYSPERWEEK; 02103 02104 y = EPOCH_YEAR; 02105 02106 #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) 02107 02108 while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) { 02109 register int newy; 02110 02111 newy = (int) (y + days / DAYSPERNYEAR); 02112 if (days < 0) 02113 --newy; 02114 days -= (newy - y) * DAYSPERNYEAR + LEAPS_THRU_END_OF(newy - 1) - LEAPS_THRU_END_OF(y - 1); 02115 y = newy; 02116 } 02117 02118 tmp->tm_year = y - TM_YEAR_BASE; 02119 tmp->tm_yday = (int) days; 02120 02121 ip = mon_lengths[yleap]; 02122 02123 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) 02124 days = days - (long) ip[tmp->tm_mon]; 02125 02126 tmp->tm_mday = (int) (days + 1); 02127 tmp->tm_isdst = 0; 02128 #if defined(HAVE_STRUCT_TM_TM_GMTOFF) 02129 tmp->tm_gmtoff = offset; 02130 #endif 02131 }
| static void tm2switchtime | ( | struct tm * | tm, | |
| switch_time_exp_t * | xt | |||
| ) | [static] |
Definition at line 1036 of file switch_time.c.
Referenced by switch_strftime_tz(), and switch_time_exp_tz_name().
01037 { 01038 01039 if (!xt || !tm) { 01040 return; 01041 } 01042 memset(xt, 0, sizeof(*xt)); 01043 01044 xt->tm_sec = tm->tm_sec; 01045 xt->tm_min = tm->tm_min; 01046 xt->tm_hour = tm->tm_hour; 01047 xt->tm_mday = tm->tm_mday; 01048 xt->tm_mon = tm->tm_mon; 01049 xt->tm_year = tm->tm_year; 01050 xt->tm_wday = tm->tm_wday; 01051 xt->tm_yday = tm->tm_yday; 01052 xt->tm_isdst = tm->tm_isdst; 01053 01054 #if defined(HAVE_STRUCT_TM_TM_GMTOFF) 01055 xt->tm_gmtoff = tm->tm_gmtoff; 01056 #endif 01057 01058 return; 01059 }
| static time_t transtime | ( | const time_t | janfirst, | |
| const int | year, | |||
| register const struct rule *const | rulep, | |||
| const long | offset | |||
| ) | [static] |
Definition at line 1718 of file switch_time.c.
References DAY_OF_YEAR, DAYSPERWEEK, INITIALIZE, isleap, JULIAN_DAY, mon_lengths, MONTH_NTH_DAY_OF_WEEK, and SECSPERDAY.
Referenced by tzparse().
01719 { 01720 register int leapyear; 01721 register time_t value; 01722 register int i; 01723 int d, m1, yy0, yy1, yy2, dow; 01724 01725 INITIALIZE(value); 01726 leapyear = isleap(year); 01727 switch (rulep->r_type) { 01728 01729 case JULIAN_DAY: 01730 /* 01731 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap 01732 ** years. 01733 ** In non-leap years, or if the day number is 59 or less, just 01734 ** add SECSPERDAY times the day number-1 to the time of 01735 ** January 1, midnight, to get the day. 01736 */ 01737 value = janfirst + (rulep->r_day - 1) * SECSPERDAY; 01738 if (leapyear && rulep->r_day >= 60) 01739 value += SECSPERDAY; 01740 break; 01741 01742 case DAY_OF_YEAR: 01743 /* 01744 ** n - day of year. 01745 ** Just add SECSPERDAY times the day number to the time of 01746 ** January 1, midnight, to get the day. 01747 */ 01748 value = janfirst + rulep->r_day * SECSPERDAY; 01749 break; 01750 01751 case MONTH_NTH_DAY_OF_WEEK: 01752 /* 01753 ** Mm.n.d - nth "dth day" of month m. 01754 */ 01755 value = janfirst; 01756 for (i = 0; i < rulep->r_mon - 1; ++i) 01757 value += mon_lengths[leapyear][i] * SECSPERDAY; 01758 01759 /* 01760 ** Use Zeller's Congruence to get day-of-week of first day of 01761 ** month. 01762 */ 01763 m1 = (rulep->r_mon + 9) % 12 + 1; 01764 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; 01765 yy1 = yy0 / 100; 01766 yy2 = yy0 % 100; 01767 dow = ((26 * m1 - 2) / 10 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; 01768 if (dow < 0) 01769 dow += DAYSPERWEEK; 01770 01771 /* 01772 ** "dow" is the day-of-week of the first day of the month. Get 01773 ** the day-of-month (zero-origin) of the first "dow" day of the 01774 ** month. 01775 */ 01776 d = rulep->r_day - dow; 01777 if (d < 0) 01778 d += DAYSPERWEEK; 01779 for (i = 1; i < rulep->r_week; ++i) { 01780 if (d + DAYSPERWEEK >= mon_lengths[leapyear][rulep->r_mon - 1]) 01781 break; 01782 d += DAYSPERWEEK; 01783 } 01784 01785 /* 01786 ** "d" is the day-of-month (zero-origin) of the day we want. 01787 */ 01788 value += d * SECSPERDAY; 01789 break; 01790 } 01791 01792 /* 01793 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in 01794 ** question. To get the Epoch-relative time of the specified local 01795 ** time on that day, add the transition time and the current offset 01796 ** from UTC. 01797 */ 01798 return value + rulep->r_time + offset; 01799 }
| static int tzparse | ( | const char * | name, | |
| register struct state *const | sp, | |||
| const int | lastditch | |||
| ) | [static] |
Definition at line 1808 of file switch_time.c.
References EPOCH_YEAR, FALSE, getoffset(), getrule(), getzname(), INITIALIZE, isleap, SECSPERDAY, SECSPERHOUR, transtime(), TZ_MAX_TIMES, and year_lengths.
Referenced by tztime().
01809 { 01810 const char *stdname; 01811 const char *dstname; 01812 size_t stdlen; 01813 size_t dstlen; 01814 long stdoffset; 01815 long dstoffset; 01816 register time_t *atp; 01817 register unsigned char *typep; 01818 register char *cp; 01819 01820 01821 INITIALIZE(dstname); 01822 stdname = name; 01823 01824 if (lastditch) { 01825 stdlen = strlen(name); /* length of standard zone name */ 01826 name += stdlen; 01827 if (stdlen >= sizeof sp->chars) 01828 stdlen = (sizeof sp->chars) - 1; 01829 stdoffset = 0; 01830 } else { 01831 name = getzname(name); 01832 stdlen = name - stdname; 01833 if (stdlen < 3) 01834 return -1; 01835 if (*name == '\0') 01836 return -1; 01837 name = getoffset(name, &stdoffset); 01838 if (name == NULL) 01839 return -1; 01840 } 01841 01842 sp->leapcnt = 0; /* so, we're off a little */ 01843 01844 if (*name != '\0') { 01845 dstname = name; 01846 name = getzname(name); 01847 dstlen = name - dstname; /* length of DST zone name */ 01848 if (dstlen < 3) 01849 return -1; 01850 if (*name != '\0' && *name != ',' && *name != ';') { 01851 name = getoffset(name, &dstoffset); 01852 if (name == NULL) 01853 return -1; 01854 } else 01855 dstoffset = stdoffset - SECSPERHOUR; 01856 01857 /* Go parsing the daylight saving stuff */ 01858 if (*name == ',' || *name == ';') { 01859 struct rule start; 01860 struct rule end; 01861 register int year; 01862 register time_t janfirst; 01863 time_t starttime; 01864 time_t endtime; 01865 01866 ++name; 01867 if ((name = getrule(name, &start)) == NULL) 01868 return -1; 01869 if (*name++ != ',') 01870 return -1; 01871 if ((name = getrule(name, &end)) == NULL) 01872 return -1; 01873 if (*name != '\0') 01874 return -1; 01875 01876 sp->typecnt = 2; /* standard time and DST */ 01877 01878 /* 01879 ** Two transitions per year, from EPOCH_YEAR to 2037. 01880 */ 01881 sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1); 01882 01883 if (sp->timecnt > TZ_MAX_TIMES) 01884 return -1; 01885 01886 sp->ttis[0].tt_gmtoff = -dstoffset; 01887 sp->ttis[0].tt_isdst = 1; 01888 sp->ttis[0].tt_abbrind = (int) (stdlen + 1); 01889 sp->ttis[1].tt_gmtoff = -stdoffset; 01890 sp->ttis[1].tt_isdst = 0; 01891 sp->ttis[1].tt_abbrind = 0; 01892 01893 atp = sp->ats; 01894 typep = sp->types; 01895 janfirst = 0; 01896 01897 for (year = EPOCH_YEAR; year <= 2037; ++year) { 01898 starttime = transtime(janfirst, year, &start, stdoffset); 01899 endtime = transtime(janfirst, year, &end, dstoffset); 01900 if (starttime > endtime) { 01901 *atp++ = endtime; 01902 *typep++ = 1; /* DST ends */ 01903 *atp++ = starttime; 01904 *typep++ = 0; /* DST begins */ 01905 } else { 01906 *atp++ = starttime; 01907 *typep++ = 0; /* DST begins */ 01908 *atp++ = endtime; 01909 *typep++ = 1; /* DST ends */ 01910 } 01911 01912 janfirst += year_lengths[isleap(year)] * SECSPERDAY; 01913 } 01914 01915 } else { 01916 register long theirstdoffset; 01917 register long theirdstoffset; 01918 register long theiroffset; 01919 register int isdst; 01920 register int i; 01921 register int j; 01922 01923 if (*name != '\0') 01924 return -1; 01925 /* 01926 Initial values of theirstdoffset and theirdstoffset. 01927 */ 01928 theirstdoffset = 0; 01929 for (i = 0; i < sp->timecnt; ++i) { 01930 j = sp->types[i]; 01931 if (!sp->ttis[j].tt_isdst) { 01932 theirstdoffset = -sp->ttis[j].tt_gmtoff; 01933 break; 01934 } 01935 } 01936 theirdstoffset = 0; 01937 for (i = 0; i < sp->timecnt; ++i) { 01938 j = sp->types[i]; 01939 if (sp->ttis[j].tt_isdst) { 01940 theirdstoffset = -sp->ttis[j].tt_gmtoff; 01941 break; 01942 } 01943 } 01944 /* 01945 ** Initially we're assumed to be in standard time. 01946 */ 01947 isdst = FALSE; 01948 theiroffset = theirstdoffset; 01949 /* 01950 ** Now juggle transition times and types 01951 ** tracking offsets as you do. 01952 */ 01953 for (i = 0; i < sp->timecnt; ++i) { 01954 j = sp->types[i]; 01955 sp->types[i] = (unsigned char) sp->ttis[j].tt_isdst; 01956 if (sp->ttis[j].tt_ttisgmt) { 01957 /* No adjustment to transition time */ 01958 } else { 01959 /* 01960 ** If summer time is in effect, and the 01961 ** transition time was not specified as 01962 ** standard time, add the summer time 01963 ** offset to the transition time; 01964 ** otherwise, add the standard time 01965 ** offset to the transition time. 01966 */ 01967 /* 01968 ** Transitions from DST to DDST 01969 ** will effectively disappear since 01970 ** POSIX provides for only one DST 01971 ** offset. 01972 */ 01973 if (isdst && !sp->ttis[j].tt_ttisstd) { 01974 sp->ats[i] += dstoffset - theirdstoffset; 01975 } else { 01976 sp->ats[i] += stdoffset - theirstdoffset; 01977 } 01978 } 01979 theiroffset = -sp->ttis[j].tt_gmtoff; 01980 if (sp->ttis[j].tt_isdst) 01981 theirdstoffset = theiroffset; 01982 else 01983 theirstdoffset = theiroffset; 01984 } 01985 /* 01986 ** Finally, fill in ttis. 01987 ** ttisstd and ttisgmt need not be handled. 01988 */ 01989 sp->ttis[0].tt_gmtoff = -stdoffset; 01990 sp->ttis[0].tt_isdst = FALSE; 01991 sp->ttis[0].tt_abbrind = 0; 01992 sp->ttis[1].tt_gmtoff = -dstoffset; 01993 sp->ttis[1].tt_isdst = TRUE; 01994 sp->ttis[1].tt_abbrind = (int) (stdlen + 1); 01995 sp->typecnt = 2; 01996 } 01997 } else { 01998 dstlen = 0; 01999 sp->typecnt = 1; /* only standard time */ 02000 sp->timecnt = 0; 02001 sp->ttis[0].tt_gmtoff = -stdoffset; 02002 sp->ttis[0].tt_isdst = 0; 02003 sp->ttis[0].tt_abbrind = 0; 02004 } 02005 02006 sp->charcnt = (int) (stdlen + 1); 02007 if (dstlen != 0) 02008 sp->charcnt += (int) (dstlen + 1); 02009 if ((size_t) sp->charcnt > sizeof sp->chars) 02010 return -1; 02011 cp = sp->chars; 02012 (void) strncpy(cp, stdname, stdlen); 02013 cp += stdlen; 02014 *cp++ = '\0'; 02015 if (dstlen != 0) { 02016 (void) strncpy(cp, dstname, dstlen); 02017 *(cp + dstlen) = '\0'; 02018 } 02019 return 0; 02020 }
| static void tztime | ( | const time_t *const | timep, | |
| const char * | tzstring, | |||
| struct tm *const | tmp | |||
| ) | [static] |
Definition at line 2137 of file switch_time.c.
References state::ats, state::chars, FALSE, gmt, state::timecnt, timesub(), ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and tzparse().
Referenced by switch_strftime_tz(), and switch_time_exp_tz_name().
02138 { 02139 struct state *tzptr, *sp; 02140 const time_t t = *timep; 02141 register int i; 02142 register const struct ttinfo *ttisp; 02143 02144 if (tzstring == NULL) 02145 tzstring = gmt; 02146 02147 tzptr = (struct state *) malloc(sizeof(struct state)); 02148 sp = tzptr; 02149 02150 if (tzptr != NULL) { 02151 02152 memset(tzptr, 0, sizeof(struct state)); 02153 02154 (void) tzparse(tzstring, tzptr, FALSE); 02155 02156 if (sp->timecnt == 0 || t < sp->ats[0]) { 02157 i = 0; 02158 while (sp->ttis[i].tt_isdst) 02159 if (++i >= sp->typecnt) { 02160 i = 0; 02161 break; 02162 } 02163 } else { 02164 for (i = 1; i < sp->timecnt; ++i) 02165 if (t < sp->ats[i]) 02166 break; 02167 i = sp->types[i - 1]; // DST begin or DST end 02168 } 02169 ttisp = &sp->ttis[i]; 02170 02171 /* 02172 To get (wrong) behavior that's compatible with System V Release 2.0 02173 you'd replace the statement below with 02174 t += ttisp->tt_gmtoff; 02175 timesub(&t, 0L, sp, tmp); 02176 */ 02177 if (tmp != NULL) { /* Just a check not to assert */ 02178 timesub(&t, ttisp->tt_gmtoff, sp, tmp); 02179 tmp->tm_isdst = ttisp->tt_isdst; 02180 #if defined(HAVE_STRUCT_TM_TM_ZONE) 02181 tmp->tm_zone = &sp->chars[ttisp->tt_abbrind]; 02182 #endif 02183 } 02184 02185 free(tzptr); 02186 } 02187 02188 }
| static void win32_init_timers | ( | void | ) | [static] |
Definition at line 711 of file switch_time.c.
Referenced by SWITCH_MODULE_LOAD_FUNCTION(), and SWITCH_MODULE_RUNTIME_FUNCTION().
00712 { 00713 #ifdef WIN32 00714 OSVERSIONINFOEX version_info; /* Used to fetch current OS version from Windows */ 00715 00716 EnterCriticalSection(&timer_section); 00717 00718 ZeroMemory(&version_info, sizeof(OSVERSIONINFOEX)); 00719 version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 00720 00721 /* Check if we should use timeGetTime() (pre-Vista) or QueryPerformanceCounter() (Vista and later) */ 00722 00723 if (GetVersionEx((OSVERSIONINFO*) &version_info)) { 00724 if (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT && version_info.dwMajorVersion >= 6) { 00725 if (QueryPerformanceFrequency((LARGE_INTEGER*)&win32_qpc_freq) && win32_qpc_freq > 0) { 00726 /* At least Vista, and QueryPerformanceFrequency() suceeded, enable qpc */ 00727 win32_use_qpc = 1; 00728 } else { 00729 /* At least Vista, but QueryPerformanceFrequency() failed, disable qpc */ 00730 win32_use_qpc = 0; 00731 } 00732 } else { 00733 /* Older then Vista, disable qpc */ 00734 win32_use_qpc = 0; 00735 } 00736 } else { 00737 /* Unknown version - we want at least Vista, disable qpc */ 00738 win32_use_qpc = 0; 00739 } 00740 00741 if (win32_use_qpc) { 00742 uint64_t count = 0; 00743 00744 if (!QueryPerformanceCounter((LARGE_INTEGER*)&count) || count == 0) { 00745 /* Call to QueryPerformanceCounter() failed, disable qpc again */ 00746 win32_use_qpc = 0; 00747 } 00748 } 00749 00750 if (!win32_use_qpc) { 00751 /* This will enable timeGetTime() instead, qpc init failed */ 00752 win32_last_get_time_tick = timeGetTime(); 00753 win32_tick_time_since_start = win32_last_get_time_tick; 00754 } 00755 00756 LeaveCriticalSection(&timer_section); 00757 #endif 00758 }
int COND = 1 [static] |
Definition at line 90 of file switch_time.c.
Referenced by SWITCH_MODULE_RUNTIME_FUNCTION(), and switch_time_set_cond_yield().
struct { ... } globals [static] |
const char gmt[] = "GMT" [static] |
switch_time_t last_time = 0 [static] |
int MATRIX = 1 [static] |
Definition at line 92 of file switch_time.c.
Referenced by SWITCH_MODULE_RUNTIME_FUNCTION(), switch_time_set_cond_yield(), switch_time_set_matrix(), and timer_next().
switch_memory_pool_t* module_pool = NULL [static] |
Definition at line 103 of file switch_time.c.
Referenced by SWITCH_MODULE_LOAD_FUNCTION(), SWITCH_MODULE_RUNTIME_FUNCTION(), and timer_init().
const int mon_lengths[2][MONSPERYEAR] [static] |
Initial value:
{
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
}
Definition at line 1535 of file switch_time.c.
Referenced by timesub(), and transtime().
int MONO = 0 [static] |
Definition at line 70 of file switch_time.c.
Referenced by SWITCH_MODULE_LOAD_FUNCTION(), SWITCH_MODULE_RUNTIME_FUNCTION(), switch_time_set_monotonic(), and time_now().
Definition at line 109 of file switch_time.c.
int NANO = 0 [static] |
Definition at line 85 of file switch_time.c.
Referenced by do_sleep(), SWITCH_MODULE_RUNTIME_FUNCTION(), and switch_time_set_nanosleep().
switch_event_node_t* NODE = NULL [static] |
Definition at line 1071 of file switch_time.c.
Referenced by SWITCH_MODULE_LOAD_FUNCTION(), and SWITCH_MODULE_SHUTDOWN_FUNCTION().
int OFFSET = 0 [static] |
Definition at line 88 of file switch_time.c.
Referenced by do_sleep(), and switch_time_calibrate_clock().
| int32_t RUNNING |
Definition at line 106 of file switch_time.c.
| int32_t STARTED |
Definition at line 107 of file switch_time.c.
int TFD = 0 [static] |
Definition at line 84 of file switch_time.c.
Referenced by SWITCH_MODULE_LOAD_FUNCTION(), SWITCH_MODULE_RUNTIME_FUNCTION(), and switch_time_set_timerfd().
| uint32_t timer_count |
Definition at line 110 of file switch_time.c.
timer_matrix_t TIMER_MATRIX[MAX_ELEMENTS+1] [static] |
Definition at line 141 of file switch_time.c.
Referenced by switch_cond_next(), switch_cond_yield(), SWITCH_MODULE_RUNTIME_FUNCTION(), timer_check(), timer_destroy(), timer_init(), timer_next(), and timer_sync().
switch_timezones_list_t TIMEZONES_LIST = { 0 } [static] |
Definition at line 1070 of file switch_time.c.
Referenced by switch_load_timezones(), switch_lookup_timezone(), and SWITCH_MODULE_SHUTDOWN_FUNCTION().
| int32_t use_cond_yield |
Definition at line 108 of file switch_time.c.
const int year_lengths[2] [static] |
1.4.7