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