xref: /PHP-5.5/win32/time.c (revision b022e54b)
1 /*****************************************************************************
2  *                                                                           *
3  * DH_TIME.C                                                                 *
4  *                                                                           *
5  * Freely redistributable and modifiable.  Use at your own risk.             *
6  *                                                                           *
7  * Copyright 1994 The Downhill Project                                       *
8  *
9  * Modified by Shane Caraveo for use with PHP
10  *
11  *****************************************************************************/
12 
13 /* $Id$ */
14 
15 /* Include stuff ************************************************************ */
16 
17 #include <config.w32.h>
18 
19 #include "time.h"
20 #include "unistd.h"
21 #include "signal.h"
22 #include <windows.h>
23 #include <winbase.h>
24 #include <mmsystem.h>
25 #include <errno.h>
26 #include "php_win32_globals.h"
27 
28 typedef VOID (WINAPI *MyGetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTime);
29 
get_time_func(void)30 static MyGetSystemTimeAsFileTime get_time_func(void)
31 {
32 	MyGetSystemTimeAsFileTime timefunc = NULL;
33 	HMODULE hMod = LoadLibrary("kernel32.dll");
34 
35 	if (hMod) {
36 		/* Max possible resolution <1us, win8/server2012 */
37 		timefunc = (MyGetSystemTimeAsFileTime)GetProcAddress(hMod, "GetSystemTimePreciseAsFileTime");
38 
39 		if(!timefunc) {
40 			/* 100ns blocks since 01-Jan-1641 */
41 			timefunc = (MyGetSystemTimeAsFileTime)GetProcAddress(hMod, "GetSystemTimeAsFileTime");
42 		}
43 	}
44 
45 	return timefunc;
46 }
47 
getfilesystemtime(struct timeval * tv)48 int getfilesystemtime(struct timeval *tv)
49 {
50 	FILETIME ft;
51 	unsigned __int64 ff = 0;
52 	MyGetSystemTimeAsFileTime timefunc;
53 	ULARGE_INTEGER fft;
54 
55 	timefunc = get_time_func();
56 	if (timefunc) {
57 		timefunc(&ft);
58 	} else {
59 		GetSystemTimeAsFileTime(&ft);
60 	}
61 
62         /*
63 	 * Do not cast a pointer to a FILETIME structure to either a
64 	 * ULARGE_INTEGER* or __int64* value because it can cause alignment faults on 64-bit Windows.
65 	 * via  http://technet.microsoft.com/en-us/library/ms724284(v=vs.85).aspx
66 	 */
67 	fft.HighPart = ft.dwHighDateTime;
68 	fft.LowPart = ft.dwLowDateTime;
69 	ff = fft.QuadPart;
70 
71 	ff /= 10Ui64; /* convert to microseconds */
72 	ff -= 11644473600000000Ui64; /* convert to unix epoch */
73 
74 	tv->tv_sec = (long)(ff / 1000000Ui64);
75 	tv->tv_usec = (long)(ff % 1000000Ui64);
76 
77 	return 0;
78 }
79 
gettimeofday(struct timeval * time_Info,struct timezone * timezone_Info)80 PHPAPI int gettimeofday(struct timeval *time_Info, struct timezone *timezone_Info)
81 {
82 	/* Get the time, if they want it */
83 	if (time_Info != NULL) {
84 		getfilesystemtime(time_Info);
85 	}
86 	/* Get the timezone, if they want it */
87 	if (timezone_Info != NULL) {
88 		_tzset();
89 		timezone_Info->tz_minuteswest = _timezone;
90 		timezone_Info->tz_dsttime = _daylight;
91 	}
92 	/* And return */
93 	return 0;
94 }
95 
usleep(unsigned int useconds)96 PHPAPI int usleep(unsigned int useconds)
97 {
98 	HANDLE timer;
99 	LARGE_INTEGER due;
100 
101 	due.QuadPart = -(10 * (__int64)useconds);
102 
103 	timer = CreateWaitableTimer(NULL, TRUE, NULL);
104 	SetWaitableTimer(timer, &due, 0, NULL, NULL, 0);
105 	WaitForSingleObject(timer, INFINITE);
106 	CloseHandle(timer);
107 	return 0;
108 }
109 
nanosleep(const struct timespec * rqtp,struct timespec * rmtp)110 PHPAPI int nanosleep( const struct timespec * rqtp, struct timespec * rmtp )
111 {
112 	if (rqtp->tv_nsec > 999999999) {
113 		/* The time interval specified 1,000,000 or more microseconds. */
114 		errno = EINVAL;
115 		return -1;
116 	}
117 	return usleep( rqtp->tv_sec * 1000000 + rqtp->tv_nsec / 1000  );
118 }
119 
120 #if 0 /* looks pretty ropey in here */
121 #ifdef HAVE_SETITIMER
122 
123 
124 #ifndef THREAD_SAFE
125 unsigned int proftimer, virttimer, realtimer;
126 extern LPMSG phpmsg;
127 #endif
128 
129 struct timer_msg {
130 	int signal;
131 	unsigned int threadid;
132 };
133 
134 
135 LPTIMECALLBACK setitimer_timeout(UINT uTimerID, UINT info, DWORD dwUser, DWORD dw1, DWORD dw2)
136 {
137 	struct timer_msg *msg = (struct timer_msg *) info;
138 
139 	if (msg) {
140 		raise((int) msg->signal);
141 		PostThreadMessage(msg->threadid,
142 						  WM_NOTIFY, msg->signal, 0);
143 		free(msg);
144 	}
145 	return 0;
146 }
147 
148 PHPAPI int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
149 {
150 	int timeout = value->it_value.tv_sec * 1000 + value->it_value.tv_usec;
151 	int repeat = TIME_ONESHOT;
152 
153 	/*make sure the message queue is initialized */
154 	PeekMessage(phpmsg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
155 	if (timeout > 0) {
156 		struct timer_msg *msg = malloc(sizeof(struct timer_msg));
157 		msg->threadid = GetCurrentThreadId();
158 		if (!ovalue) {
159 			repeat = TIME_PERIODIC;
160 		}
161 		switch (which) {
162 			case ITIMER_REAL:
163 				msg->signal = SIGALRM;
164 				realtimer = timeSetEvent(timeout, 100, (LPTIMECALLBACK) setitimer_timeout, (UINT) msg, repeat);
165 				break;
166 			case ITIMER_VIRT:
167 				msg->signal = SIGVTALRM;
168 				virttimer = timeSetEvent(timeout, 100, (LPTIMECALLBACK) setitimer_timeout, (UINT) msg, repeat);
169 				break;
170 			case ITIMER_PROF:
171 				msg->signal = SIGPROF;
172 				proftimer = timeSetEvent(timeout, 100, (LPTIMECALLBACK) setitimer_timeout, (UINT) msg, repeat);
173 				break;
174 			default:
175 				errno = EINVAL;
176 				return -1;
177 				break;
178 		}
179 	} else {
180 		switch (which) {
181 			case ITIMER_REAL:
182 				timeKillEvent(realtimer);
183 				break;
184 			case ITIMER_VIRT:
185 				timeKillEvent(virttimer);
186 				break;
187 			case ITIMER_PROF:
188 				timeKillEvent(proftimer);
189 				break;
190 			default:
191 				errno = EINVAL;
192 				return -1;
193 				break;
194 		}
195 	}
196 
197 
198 	return 0;
199 }
200 
201 #endif
202 #endif
203 
204