diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2023-05-11 09:50:22 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2023-06-12 12:22:17 -0400 |
commit | f5b6e7710fae76f031b899f24710b82e9c5602de (patch) | |
tree | 5d85c97420c77ff467e2f7629b34fa8c63ff0cf1 | |
parent | 36906834d9e6f8381e71ec3ddb66952c509ad869 (diff) | |
download | bfs-f5b6e7710fae76f031b899f24710b82e9c5602de.tar.xz |
xtime: Make lazy tzset() call thread-safe
-rw-r--r-- | src/xtime.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/src/xtime.c b/src/xtime.c index 406d694..79dafad 100644 --- a/src/xtime.c +++ b/src/xtime.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: 0BSD #include "xtime.h" +#include "atomic.h" #include "config.h" #include <errno.h> #include <limits.h> @@ -10,15 +11,19 @@ #include <time.h> #include <unistd.h> -/** Whether tzset() has been called. */ -static bool tz_is_set = false; +/** Call tzset() if necessary. */ +static void xtzset(void) { + static atomic bool is_set = false; -int xlocaltime(const time_t *timep, struct tm *result) { - // Should be called before localtime_r() according to POSIX.1-2004 - if (!tz_is_set) { + if (!load(&is_set, relaxed)) { tzset(); - tz_is_set = true; + store(&is_set, true, relaxed); } +} + +int xlocaltime(const time_t *timep, struct tm *result) { + // Should be called before localtime_r() according to POSIX.1-2004 + xtzset(); if (localtime_r(timep, result)) { return 0; @@ -29,10 +34,7 @@ int xlocaltime(const time_t *timep, struct tm *result) { int xgmtime(const time_t *timep, struct tm *result) { // Should be called before gmtime_r() according to POSIX.1-2004 - if (!tz_is_set) { - tzset(); - tz_is_set = true; - } + xtzset(); if (gmtime_r(timep, result)) { return 0; |