bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: High CPU load


From: YAMAMOTO Mitsuharu
Subject: Re: High CPU load
Date: Thu, 29 Nov 2007 09:33:57 +0900
User-agent: Wanderlust/2.14.0 (Africa) SEMI/1.14.6 (Maruoka) FLIM/1.14.8 (Shijō) APEL/10.6 Emacs/23.0.50 (sparc-sun-solaris2.8) MULE/5.0 (SAKAKI)

>>>>> On Wed, 28 Nov 2007 10:24:00 +0900, YAMAMOTO Mitsuharu 
>>>>> <mituharu@math.s.chiba-u.ac.jp> 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
  




reply via email to

[Prev in Thread] Current Thread [Next in Thread]