Bug Summary

File:src/switch_time.c
Location:line 1064, column 2
Description:Value stored to 'time_sync' is never read

Annotated Source Code

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)
61static int MONO = 1;
62#else
63static int MONO = 0;
64#endif
65
66
67static 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)
73static int TFD = 2;
74#if defined(HAVE_CLOCK_NANOSLEEP1)
75static int NANO = 1;
76#else
77static int NANO = 0;
78#endif
79#else
80static int TFD = 0;
81static int NANO = 0;
82#endif
83
84static int OFFSET = 0;
85
86static int COND = 1;
87
88static int MATRIX = 1;
89
90#ifdef WIN32
91static CRITICAL_SECTION timer_section;
92static switch_time_t win32_tick_time_since_start = -1;
93static DWORD win32_last_get_time_tick = 0;
94
95static uint8_t win32_use_qpc = 0;
96static uint64_t win32_qpc_freq = 0;
97#endif
98
99static switch_memory_pool_t *module_pool = NULL((void*)0);
100
101static 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
114SWITCH_MODULE_LOAD_FUNCTION(softtimer_load)switch_status_t softtimer_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
;
115SWITCH_MODULE_SHUTDOWN_FUNCTION(softtimer_shutdown)switch_status_t softtimer_shutdown (void);
116SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)switch_status_t softtimer_runtime (void);
117SWITCH_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
119struct timer_private {
120 switch_size_t reference;
121 switch_size_t start;
122 uint32_t roll;
123 uint32_t ready;
124};
125typedef struct timer_private timer_private_t;
126
127struct 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};
135typedef struct timer_matrix timer_matrix_t;
136
137static timer_matrix_t TIMER_MATRIX[MAX_ELEMENTS3600 + 1];
138
139static switch_time_t time_now(int64_t offset);
140
141SWITCH_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
150static 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
190static 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--
207SWITCH_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
310SWITCH_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
315SWITCH_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
321SWITCH_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
330SWITCH_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
341SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_use_system_time(switch_bool_t enable)
342{
343 SYSTEM_TIME = enable;
344}
345
346
347SWITCH_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
359SWITCH_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
365SWITCH_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
372SWITCH_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
381static 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
399struct interval_timer {
400 int fd;
401};
402typedef struct interval_timer interval_timer_t;
403
404static 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
436static 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
443static 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
461static 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
469static 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
484static 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
507static 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
520static 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
576SWITCH_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
587static switch_time_t last_time = 0;
588
589SWITCH_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
615SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_micro_sleep(switch_interval_time_t t)
616{
617 do_sleep(t);
618}
619
620SWITCH_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
638SWITCH_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
657SWITCH_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
679static 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
756static 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
791static 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
821static 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
884static 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
925static 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
970static 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
1019SWITCH_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;
Value stored to 'time_sync' is never read
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
1324static 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
1353typedef struct {
1354 switch_memory_pool_t *pool;
1355 switch_hash_t *hash;
1356} switch_timezones_list_t;
1357
1358static switch_timezones_list_t TIMEZONES_LIST = { 0 };
1359static switch_event_node_t *NODE = NULL((void*)0);
1360
1361SWITCH_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
1372void 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
1414static 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
1421static void tztime(const time_t *const timep, const char *tzstring, struct tm *const tmp);
1422
1423SWITCH_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
1454SWITCH_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";
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
1491SWITCH_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
1563SWITCH_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
1786static 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
1790struct 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
1798struct 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
1806struct lsinfo { /* leap second information */
1807 time_t ls_trans; /* transition time */
1808 long ls_corr; /* correction to apply */
1809};
1810
1811
1812struct 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
1825static 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
1830static 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
1846static 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
1863static 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
1891static 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
1930static 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
1954static 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
2008static 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
2098static 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
2321static 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
2427static 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 */