mi: Grow event queue while reading events
Now that events are read at normal process time, we can use malloc to grow the event queue instead of discarding events. Signed-off-by: Keith Packard <keithp@keithp.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
30ac756798
commit
e2df803fca
103
mi/mieq.c
103
mi/mieq.c
|
@ -119,7 +119,7 @@ mieqNumEnqueued(EventQueuePtr eventQueue)
|
||||||
return n_enqueued;
|
return n_enqueued;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pre-condition: Called with miEventQueueMutex held */
|
/* Pre-condition: Called with input_lock held */
|
||||||
static Bool
|
static Bool
|
||||||
mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents)
|
mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents)
|
||||||
{
|
{
|
||||||
|
@ -142,11 +142,6 @@ mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents)
|
||||||
|
|
||||||
n_enqueued = mieqNumEnqueued(eventQueue);
|
n_enqueued = mieqNumEnqueued(eventQueue);
|
||||||
|
|
||||||
/* We lock input, so an mieqEnqueue does not
|
|
||||||
* write to our queue as we are modifying it.
|
|
||||||
*/
|
|
||||||
input_lock();
|
|
||||||
|
|
||||||
/* First copy the existing events */
|
/* First copy the existing events */
|
||||||
first_hunk = eventQueue->nevents - eventQueue->head;
|
first_hunk = eventQueue->nevents - eventQueue->head;
|
||||||
memcpy(new_events,
|
memcpy(new_events,
|
||||||
|
@ -178,7 +173,6 @@ mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents)
|
||||||
free(eventQueue->events);
|
free(eventQueue->events);
|
||||||
eventQueue->events = new_events;
|
eventQueue->events = new_events;
|
||||||
|
|
||||||
input_unlock();
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,8 +182,10 @@ mieqInit(void)
|
||||||
memset(&miEventQueue, 0, sizeof(miEventQueue));
|
memset(&miEventQueue, 0, sizeof(miEventQueue));
|
||||||
miEventQueue.lastEventTime = GetTimeInMillis();
|
miEventQueue.lastEventTime = GetTimeInMillis();
|
||||||
|
|
||||||
|
input_lock();
|
||||||
if (!mieqGrowQueue(&miEventQueue, QUEUE_INITIAL_SIZE))
|
if (!mieqGrowQueue(&miEventQueue, QUEUE_INITIAL_SIZE))
|
||||||
FatalError("Could not allocate event queue.\n");
|
FatalError("Could not allocate event queue.\n");
|
||||||
|
input_unlock();
|
||||||
|
|
||||||
SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
|
SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -209,32 +205,9 @@ mieqFini(void)
|
||||||
free(miEventQueue.events);
|
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
|
* Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue
|
||||||
* will never be interrupted. If this is called from both signal
|
* will never be interrupted. Must be called with input_lock held
|
||||||
* handlers and regular code, make sure the signal is suspended when
|
|
||||||
* called from regular code.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -263,36 +236,36 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
|
||||||
oldtail != miEventQueue.head) {
|
oldtail != miEventQueue.head) {
|
||||||
oldtail = (oldtail - 1) % miEventQueue.nevents;
|
oldtail = (oldtail - 1) % miEventQueue.nevents;
|
||||||
}
|
}
|
||||||
else if ((n_enqueued + 1 == miEventQueue.nevents) ||
|
else if (n_enqueued + 1 == miEventQueue.nevents) {
|
||||||
((n_enqueued + 1 >= miEventQueue.nevents - QUEUE_RESERVED_SIZE) &&
|
if (!mieqGrowQueue(&miEventQueue, miEventQueue.nevents << 1)) {
|
||||||
!mieqReservedCandidate(e))) {
|
/* Toss events which come in late. Usually this means your server's
|
||||||
/* Toss events which come in late. Usually this means your server's
|
* stuck in an infinite loop somewhere, but SIGIO is still getting
|
||||||
* stuck in an infinite loop somewhere, but SIGIO is still getting
|
* handled.
|
||||||
* handled.
|
*/
|
||||||
*/
|
miEventQueue.dropped++;
|
||||||
miEventQueue.dropped++;
|
if (miEventQueue.dropped == 1) {
|
||||||
if (miEventQueue.dropped == 1) {
|
ErrorFSigSafe("[mi] EQ overflowing. Additional events will be "
|
||||||
ErrorFSigSafe("[mi] EQ overflowing. Additional events will be "
|
"discarded until existing events are processed.\n");
|
||||||
"discarded until existing events are processed.\n");
|
xorg_backtrace();
|
||||||
xorg_backtrace();
|
ErrorFSigSafe("[mi] These backtraces from mieqEnqueue may point to "
|
||||||
ErrorFSigSafe("[mi] These backtraces from mieqEnqueue may point to "
|
"a culprit higher up the stack.\n");
|
||||||
"a culprit higher up the stack.\n");
|
ErrorFSigSafe("[mi] mieq is *NOT* the cause. It is a victim.\n");
|
||||||
ErrorFSigSafe("[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) {
|
|
||||||
ErrorFSigSafe("[mi] EQ overflow continuing. %zu events have been "
|
|
||||||
"dropped.\n", miEventQueue.dropped);
|
|
||||||
if (miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY ==
|
|
||||||
QUEUE_DROP_BACKTRACE_MAX) {
|
|
||||||
ErrorFSigSafe("[mi] No further overflow reports will be "
|
|
||||||
"reported until the clog is cleared.\n");
|
|
||||||
}
|
}
|
||||||
xorg_backtrace();
|
else if (miEventQueue.dropped % QUEUE_DROP_BACKTRACE_FREQUENCY == 0 &&
|
||||||
|
miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY <=
|
||||||
|
QUEUE_DROP_BACKTRACE_MAX) {
|
||||||
|
ErrorFSigSafe("[mi] EQ overflow continuing. %zu events have been "
|
||||||
|
"dropped.\n", miEventQueue.dropped);
|
||||||
|
if (miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY ==
|
||||||
|
QUEUE_DROP_BACKTRACE_MAX) {
|
||||||
|
ErrorFSigSafe("[mi] No further overflow reports will be "
|
||||||
|
"reported until the clog is cleared.\n");
|
||||||
|
}
|
||||||
|
xorg_backtrace();
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
oldtail = miEventQueue.tail;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
evlen = e->any.length;
|
evlen = e->any.length;
|
||||||
|
@ -556,7 +529,6 @@ mieqProcessInputEvents(void)
|
||||||
ScreenPtr screen;
|
ScreenPtr screen;
|
||||||
InternalEvent event;
|
InternalEvent event;
|
||||||
DeviceIntPtr dev = NULL, master = NULL;
|
DeviceIntPtr dev = NULL, master = NULL;
|
||||||
size_t n_enqueued;
|
|
||||||
static Bool inProcessInputEvents = FALSE;
|
static Bool inProcessInputEvents = FALSE;
|
||||||
|
|
||||||
input_lock();
|
input_lock();
|
||||||
|
@ -569,17 +541,6 @@ mieqProcessInputEvents(void)
|
||||||
BUG_WARN_MSG(inProcessInputEvents, "[mi] mieqProcessInputEvents() called recursively.\n");
|
BUG_WARN_MSG(inProcessInputEvents, "[mi] mieqProcessInputEvents() called recursively.\n");
|
||||||
inProcessInputEvents = TRUE;
|
inProcessInputEvents = TRUE;
|
||||||
|
|
||||||
/* Grow our queue if we are reaching capacity: < 2 * QUEUE_RESERVED_SIZE remaining */
|
|
||||||
n_enqueued = mieqNumEnqueued(&miEventQueue);
|
|
||||||
if (n_enqueued >= (miEventQueue.nevents - (2 * QUEUE_RESERVED_SIZE)) &&
|
|
||||||
miEventQueue.nevents < QUEUE_MAXIMUM_SIZE) {
|
|
||||||
ErrorF("[mi] Increasing EQ size to %lu to prevent dropped events.\n",
|
|
||||||
(unsigned long) (miEventQueue.nevents << 1));
|
|
||||||
if (!mieqGrowQueue(&miEventQueue, miEventQueue.nevents << 1)) {
|
|
||||||
ErrorF("[mi] Increasing the size of EQ failed.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (miEventQueue.dropped) {
|
if (miEventQueue.dropped) {
|
||||||
ErrorF("[mi] EQ processing has resumed after %lu dropped events.\n",
|
ErrorF("[mi] EQ processing has resumed after %lu dropped events.\n",
|
||||||
(unsigned long) miEventQueue.dropped);
|
(unsigned long) miEventQueue.dropped);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user