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