summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2023-05-11 09:50:22 -0400
committerTavian Barnes <tavianator@tavianator.com>2023-06-12 12:22:17 -0400
commitf5b6e7710fae76f031b899f24710b82e9c5602de (patch)
tree5d85c97420c77ff467e2f7629b34fa8c63ff0cf1
parent36906834d9e6f8381e71ec3ddb66952c509ad869 (diff)
downloadbfs-f5b6e7710fae76f031b899f24710b82e9c5602de.tar.xz
xtime: Make lazy tzset() call thread-safe
-rw-r--r--src/xtime.c22
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;