> * These need to be made MT-safe: > > mktime, mktime-internal > timegm > > time_r > > time_rz > c-nstrftime, nstrftime > parse-datetime, parse-datetime2
For these modules, the next function to provide in an MT-safe way is localtime_r. On native Windows, when the 'localtime_s' function [1][2] is not available, such as on the older Windows versions that Emacs cares about, the solution is to use GetTimeZoneInformation [3]. The next function, then, is a localtime_r variant with time zone argument. It's needed * for implementing 'localtime_rz', in the 'time_rz' module. * as a 'convert' subroutine for the 'mktime_z' function, in the 'time_rz' module. * indirectly by nstrftime, c-nstrftime, fprintftime, parse-datetime, that all rely on 'time_rz'. Such a localtime_r variant with time zone argument needs to use the time zone database that the system has access to. But the only public API that the system offers (localtime{,_r}) relies on the environment "TZ" variable "TZ" and some global variables (tzname, timezone, daylight) derived from it, and changing an environment variable is not MT-safe. So, there are only two approaches that I can see: (a) Read the time zone database information into memory from a file shipped together with Gnulib. This is how the libstdc++ implementation of the C++ time zone functionality [4] does it [5][6]. (b) Read the time zone database information into memory from the system locations, in a platform dependent way. The code for doing this exists in glibc and libstdc++ and would need to be adapted. BUT this is a major project: it would take several weeks. And it is overkill for - the proposed safer_ctime function, - most practical uses of nstrftime, c_nstrftime. Namely, for these cases, a general timezone_t is not needed, only a boolean that covers the case of local time and GMT/UTC. And these cases *can* be done in a multithread-safe way: - The value of "TZ" does not need to be changed on the fly. - The values of the global variables (tzname, timezone, daylight) may be set through tzset(), in a thread, but these values are OK for the other threads as well, since getenv ("TZ") is the same in all threads. - The GMT/UTC case can be implemented by not looking at "TZ" nor the global variables. I therefore intend to do this latter part: 1) Make localtime_r on native Windows MT-safe. 2) Document which LGPLed interfaces are not MT-safe. 3) Provide an MT-safe and bug-fixed 'strftime' function (that assumes local time, no time zone argument). 4) Provide an analogous 'c_strftime' function that does not even access "TZ". 5) The proposed safer_ctime, based on localtime_r and c_strftime. Bruno [1] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s [2] https://learn.microsoft.com/en-us/previous-versions/a442x3ye [3] https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-gettimezoneinformation [4] https://en.cppreference.com/w/cpp/chrono [5] https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/include/std/chrono [6] https://gcc.gnu.org/git/?p=gcc.git;a=tree;f=libstdc%2B%2B-v3/src/c%2B%2B20