switch_time.c File Reference

#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_tmodule_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_tNODE = NULL
static const char gmt [] = "GMT"
static const int mon_lengths [2][MONSPERYEAR]
static const int year_lengths [2]


Define Documentation

#define BIGGEST ( a,
 )     (((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--

Definition at line 207 of file switch_time.c.

Referenced by switch_time_calibrate_clock().

#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

Definition at line 1396 of file switch_time.c.

Referenced by getrule(), and transtime().

#define DAYSPERLYEAR   366

Definition at line 1390 of file switch_time.c.

Referenced by getrule().

#define DAYSPERNYEAR   365

Definition at line 1389 of file switch_time.c.

Referenced by getrule(), and timesub().

#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

Definition at line 1489 of file switch_time.c.

Referenced by timesub().

#define EPOCH_YEAR   1970

Definition at line 1488 of file switch_time.c.

#define EPOCH_YEAR   1970

Definition at line 1488 of file switch_time.c.

Referenced by timesub(), and tzparse().

#define FALSE   0

Definition at line 1336 of file switch_time.c.

#define HOURSPERDAY   24

Definition at line 1387 of file switch_time.c.

Referenced by getsecs().

#define IDLE_SPEED   100

Definition at line 60 of file switch_time.c.

#define INITIALIZE (  ) 

Definition at line 1460 of file switch_time.c.

Referenced by transtime(), and tzparse().

#define is_digit (  )     ((unsigned)(c) - '0' <= 9)

Definition at line 1429 of file switch_time.c.

Referenced by getnum(), getrule(), and getzname().

#define isleap (  )     (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))

Definition at line 1433 of file switch_time.c.

Referenced by timesub(), transtime(), and tzparse().

#define JULIAN_DAY   0

Definition at line 1395 of file switch_time.c.

Referenced by getrule(), and transtime().

#define LEAPS_THRU_END_OF (  )     ((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

Definition at line 57 of file switch_time.c.

Referenced by SWITCH_MODULE_RUNTIME_FUNCTION().

#define MINSPERHOUR   60

Definition at line 1386 of file switch_time.c.

Referenced by getsecs().

#define MONSPERYEAR   12

Definition at line 1393 of file switch_time.c.

Referenced by getrule().

#define MONTH_NTH_DAY_OF_WEEK   2

Definition at line 1397 of file switch_time.c.

Referenced by getrule(), and transtime().

#define MY_TZNAME_MAX   255

Definition at line 1381 of file switch_time.c.

#define SECSPERDAY   ((long) SECSPERHOUR * HOURSPERDAY)

Definition at line 1392 of file switch_time.c.

Referenced by timesub(), transtime(), and tzparse().

#define SECSPERHOUR   (SECSPERMIN * MINSPERHOUR)

Definition at line 1391 of file switch_time.c.

Referenced by getrule(), getsecs(), timesub(), and tzparse().

#define SECSPERMIN   60

Definition at line 1385 of file switch_time.c.

Referenced by getsecs(), and timesub().

#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

Definition at line 1486 of file switch_time.c.

Referenced by timesub().

#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

Definition at line 1348 of file switch_time.c.

Referenced by tzparse().

#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

Definition at line 54 of file switch_time.c.

Referenced by timer_step().


Typedef Documentation

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.


Function Documentation

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.

References NANO, and OFFSET.

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 }


Variable Documentation

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]

Definition at line 1496 of file switch_time.c.

Referenced by tztime().

switch_time_t last_time = 0 [static]

Definition at line 426 of file switch_time.c.

Referenced by switch_time_sync().

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().

switch_mutex_t* mutex

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]

Initial value:

Definition at line 1540 of file switch_time.c.

Referenced by timesub(), and tzparse().


Generated on Sun May 20 04:00:14 2012 for FreeSWITCH API Documentation by  doxygen 1.4.7