From: Dongsheng S. <don...@gm...> - 2011-09-03 06:26:34
|
From: Dongsheng Song <don...@ap...> --- mingw-w64-crt/Makefile.am | 2 + mingw-w64-crt/misc/nanosleep.c | 67 ++++++++++++++++++++++++ mingw-w64-crt/testcases/t_nanosleep.c | 92 +++++++++++++++++++++++++++++++++ mingw-w64-headers/crt/time.h | 58 +++++++++++++++++++- 4 files changed, 216 insertions(+), 3 deletions(-) create mode 100644 mingw-w64-crt/misc/nanosleep.c create mode 100644 mingw-w64-crt/testcases/t_nanosleep.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index bc20948..1dd795a 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -222,6 +222,7 @@ src_libmingwex=\ misc/wctype.c misc/wdirent.c misc/winbs_uint64.c misc/winbs_ulong.c misc/winbs_ushort.c \ misc/wmemchr.c misc/wmemcmp.c misc/wmemcpy.c misc/wmemmove.c misc/wmemset.c \ misc/wcstof.c misc/mingw_wcstod.c misc/mingw_wcstof.c misc/mingw_wcstold.c \ + misc/nanosleep.c \ stdio/mingw_pformat.h \ stdio/atoll.c stdio/_Exit.c stdio/_findfirst64i32.c \ stdio/_findnext64i32.c stdio/fopen64.c \ @@ -1049,6 +1050,7 @@ testcase_progs = \ testcases/t_intrinc \ testcases/t_imagebase \ testcases/t_matherr \ + testcases/t_nanosleep \ testcases/t_nullptrexception \ testcases/t_readdir \ testcases/t_setjmp \ diff --git a/mingw-w64-crt/misc/nanosleep.c b/mingw-w64-crt/misc/nanosleep.c new file mode 100644 index 0000000..10c6c68 --- /dev/null +++ b/mingw-w64-crt/misc/nanosleep.c @@ -0,0 +1,67 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the w64 mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <errno.h> +#include <time.h> +#include <windows.h> + +#define POW10_3 1000 +#define POW10_4 10000 +#define POW10_6 1000000 +#define POW10_9 1000000000 +#define MAX_SLEEP_IN_MS 4294967294UL + +/** + * Sleep for the specified time. + * @param request The desired amount of time to sleep. + * @param remain The remain amount of time to sleep. + * @return If the function succeeds, the return value is 0. + * If the function fails, the return value is -1, + * with errno set to indicate the error. + */ +int nanosleep(const struct timespec *request, struct timespec *remain) +{ + unsigned long ms, rc = 0; + unsigned __int64 u64, want, real; + + union { + unsigned __int64 ns100; + FILETIME ft; + } _start, _end; + + if (request->tv_sec < 0 || request->tv_nsec < 0 || request->tv_nsec >= POW10_9) { + errno = EINVAL; + return -1; + } + + if (remain != NULL) GetSystemTimeAsFileTime(&_start.ft); + + want = u64 = request->tv_sec * POW10_3 + request->tv_nsec / POW10_6; + while (u64 > 0 && rc == 0) { + if (u64 >= MAX_SLEEP_IN_MS) ms = MAX_SLEEP_IN_MS; + else ms = (unsigned long) u64; + + u64 -= ms; + rc = SleepEx(ms, TRUE); + } + + if (rc != 0) { /* WAIT_IO_COMPLETION (192) */ + if (remain != NULL) { + GetSystemTimeAsFileTime(&_end.ft); + real = (_end.ns100 - _start.ns100) / POW10_4; + + if (real >= want) u64 = 0; + else u64 = want - real; + + remain->tv_sec = u64 / POW10_3; + remain->tv_nsec = (long) (u64 % POW10_3) * POW10_6; + } + + errno = EINTR; + return -1; + } + + return 0; +} diff --git a/mingw-w64-crt/testcases/t_nanosleep.c b/mingw-w64-crt/testcases/t_nanosleep.c new file mode 100644 index 0000000..21c0ceb --- /dev/null +++ b/mingw-w64-crt/testcases/t_nanosleep.c @@ -0,0 +1,92 @@ +#include <process.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#include <windows.h> + +#define POW10_3 1000 +#define POW10_6 1000000 + +extern int __cdecl getntptimeofday(struct timespec *tp, struct timezone *tz); + +__int64 timespec_diff_as_ms(struct timespec *__old, struct timespec *__new) +{ + return (__new->tv_sec - __old->tv_sec) * POW10_3 + + (__new->tv_nsec - __old->tv_nsec) / POW10_6; +} + +unsigned __stdcall start_address(void *dummy) +{ + int counter = 0; + struct timespec request = { 1, 0 }, remain; + + while (counter < 5) { + int rc = nanosleep(&request, &remain); + if (rc != 0) { + printf("nanosleep interrupted, remain %d.%09d sec.\n", + (int) remain.tv_sec, (int) remain.tv_nsec); + } else { + printf("nanosleep succeeded.\n"); + } + + counter ++; + } + + return 0; +} + +void WINAPI usr_apc(ULONG_PTR dwParam) +{ + long *index = (long *) dwParam; + printf("running apc %ld\n", *index); +} + +void test_apc() +{ + long i, rc, data[5]; + HANDLE thread; + + thread = (HANDLE) _beginthreadex(NULL, 0, start_address, NULL, 0, NULL); + if (thread == NULL) { + exit(1); + } + + for (i = 0; i < 5; i++) { + data[i] = i; + Sleep(250 + rand() % 250); + rc = QueueUserAPC(usr_apc, thread, (ULONG_PTR) & data[i]); + if (rc == 0) { + printf("QueueUserAPC failed: %ld\n", GetLastError()); + exit(1); + } + } + + rc = WaitForSingleObject(thread, INFINITE); + if (rc != WAIT_OBJECT_0) { + printf("WaitForSingleObject failed with %ld: %ld\n", rc, GetLastError()); + exit(1); + } +} + +int main(int argc, char *argv[]) +{ + int rc; + struct timespec tp, tp2, request = { 1, 0 }, remain; + + getntptimeofday(&tp, NULL); + rc = nanosleep(&request, &remain); + getntptimeofday(&tp2, NULL); + + if (rc != 0) { + printf("remain: %d.%09d\n", (int) remain.tv_sec, (int) remain.tv_nsec); + } + + printf("%d.%09d\n", (int) tp.tv_sec, (int) tp.tv_nsec); + printf("%d.%09d\n", (int) tp2.tv_sec, (int) tp2.tv_nsec); + printf("sleep %d ms\n\n", (int) timespec_diff_as_ms(&tp, &tp2)); + + test_apc(); + + return 0; +} diff --git a/mingw-w64-headers/crt/time.h b/mingw-w64-headers/crt/time.h index f1c8d1f..8c6d82f 100644 --- a/mingw-w64-headers/crt/time.h +++ b/mingw-w64-headers/crt/time.h @@ -12,6 +12,9 @@ #error Only Win32 target is supported! #endif +/* Adding timespec definition. */ +#include <sys/timeb.h> + #pragma pack(push,_CRT_PACKING) #ifdef __cplusplus @@ -51,6 +54,51 @@ extern "C" { typedef long clock_t; #endif +/* Posix timers are supported */ +#ifndef _POSIX_TIMERS + #define _POSIX_TIMERS 200809L +#endif + +/* Monotonic clocks are available. */ +#ifndef _POSIX_MONOTONIC_CLOCK + #define _POSIX_MONOTONIC_CLOCK 200809L +#endif + +/* CPU-time clocks are available. */ +#ifndef _POSIX_CPUTIME + #define _POSIX_CPUTIME 200809L +#endif + +/* Clock support in threads are available. */ +#ifndef _POSIX_THREAD_CPUTIME + #define _POSIX_THREAD_CPUTIME 200809L +#endif + +#ifndef __clockid_t_defined + typedef int clockid_t; + #define __clockid_t_defined 1 +#endif /* __clockid_t_defined */ + +#ifndef TIMER_ABSTIME + #define TIMER_ABSTIME 1 +#endif + +#ifndef CLOCK_REALTIME +#define CLOCK_REALTIME 0 +#endif + +#ifndef CLOCK_MONOTONIC +#define CLOCK_MONOTONIC 1 +#endif + +#ifndef CLOCK_PROCESS_CPUTIME_ID +#define CLOCK_PROCESS_CPUTIME_ID 2 +#endif + +#ifndef CLOCK_THREAD_CPUTIME_ID +#define CLOCK_THREAD_CPUTIME_ID 3 +#endif + #ifndef _SIZE_T_DEFINED #define _SIZE_T_DEFINED #undef size_t @@ -221,6 +269,13 @@ time_t __cdecl mktime(struct tm *_Tm); time_t __cdecl _mkgmtime(struct tm *_Tm); time_t __cdecl time(time_t *_Time); +int __cdecl nanosleep(const struct timespec *request, struct timespec *remain); + +int __cdecl clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, struct timespec *remain); +int __cdecl clock_getres(clockid_t clock_id, struct timespec *res); +int __cdecl clock_gettime(clockid_t clock_id, struct timespec *tp); +int __cdecl clock_settime(clockid_t clock_id, const struct timespec *tp); + #ifndef __CRT__NO_INLINE #ifndef _USE_32BIT_TIME_T __CRT_INLINE double __cdecl difftime(time_t _Time1,time_t _Time2) @@ -273,8 +328,5 @@ struct timezone { #include <sec_api/time_s.h> -/* Adding timespec definition. */ -#include <sys/timeb.h> - #endif /* End _TIME_H_ */ -- 1.7.5.4 |