aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenichi Handa2012-10-30 20:38:37 +0900
committerKenichi Handa2012-10-30 20:38:37 +0900
commit6ccc848cd85e75d77d6b11a46f5f23f860db9ff5 (patch)
treee10cb69f3bbe6f2d9616d3867f12bf035c70e0f8 /src
parentaee5b18ec3c7844ca125249914113eeaef04342c (diff)
parentfcc1acdadbeae00d8dcabeb6dccb20da9672af2c (diff)
downloademacs-6ccc848cd85e75d77d6b11a46f5f23f860db9ff5.tar.gz
emacs-6ccc848cd85e75d77d6b11a46f5f23f860db9ff5.zip
merge trun
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog78
-rw-r--r--src/coding.c43
-rw-r--r--src/coding.h22
-rw-r--r--src/cygw32.c33
-rw-r--r--src/cygw32.h14
-rw-r--r--src/emacs.c4
-rw-r--r--src/frame.c3
-rw-r--r--src/nsterm.m19
-rw-r--r--src/sysdep.c2
-rw-r--r--src/term.c2
-rw-r--r--src/w32fns.c14
-rw-r--r--src/w32proc.c213
12 files changed, 314 insertions, 133 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index a5f76b22def..e3371796bfb 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -3,6 +3,76 @@
3 * font.c (Ffont_at): If WINDOW is specified and it is not 3 * font.c (Ffont_at): If WINDOW is specified and it is not
4 displaying the current buffer, signal an error. 4 displaying the current buffer, signal an error.
5 5
62012-10-29 Daniel Colascione <dancol@dancol.org>
7
8 * cygw32.h, cygw32.c (Qutf_16le, from_unicode, to_unicode): In
9 preparation for fixing bug#12739, move these functions from
10 here...
11
12 * coding.h, coding.c: ... to here, and compile them only when
13 WINDOWSNT or CYGWIN. Moving these functions out of cygw32 proper
14 lets us write cygw32-agnostic code for the HAVE_NTGUI case.
15
162012-10-28 Eli Zaretskii <eliz@gnu.org>
17
18 * w32proc.c (TIMER_TICKS_PER_SEC): New macro.
19 (timer_loop, getitimer, setitimer): Use it instead of
20 CLOCKS_PER_SEC, which is no longer pertinent, since we don't use
21 'clock'.
22 (w32_get_timer_time): Use 10*TIMER_TICKS_PER_SEC instead of a
23 literal 10000.
24
252012-10-28 Jan Djärv <jan.h.d@swipnet.se>
26
27 * nsterm.m (NO_APPDEFINED_DATA): New define.
28 (last_appdefined_event_data): New variable
29 (last_appdefined_event): Remove.
30 (ns_select): Initialize t from last_appdefined_event_data instead
31 of [last_appdefined_event data1].
32 (sendEvent:): Save [theEvent data1] to last_appdefined_event_data,
33 remove last_appdefined_event (Bug#12698).
34
352012-10-28 Stefan Monnier <monnier@iro.umontreal.ca>
36
37 * frame.c (x_set_font): Catch internal error.
38
392012-10-27 Eli Zaretskii <eliz@gnu.org>
40
41 Avoid overflow in w32 implementation of interval timers.
42 When possible, for ITIMER_PROF count only times the main thread
43 actually executes.
44 * w32proc.c <struct itimer_data>: 'expire' and 'reload' are now
45 'volatile ULONGLONG' types. All the other data which was
46 previously clock_t is now ULONGLONG. 'terminate' is 'volatile int'.
47 (GetThreadTimes_Proc): New typedef.
48 (w32_get_timer_time): New function, returns a suitable time value
49 for the timer.
50 (timer_loop): Enter critical section when accessing ULONGLONG
51 values of the itimer_data struct, as these accesses are no longer
52 atomic. Call 'w32_get_timer_time' instead of 'clock'.
53 Remove unused variable.
54 (init_timers): Initialize s_pfn_Get_Thread_Times.
55 (start_timer_thread): Don't assign itimer->caller_thread here.
56 (getitimer): Assign itimer->caller_thread here.
57 (setitimer): Always call getitimer to get the value of ticks_now.
58 (sys_spawnve): Avoid compiler warning about format mismatch.
59
602012-10-26 Eli Zaretskii <eliz@gnu.org>
61
62 * w32fns.c (w32_wnd_proc) <WM_MOUSEMOVE>: Don't enable tracking of
63 mouse movement events if the menu bar is active. This avoids
64 producing a busy "hour-glass" cursor by Windows if the mouse
65 pointer is positioned over a tooltip shown for some menu item.
66
672012-10-25 Paul Eggert <eggert@cs.ucla.edu>
68
69 Don't assume process IDs fit in int.
70 * emacs.c (shut_down_emacs) [!DOS_NT]:
71 * sysdep.c (sys_suspend) [SIGTSTP && !MSDOS]:
72 * term.c (dissociate_if_controlling_tty) [!DOS_NT]:
73 Use pid_t, not int, to store process IDs, as 'int'
74 is not wide enough on a few platforms (e.g., AIX and IRIX).
75
62012-10-23 Kenichi Handa <handa@gnu.org> 762012-10-23 Kenichi Handa <handa@gnu.org>
7 77
8 The following change is to make face-font-rescale-alist work 78 The following change is to make face-font-rescale-alist work
@@ -60,8 +130,8 @@
60 130
612012-10-19 Eli Zaretskii <eliz@gnu.org> 1312012-10-19 Eli Zaretskii <eliz@gnu.org>
62 132
63 * puresize.h (BASE_PURESIZE): Bump the base value to 1700000. See 133 * puresize.h (BASE_PURESIZE): Bump the base value to 1700000.
64 http://lists.gnu.org/archive/html/emacs-devel/2012-10/msg00593.html 134 See http://lists.gnu.org/archive/html/emacs-devel/2012-10/msg00593.html
65 for the reasons. 135 for the reasons.
66 136
67 * alloc.c (NSTATICS): Decrease to 0x800. 137 * alloc.c (NSTATICS): Decrease to 0x800.
@@ -680,8 +750,8 @@
680 (ns_clear_frame_area): Remove resize handle code. 750 (ns_clear_frame_area): Remove resize handle code.
681 751
682 * nsfns.m (ns_in_resize): Remove. 752 * nsfns.m (ns_in_resize): Remove.
683 (x_set_icon_name, ns_set_name, ns_set_name_as_filename): Remove 753 (x_set_icon_name, ns_set_name, ns_set_name_as_filename):
684 ns_in_resize check. 754 Remove ns_in_resize check.
685 755
6862012-10-07 Paul Eggert <eggert@cs.ucla.edu> 7562012-10-07 Paul Eggert <eggert@cs.ucla.edu>
687 757
diff --git a/src/coding.c b/src/coding.c
index 7628a9fbf2e..56202e4861d 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -343,6 +343,10 @@ Lisp_Object Qcoding_system_p, Qcoding_system_error;
343Lisp_Object Qemacs_mule, Qraw_text; 343Lisp_Object Qemacs_mule, Qraw_text;
344Lisp_Object Qutf_8_emacs; 344Lisp_Object Qutf_8_emacs;
345 345
346#if defined (WINDOWSNT) || defined (CYGWIN)
347static Lisp_Object Qutf_16le;
348#endif
349
346/* Coding-systems are handed between Emacs Lisp programs and C internal 350/* Coding-systems are handed between Emacs Lisp programs and C internal
347 routines by the following three variables. */ 351 routines by the following three variables. */
348/* Coding system to be used to encode text for terminal display when 352/* Coding system to be used to encode text for terminal display when
@@ -7971,6 +7975,40 @@ preferred_coding_system (void)
7971 return CODING_ID_NAME (id); 7975 return CODING_ID_NAME (id);
7972} 7976}
7973 7977
7978#if defined (WINDOWSNT) || defined (CYGWIN)
7979
7980Lisp_Object
7981from_unicode (Lisp_Object str)
7982{
7983 CHECK_STRING (str);
7984 if (!STRING_MULTIBYTE (str) &&
7985 SBYTES (str) & 1)
7986 {
7987 str = Fsubstring (str, make_number (0), make_number (-1));
7988 }
7989
7990 return code_convert_string_norecord (str, Qutf_16le, 0);
7991}
7992
7993wchar_t *
7994to_unicode (Lisp_Object str, Lisp_Object *buf)
7995{
7996 *buf = code_convert_string_norecord (str, Qutf_16le, 1);
7997 /* We need to make a another copy (in addition to the one made by
7998 code_convert_string_norecord) to ensure that the final string is
7999 _doubly_ zero terminated --- that is, that the string is
8000 terminated by two zero bytes and one utf-16le null character.
8001 Because strings are already terminated with a single zero byte,
8002 we just add one additional zero. */
8003 str = make_uninit_string (SBYTES (*buf) + 1);
8004 memcpy (SDATA (str), SDATA (*buf), SBYTES (*buf));
8005 SDATA (str) [SBYTES (*buf)] = '\0';
8006 *buf = str;
8007 return WCSDATA (*buf);
8008}
8009
8010#endif /* WINDOWSNT || CYGWIN */
8011
7974 8012
7975#ifdef emacs 8013#ifdef emacs
7976/*** 8. Emacs Lisp library functions ***/ 8014/*** 8. Emacs Lisp library functions ***/
@@ -10284,6 +10322,11 @@ syms_of_coding (void)
10284 DEFSYM (Qutf_8, "utf-8"); 10322 DEFSYM (Qutf_8, "utf-8");
10285 DEFSYM (Qutf_8_emacs, "utf-8-emacs"); 10323 DEFSYM (Qutf_8_emacs, "utf-8-emacs");
10286 10324
10325#if defined (WINDOWSNT) || defined (CYGWIN)
10326 /* No, not utf-16-le: that one has a BOM. */
10327 DEFSYM (Qutf_16le, "utf-16le");
10328#endif
10329
10287 DEFSYM (Qutf_16, "utf-16"); 10330 DEFSYM (Qutf_16, "utf-16");
10288 DEFSYM (Qbig, "big"); 10331 DEFSYM (Qbig, "big");
10289 DEFSYM (Qlittle, "little"); 10332 DEFSYM (Qlittle, "little");
diff --git a/src/coding.h b/src/coding.h
index 989552bf667..192be58f083 100644
--- a/src/coding.h
+++ b/src/coding.h
@@ -701,6 +701,28 @@ extern void encode_coding_object (struct coding_system *,
701 Lisp_Object, ptrdiff_t, ptrdiff_t, 701 Lisp_Object, ptrdiff_t, ptrdiff_t,
702 ptrdiff_t, ptrdiff_t, Lisp_Object); 702 ptrdiff_t, ptrdiff_t, Lisp_Object);
703 703
704#if defined (WINDOWSNT) || defined (CYGWIN)
705
706/* These functions use Lisp string objects to store the UTF-16LE
707 strings that modern versions of Windows expect. These strings are
708 not particularly useful to Lisp, and all Lisp strings should be
709 native Emacs multibyte. */
710
711/* Access the wide-character string stored in a Lisp string object. */
712#define WCSDATA(x) ((wchar_t *) SDATA (x))
713
714/* Convert the multi-byte string in STR to UTF-16LE encoded unibyte
715 string, and store it in *BUF. BUF may safely point to STR on entry. */
716extern wchar_t *to_unicode (Lisp_Object str, Lisp_Object *buf);
717
718/* Convert STR, a UTF-16LE encoded string embedded in a unibyte string
719 object, to a multi-byte Emacs string and return it. This function
720 calls code_convert_string_norecord internally and has all its
721 failure modes. STR itself is not modified. */
722extern Lisp_Object from_unicode (Lisp_Object str);
723
724#endif /* WINDOWSNT || CYGWIN */
725
704/* Macros for backward compatibility. */ 726/* Macros for backward compatibility. */
705 727
706#define decode_coding_region(coding, from, to) \ 728#define decode_coding_region(coding, from, to) \
diff --git a/src/cygw32.c b/src/cygw32.c
index 8f63461da2a..54f2076a891 100644
--- a/src/cygw32.c
+++ b/src/cygw32.c
@@ -22,7 +22,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22#include "buffer.h" 22#include "buffer.h"
23#include <unistd.h> 23#include <unistd.h>
24#include <fcntl.h> 24#include <fcntl.h>
25static Lisp_Object Qutf_16le;
26 25
27static Lisp_Object 26static Lisp_Object
28fchdir_unwind (Lisp_Object dir_fd) 27fchdir_unwind (Lisp_Object dir_fd)
@@ -107,36 +106,6 @@ conv_filename_from_w32_unicode (const wchar_t* in, int absolute_p)
107 return unbind_to (count, DECODE_FILE (converted)); 106 return unbind_to (count, DECODE_FILE (converted));
108} 107}
109 108
110Lisp_Object
111from_unicode (Lisp_Object str)
112{
113 CHECK_STRING (str);
114 if (!STRING_MULTIBYTE (str) &&
115 SBYTES (str) & 1)
116 {
117 str = Fsubstring (str, make_number (0), make_number (-1));
118 }
119
120 return code_convert_string_norecord (str, Qutf_16le, 0);
121}
122
123wchar_t *
124to_unicode (Lisp_Object str, Lisp_Object *buf)
125{
126 *buf = code_convert_string_norecord (str, Qutf_16le, 1);
127 /* We need to make a another copy (in addition to the one made by
128 code_convert_string_norecord) to ensure that the final string is
129 _doubly_ zero terminated --- that is, that the string is
130 terminated by two zero bytes and one utf-16le null character.
131 Because strings are already terminated with a single zero byte,
132 we just add one additional zero. */
133 str = make_uninit_string (SBYTES (*buf) + 1);
134 memcpy (SDATA (str), SDATA (*buf), SBYTES (*buf));
135 SDATA (str) [SBYTES (*buf)] = '\0';
136 *buf = str;
137 return WCSDATA (*buf);
138}
139
140DEFUN ("cygwin-convert-path-to-windows", 109DEFUN ("cygwin-convert-path-to-windows",
141 Fcygwin_convert_path_to_windows, Scygwin_convert_path_to_windows, 110 Fcygwin_convert_path_to_windows, Scygwin_convert_path_to_windows,
142 1, 2, 0, 111 1, 2, 0,
@@ -162,8 +131,6 @@ DEFUN ("cygwin-convert-path-from-windows",
162void 131void
163syms_of_cygw32 (void) 132syms_of_cygw32 (void)
164{ 133{
165 /* No, not utf-16-le: that one has a BOM. */
166 DEFSYM (Qutf_16le, "utf-16le");
167 defsubr (&Scygwin_convert_path_from_windows); 134 defsubr (&Scygwin_convert_path_from_windows);
168 defsubr (&Scygwin_convert_path_to_windows); 135 defsubr (&Scygwin_convert_path_to_windows);
169} 136}
diff --git a/src/cygw32.h b/src/cygw32.h
index 78e77a9a141..51571913fd1 100644
--- a/src/cygw32.h
+++ b/src/cygw32.h
@@ -33,20 +33,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
33#include "lisp.h" 33#include "lisp.h"
34#include "coding.h" 34#include "coding.h"
35 35
36/* *** Character conversion *** */
37
38/* Access the wide-character string stored in a Lisp string object. */
39#define WCSDATA(x) ((wchar_t *) SDATA (x))
40
41/* Convert the multi-byte string in STR to UTF-16LE encoded unibyte
42 string, and store it in *BUF. BUF may safely point to STR on entry. */
43extern wchar_t *to_unicode (Lisp_Object str, Lisp_Object *buf);
44
45/* Convert STR, a UTF-16LE encoded string embedded in a unibyte string
46 object, to a multi-byte Emacs string, and return it. */
47extern Lisp_Object from_unicode (Lisp_Object str);
48
49/* *** Misc *** */
50extern void syms_of_cygw32 (void); 36extern void syms_of_cygw32 (void);
51extern char * w32_strerror (int error_no); 37extern char * w32_strerror (int error_no);
52 38
diff --git a/src/emacs.c b/src/emacs.c
index 0a2a60bee0c..7f3228641ae 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1903,8 +1903,8 @@ shut_down_emacs (int sig, Lisp_Object stuff)
1903 /* If we are controlling the terminal, reset terminal modes. */ 1903 /* If we are controlling the terminal, reset terminal modes. */
1904#ifndef DOS_NT 1904#ifndef DOS_NT
1905 { 1905 {
1906 int pgrp = EMACS_GETPGRP (0); 1906 pid_t pgrp = EMACS_GETPGRP (0);
1907 int tpgrp = tcgetpgrp (0); 1907 pid_t tpgrp = tcgetpgrp (0);
1908 if ((tpgrp != -1) && tpgrp == pgrp) 1908 if ((tpgrp != -1) && tpgrp == pgrp)
1909 { 1909 {
1910 reset_all_sys_modes (); 1910 reset_all_sys_modes ();
diff --git a/src/frame.c b/src/frame.c
index 6478ad1e06f..17a99000c9b 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3242,6 +3242,9 @@ x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3242 Lisp_Object ascii_font = fontset_ascii (fontset); 3242 Lisp_Object ascii_font = fontset_ascii (fontset);
3243 Lisp_Object spec = font_spec_from_name (ascii_font); 3243 Lisp_Object spec = font_spec_from_name (ascii_font);
3244 3244
3245 if (NILP (spec))
3246 signal_error ("Invalid font name", ascii_font);
3247
3245 if (! font_match_p (spec, font_object)) 3248 if (! font_match_p (spec, font_object))
3246 fontset = -1; 3249 fontset = -1;
3247 } 3250 }
diff --git a/src/nsterm.m b/src/nsterm.m
index a4eaad47ac1..9b2e544c75b 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -190,7 +190,8 @@ static BOOL ns_menu_bar_is_hidden = NO;
190 190
191/* event loop */ 191/* event loop */
192static BOOL send_appdefined = YES; 192static BOOL send_appdefined = YES;
193static NSEvent *last_appdefined_event = 0; 193#define NO_APPDEFINED_DATA (-8)
194static int last_appdefined_event_data = NO_APPDEFINED_DATA;
194static NSTimer *timed_entry = 0; 195static NSTimer *timed_entry = 0;
195static NSTimer *scroll_repeat_entry = nil; 196static NSTimer *scroll_repeat_entry = nil;
196static fd_set select_readfds, select_writefds; 197static fd_set select_readfds, select_writefds;
@@ -3436,8 +3437,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3436 -------------------------------------------------------------------------- */ 3437 -------------------------------------------------------------------------- */
3437{ 3438{
3438 int result; 3439 int result;
3439 NSEvent *ev; 3440 int t, k, nr = 0;
3440 int k, nr = 0;
3441 struct input_event event; 3441 struct input_event event;
3442 char c; 3442 char c;
3443 3443
@@ -3521,16 +3521,11 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3521 } 3521 }
3522 unblock_input (); 3522 unblock_input ();
3523 3523
3524 ev = last_appdefined_event; 3524 t = last_appdefined_event_data;
3525 3525
3526 if (ev) 3526 if (t != NO_APPDEFINED_DATA)
3527 { 3527 {
3528 int t; 3528 last_appdefined_event_data = NO_APPDEFINED_DATA;
3529 if ([ev type] != NSApplicationDefined)
3530 emacs_abort ();
3531
3532 t = [ev data1];
3533 last_appdefined_event = 0;
3534 3529
3535 if (t == -2) 3530 if (t == -2)
3536 { 3531 {
@@ -4307,7 +4302,7 @@ ns_term_shutdown (int sig)
4307 modal loop. Just defer it until later. */ 4302 modal loop. Just defer it until later. */
4308 if ([NSApp modalWindow] == nil) 4303 if ([NSApp modalWindow] == nil)
4309 { 4304 {
4310 last_appdefined_event = theEvent; 4305 last_appdefined_event_data = [theEvent data1];
4311 [self stop: self]; 4306 [self stop: self];
4312 } 4307 }
4313 else 4308 else
diff --git a/src/sysdep.c b/src/sysdep.c
index 35beeaa7202..c7174e91612 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -452,7 +452,7 @@ sys_suspend (void)
452#if defined (SIGTSTP) && !defined (MSDOS) 452#if defined (SIGTSTP) && !defined (MSDOS)
453 453
454 { 454 {
455 int pgrp = EMACS_GETPGRP (0); 455 pid_t pgrp = EMACS_GETPGRP (0);
456 EMACS_KILLPG (pgrp, SIGTSTP); 456 EMACS_KILLPG (pgrp, SIGTSTP);
457 } 457 }
458 458
diff --git a/src/term.c b/src/term.c
index f7c87b7608d..74b02b0af27 100644
--- a/src/term.c
+++ b/src/term.c
@@ -2919,7 +2919,7 @@ static void
2919dissociate_if_controlling_tty (int fd) 2919dissociate_if_controlling_tty (int fd)
2920{ 2920{
2921#ifndef DOS_NT 2921#ifndef DOS_NT
2922 int pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */ 2922 pid_t pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */
2923 if (pgid != -1) 2923 if (pgid != -1)
2924 { 2924 {
2925#if defined (USG5) 2925#if defined (USG5)
diff --git a/src/w32fns.c b/src/w32fns.c
index 28e8ea02e05..aa120d59ce5 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -3331,7 +3331,19 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
3331 versions, there is no way of telling when the mouse leaves the 3331 versions, there is no way of telling when the mouse leaves the
3332 frame, so we just have to put up with help-echo and mouse 3332 frame, so we just have to put up with help-echo and mouse
3333 highlighting remaining while the frame is not active. */ 3333 highlighting remaining while the frame is not active. */
3334 if (track_mouse_event_fn && !track_mouse_window) 3334 if (track_mouse_event_fn && !track_mouse_window
3335 /* If the menu bar is active, turning on tracking of mouse
3336 movement events might send these events to the tooltip
3337 frame, if the user happens to move the mouse pointer over
3338 the tooltip. But since we don't process events for
3339 tooltip frames, this causes Windows to present a
3340 hourglass cursor, which is ugly and unexpected. So don't
3341 enable tracking mouse events in this case; they will be
3342 restarted when the menu pops down. (Confusingly, the
3343 menubar_active member of f->output_data.w32, tested
3344 above, is only set when a menu was popped up _not_ from
3345 the frame's menu bar, but via x-popup-menu.) */
3346 && !menubar_in_use)
3335 { 3347 {
3336 TRACKMOUSEEVENT tme; 3348 TRACKMOUSEEVENT tme;
3337 tme.cbSize = sizeof (tme); 3349 tme.cbSize = sizeof (tme);
diff --git a/src/w32proc.c b/src/w32proc.c
index 57b3860cb76..d45d9879a24 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -244,28 +244,92 @@ setpgrp (int pid, int gid)
244 the thread calls the appropriate signal handler when the timer 244 the thread calls the appropriate signal handler when the timer
245 expires, after stopping the thread which installed the timer. */ 245 expires, after stopping the thread which installed the timer. */
246 246
247/* FIXME: clock_t counts overflow after 49 days, need to handle the
248 wrap-around. */
249struct itimer_data { 247struct itimer_data {
250 clock_t expire; 248 volatile ULONGLONG expire;
251 clock_t reload; 249 volatile ULONGLONG reload;
252 int terminate; 250 volatile int terminate;
253 int type; 251 int type;
254 HANDLE caller_thread; 252 HANDLE caller_thread;
255 HANDLE timer_thread; 253 HANDLE timer_thread;
256}; 254};
257 255
258static clock_t ticks_now; 256static ULONGLONG ticks_now;
259static struct itimer_data real_itimer, prof_itimer; 257static struct itimer_data real_itimer, prof_itimer;
260static clock_t clocks_min; 258static ULONGLONG clocks_min;
261/* If non-zero, itimers are disabled. Used during shutdown, when we 259/* If non-zero, itimers are disabled. Used during shutdown, when we
262 delete the critical sections used by the timer threads. */ 260 delete the critical sections used by the timer threads. */
263static int disable_itimers; 261static int disable_itimers;
264 262
265static CRITICAL_SECTION crit_real, crit_prof; 263static CRITICAL_SECTION crit_real, crit_prof;
266 264
267#define MAX_SINGLE_SLEEP 30 265/* GetThreadTimes is not available on Windows 9X and possibly also on 2K. */
266typedef BOOL (WINAPI *GetThreadTimes_Proc) (
267 HANDLE hThread,
268 LPFILETIME lpCreationTime,
269 LPFILETIME lpExitTime,
270 LPFILETIME lpKernelTime,
271 LPFILETIME lpUserTime);
272
273static GetThreadTimes_Proc s_pfn_Get_Thread_Times;
274
275#define MAX_SINGLE_SLEEP 30
276#define TIMER_TICKS_PER_SEC 1000
277
278/* Return a suitable time value, in 1-ms units, for THREAD, a handle
279 to a thread. If THREAD is NULL or an invalid handle, return the
280 current wall-clock time since January 1, 1601 (UTC). Otherwise,
281 return the sum of kernel and user times used by THREAD since it was
282 created, plus its creation time. */
283static ULONGLONG
284w32_get_timer_time (HANDLE thread)
285{
286 ULONGLONG retval;
287 int use_system_time = 1;
288 /* The functions below return times in 100-ns units. */
289 const int tscale = 10 * TIMER_TICKS_PER_SEC;
290
291 if (thread && thread != INVALID_HANDLE_VALUE
292 && s_pfn_Get_Thread_Times != NULL)
293 {
294 FILETIME creation_ftime, exit_ftime, kernel_ftime, user_ftime;
295 ULARGE_INTEGER temp_creation, temp_kernel, temp_user;
296
297 if (s_pfn_Get_Thread_Times (thread, &creation_ftime, &exit_ftime,
298 &kernel_ftime, &user_ftime))
299 {
300 use_system_time = 0;
301 temp_creation.LowPart = creation_ftime.dwLowDateTime;
302 temp_creation.HighPart = creation_ftime.dwHighDateTime;
303 temp_kernel.LowPart = kernel_ftime.dwLowDateTime;
304 temp_kernel.HighPart = kernel_ftime.dwHighDateTime;
305 temp_user.LowPart = user_ftime.dwLowDateTime;
306 temp_user.HighPart = user_ftime.dwHighDateTime;
307 retval =
308 temp_creation.QuadPart / tscale + temp_kernel.QuadPart / tscale
309 + temp_user.QuadPart / tscale;
310 }
311 else
312 DebPrint (("GetThreadTimes failed with error code %lu\n",
313 GetLastError ()));
314 }
315
316 if (use_system_time)
317 {
318 FILETIME current_ftime;
319 ULARGE_INTEGER temp;
320
321 GetSystemTimeAsFileTime (&current_ftime);
322
323 temp.LowPart = current_ftime.dwLowDateTime;
324 temp.HighPart = current_ftime.dwHighDateTime;
325
326 retval = temp.QuadPart / tscale;
327 }
268 328
329 return retval;
330}
331
332/* Thread function for a timer thread. */
269static DWORD WINAPI 333static DWORD WINAPI
270timer_loop (LPVOID arg) 334timer_loop (LPVOID arg)
271{ 335{
@@ -273,14 +337,14 @@ timer_loop (LPVOID arg)
273 int which = itimer->type; 337 int which = itimer->type;
274 int sig = (which == ITIMER_REAL) ? SIGALRM : SIGPROF; 338 int sig = (which == ITIMER_REAL) ? SIGALRM : SIGPROF;
275 CRITICAL_SECTION *crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof; 339 CRITICAL_SECTION *crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof;
276 const DWORD max_sleep = MAX_SINGLE_SLEEP * 1000 / CLOCKS_PER_SEC; 340 const DWORD max_sleep = MAX_SINGLE_SLEEP * 1000 / TIMER_TICKS_PER_SEC;
277 int new_count = 0; 341 HANDLE hth = (which == ITIMER_REAL) ? NULL : itimer->caller_thread;
278 342
279 while (1) 343 while (1)
280 { 344 {
281 DWORD sleep_time; 345 DWORD sleep_time;
282 signal_handler handler; 346 signal_handler handler;
283 clock_t now, expire, reload; 347 ULONGLONG now, expire, reload;
284 348
285 /* Load new values if requested by setitimer. */ 349 /* Load new values if requested by setitimer. */
286 EnterCriticalSection (crit); 350 EnterCriticalSection (crit);
@@ -290,15 +354,14 @@ timer_loop (LPVOID arg)
290 if (itimer->terminate) 354 if (itimer->terminate)
291 return 0; 355 return 0;
292 356
293 if (itimer->expire == 0) 357 if (expire == 0)
294 { 358 {
295 /* We are idle. */ 359 /* We are idle. */
296 Sleep (max_sleep); 360 Sleep (max_sleep);
297 continue; 361 continue;
298 } 362 }
299 363
300 expire = itimer->expire; 364 if (expire > (now = w32_get_timer_time (hth)))
301 if (expire > (now = clock ()))
302 sleep_time = expire - now; 365 sleep_time = expire - now;
303 else 366 else
304 sleep_time = 0; 367 sleep_time = 0;
@@ -309,24 +372,30 @@ timer_loop (LPVOID arg)
309 if (itimer->terminate) 372 if (itimer->terminate)
310 return 0; 373 return 0;
311 Sleep (max_sleep); 374 Sleep (max_sleep);
375 EnterCriticalSection (crit);
312 expire = itimer->expire; 376 expire = itimer->expire;
313 sleep_time = (expire > (now = clock ())) ? expire - now : 0; 377 LeaveCriticalSection (crit);
378 sleep_time =
379 (expire > (now = w32_get_timer_time (hth))) ? expire - now : 0;
314 } 380 }
315 if (itimer->terminate) 381 if (itimer->terminate)
316 return 0; 382 return 0;
317 if (sleep_time > 0) 383 if (sleep_time > 0)
318 { 384 {
319 Sleep (sleep_time * 1000 / CLOCKS_PER_SEC); 385 Sleep (sleep_time * 1000 / TIMER_TICKS_PER_SEC);
320 /* Always sleep past the expiration time, to make sure we 386 /* Always sleep past the expiration time, to make sure we
321 never call the handler _before_ the expiration time, 387 never call the handler _before_ the expiration time,
322 always slightly after it. Sleep(5) makes sure we don't 388 always slightly after it. Sleep(5) makes sure we don't
323 hog the CPU by calling 'clock' with high frequency, and 389 hog the CPU by calling 'w32_get_timer_time' with high
324 also let other threads work. */ 390 frequency, and also let other threads work. */
325 while (clock () < expire) 391 while (w32_get_timer_time (hth) < expire)
326 Sleep (5); 392 Sleep (5);
327 } 393 }
328 394
329 if (itimer->expire == 0) 395 EnterCriticalSection (crit);
396 expire = itimer->expire;
397 LeaveCriticalSection (crit);
398 if (expire == 0)
330 continue; 399 continue;
331 400
332 /* Time's up. */ 401 /* Time's up. */
@@ -353,19 +422,21 @@ timer_loop (LPVOID arg)
353 ResumeThread (itimer->caller_thread); 422 ResumeThread (itimer->caller_thread);
354 } 423 }
355 424
356 if (itimer->expire == 0)
357 continue;
358
359 /* Update expiration time and loop. */ 425 /* Update expiration time and loop. */
360 EnterCriticalSection (crit); 426 EnterCriticalSection (crit);
361 expire = itimer->expire; 427 expire = itimer->expire;
428 if (expire == 0)
429 {
430 LeaveCriticalSection (crit);
431 continue;
432 }
362 reload = itimer->reload; 433 reload = itimer->reload;
363 if (reload > 0) 434 if (reload > 0)
364 { 435 {
365 now = clock (); 436 now = w32_get_timer_time (hth);
366 if (expire <= now) 437 if (expire <= now)
367 { 438 {
368 clock_t lag = now - expire; 439 ULONGLONG lag = now - expire;
369 440
370 /* If we missed some opportunities (presumably while 441 /* If we missed some opportunities (presumably while
371 sleeping or while the signal handler ran), skip 442 sleeping or while the signal handler ran), skip
@@ -448,6 +519,15 @@ term_timers (void)
448void 519void
449init_timers (void) 520init_timers (void)
450{ 521{
522 /* GetThreadTimes is not avaiulable on all versions of Windows, so
523 need to probe for its availability dynamically, and call it
524 through a pointer. */
525 s_pfn_Get_Thread_Times = NULL; /* in case dumped Emacs comes with a value */
526 if (os_subtype != OS_9X)
527 s_pfn_Get_Thread_Times =
528 (GetThreadTimes_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
529 "GetThreadTimes");
530
451 /* Make sure we start with zeroed out itimer structures, since 531 /* Make sure we start with zeroed out itimer structures, since
452 dumping may have left there traces of threads long dead. */ 532 dumping may have left there traces of threads long dead. */
453 memset (&real_itimer, 0, sizeof real_itimer); 533 memset (&real_itimer, 0, sizeof real_itimer);
@@ -473,14 +553,6 @@ start_timer_thread (int which)
473 return 0; 553 return 0;
474 554
475 /* Start a new thread. */ 555 /* Start a new thread. */
476 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
477 GetCurrentProcess (), &itimer->caller_thread, 0,
478 FALSE, DUPLICATE_SAME_ACCESS))
479 {
480 errno = ESRCH;
481 return -1;
482 }
483
484 itimer->terminate = 0; 556 itimer->terminate = 0;
485 itimer->type = which; 557 itimer->type = which;
486 /* Request that no more than 64KB of stack be reserved for this 558 /* Request that no more than 64KB of stack be reserved for this
@@ -512,17 +584,16 @@ start_timer_thread (int which)
512int 584int
513getitimer (int which, struct itimerval *value) 585getitimer (int which, struct itimerval *value)
514{ 586{
515 volatile clock_t *t_expire; 587 volatile ULONGLONG *t_expire;
516 volatile clock_t *t_reload; 588 volatile ULONGLONG *t_reload;
517 clock_t expire, reload; 589 ULONGLONG expire, reload;
518 __int64 usecs; 590 __int64 usecs;
519 CRITICAL_SECTION *crit; 591 CRITICAL_SECTION *crit;
592 struct itimer_data *itimer;
520 593
521 if (disable_itimers) 594 if (disable_itimers)
522 return -1; 595 return -1;
523 596
524 ticks_now = clock ();
525
526 if (!value) 597 if (!value)
527 { 598 {
528 errno = EFAULT; 599 errno = EFAULT;
@@ -535,8 +606,22 @@ getitimer (int which, struct itimerval *value)
535 return -1; 606 return -1;
536 } 607 }
537 608
538 t_expire = (which == ITIMER_REAL) ? &real_itimer.expire: &prof_itimer.expire; 609 itimer = (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
539 t_reload = (which == ITIMER_REAL) ? &real_itimer.reload: &prof_itimer.reload; 610
611 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
612 GetCurrentProcess (), &itimer->caller_thread, 0,
613 FALSE, DUPLICATE_SAME_ACCESS))
614 {
615 errno = ESRCH;
616 return -1;
617 }
618
619 ticks_now = w32_get_timer_time ((which == ITIMER_REAL)
620 ? NULL
621 : itimer->caller_thread);
622
623 t_expire = &itimer->expire;
624 t_reload = &itimer->reload;
540 crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof; 625 crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof;
541 626
542 EnterCriticalSection (crit); 627 EnterCriticalSection (crit);
@@ -547,11 +632,13 @@ getitimer (int which, struct itimerval *value)
547 if (expire) 632 if (expire)
548 expire -= ticks_now; 633 expire -= ticks_now;
549 634
550 value->it_value.tv_sec = expire / CLOCKS_PER_SEC; 635 value->it_value.tv_sec = expire / TIMER_TICKS_PER_SEC;
551 usecs = (expire % CLOCKS_PER_SEC) * (__int64)1000000 / CLOCKS_PER_SEC; 636 usecs =
637 (expire % TIMER_TICKS_PER_SEC) * (__int64)1000000 / TIMER_TICKS_PER_SEC;
552 value->it_value.tv_usec = usecs; 638 value->it_value.tv_usec = usecs;
553 value->it_interval.tv_sec = reload / CLOCKS_PER_SEC; 639 value->it_interval.tv_sec = reload / TIMER_TICKS_PER_SEC;
554 usecs = (reload % CLOCKS_PER_SEC) * (__int64)1000000 / CLOCKS_PER_SEC; 640 usecs =
641 (reload % TIMER_TICKS_PER_SEC) * (__int64)1000000 / TIMER_TICKS_PER_SEC;
555 value->it_interval.tv_usec= usecs; 642 value->it_interval.tv_usec= usecs;
556 643
557 return 0; 644 return 0;
@@ -560,10 +647,11 @@ getitimer (int which, struct itimerval *value)
560int 647int
561setitimer(int which, struct itimerval *value, struct itimerval *ovalue) 648setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
562{ 649{
563 volatile clock_t *t_expire, *t_reload; 650 volatile ULONGLONG *t_expire, *t_reload;
564 clock_t expire, reload, expire_old, reload_old; 651 ULONGLONG expire, reload, expire_old, reload_old;
565 __int64 usecs; 652 __int64 usecs;
566 CRITICAL_SECTION *crit; 653 CRITICAL_SECTION *crit;
654 struct itimerval tem, *ptem;
567 655
568 if (disable_itimers) 656 if (disable_itimers)
569 return -1; 657 return -1;
@@ -573,26 +661,21 @@ setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
573 time we are called, measure the clock tick resolution. */ 661 time we are called, measure the clock tick resolution. */
574 if (!clocks_min) 662 if (!clocks_min)
575 { 663 {
576 clock_t t1, t2; 664 ULONGLONG t1, t2;
577 665
578 for (t1 = clock (); (t2 = clock ()) == t1; ) 666 for (t1 = w32_get_timer_time (NULL);
667 (t2 = w32_get_timer_time (NULL)) == t1; )
579 ; 668 ;
580 clocks_min = t2 - t1; 669 clocks_min = t2 - t1;
581 } 670 }
582 671
583 if (ovalue) 672 if (ovalue)
584 { 673 ptem = ovalue;
585 if (getitimer (which, ovalue)) /* also sets ticks_now */
586 return -1; /* errno already set */
587 }
588 else 674 else
589 ticks_now = clock (); 675 ptem = &tem;
590 676
591 if (which != ITIMER_REAL && which != ITIMER_PROF) 677 if (getitimer (which, ptem)) /* also sets ticks_now */
592 { 678 return -1; /* errno already set */
593 errno = EINVAL;
594 return -1;
595 }
596 679
597 t_expire = 680 t_expire =
598 (which == ITIMER_REAL) ? &real_itimer.expire : &prof_itimer.expire; 681 (which == ITIMER_REAL) ? &real_itimer.expire : &prof_itimer.expire;
@@ -612,26 +695,26 @@ setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
612 return 0; 695 return 0;
613 } 696 }
614 697
615 reload = value->it_interval.tv_sec * CLOCKS_PER_SEC; 698 reload = value->it_interval.tv_sec * TIMER_TICKS_PER_SEC;
616 699
617 usecs = value->it_interval.tv_usec; 700 usecs = value->it_interval.tv_usec;
618 if (value->it_interval.tv_sec == 0 701 if (value->it_interval.tv_sec == 0
619 && usecs && usecs * CLOCKS_PER_SEC < clocks_min * 1000000) 702 && usecs && usecs * TIMER_TICKS_PER_SEC < clocks_min * 1000000)
620 reload = clocks_min; 703 reload = clocks_min;
621 else 704 else
622 { 705 {
623 usecs *= CLOCKS_PER_SEC; 706 usecs *= TIMER_TICKS_PER_SEC;
624 reload += usecs / 1000000; 707 reload += usecs / 1000000;
625 } 708 }
626 709
627 expire = value->it_value.tv_sec * CLOCKS_PER_SEC; 710 expire = value->it_value.tv_sec * TIMER_TICKS_PER_SEC;
628 usecs = value->it_value.tv_usec; 711 usecs = value->it_value.tv_usec;
629 if (value->it_value.tv_sec == 0 712 if (value->it_value.tv_sec == 0
630 && usecs * CLOCKS_PER_SEC < clocks_min * 1000000) 713 && usecs * TIMER_TICKS_PER_SEC < clocks_min * 1000000)
631 expire = clocks_min; 714 expire = clocks_min;
632 else 715 else
633 { 716 {
634 usecs *= CLOCKS_PER_SEC; 717 usecs *= TIMER_TICKS_PER_SEC;
635 expire += usecs / 1000000; 718 expire += usecs / 1000000;
636 } 719 }
637 720
@@ -1577,7 +1660,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
1577 numenv++; 1660 numenv++;
1578 } 1661 }
1579 /* extra env vars... */ 1662 /* extra env vars... */
1580 sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%d", 1663 sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%lu",
1581 GetCurrentProcessId ()); 1664 GetCurrentProcessId ());
1582 arglen += strlen (ppid_env_var_buffer) + 1; 1665 arglen += strlen (ppid_env_var_buffer) + 1;
1583 numenv++; 1666 numenv++;