From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: YAMAMOTO Mitsuharu Newsgroups: gmane.emacs.bugs Subject: Re: High CPU load Date: Thu, 29 Nov 2007 09:33:57 +0900 Organization: Faculty of Science, Chiba University Message-ID: References: <50C9A1E3-35A9-4B7D-8F86-46E9995D6D35@gmail.com> <20071127.220645.53363870.mituharu@math.s.chiba-u.ac.jp> <26C09430-463C-4F04-972D-36039C495E74@gmail.com> <2720AEE2-B989-4F54-81DC-B25A72E0BF6E@gmail.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII X-Trace: ger.gmane.org 1196296466 1659 80.91.229.12 (29 Nov 2007 00:34:26 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 29 Nov 2007 00:34:26 +0000 (UTC) Cc: bug-gnu-emacs@gnu.org, Ugur Ozdemir , Seiji Zenitani To: David Reitter Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Thu Nov 29 01:34:34 2007 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1IxXMI-0000Cu-Uo for geb-bug-gnu-emacs@m.gmane.org; Thu, 29 Nov 2007 01:34:27 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IxXM3-0004Xh-Cs for geb-bug-gnu-emacs@m.gmane.org; Wed, 28 Nov 2007 19:34:11 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1IxXLy-0004Xc-Bt for bug-gnu-emacs@gnu.org; Wed, 28 Nov 2007 19:34:06 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1IxXLw-0004XQ-PE for bug-gnu-emacs@gnu.org; Wed, 28 Nov 2007 19:34:05 -0500 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IxXLw-0004XN-IU for bug-gnu-emacs@gnu.org; Wed, 28 Nov 2007 19:34:04 -0500 Original-Received: from ntp.math.s.chiba-u.ac.jp ([133.82.132.2] helo=mathmail.math.s.chiba-u.ac.jp) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1IxXLv-0000RF-LI for bug-gnu-emacs@gnu.org; Wed, 28 Nov 2007 19:34:04 -0500 Original-Received: from church.math.s.chiba-u.ac.jp (church [133.82.132.36]) by mathmail.math.s.chiba-u.ac.jp (Postfix) with ESMTP id 110A02C46; Thu, 29 Nov 2007 09:33:58 +0900 (JST) In-Reply-To: User-Agent: Wanderlust/2.14.0 (Africa) SEMI/1.14.6 (Maruoka) FLIM/1.14.8 (=?ISO-8859-4?Q?Shij=F2?=) APEL/10.6 Emacs/23.0.50 (sparc-sun-solaris2.8) MULE/5.0 (SAKAKI) X-detected-kernel: by monty-python.gnu.org: NetBSD 3.0 (DF) X-BeenThere: bug-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:17085 Archived-At: >>>>> On Wed, 28 Nov 2007 10:24:00 +0900, YAMAMOTO Mitsuharu said: > Maybe you can avoid this situation by setting use-dialog-box to nil > in the meanwhile. Actually, setting use-file-dialog to nil was sufficient. I could reproduce the high CPU load with unmodified Carbon Emacs on Leopard using the following steps. 1. Create 7 instances of shell buffers using C-u M-x shell repeatedly. 2. Kill all the shell buffers. 3. Open a file dialog and cancel it. > I also guess high CPU usage has something to do with filesystems > over network, because SystemNotificationTaskProc above seems to > monitor file system volume and the socket monitor thread (the first > thread above) is also busy. Maybe you can monitor network packets > while high CPU load is observed. This guess was not right. Normally, SystemNotificationTaskProc waits for a Unix domain socket /var/run/mDNSResponder to become readable. But if the file descriptor is the one that was used in the Emacs main thread previously, the socket is waited to become either readable or writable because of the specification of CFSocketCreateWithNative. Since /var/run/mDNSResponder is always writable, that leads to a busy loop. Please try the following patch. It invalidates CFSocket objects every time to avoid the above situation. YAMAMOTO Mitsuharu mituharu@math.s.chiba-u.ac.jp Index: src/mac.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/mac.c,v retrieving revision 1.77.2.3 diff -c -p -r1.77.2.3 mac.c *** src/mac.c 1 Aug 2007 22:20:41 -0000 1.77.2.3 --- src/mac.c 29 Nov 2007 00:18:55 -0000 *************** static ComponentInstance as_scripting_co *** 79,84 **** --- 79,85 ---- /* The single script context used for all script executions. */ static OSAID as_script_context; + #ifndef MAC_OS_X #if TARGET_API_MAC_CARBON static int wakeup_from_rne_enabled_p = 0; #define ENABLE_WAKEUP_FROM_RNE (wakeup_from_rne_enabled_p = 1) *************** static int wakeup_from_rne_enabled_p = 0 *** 87,92 **** --- 88,94 ---- #define ENABLE_WAKEUP_FROM_RNE 0 #define DISABLE_WAKEUP_FROM_RNE 0 #endif + #endif #ifndef MAC_OSX static OSErr posix_pathname_to_fsspec P_ ((const char *, FSSpec *)); *************** Lisp_Object *** 1127,1144 **** cfdate_to_lisp (date) CFDateRef date; { ! static const CFGregorianDate epoch_gdate = {1970, 1, 1, 0, 0, 0.0}; ! static CFAbsoluteTime epoch = 0.0, sec; ! int high, low; ! ! if (epoch == 0.0) ! epoch = CFGregorianDateGetAbsoluteTime (epoch_gdate, NULL); ! sec = CFDateGetAbsoluteTime (date) - epoch; high = sec / 65536.0; low = sec - high * 65536.0; ! return list3 (make_number (high), make_number (low), make_number (0)); } --- 1129,1143 ---- cfdate_to_lisp (date) CFDateRef date; { ! CFTimeInterval sec; ! int high, low, microsec; ! sec = CFDateGetAbsoluteTime (date) + kCFAbsoluteTimeIntervalSince1970; high = sec / 65536.0; low = sec - high * 65536.0; + microsec = (sec - floor (sec)) * 1000000.0; ! return list3 (make_number (high), make_number (low), make_number (microsec)); } *************** xrm_get_preference_database (application *** 1826,1833 **** GCPRO3 (database, quarks, value); - BLOCK_INPUT; - app_id = kCFPreferencesCurrentApplication; if (application) { --- 1825,1830 ---- *************** xrm_get_preference_database (application *** 1879,1886 **** CFRelease (key_set); CFRelease (app_id); - UNBLOCK_INPUT; - UNGCPRO; return database; --- 1876,1881 ---- *************** extern int noninteractive; *** 4994,5001 **** SELECT_TIMEOUT_THRESHOLD_RUNLOOP seconds). -> Create CFSocket for each socket and add it into the current event RunLoop so that the current event loop gets quit when ! the socket becomes ready. Then ReceiveNextEvent can wait for ! both kinds of inputs. 4. Otherwise. -> Periodically poll the window input channel while repeatedly executing `select' with a short timeout --- 4989,4996 ---- SELECT_TIMEOUT_THRESHOLD_RUNLOOP seconds). -> Create CFSocket for each socket and add it into the current event RunLoop so that the current event loop gets quit when ! the socket becomes ready. Then CFRunLoopRunInMode can wait ! for both kinds of inputs. 4. Otherwise. -> Periodically poll the window input channel while repeatedly executing `select' with a short timeout *************** socket_callback (s, type, address, data, *** 5017,5028 **** const void *data; void *info; { - int fd = CFSocketGetNative (s); - SELECT_TYPE *ofds = (SELECT_TYPE *)info; - - if ((type == kCFSocketReadCallBack && FD_ISSET (fd, &ofds[0])) - || (type == kCFSocketConnectCallBack && FD_ISSET (fd, &ofds[1]))) - QuitEventLoop (GetCurrentEventLoop ()); } #endif /* SELECT_USE_CFSOCKET */ --- 5012,5017 ---- *************** select_and_poll_event (nfds, rfds, wfds, *** 5032,5073 **** SELECT_TYPE *rfds, *wfds, *efds; EMACS_TIME *timeout; { ! OSStatus err = noErr; int r = 0; ! /* Try detect_input_pending before ReceiveNextEvent in the same BLOCK_INPUT block, in case that some input has already been read asynchronously. */ BLOCK_INPUT; ! ENABLE_WAKEUP_FROM_RNE; ! if (!detect_input_pending ()) { ! EMACS_TIME select_timeout; ! EventTimeout timeoutval = ! (timeout ! ? (EMACS_SECS (*timeout) * kEventDurationSecond ! + EMACS_USECS (*timeout) * kEventDurationMicrosecond) ! : kEventDurationForever); EMACS_SET_SECS_USECS (select_timeout, 0, 0); r = select (nfds, rfds, wfds, efds, &select_timeout); if (timeoutval == 0.0) ! err = eventLoopTimedOutErr; ! else if (r == 0) { #if USE_CG_DRAWING mac_prepare_for_quickdraw (NULL); #endif ! err = ReceiveNextEvent (0, NULL, timeoutval, ! kEventLeaveInQueue, NULL); } } - DISABLE_WAKEUP_FROM_RNE; UNBLOCK_INPUT; if (r != 0) return r; ! else if (err == noErr) { /* Pretend that `select' is interrupted by a signal. */ detect_input_pending (); --- 5021,5084 ---- SELECT_TYPE *rfds, *wfds, *efds; EMACS_TIME *timeout; { ! int timedout_p = 0; int r = 0; + EMACS_TIME select_timeout; + EventTimeout timeoutval = + (timeout + ? (EMACS_SECS (*timeout) * kEventDurationSecond + + EMACS_USECS (*timeout) * kEventDurationMicrosecond) + : kEventDurationForever); + SELECT_TYPE orfds, owfds, oefds; ! if (timeout == NULL) ! { ! if (rfds) orfds = *rfds; ! if (wfds) owfds = *wfds; ! if (efds) oefds = *efds; ! } ! ! /* Try detect_input_pending before CFRunLoopRunInMode in the same BLOCK_INPUT block, in case that some input has already been read asynchronously. */ BLOCK_INPUT; ! while (1) { ! if (detect_input_pending ()) ! break; EMACS_SET_SECS_USECS (select_timeout, 0, 0); r = select (nfds, rfds, wfds, efds, &select_timeout); + if (r != 0) + break; + if (timeoutval == 0.0) ! timedout_p = 1; ! else { #if USE_CG_DRAWING mac_prepare_for_quickdraw (NULL); #endif ! if (CFRunLoopRunInMode (kCFRunLoopDefaultMode, ! timeoutval >= 0 ? timeoutval : 100000, true) ! == kCFRunLoopRunTimedOut) ! timedout_p = 1; } + + if (timeout == NULL && timedout_p) + { + if (rfds) *rfds = orfds; + if (wfds) *wfds = owfds; + if (efds) *efds = oefds; + } + else + break; } UNBLOCK_INPUT; if (r != 0) return r; ! else if (!timedout_p) { /* Pretend that `select' is interrupted by a signal. */ detect_input_pending (); *************** sys_select (nfds, rfds, wfds, efds, time *** 5084,5108 **** SELECT_TYPE *rfds, *wfds, *efds; EMACS_TIME *timeout; { ! OSStatus err = noErr; int r; EMACS_TIME select_timeout; ! static SELECT_TYPE ofds[3]; if (inhibit_window_system || noninteractive || nfds < 1 || rfds == NULL || !FD_ISSET (0, rfds)) return select (nfds, rfds, wfds, efds, timeout); FD_CLR (0, rfds); ! ofds[0] = *rfds; if (wfds) ! ofds[1] = *wfds; else ! FD_ZERO (&ofds[1]); if (efds) ! ofds[2] = *efds; else { EventTimeout timeoutval = --- 5095,5119 ---- SELECT_TYPE *rfds, *wfds, *efds; EMACS_TIME *timeout; { ! int timedout_p = 0; int r; EMACS_TIME select_timeout; ! SELECT_TYPE orfds, owfds, oefds; if (inhibit_window_system || noninteractive || nfds < 1 || rfds == NULL || !FD_ISSET (0, rfds)) return select (nfds, rfds, wfds, efds, timeout); FD_CLR (0, rfds); ! orfds = *rfds; if (wfds) ! owfds = *wfds; else ! FD_ZERO (&owfds); if (efds) ! oefds = *efds; else { EventTimeout timeoutval = *************** sys_select (nfds, rfds, wfds, efds, time *** 5130,5212 **** if (r != 0 || timeoutval == 0.0) return r; ! *rfds = ofds[0]; if (wfds) ! *wfds = ofds[1]; #if SELECT_USE_CFSOCKET if (timeoutval > 0 && timeoutval <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP) goto poll_periodically; ! /* Try detect_input_pending before ReceiveNextEvent in the same ! BLOCK_INPUT block, in case that some input has already been ! read asynchronously. */ BLOCK_INPUT; - ENABLE_WAKEUP_FROM_RNE; if (!detect_input_pending ()) { ! int minfd, fd; CFRunLoopRef runloop = (CFRunLoopRef) GetCFRunLoopFromEventLoop (GetCurrentEventLoop ()); ! static const CFSocketContext context = {0, ofds, NULL, NULL, NULL}; ! static CFMutableDictionaryRef sources; ! ! if (sources == NULL) ! sources = ! CFDictionaryCreateMutable (NULL, 0, NULL, ! &kCFTypeDictionaryValueCallBacks); for (minfd = 1; ; minfd++) /* nfds-1 works as a sentinel. */ if (FD_ISSET (minfd, rfds) || (wfds && FD_ISSET (minfd, wfds))) break; for (fd = minfd; fd < nfds; fd++) if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds))) { ! void *key = (void *) fd; ! CFRunLoopSourceRef source = ! (CFRunLoopSourceRef) CFDictionaryGetValue (sources, key); if (source == NULL) { - CFSocketRef socket = - CFSocketCreateWithNative (NULL, fd, - (kCFSocketReadCallBack - | kCFSocketConnectCallBack), - socket_callback, &context); - - if (socket == NULL) - continue; - source = CFSocketCreateRunLoopSource (NULL, socket, 0); CFRelease (socket); ! if (source == NULL) ! continue; ! CFDictionaryAddValue (sources, key, source); ! CFRelease (source); } CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode); } #if USE_CG_DRAWING mac_prepare_for_quickdraw (NULL); #endif ! err = ReceiveNextEvent (0, NULL, timeoutval, ! kEventLeaveInQueue, NULL); ! ! for (fd = minfd; fd < nfds; fd++) ! if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds))) ! { ! void *key = (void *) fd; ! CFRunLoopSourceRef source = ! (CFRunLoopSourceRef) CFDictionaryGetValue (sources, key); ! CFRunLoopRemoveSource (runloop, source, kCFRunLoopDefaultMode); ! } } - DISABLE_WAKEUP_FROM_RNE; UNBLOCK_INPUT; ! if (err == noErr || err == eventLoopQuitErr) { EMACS_SET_SECS_USECS (select_timeout, 0, 0); return select_and_poll_event (nfds, rfds, wfds, efds, --- 5141,5244 ---- if (r != 0 || timeoutval == 0.0) return r; ! *rfds = orfds; if (wfds) ! *wfds = owfds; #if SELECT_USE_CFSOCKET if (timeoutval > 0 && timeoutval <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP) goto poll_periodically; ! /* Try detect_input_pending before CFRunLoopRunInMode in the ! same BLOCK_INPUT block, in case that some input has already ! been read asynchronously. */ BLOCK_INPUT; if (!detect_input_pending ()) { ! int minfd, fd, nsocks; CFRunLoopRef runloop = (CFRunLoopRef) GetCFRunLoopFromEventLoop (GetCurrentEventLoop ()); ! #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 ! CFSocketRef *shead, *s; ! #else ! CFRunLoopSourceRef *shead, *s; ! #endif for (minfd = 1; ; minfd++) /* nfds-1 works as a sentinel. */ if (FD_ISSET (minfd, rfds) || (wfds && FD_ISSET (minfd, wfds))) break; + nsocks = 1; + for (fd = minfd + 1; fd < nfds; fd++) + if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds))) + nsocks++; + + #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 + shead = alloca (sizeof (CFSocketRef) * nsocks); + #else + shead = alloca (sizeof (CFRunLoopSourceRef) * nsocks); + #endif + s = shead; for (fd = minfd; fd < nfds; fd++) if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds))) { ! CFSocketRef socket = ! CFSocketCreateWithNative (NULL, fd, ! (kCFSocketReadCallBack ! | kCFSocketConnectCallBack), ! socket_callback, NULL); ! CFRunLoopSourceRef source; ! ! if (socket == NULL) ! continue; ! #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 ! { ! CFOptionFlags flags = CFSocketGetSocketFlags (socket); + CFSocketSetSocketFlags (socket, + flags & ~kCFSocketCloseOnInvalidate); + } + #endif + source = CFSocketCreateRunLoopSource (NULL, socket, 0); if (source == NULL) { CFRelease (socket); ! continue; } CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode); + #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 + CFRelease (source); + *s = socket; + #else + CFRelease (socket); + *s = source; + #endif + s++; } #if USE_CG_DRAWING mac_prepare_for_quickdraw (NULL); #endif ! if (CFRunLoopRunInMode (kCFRunLoopDefaultMode, ! timeoutval >= 0 ? timeoutval : 100000, true) ! == kCFRunLoopRunTimedOut) ! timedout_p = 1; ! do ! { ! --s; ! #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 ! CFSocketInvalidate (*s); ! #else ! CFRunLoopRemoveSource (runloop, *s, kCFRunLoopDefaultMode); ! #endif ! CFRelease (*s); ! } ! while (s != shead); } UNBLOCK_INPUT; ! if (!timedout_p) { EMACS_SET_SECS_USECS (select_timeout, 0, 0); return select_and_poll_event (nfds, rfds, wfds, efds, *************** sys_select (nfds, rfds, wfds, efds, time *** 5242,5252 **** if (r != 0) return r; ! *rfds = ofds[0]; if (wfds) ! *wfds = ofds[1]; if (efds) ! *efds = ofds[2]; if (timeout) { --- 5274,5284 ---- if (r != 0) return r; ! *rfds = orfds; if (wfds) ! *wfds = owfds; if (efds) ! *efds = oefds; if (timeout) { *************** init_mac_osx_environment () *** 5409,5418 **** --- 5441,5452 ---- void mac_wakeup_from_rne () { + #ifndef MAC_OSX if (wakeup_from_rne_enabled_p) /* Post a harmless event so as to wake up from ReceiveNextEvent. */ mac_post_mouse_moved_event (); + #endif } #endif