Commit 06c1a36b authored by Alexandre Julliard's avatar Alexandre Julliard

msvcrt: Return a per-thread buffer in localtime and gmtime.

parent 2bb87a90
...@@ -74,6 +74,18 @@ typedef void (*MSVCRT__beginthread_start_routine_t)(void *); ...@@ -74,6 +74,18 @@ typedef void (*MSVCRT__beginthread_start_routine_t)(void *);
typedef unsigned int (__stdcall *MSVCRT__beginthreadex_start_routine_t)(void *); typedef unsigned int (__stdcall *MSVCRT__beginthreadex_start_routine_t)(void *);
typedef int (*MSVCRT__onexit_t)(void); typedef int (*MSVCRT__onexit_t)(void);
struct MSVCRT_tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
/* TLS data */ /* TLS data */
extern DWORD msvcrt_tls_index; extern DWORD msvcrt_tls_index;
...@@ -84,6 +96,7 @@ struct __thread_data { ...@@ -84,6 +96,7 @@ struct __thread_data {
unsigned char *mbstok_next; /* next ptr for mbstok() */ unsigned char *mbstok_next; /* next ptr for mbstok() */
char *efcvt_buffer; /* buffer for ecvt/fcvt */ char *efcvt_buffer; /* buffer for ecvt/fcvt */
MSVCRT_wchar_t *wasctime_buffer; /* buffer for asctime */ MSVCRT_wchar_t *wasctime_buffer; /* buffer for asctime */
struct MSVCRT_tm time_buffer; /* buffer for localtime/gmtime */
int fpecode; int fpecode;
MSVCRT_terminate_function terminate_handler; MSVCRT_terminate_function terminate_handler;
MSVCRT_unexpected_function unexpected_handler; MSVCRT_unexpected_function unexpected_handler;
...@@ -173,18 +186,6 @@ extern unsigned msvcrt_create_io_inherit_block(STARTUPINFOA*); ...@@ -173,18 +186,6 @@ extern unsigned msvcrt_create_io_inherit_block(STARTUPINFOA*);
#define _RT_CRNL 252 #define _RT_CRNL 252
#define _RT_BANNER 255 #define _RT_BANNER 255
struct MSVCRT_tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
struct MSVCRT__timeb { struct MSVCRT__timeb {
MSVCRT_time_t time; MSVCRT_time_t time;
unsigned short millitm; unsigned short millitm;
......
...@@ -54,9 +54,6 @@ static inline int IsLeapYear(int Year) ...@@ -54,9 +54,6 @@ static inline int IsLeapYear(int Year)
#define TICKSPERMSEC 10000 #define TICKSPERMSEC 10000
#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC) #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
/* native uses a single static buffer for localtime/gmtime/mktime */
static struct MSVCRT_tm tm;
/********************************************************************** /**********************************************************************
* mktime (MSVCRT.@) * mktime (MSVCRT.@)
*/ */
...@@ -65,7 +62,7 @@ MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t) ...@@ -65,7 +62,7 @@ MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t)
MSVCRT_time_t secs; MSVCRT_time_t secs;
FILETIME lft, uft; FILETIME lft, uft;
ULONGLONG time; ULONGLONG time;
struct MSVCRT_tm ts; struct MSVCRT_tm ts, *ptm;
int cleaps, day; int cleaps, day;
ts=*t; ts=*t;
...@@ -125,7 +122,7 @@ MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t) ...@@ -125,7 +122,7 @@ MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t)
secs = time - SECS_1601_TO_1970; secs = time - SECS_1601_TO_1970;
/* compute tm_wday, tm_yday and renormalize the other fields of the /* compute tm_wday, tm_yday and renormalize the other fields of the
* tm structure */ * tm structure */
if( MSVCRT_localtime( &secs)) *t = tm; if ((ptm = MSVCRT_localtime( &secs ))) *t = *ptm;
return secs; return secs;
} }
...@@ -135,8 +132,8 @@ MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t) ...@@ -135,8 +132,8 @@ MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t)
*/ */
struct MSVCRT_tm* MSVCRT_localtime(const MSVCRT_time_t* secs) struct MSVCRT_tm* MSVCRT_localtime(const MSVCRT_time_t* secs)
{ {
thread_data_t * const data = msvcrt_get_thread_data();
int i; int i;
FILETIME ft, lft; FILETIME ft, lft;
SYSTEMTIME st; SYSTEMTIME st;
DWORD tzid; DWORD tzid;
...@@ -152,34 +149,37 @@ struct MSVCRT_tm* MSVCRT_localtime(const MSVCRT_time_t* secs) ...@@ -152,34 +149,37 @@ struct MSVCRT_tm* MSVCRT_localtime(const MSVCRT_time_t* secs)
if (st.wYear < 1970) return NULL; if (st.wYear < 1970) return NULL;
tm.tm_sec = st.wSecond; data->time_buffer.tm_sec = st.wSecond;
tm.tm_min = st.wMinute; data->time_buffer.tm_min = st.wMinute;
tm.tm_hour = st.wHour; data->time_buffer.tm_hour = st.wHour;
tm.tm_mday = st.wDay; data->time_buffer.tm_mday = st.wDay;
tm.tm_year = st.wYear - 1900; data->time_buffer.tm_year = st.wYear - 1900;
tm.tm_mon = st.wMonth - 1; data->time_buffer.tm_mon = st.wMonth - 1;
tm.tm_wday = st.wDayOfWeek; data->time_buffer.tm_wday = st.wDayOfWeek;
for (i = tm.tm_yday = 0; i < st.wMonth - 1; i++) { for (i = data->time_buffer.tm_yday = 0; i < st.wMonth - 1; i++) {
tm.tm_yday += MonthLengths[IsLeapYear(st.wYear)][i]; data->time_buffer.tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
} }
tm.tm_yday += st.wDay - 1; data->time_buffer.tm_yday += st.wDay - 1;
tzid = GetTimeZoneInformation(&tzinfo); tzid = GetTimeZoneInformation(&tzinfo);
if (tzid == TIME_ZONE_ID_INVALID) if (tzid == TIME_ZONE_ID_INVALID)
tm.tm_isdst = -1; data->time_buffer.tm_isdst = -1;
else else
tm.tm_isdst = (tzid == TIME_ZONE_ID_DAYLIGHT?1:0); data->time_buffer.tm_isdst = (tzid == TIME_ZONE_ID_DAYLIGHT?1:0);
return &tm; return &data->time_buffer;
} }
/*********************************************************************
* gmtime (MSVCRT.@)
*/
struct MSVCRT_tm* MSVCRT_gmtime(const MSVCRT_time_t* secs) struct MSVCRT_tm* MSVCRT_gmtime(const MSVCRT_time_t* secs)
{ {
thread_data_t * const data = msvcrt_get_thread_data();
int i; int i;
FILETIME ft; FILETIME ft;
SYSTEMTIME st; SYSTEMTIME st;
...@@ -192,21 +192,21 @@ struct MSVCRT_tm* MSVCRT_gmtime(const MSVCRT_time_t* secs) ...@@ -192,21 +192,21 @@ struct MSVCRT_tm* MSVCRT_gmtime(const MSVCRT_time_t* secs)
if (st.wYear < 1970) return NULL; if (st.wYear < 1970) return NULL;
tm.tm_sec = st.wSecond; data->time_buffer.tm_sec = st.wSecond;
tm.tm_min = st.wMinute; data->time_buffer.tm_min = st.wMinute;
tm.tm_hour = st.wHour; data->time_buffer.tm_hour = st.wHour;
tm.tm_mday = st.wDay; data->time_buffer.tm_mday = st.wDay;
tm.tm_year = st.wYear - 1900; data->time_buffer.tm_year = st.wYear - 1900;
tm.tm_mon = st.wMonth - 1; data->time_buffer.tm_mon = st.wMonth - 1;
tm.tm_wday = st.wDayOfWeek; data->time_buffer.tm_wday = st.wDayOfWeek;
for (i = tm.tm_yday = 0; i < st.wMonth - 1; i++) { for (i = data->time_buffer.tm_yday = 0; i < st.wMonth - 1; i++) {
tm.tm_yday += MonthLengths[IsLeapYear(st.wYear)][i]; data->time_buffer.tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
} }
tm.tm_yday += st.wDay - 1; data->time_buffer.tm_yday += st.wDay - 1;
tm.tm_isdst = 0; data->time_buffer.tm_isdst = 0;
return &tm; return &data->time_buffer;
} }
/********************************************************************** /**********************************************************************
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment