[Xquartz-changes] xserver: Branch 'server-1.12-apple' - 4 commits

Jeremy Huddleston jeremyhu at freedesktop.org
Sun Oct 16 22:27:31 PDT 2011


Rebased ref, commits from common ancestor:
commit 336c4e4934cd3a90465047e551f9b3fdc987c660
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sun Oct 16 21:09:15 2011 -0700

    mieq: Reserve some space in EQ for release and other special events
    
    The last 64 events in the event queue will be reserved for release
    events in order to help return the system to a cleaner state when
    it comes back from a soft wedge.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/mi/mieq.c b/mi/mieq.c
index 5ccfe01..cbf8897 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -59,7 +59,8 @@ in this Software without prior written authorization from The Open Group.
 # include <X11/extensions/dpmsconst.h>
 #endif
 
-#define QUEUE_INITIAL_SIZE                 128
+#define QUEUE_INITIAL_SIZE                 256
+#define QUEUE_RESERVED_SIZE                 64
 #define QUEUE_MAXIMUM_SIZE                4096
 #define QUEUE_DROP_BACKTRACE_FREQUENCY     100
 #define QUEUE_DROP_BACKTRACE_MAX            10
@@ -104,6 +105,17 @@ static inline void wait_for_server_init(void) {
 }
 #endif
 
+static size_t mieqNumEnqueued(EventQueuePtr eventQueue) {
+    size_t n_enqueued = 0;
+    if (eventQueue->nevents) {
+        /* % is not well-defined with negative numbers... sigh */
+        n_enqueued = miEventQueue.tail - miEventQueue.head + eventQueue->nevents;
+        if (n_enqueued >= eventQueue->nevents)
+            n_enqueued -= eventQueue->nevents;
+    }
+    return n_enqueued;
+}
+
 /* Pre-condition: Called with miEventQueueMutex held */
 static Bool
 mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents) {
@@ -129,14 +141,7 @@ mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents) {
         return FALSE;
     }
 
-    if (eventQueue->nevents) {
-        /* % is not well-defined with negative numbers... sigh */
-        n_enqueued = miEventQueue.tail - miEventQueue.head + eventQueue->nevents;
-        if (n_enqueued >= eventQueue->nevents)
-            n_enqueued -= eventQueue->nevents;
-    } else { 
-        n_enqueued = 0;
-    }
+    n_enqueued = mieqNumEnqueued(eventQueue);
 
     /* We block signals, so an mieqEnqueue triggered by SIGIO does not
      * write to our queue as we are modifying it.
@@ -204,6 +209,26 @@ mieqFini(void)
     free(miEventQueue.events);
 }
 
+/* This function will determine if the given event is allowed to used the reserved
+ * queue space.
+ */
+static Bool
+mieqReservedCandidate(InternalEvent *e) {
+    switch(e->any.type) {
+        case ET_KeyRelease:
+        case ET_ButtonRelease:
+#if XFreeXDGA
+        case ET_DGAEvent:
+#endif
+        case ET_RawKeyRelease:
+        case ET_RawButtonRelease:
+        case ET_XQuartz:
+            return TRUE;
+        default:
+            return FALSE;
+    }
+}
+
 /*
  * Must be reentrant with ProcessInputEvents.  Assumption: mieqEnqueue
  * will never be interrupted.  If this is called from both signal
@@ -219,6 +244,7 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
     int                    isMotion = 0;
     int                    evlen;
     Time                   time;
+    size_t                 n_enqueued;
 
 #ifdef XQUARTZ
     wait_for_server_init();
@@ -241,6 +267,8 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
 
     verify_internal_event(e);
 
+    n_enqueued = mieqNumEnqueued(&miEventQueue);
+
     /* avoid merging events from different devices */
     if (e->any.type == ET_Motion)
         isMotion = pDev->id;
@@ -248,7 +276,8 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
     if (isMotion && isMotion == miEventQueue.lastMotion &&
         oldtail != miEventQueue.head) {
         oldtail = (oldtail - 1) % miEventQueue.nevents;
-    } else if (((oldtail + 1) % miEventQueue.nevents) == miEventQueue.head) {
+    } else if ((n_enqueued + 1 == miEventQueue.nevents) ||
+               ((n_enqueued + 1 >= miEventQueue.nevents - QUEUE_RESERVED_SIZE) && !mieqReservedCandidate(e))) {
         /* Toss events which come in late.  Usually this means your server's
          * stuck in an infinite loop somewhere, but SIGIO is still getting
          * handled.
commit a67b6788b8815de1da7c9a33932b3c0147adf16e
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sat Oct 15 22:51:30 2011 -0700

    mieq: Provide better adaptability and diagnostics during mieq overflow
    
    This patch changes from a static length event queue (512) to one that
    starts at 128 and grows to 4096 as it overflows, logging each time it
    grows.
    
    This change also allows for multiple backtraces to be printed when the
    server is wedged rather than just one.  This increased sampling should
    help identify the true hog in cases where one backtrace might be
    insufficient.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/mi/mieq.c b/mi/mieq.c
index b75bde9..5ccfe01 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -59,7 +59,10 @@ in this Software without prior written authorization from The Open Group.
 # include <X11/extensions/dpmsconst.h>
 #endif
 
-#define QUEUE_SIZE  512
+#define QUEUE_INITIAL_SIZE                 128
+#define QUEUE_MAXIMUM_SIZE                4096
+#define QUEUE_DROP_BACKTRACE_FREQUENCY     100
+#define QUEUE_DROP_BACKTRACE_MAX            10
 
 #define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen
 #define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen
@@ -74,7 +77,9 @@ typedef struct _EventQueue {
     HWEventQueueType head, tail;         /* long for SetInputCheck */
     CARD32           lastEventTime;      /* to avoid time running backwards */
     int              lastMotion;         /* device ID if last event motion? */
-    EventRec         events[QUEUE_SIZE]; /* static allocation for signals */
+    EventRec         *events;            /* our queue as an array */
+    size_t           nevents;            /* the number of buckets in our queue */
+    size_t           dropped;            /* counter for number of consecutive dropped events */
     mieqHandler      handlers[128];      /* custom event handler */
 } EventQueueRec, *EventQueuePtr;
 
@@ -99,25 +104,87 @@ static inline void wait_for_server_init(void) {
 }
 #endif
 
+/* Pre-condition: Called with miEventQueueMutex held */
+static Bool
+mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents) {
+    size_t i, n_enqueued, first_hunk;
+    EventRec *new_events;
+
+    if (new_nevents <= eventQueue->nevents)
+        return FALSE;
+
+    if (!eventQueue) {
+        ErrorF("[mi] mieqGrowQueue called with a NULL eventQueue\n");
+        return FALSE;
+    }
+
+    if (CountBits((const uint8_t *)&new_nevents, sizeof(new_nevents) != 1)) {
+        ErrorF("[mi] mieqGrowQueue called with an invalid size: %lu\n", new_nevents);
+        return FALSE;
+    }
+
+    new_events = calloc(new_nevents, sizeof(EventRec));
+    if (new_events == NULL) {
+    	ErrorF("[mi] mieqGrowQueue memory allocation error.\n");
+        return FALSE;
+    }
+
+    if (eventQueue->nevents) {
+        /* % is not well-defined with negative numbers... sigh */
+        n_enqueued = miEventQueue.tail - miEventQueue.head + eventQueue->nevents;
+        if (n_enqueued >= eventQueue->nevents)
+            n_enqueued -= eventQueue->nevents;
+    } else { 
+        n_enqueued = 0;
+    }
+
+    /* We block signals, so an mieqEnqueue triggered by SIGIO does not
+     * write to our queue as we are modifying it.
+     */
+    OsBlockSignals();
+
+    /* First copy the existing events */
+    first_hunk = eventQueue->nevents - eventQueue->head;
+    memcpy(new_events,
+           &eventQueue->events[miEventQueue.head],
+           first_hunk * sizeof(EventRec));
+    memcpy(&new_events[first_hunk],
+           eventQueue->events,
+           (eventQueue->head) * sizeof(EventRec));
+
+    /* Initialize the new portion */
+    for (i = eventQueue->nevents; i < new_nevents; i++) {
+        InternalEvent* evlist = InitEventList(1);
+        if (!evlist) {
+            size_t j;
+            for (j = 0; j < i; j++)
+                FreeEventList(new_events[j].events, 1);
+            free(new_events);
+            OsReleaseSignals();
+            return FALSE;
+        }
+        new_events[i].events = evlist;
+    }
+
+    /* And update our record */
+    miEventQueue.tail = n_enqueued;
+    miEventQueue.head = 0;
+    miEventQueue.nevents = new_nevents;
+    free(miEventQueue.events);
+    miEventQueue.events = new_events;
+
+    OsReleaseSignals();
+    return TRUE;
+}
+
 Bool
 mieqInit(void)
 {
-    int i;
-
-    miEventQueue.head = miEventQueue.tail = 0;
+    memset(&miEventQueue, 0, sizeof(miEventQueue));
     miEventQueue.lastEventTime = GetTimeInMillis ();
-    miEventQueue.lastMotion = FALSE;
-    for (i = 0; i < 128; i++)
-        miEventQueue.handlers[i] = NULL;
-    for (i = 0; i < QUEUE_SIZE; i++)
-    {
-	if (miEventQueue.events[i].events == NULL) {
-	    InternalEvent* evlist = InitEventList(1);
-	    if (!evlist)
-		FatalError("Could not allocate event queue.\n");
-	    miEventQueue.events[i].events = evlist;
-	}
-    }
+
+    if(!mieqGrowQueue(&miEventQueue, QUEUE_INITIAL_SIZE))
+	FatalError("Could not allocate event queue.\n");
 
     SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
     return TRUE;
@@ -127,13 +194,14 @@ void
 mieqFini(void)
 {
     int i;
-    for (i = 0; i < QUEUE_SIZE; i++)
+    for (i = 0; i < miEventQueue.nevents; i++)
     {
 	if (miEventQueue.events[i].events != NULL) {
 	    FreeEventList(miEventQueue.events[i].events, 1);
 	    miEventQueue.events[i].events = NULL;
 	}
     }
+    free(miEventQueue.events);
 }
 
 /*
@@ -157,6 +225,20 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
     pthread_mutex_lock(&miEventQueueMutex);
 #endif
 
+    if (!miEventQueue.nevents) {
+        /* The event queue is being resized due to previous overflow.
+         * This event will be dropped on the floor.
+         */
+        if (!miEventQueue.dropped) {
+            ErrorF("[mi] Event discarded during EQ resize.\n");
+        }
+        miEventQueue.dropped++;
+#ifdef XQUARTZ
+        pthread_mutex_unlock(&miEventQueueMutex);
+#endif
+        return;
+    }
+
     verify_internal_event(e);
 
     /* avoid merging events from different devices */
@@ -165,26 +247,31 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
 
     if (isMotion && isMotion == miEventQueue.lastMotion &&
         oldtail != miEventQueue.head) {
-        oldtail = (oldtail - 1) % QUEUE_SIZE;
-    }
-    else {
-        static int stuck = 0;
+        oldtail = (oldtail - 1) % miEventQueue.nevents;
+    } else if (((oldtail + 1) % miEventQueue.nevents) == miEventQueue.head) {
         /* Toss events which come in late.  Usually this means your server's
          * stuck in an infinite loop somewhere, but SIGIO is still getting
-         * handled. */
-        if (((oldtail + 1) % QUEUE_SIZE) == miEventQueue.head) {
-            if (!stuck) {
-                ErrorF("[mi] EQ overflowing. The server is probably stuck "
-                        "in an infinite loop.\n");
-                xorg_backtrace();
-                stuck = 1;
+         * handled.
+         */
+        miEventQueue.dropped++;
+        if (miEventQueue.dropped == 1) {
+            ErrorF("[mi] EQ overflowing.  Additional events will be discarded until existing events are processed.\n");
+            xorg_backtrace();
+            ErrorF("[mi] These backtraces from mieqEnqueue may point to a culprit higher up the stack.\n");
+            ErrorF("[mi] mieq is *NOT* the cause.  It is a victim.\n");
+        } else if (miEventQueue.dropped %  QUEUE_DROP_BACKTRACE_FREQUENCY == 0 &&
+                   miEventQueue.dropped /  QUEUE_DROP_BACKTRACE_FREQUENCY <= QUEUE_DROP_BACKTRACE_MAX) {
+            ErrorF("[mi] EQ overflow continuing.  %lu events have been dropped.\n", miEventQueue.dropped);
+            if (miEventQueue.dropped /  QUEUE_DROP_BACKTRACE_FREQUENCY == QUEUE_DROP_BACKTRACE_MAX) {
+                ErrorF("[mi] No further overflow reports will be reported until the clog is cleared.\n");
             }
+            xorg_backtrace();
+        }
+
 #ifdef XQUARTZ
-            pthread_mutex_unlock(&miEventQueueMutex);
+        pthread_mutex_unlock(&miEventQueueMutex);
 #endif
-	        return;
-        }
-        stuck = 0;
+        return;
     }
 
     evlen = e->any.length;
@@ -203,7 +290,7 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
     miEventQueue.events[oldtail].pDev = pDev;
 
     miEventQueue.lastMotion = isMotion;
-    miEventQueue.tail = (oldtail + 1) % QUEUE_SIZE;
+    miEventQueue.tail = (oldtail + 1) % miEventQueue.nevents;
 #ifdef XQUARTZ
     pthread_mutex_unlock(&miEventQueueMutex);
 #endif
@@ -441,7 +528,21 @@ mieqProcessInputEvents(void)
 #ifdef XQUARTZ
     pthread_mutex_lock(&miEventQueueMutex);
 #endif
-    
+
+    if ((miEventQueue.tail - miEventQueue.head) % miEventQueue.nevents >= (miEventQueue.nevents >> 1) &&
+        miEventQueue.nevents < QUEUE_MAXIMUM_SIZE) {
+        ErrorF("[mi] Increasing EQ size to %lu to prevent dropped events.\n", miEventQueue.nevents << 1);
+        if (!mieqGrowQueue(&miEventQueue, miEventQueue.nevents << 1)) {
+            ErrorF("[mi] Increasing the size of EQ failed.\n");
+        }
+    }
+
+    if (miEventQueue.dropped) {
+        ErrorF("[mi] EQ processing has resumed after %lu dropped events.\n", miEventQueue.dropped);
+        ErrorF("[mi] This may be caused my a misbehaving driver monopolizing the server's resources.\n");
+        miEventQueue.dropped = 0;
+    }
+
     while (miEventQueue.head != miEventQueue.tail) {
         e = &miEventQueue.events[miEventQueue.head];
 
@@ -449,7 +550,7 @@ mieqProcessInputEvents(void)
         dev     = e->pDev;
         screen  = e->pScreen;
 
-        miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
+        miEventQueue.head = (miEventQueue.head + 1) % miEventQueue.nevents;
 
 #ifdef XQUARTZ
         pthread_mutex_unlock(&miEventQueueMutex);
commit aa04d975a9662186dc443694f10ed4911bc0a213
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sun Oct 16 02:12:38 2011 -0700

    Xnest: Match the host's keymap
    
    This was a regression.
    
    Introduced by: 08363c5830bdea34012dcd954b45ccfdc79a3a7e and
                   32db27a7f867b503c2840ca7b815e96d10be9210
    Masked by: 1e69fd4a60147287b31e53bfc61543fb17bb82c8
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xnest/Keyboard.c b/hw/xnest/Keyboard.c
index ec629dc..c20ad12 100644
--- a/hw/xnest/Keyboard.c
+++ b/hw/xnest/Keyboard.c
@@ -114,11 +114,13 @@ xnestChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
 int
 xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
 {
+  XModifierKeymap *modifier_keymap;
   KeySym *keymap;
   int mapWidth;
   int min_keycode, max_keycode;
   KeySymsRec keySyms;
-  int i;
+  CARD8 modmap[MAP_LENGTH];
+  int i, j;
   XKeyboardState values;
   XkbDescPtr xkb;
   int op, event, error, major, minor;
@@ -130,7 +132,7 @@ xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
 #ifdef _XSERVER64
       {
 	KeySym64 *keymap64;
-	int i, len;
+	int len;
 	keymap64 = XGetKeyboardMapping(xnestDisplay,
 				     min_keycode,
 				     max_keycode - min_keycode + 1,
@@ -147,7 +149,17 @@ xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
 				   max_keycode - min_keycode + 1,
 				   &mapWidth);
 #endif
-      
+
+      memset(modmap, 0, sizeof(modmap));
+      modifier_keymap = XGetModifierMapping(xnestDisplay);
+      for (j = 0; j < 8; j++)
+            for(i = 0; i < modifier_keymap->max_keypermod; i++) {
+                  CARD8 keycode;
+                  if ((keycode = modifier_keymap->modifiermap[j * modifier_keymap->max_keypermod + i]))
+                      modmap[keycode] |= 1<<j;
+      }
+      XFreeModifiermap(modifier_keymap);
+
       keySyms.minKeyCode = min_keycode;
       keySyms.maxKeyCode = max_keycode;
       keySyms.mapWidth = mapWidth;
@@ -165,7 +177,12 @@ xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
       XkbGetControls(xnestDisplay, XkbAllControlsMask, xkb);
 
       InitKeyboardDeviceStruct(pDev, NULL,
-			       xnestBell, xnestChangeKeyboardControl);
+                               xnestBell, xnestChangeKeyboardControl);
+ 
+      XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode,
+                            keySyms.maxKeyCode - keySyms.minKeyCode + 1,
+                            modmap, serverClient);
+
       XkbDDXChangeControls(pDev, xkb->ctrls, xkb->ctrls);
       XkbFreeKeyboard(xkb, 0, False);
       free(keymap);
commit 80a28cede4bdb823e5dfcd56fe352cb5c25f4026
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sun Oct 16 02:24:40 2011 -0700

    xfree86: Fix prototype for ConfigFilter
    
    This allows scan.c to build with -Wincompatible-pointer-types
    
    Build regression introduced by: efa5269f23c2237eb5368bf5245ffbbf35714153
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xfree86/parser/scan.c b/hw/xfree86/parser/scan.c
index 1cff3bc..7ce8c6d 100644
--- a/hw/xfree86/parser/scan.c
+++ b/hw/xfree86/parser/scan.c
@@ -767,7 +767,7 @@ OpenConfigFile(const char *path, const char *cmdline, const char *projroot,
  * suffix. This filter is passed to scandir(3).
  */
 static int
-ConfigFilter(const struct dirent *de)
+ConfigFilter(struct dirent *de)
 {
 	const char *name = de->d_name;
 	size_t len;


More information about the Xquartz-changes mailing list