From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Paul Eggert Newsgroups: gmane.emacs.bugs Subject: bug#32746: stop using obsolescent setitimer API Date: Sun, 16 Sep 2018 13:19:45 -0700 Organization: UCLA Computer Science Department Message-ID: <3c8e16a0-bae6-4ee7-d8e1-5da307ff6e84@cs.ucla.edu> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------7B671F95A44ECB3DC958A8C3" X-Trace: blaine.gmane.org 1537129151 8716 195.159.176.226 (16 Sep 2018 20:19:11 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Sun, 16 Sep 2018 20:19:11 +0000 (UTC) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 To: 32746@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sun Sep 16 22:19:07 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g1dVa-00028i-Iv for geb-bug-gnu-emacs@m.gmane.org; Sun, 16 Sep 2018 22:19:06 +0200 Original-Received: from localhost ([::1]:60146 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1dXg-0000Hh-Oc for geb-bug-gnu-emacs@m.gmane.org; Sun, 16 Sep 2018 16:21:16 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:37431) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1dXY-0000Ha-6Q for bug-gnu-emacs@gnu.org; Sun, 16 Sep 2018 16:21:10 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1dXT-0004mD-22 for bug-gnu-emacs@gnu.org; Sun, 16 Sep 2018 16:21:08 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:38067) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1g1dXS-0004m2-Qn for bug-gnu-emacs@gnu.org; Sun, 16 Sep 2018 16:21:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1g1dXS-0001xP-I6 for bug-gnu-emacs@gnu.org; Sun, 16 Sep 2018 16:21:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Paul Eggert Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 16 Sep 2018 20:21:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 32746 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: X-Debbugs-Original-To: Emacs bug reports and feature requests Original-Received: via spool by submit@debbugs.gnu.org id=B.15371292087431 (code B ref -1); Sun, 16 Sep 2018 20:21:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 16 Sep 2018 20:20:08 +0000 Original-Received: from localhost ([127.0.0.1]:42325 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g1dWZ-0001vk-Cx for submit@debbugs.gnu.org; Sun, 16 Sep 2018 16:20:08 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:44379) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g1dWW-0001v7-E8 for submit@debbugs.gnu.org; Sun, 16 Sep 2018 16:20:06 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1dWP-00036g-9r for submit@debbugs.gnu.org; Sun, 16 Sep 2018 16:19:59 -0400 Original-Received: from lists.gnu.org ([2001:4830:134:3::11]:41574) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1g1dWP-00036Y-4l for submit@debbugs.gnu.org; Sun, 16 Sep 2018 16:19:57 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:37111) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1dWM-00007E-Ui for bug-gnu-emacs@gnu.org; Sun, 16 Sep 2018 16:19:56 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1dWH-00030F-Rp for bug-gnu-emacs@gnu.org; Sun, 16 Sep 2018 16:19:54 -0400 Original-Received: from zimbra.cs.ucla.edu ([131.179.128.68]:49244) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1g1dWH-0002ys-AC for bug-gnu-emacs@gnu.org; Sun, 16 Sep 2018 16:19:49 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 513E11614C4 for ; Sun, 16 Sep 2018 13:19:48 -0700 (PDT) Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id 1Bq5-6zz8Zni for ; Sun, 16 Sep 2018 13:19:45 -0700 (PDT) Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 98ED5161511 for ; Sun, 16 Sep 2018 13:19:45 -0700 (PDT) X-Virus-Scanned: amavisd-new at zimbra.cs.ucla.edu Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id GH7pxcVai4SR for ; Sun, 16 Sep 2018 13:19:45 -0700 (PDT) Original-Received: from [192.168.1.9] (cpe-23-242-74-103.socal.res.rr.com [23.242.74.103]) by zimbra.cs.ucla.edu (Postfix) with ESMTPSA id 69A631614C4 for ; Sun, 16 Sep 2018 13:19:45 -0700 (PDT) Content-Language: en-US X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:150353 Archived-At: This is a multi-part message in MIME format. --------------7B671F95A44ECB3DC958A8C3 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit POSIX obsoleted the getitimer/setitimer API a decade ago, and now's a good time for Emacs to stop using this obsolescent API, partly to simplify other timestamp improvements that I have in mind, partly to head off any other lurking bugs like the problem I just fixed in commit 238c7cd730819ddba2dbde3c46ee36136575695b relating to a mistaken assumption about the old API. Attached please find two proposed patches. The first simplifies Emacs proper to just use the current timer_gettime/timer_settime API instead (this is the standard replacement for the obsolescent API). The second patch affects only the MS-Windows code, modifying it to use the new API instead of the old one; I haven't tested it as I don't use MS-Windows. --------------7B671F95A44ECB3DC958A8C3 Content-Type: text/x-patch; name="0001-Simplify-by-not-worrying-about-setitimer.patch" Content-Disposition: attachment; filename="0001-Simplify-by-not-worrying-about-setitimer.patch" Content-Transfer-Encoding: quoted-printable >From 57c9f6a9dfd070fba31da73bfaa14769324be668 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 16 Sep 2018 09:02:15 -0700 Subject: [PATCH 1/2] Simplify by not worrying about setitimer MIME-Version: 1.0 Content-Type: text/plain; charset=3DUTF-8 Content-Transfer-Encoding: 8bit For a decade, POSIX has recommended that applications use timer_settime, not the obsolescent setitimer function. By now support for timer_settime is universal on POSIXish platforms, so it=E2=80=99s time to drop attempts to use setitimer. * configure.ac: Do not check for setitimer. * src/atimer.c (start_atimer, set_alarm) (debug_timer_callback): * src/profiler.c (setup_cpu_timer, Fprofiler_cpu_stop): * src/syssignal.h (PROFILER_CPU_SUPPORT): Simplify by not worrying about setitimer. * src/profiler.c (SETITIMER_RUNNING): Remove. All uses removed. --- admin/CPP-DEFINES | 1 - configure.ac | 2 +- src/atimer.c | 15 ++------------- src/profiler.c | 20 +------------------- src/syssignal.h | 3 +-- 5 files changed, 5 insertions(+), 36 deletions(-) diff --git a/admin/CPP-DEFINES b/admin/CPP-DEFINES index 04d1ff76f3..86a9a3c820 100644 --- a/admin/CPP-DEFINES +++ b/admin/CPP-DEFINES @@ -251,7 +251,6 @@ HAVE_RSVG HAVE_SELECT HAVE_SENDTO HAVE_SEQPACKET -HAVE_SETITIMER HAVE_SETLOCALE HAVE_SETRLIMIT HAVE_SHARED_GAME_DIR diff --git a/configure.ac b/configure.ac index 6f3d7338c3..9277f3789f 100644 --- a/configure.ac +++ b/configure.ac @@ -4013,7 +4013,7 @@ AC_DEFUN lrand48 random rint trunc \ select getpagesize setlocale newlocale \ getrlimit setrlimit shutdown \ -pthread_sigmask strsignal setitimer \ +pthread_sigmask strsignal \ sendto recvfrom getsockname getifaddrs freeifaddrs \ gai_strerror sync \ getpwent endpwent getgrent endgrent \ diff --git a/src/atimer.c b/src/atimer.c index 505f6bcea1..5848627d45 100644 --- a/src/atimer.c +++ b/src/atimer.c @@ -113,7 +113,7 @@ start_atimer (enum atimer_type type, struct timespec = timestamp, sigset_t oldset; =20 /* Round TIMESTAMP up to the next full second if we don't have itimers= . */ -#if ! (defined HAVE_ITIMERSPEC || defined HAVE_SETITIMER) +#ifndef HAVE_ITIMERSPEC if (timestamp.tv_nsec !=3D 0 && timestamp.tv_sec < TYPE_MAXIMUM (time_= t)) timestamp =3D make_timespec (timestamp.tv_sec + 1, 0); #endif @@ -295,9 +295,6 @@ set_alarm (void) { if (atimers) { -#ifdef HAVE_SETITIMER - struct itimerval it; -#endif struct timespec now, interval; =20 #ifdef HAVE_ITIMERSPEC @@ -325,15 +322,7 @@ set_alarm (void) interval =3D (timespec_cmp (atimers->expiration, now) <=3D 0 ? make_timespec (0, 1000 * 1000) : timespec_sub (atimers->expiration, now)); - -#ifdef HAVE_SETITIMER - - memset (&it, 0, sizeof it); - it.it_value =3D make_timeval (interval); - setitimer (ITIMER_REAL, &it, 0); -#else /* not HAVE_SETITIMER */ alarm (max (interval.tv_sec, 1)); -#endif /* not HAVE_SETITIMER */ } } =20 @@ -495,7 +484,7 @@ debug_timer_callback (struct atimer *t) else if (result >=3D 0) { bool intime =3D true; -#if defined HAVE_ITIMERSPEC || defined HAVE_SETITIMER +#ifdef HAVE_ITIMERSPEC struct timespec delta =3D timespec_sub (now, r->expected); /* Too late if later than expected + 0.02s. FIXME: this should depend from system clock resolution. */ diff --git a/src/profiler.c b/src/profiler.c index 7330f8861f..23b82600f3 100644 --- a/src/profiler.c +++ b/src/profiler.c @@ -202,9 +202,8 @@ static bool profiler_timer_ok; static enum profiler_cpu_running { NOT_RUNNING, #ifdef HAVE_ITIMERSPEC - TIMER_SETTIME_RUNNING, + TIMER_SETTIME_RUNNING #endif - SETITIMER_RUNNING } profiler_cpu_running; =20 @@ -262,7 +261,6 @@ static int setup_cpu_timer (Lisp_Object sampling_interval) { struct sigaction action; - struct itimerval timer; struct timespec interval; int billion =3D 1000000000; =20 @@ -318,12 +316,6 @@ setup_cpu_timer (Lisp_Object sampling_interval) } #endif =20 -#ifdef HAVE_SETITIMER - timer.it_value =3D timer.it_interval =3D make_timeval (interval); - if (setitimer (ITIMER_PROF, &timer, 0) =3D=3D 0) - return SETITIMER_RUNNING; -#endif - return NOT_RUNNING; } =20 @@ -380,16 +372,6 @@ Return non-nil if the profiler was running. */) } break; #endif - -#ifdef HAVE_SETITIMER - case SETITIMER_RUNNING: - { - struct itimerval disable; - memset (&disable, 0, sizeof disable); - setitimer (ITIMER_PROF, &disable, 0); - } - break; -#endif } =20 signal (SIGPROF, SIG_IGN); diff --git a/src/syssignal.h b/src/syssignal.h index 0887eacb05..790413178e 100644 --- a/src/syssignal.h +++ b/src/syssignal.h @@ -47,8 +47,7 @@ extern void unblock_tty_out_signal (sigset_t const *); # define HAVE_ITIMERSPEC #endif =20 -#if (defined SIGPROF && !defined PROFILING \ - && (defined HAVE_SETITIMER || defined HAVE_ITIMERSPEC)) +#if defined SIGPROF && !defined PROFILING && defined HAVE_ITIMERSPEC # define PROFILER_CPU_SUPPORT #endif =20 --=20 2.17.1 --------------7B671F95A44ECB3DC958A8C3 Content-Type: text/x-patch; name="0002-Adjust-w32-to-emulate-timer_settime-not-setitimer.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="0002-Adjust-w32-to-emulate-timer_settime-not-setitimer.patch" >From aeec1bcc629a722cba7413287f965e4ab3dc9495 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 16 Sep 2018 12:35:58 -0700 Subject: [PATCH 2/2] Adjust w32 to emulate timer_settime, not setitimer This adjusts the w32 code to emulate the current timer_settime etc. functions instead of the obsolescent setitimer etc. functions. * nt/inc/sys/time.h (ITIMER_REAL, ITIMER_PROF): Remove. All uses removed. (struct itimerspec, pthread_attr_t, union sigval, struct sigevent) (SIGEV_SIGNAL, TIMER_ABSTIME, CLOCK_REALTIME) (CLOCK_THREAD_CPUTIME_ID, timer_t): New definitions. * src/w32proc.c (struct itimer_data, stop_timer_thread): (start_timer_thread): Clock type is now clockid_t, not int. All uses changed. (timer_create, timer_gettime, timer_settime): New functions, replacing getitimer and setitimer. All uses changed. --- nt/inc/sys/time.h | 38 +++++++++--- src/w32proc.c | 143 ++++++++++++++++++++++++---------------------- 2 files changed, 106 insertions(+), 75 deletions(-) diff --git a/nt/inc/sys/time.h b/nt/inc/sys/time.h index 6f67e5db4e..d03bc456ea 100644 --- a/nt/inc/sys/time.h +++ b/nt/inc/sys/time.h @@ -3,19 +3,41 @@ #include_next -#define ITIMER_REAL 0 -#define ITIMER_PROF 1 +struct itimerspec +{ + struct timespec it_interval; /* timer interval */ + struct timespec it_value; /* current value */ +}; -struct itimerval +typedef struct pthread_attr_t *pthread_attr_t; +union sigval +{ + int sival_int; + void *sival_ptr; +}; +struct sigevent { - struct timeval it_interval; /* timer interval */ - struct timeval it_value; /* current value */ + int sigev_notify; + int sigev_signo; + union sigval sigev_value; + void (*sigev_notify_function) (union sigval); + pthread_attr_t *sigev_notify_attributes; }; +#define SIGEV_SIGNAL 0 -int getitimer (int, struct itimerval *); -int setitimer (int, struct itimerval *, struct itimerval *); +#define TIMER_ABSTIME 1 +typedef enum { CLOCK_REALTIME, CLOCK_THREAD_CPUTIME_ID } clockid_t; +#define CLOCK_REALTIME CLOCK_REALTIME +#define CLOCK_THREAD_CPUTIME_ID CLOCK_THREAD_CPUTIME_ID +typedef struct +{ + clockid_t clockid; +} timer_t; +int timer_create (clockid_t, struct sigevent *restrict, timer_t *restrict); +int timer_settime (timer_t, int, struct itimerspec const *, + struct itimerspec *restrict); +int timer_getoverrun (timer_t); #endif /* SYS_TIME_H_INCLUDED */ /* end of sys/time.h */ - diff --git a/src/w32proc.c b/src/w32proc.c index cb02ba6341..23869768cf 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -89,7 +89,7 @@ sys_signal (int sig, signal_handler handler) signal_handler old; /* SIGCHLD is needed for supporting subprocesses, see sys_kill - below. SIGALRM and SIGPROF are used by setitimer. All the + below. SIGALRM and SIGPROF are used by timer_settime. All the others are the only ones supported by the MS runtime. */ if (!(sig == SIGINT || sig == SIGSEGV || sig == SIGILL || sig == SIGFPE || sig == SIGABRT || sig == SIGTERM @@ -261,7 +261,8 @@ setsid (void) /* Emulations of interval timers. - Limitations: only ITIMER_REAL and ITIMER_PROF are supported. + Limitations: only CLOCK_REALTIME and CLOCK_THREAD_CPUTIME_ID are + supported, and only a single timer of each time is supported. Implementation: a separate thread is started for each timer type, the thread calls the appropriate signal handler when the timer @@ -271,7 +272,7 @@ struct itimer_data { volatile ULONGLONG expire; volatile ULONGLONG reload; volatile int terminate; - int type; + clockid_t type; HANDLE caller_thread; HANDLE timer_thread; }; @@ -357,11 +358,11 @@ static DWORD WINAPI timer_loop (LPVOID arg) { struct itimer_data *itimer = (struct itimer_data *)arg; - int which = itimer->type; - int sig = (which == ITIMER_REAL) ? SIGALRM : SIGPROF; - CRITICAL_SECTION *crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof; + bool realtime = itimer->type == CLOCK_REALTIME; + int sig = realtime ? SIGALRM : SIGPROF; + CRITICAL_SECTION *crit = realtime ? &crit_real : &crit_prof; const DWORD max_sleep = MAX_SINGLE_SLEEP * 1000 / TIMER_TICKS_PER_SEC; - HANDLE hth = (which == ITIMER_REAL) ? NULL : itimer->caller_thread; + HANDLE hth = realtime ? NULL : itimer->caller_thread; while (1) { @@ -369,7 +370,7 @@ timer_loop (LPVOID arg) signal_handler handler; ULONGLONG now, expire, reload; - /* Load new values if requested by setitimer. */ + /* Load new values if requested by timer_settime. */ EnterCriticalSection (crit); expire = itimer->expire; reload = itimer->reload; @@ -480,10 +481,10 @@ timer_loop (LPVOID arg) } static void -stop_timer_thread (int which) +stop_timer_thread (clockid_t clockid) { struct itimer_data *itimer = - (which == ITIMER_REAL) ? &real_itimer : &prof_itimer; + clockid == CLOCK_REALTIME ? &real_itimer : &prof_itimer; int i; DWORD err = 0, exit_code = 255; BOOL status; @@ -526,9 +527,9 @@ void term_timers (void) { if (real_itimer.timer_thread) - stop_timer_thread (ITIMER_REAL); + stop_timer_thread (CLOCK_REALTIME); if (prof_itimer.timer_thread) - stop_timer_thread (ITIMER_PROF); + stop_timer_thread (CLOCK_THREAD_CPUTIME_ID); /* We are going to delete the critical sections, so timers cannot work after this. */ @@ -564,12 +565,12 @@ init_timers (void) } static int -start_timer_thread (int which) +start_timer_thread (clockid_t clockid) { DWORD exit_code, tid; HANDLE th; struct itimer_data *itimer = - (which == ITIMER_REAL) ? &real_itimer : &prof_itimer; + clockid == CLOCK_REALTIME ? &real_itimer : &prof_itimer; if (itimer->timer_thread && GetExitCodeThread (itimer->timer_thread, &exit_code) @@ -597,7 +598,7 @@ start_timer_thread (int which) return -1; } itimer->terminate = 0; - itimer->type = which; + itimer->type = clockid; itimer->caller_thread = th; /* Request that no more than 64KB of stack be reserved for this thread, to avoid reserving too much memory, which would get in @@ -616,24 +617,42 @@ start_timer_thread (int which) /* This is needed to make sure that the timer thread running for profiling gets CPU as soon as the Sleep call terminates. */ - if (which == ITIMER_PROF) + if (clockid == CLOCK_THREAD_CPUTIME_ID) SetThreadPriority (itimer->timer_thread, THREAD_PRIORITY_TIME_CRITICAL); return 0; } -/* Most of the code of getitimer and setitimer (but not of their +int +timer_create (clockid_t clockid, struct sigevent *restrict evp, + timer_t *restrict timerid) +{ + if ((clockid == CLOCK_REALTIME || clockid == CLOCK_THREAD_CPUTIME_ID) + && (!evp || (evp->sigev_notify == SIGEV_SIGNAL + && evp->sigev_signo == (clockid == CLOCK_REALTIME + ? SIGALRM : SIGPROF) + && evp->sigev_value.sival_ptr == timerid))) + { + timerid->clockid = clockid; + return 0; + } + errno = EINVAL; + return -1; +} + +/* Most of the code of timer_gettime and timer_settime (but not of their subroutines) was shamelessly stolen from itimer.c in the DJGPP library, see www.delorie.com/djgpp. */ int -getitimer (int which, struct itimerval *value) +timer_gettime (timer_t timerid, struct itimerspec *value) { volatile ULONGLONG *t_expire; volatile ULONGLONG *t_reload; ULONGLONG expire, reload; - __int64 usecs; CRITICAL_SECTION *crit; struct itimer_data *itimer; + HANDLE thread_hand; + bool realtime = timerid.clockid == CLOCK_REALTIME; if (disable_itimers) return -1; @@ -644,21 +663,18 @@ getitimer (int which, struct itimerval *value) return -1; } - if (which != ITIMER_REAL && which != ITIMER_PROF) - { - errno = EINVAL; - return -1; - } - - itimer = (which == ITIMER_REAL) ? &real_itimer : &prof_itimer; + itimer = realtime ? &real_itimer : &prof_itimer; - ticks_now = w32_get_timer_time ((which == ITIMER_REAL) + ticks_now = w32_get_timer_time (realtime ? NULL : GetCurrentThread ()); + itimer = realtime ? &real_itimer : &prof_itimer; + + ticks_now = w32_get_timer_time (thread_hand); t_expire = &itimer->expire; t_reload = &itimer->reload; - crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof; + crit = realtime ? &crit_real : &crit_prof; EnterCriticalSection (crit); reload = *t_reload; @@ -669,25 +685,25 @@ getitimer (int which, struct itimerval *value) expire -= ticks_now; value->it_value.tv_sec = expire / TIMER_TICKS_PER_SEC; - usecs = - (expire % TIMER_TICKS_PER_SEC) * (__int64)1000000 / TIMER_TICKS_PER_SEC; - value->it_value.tv_usec = usecs; + value->it_value.tv_nsec = (expire % TIMER_TICKS_PER_SEC + * (1000000000 / TIMER_TICKS_PER_SEC)); value->it_interval.tv_sec = reload / TIMER_TICKS_PER_SEC; - usecs = - (reload % TIMER_TICKS_PER_SEC) * (__int64)1000000 / TIMER_TICKS_PER_SEC; - value->it_interval.tv_usec= usecs; - + value->it_interval.tv_nsec= (reload % TIMER_TICKS_PER_SEC + * (1000000000 / TIMER_TICKS_PER_SEC)); return 0; } int -setitimer(int which, struct itimerval *value, struct itimerval *ovalue) +timer_settime (timer_t timerid, int flags, + struct itimerspec const *restrict value, + struct itimerspec *restrict ovalue) { volatile ULONGLONG *t_expire, *t_reload; ULONGLONG expire, reload, expire_old, reload_old; - __int64 usecs; + int ns; CRITICAL_SECTION *crit; - struct itimerval tem, *ptem; + struct itimerspec tem, *ptem; + bool realtime = timerid.clockid == CLOCK_REALTIME; if (disable_itimers) return -1; @@ -710,18 +726,15 @@ setitimer(int which, struct itimerval *value, struct itimerval *ovalue) else ptem = &tem; - if (getitimer (which, ptem)) /* also sets ticks_now */ + if (timer_gettime (timerid, ptem)) /* also sets ticks_now */ return -1; /* errno already set */ - t_expire = - (which == ITIMER_REAL) ? &real_itimer.expire : &prof_itimer.expire; - t_reload = - (which == ITIMER_REAL) ? &real_itimer.reload : &prof_itimer.reload; - - crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof; + t_expire = realtime ? &real_itimer.expire : &prof_itimer.expire; + t_reload = realtime ? &real_itimer.reload : &prof_itimer.reload; + crit = realtime ? &crit_real : &crit_prof; if (!value - || (value->it_value.tv_sec == 0 && value->it_value.tv_usec == 0)) + || (value->it_value.tv_sec == 0 && value->it_value.tv_nsec == 0)) { EnterCriticalSection (crit); /* Disable the timer. */ @@ -733,28 +746,23 @@ setitimer(int which, struct itimerval *value, struct itimerval *ovalue) reload = value->it_interval.tv_sec * TIMER_TICKS_PER_SEC; - usecs = value->it_interval.tv_usec; + ns = value->it_interval.tv_nsec; if (value->it_interval.tv_sec == 0 - && usecs && usecs * TIMER_TICKS_PER_SEC < clocks_min * 1000000) + && 0 < ns && ns < clocks_min * (1000000000 / TIMER_TICKS_PER_SEC)) reload = clocks_min; else - { - usecs *= TIMER_TICKS_PER_SEC; - reload += usecs / 1000000; - } + reload += ns / (1000000000 / TIMER_TICKS_PER_SEC); - expire = value->it_value.tv_sec * TIMER_TICKS_PER_SEC; - usecs = value->it_value.tv_usec; - if (value->it_value.tv_sec == 0 - && usecs * TIMER_TICKS_PER_SEC < clocks_min * 1000000) + expire = ex.tv_sec * TIMER_TICKS_PER_SEC; + ns = ex.tv_nsec; + if (ex.tv_sec == 0 + && 0 < ns && ns < clocks_min * (1000000000 / TIMER_TICKS_PER_SEC)) expire = clocks_min; else - { - usecs *= TIMER_TICKS_PER_SEC; - expire += usecs / 1000000; - } + reload += ns / (1000000000 / TIMER_TICKS_PER_SEC); - expire += ticks_now; + if (flags & TIMER_ABSTIME) + expire += ticks_now; EnterCriticalSection (crit); expire_old = *t_expire; @@ -766,20 +774,21 @@ setitimer(int which, struct itimerval *value, struct itimerval *ovalue) } LeaveCriticalSection (crit); - return start_timer_thread (which); + return start_timer_thread (timerid.clockid); } int alarm (int seconds) { -#ifdef HAVE_SETITIMER - struct itimerval new_values, old_values; +#ifdef HAVE_ITIMERSPEC + struct itimerspec new_values, old_values; new_values.it_value.tv_sec = seconds; - new_values.it_value.tv_usec = 0; - new_values.it_interval.tv_sec = new_values.it_interval.tv_usec = 0; + new_values.it_value.tv_nsec = 0; + new_values.it_interval.tv_sec = new_values.it_interval.tv_nsec = 0; - if (setitimer (ITIMER_REAL, &new_values, &old_values) < 0) + timer_t id = { .clockid = CLOCK_REALTIME }; + if (timer_settime (id, 0, &new_values, &old_values) < 0) return 0; return old_values.it_value.tv_sec; #else -- 2.17.1 --------------7B671F95A44ECB3DC958A8C3--