time.c 5.0 KB

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