Another fix to avoid timer starvation by X events.
- Thanks to Mark Bowyer for help to sort this out. Change timers to use absolute time. SVN revision: 19657
This commit is contained in:
parent
cf34dce748
commit
2dd6d5f12b
5
src/E.h
5
src/E.h
|
@ -579,12 +579,11 @@ EMode;
|
|||
typedef struct _qentry
|
||||
{
|
||||
char *name;
|
||||
double in_time;
|
||||
double at_time;
|
||||
void (*func) (int val, void *data);
|
||||
struct _qentry *next;
|
||||
int runtime_val;
|
||||
void *runtime_data;
|
||||
char just_added;
|
||||
}
|
||||
Qentry;
|
||||
|
||||
|
@ -742,7 +741,7 @@ void EventDebugSet(unsigned int type, int value);
|
|||
#define EventDebugSet(type, value)
|
||||
#endif
|
||||
void EventsInit(void);
|
||||
void WaitEvent(void);
|
||||
void EventsMain(void);
|
||||
void EventDebugInit(const char *s);
|
||||
void EventShow(const XEvent * ev);
|
||||
|
||||
|
|
102
src/events.c
102
src/events.c
|
@ -533,47 +533,38 @@ EventsProcess(XEvent ** evq_p, int *evq_n, int *evq_f)
|
|||
* events from the X server are interpreted, timer events are inserted, etc
|
||||
*/
|
||||
void
|
||||
WaitEvent(void)
|
||||
EventsMain(void)
|
||||
{
|
||||
static int evq_alloc = 0;
|
||||
static int evq_fetch = 0;
|
||||
static XEvent *evq_ptr = NULL;
|
||||
fd_set fdset;
|
||||
struct timeval tval;
|
||||
static struct timeval tval_last = { 0, 0 };
|
||||
double time1, time2;
|
||||
double time1, time2, dt;
|
||||
Qentry *qe;
|
||||
int count, pcount, pfetch;
|
||||
int count, pfetch;
|
||||
int fdsize;
|
||||
int xfd, smfd;
|
||||
|
||||
pcount = pfetch = 0;
|
||||
time1 = GetTime();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
pfetch = 0;
|
||||
count = EventsProcess(&evq_ptr, &evq_alloc, &pfetch);
|
||||
|
||||
if (count > pcount)
|
||||
pcount = count;
|
||||
|
||||
if (XPending(disp))
|
||||
continue;
|
||||
|
||||
if (EventDebug(EDBUG_TYPE_EVENTS))
|
||||
Eprintf("WaitEvent - Idlers\n");
|
||||
Eprintf("EventsMain - Idlers\n");
|
||||
DialogsCheckUpdate(); /* FIXME - Shouldn't be here */
|
||||
ModulesSignal(ESIGNAL_IDLE, NULL);
|
||||
|
||||
if (!XPending(disp))
|
||||
break;
|
||||
}
|
||||
|
||||
if (pfetch)
|
||||
{
|
||||
evq_fetch =
|
||||
(pfetch > evq_fetch) ? pfetch : (3 * evq_fetch + pfetch) / 4;
|
||||
if (EventDebug(EDBUG_TYPE_EVENTS))
|
||||
Eprintf("WaitEvent - Alloc/fetch/pfetch/peak=%d/%d/%d/%d)\n",
|
||||
evq_alloc, evq_fetch, pfetch, pcount);
|
||||
Eprintf("EventsMain - Alloc/fetch/pfetch/peak=%d/%d/%d/%d)\n",
|
||||
evq_alloc, evq_fetch, pfetch, count);
|
||||
if ((evq_ptr) && ((evq_alloc - evq_fetch) > 64))
|
||||
{
|
||||
evq_alloc = 0;
|
||||
|
@ -590,67 +581,64 @@ WaitEvent(void)
|
|||
FD_SET(smfd, &fdset);
|
||||
fdsize = MAX(xfd, smfd) + 1;
|
||||
|
||||
/* First time */
|
||||
if ((tval_last.tv_sec == 0) && (tval_last.tv_usec == 0))
|
||||
gettimeofday(&tval_last, NULL);
|
||||
/* time1 = time we last were here */
|
||||
time1 = ((double)tval_last.tv_sec) + (((double)tval_last.tv_usec) / 1000000);
|
||||
|
||||
/* time2 = current time */
|
||||
gettimeofday(&tval, NULL);
|
||||
time2 = ((double)tval.tv_sec) + (((double)tval.tv_usec) / 1000000);
|
||||
time2 -= time1;
|
||||
if (time2 < 0.0)
|
||||
time2 = 0.0;
|
||||
/* time2 = time spent since we last were here */
|
||||
|
||||
tval_last.tv_sec = tval.tv_sec;
|
||||
tval_last.tv_usec = tval.tv_usec;
|
||||
time2 = GetTime();
|
||||
dt = time2 - time1;
|
||||
time1 = time2;
|
||||
if (dt < 0.0)
|
||||
dt = 0.0;
|
||||
/* dt = time spent since we last were here */
|
||||
|
||||
qe = GetHeadTimerQueue();
|
||||
if (qe)
|
||||
{
|
||||
if (qe->just_added)
|
||||
{
|
||||
qe->just_added = 0;
|
||||
time1 = qe->in_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
time1 = qe->in_time - time2;
|
||||
if (time1 < 0.0)
|
||||
time1 = 0.0;
|
||||
qe->in_time = time1;
|
||||
}
|
||||
tval.tv_sec = (long)time1;
|
||||
tval.tv_usec = (long)((time1 - ((double)tval.tv_sec)) * 1000000);
|
||||
count = 0;
|
||||
time2 = qe->at_time - time2;
|
||||
if (time2 < 0.0)
|
||||
time2 = 0.0;
|
||||
if (time2 <= 0.0)
|
||||
goto do_timer;
|
||||
if (XPending(disp))
|
||||
continue;
|
||||
tval.tv_sec = (long)time2;
|
||||
tval.tv_usec = (long)((time2 - ((double)tval.tv_sec)) * 1000000);
|
||||
count = select(fdsize, &fdset, NULL, NULL, &tval);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (XPending(disp))
|
||||
continue;
|
||||
count = select(fdsize, &fdset, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (EventDebug(EDBUG_TYPE_EVENTS))
|
||||
Eprintf
|
||||
("WaitEvent - count=%d xfd=%d:%d smfd=%d:%d qe=%p time1=%lf time2=%lf\n",
|
||||
("EventsMain - count=%d xfd=%d:%d smfd=%d:%d qe=%p dt=%lf time2=%lf\n",
|
||||
count, xfd, FD_ISSET(xfd, &fdset), smfd,
|
||||
(smfd >= 0) ? FD_ISSET(smfd, &fdset) : 0, qe, time1, time2);
|
||||
(smfd >= 0) ? FD_ISSET(smfd, &fdset) : 0, qe, dt, time2);
|
||||
|
||||
if (count < 0)
|
||||
return;
|
||||
continue;
|
||||
|
||||
if ((smfd >= 0) && (count > 0) && (FD_ISSET(smfd, &fdset)))
|
||||
if (count > 0)
|
||||
{
|
||||
if ((smfd >= 0) && (FD_ISSET(smfd, &fdset)))
|
||||
{
|
||||
if (EventDebug(EDBUG_TYPE_EVENTS))
|
||||
Eprintf("WaitEvent - ICE\n");
|
||||
Eprintf("EventsMain - ICE\n");
|
||||
ProcessICEMSGS();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (qe && (count == 0 || time1 <= 0.0))
|
||||
do_timer:
|
||||
if (qe)
|
||||
{
|
||||
if (EventDebug(EDBUG_TYPE_EVENTS))
|
||||
Eprintf("WaitEvent - Timers (%s)\n", qe->name);
|
||||
Eprintf("EventsMain - Timers (%s)\n", qe->name);
|
||||
HandleTimerEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_DEBUG_EVENTS
|
||||
|
@ -906,7 +894,11 @@ EventShow(const XEvent * ev)
|
|||
Eprintf("%#08lx EV-%s win=%#lx\n", ser, name, win);
|
||||
break;
|
||||
case EX_EVENT_SHAPE_NOTIFY:
|
||||
Eprintf("%#08lx EV-%s win=%#lx\n", ser, name, win);
|
||||
#define se ((XShapeEvent *)ev)
|
||||
Eprintf("%#08lx EV-%s win=%#lx kind=%d shaped=%d %d,%d %dx%d\n",
|
||||
ser, name, win, se->kind, se->shaped,
|
||||
se->x, se->y, se->width, se->height);
|
||||
#undef se
|
||||
break;
|
||||
#if USE_XRANDR
|
||||
case EX_EVENT_SCREEN_CHANGE_NOTIFY:
|
||||
|
|
|
@ -304,8 +304,7 @@ main(int argc, char **argv)
|
|||
autosave();
|
||||
|
||||
/* The primary event loop */
|
||||
for (;;)
|
||||
WaitEvent();
|
||||
EventsMain();
|
||||
|
||||
/* Of course, we should NEVER get to this point */
|
||||
|
||||
|
|
83
src/timers.c
83
src/timers.c
|
@ -39,72 +39,40 @@ DoIn(const char *name, double in_time, void (*func) (int val, void *data),
|
|||
int runtime_val, void *runtime_data)
|
||||
{
|
||||
Qentry *qe, *ptr, *pptr;
|
||||
double tally;
|
||||
|
||||
RemoveTimerEvent(name);
|
||||
qe = Emalloc(sizeof(Qentry));
|
||||
if (!qe)
|
||||
return;
|
||||
|
||||
if (EventDebug(EDBUG_TYPE_EVENTS))
|
||||
Eprintf("DoIn %8.3f: %s\n", in_time, name);
|
||||
|
||||
qe->name = Estrdup(name);
|
||||
qe->func = func;
|
||||
qe->next = NULL;
|
||||
qe->in_time = in_time;
|
||||
qe->at_time = GetTime() + in_time;
|
||||
qe->runtime_val = runtime_val;
|
||||
qe->runtime_data = runtime_data;
|
||||
qe->just_added = 1;
|
||||
|
||||
/* if there is no queue it becomes the queue */
|
||||
if (!q_first)
|
||||
{
|
||||
q_first = qe;
|
||||
qe->next = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
pptr = NULL;
|
||||
ptr = q_first;
|
||||
tally = 0.0;
|
||||
/* scan along the queue from start until sum of all timer intervals */
|
||||
/* greater than time then insert before last entry found (since it */
|
||||
/* managed to push the tally over past the end of out new timer) */
|
||||
while (ptr)
|
||||
for (ptr = q_first; ptr; pptr = ptr, ptr = ptr->next)
|
||||
{
|
||||
/* add to tally */
|
||||
tally += ptr->in_time;
|
||||
/* if this entry is after our new one add before this entry */
|
||||
if (tally > in_time)
|
||||
{
|
||||
/* number of seconds of stuff to do before the new entry */
|
||||
tally -= ptr->in_time;
|
||||
/* if the previous pointer exists then add like normal */
|
||||
if (ptr->at_time > qe->at_time)
|
||||
break;
|
||||
}
|
||||
if (pptr)
|
||||
pptr->next = qe;
|
||||
else
|
||||
q_first = qe;
|
||||
qe->next = ptr;
|
||||
if (pptr)
|
||||
{
|
||||
pptr->next = qe;
|
||||
}
|
||||
/* no previous - must have to add as first in list */
|
||||
else
|
||||
q_first = qe;
|
||||
/* subtract "stuff to do before" as timers are relative */
|
||||
qe->in_time -= tally;
|
||||
/* if there is a timer after this one, subtract the time this
|
||||
* new timer has to wait from it since its inserted into the
|
||||
* time span here
|
||||
*/
|
||||
if (qe->next)
|
||||
qe->next->in_time -= qe->in_time;
|
||||
/* we're done */
|
||||
return;
|
||||
}
|
||||
pptr = ptr;
|
||||
ptr = ptr->next;
|
||||
/* keep going through the list till we reach the end */
|
||||
}
|
||||
/* add to end of list */
|
||||
if (pptr)
|
||||
pptr->next = qe;
|
||||
else
|
||||
q_first = qe;
|
||||
|
||||
qe->in_time -= tally;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +96,7 @@ HandleTimerEvent(void)
|
|||
/* remove it */
|
||||
q_first = q_first->next;
|
||||
/* run this callback */
|
||||
(*(qe->func)) (qe->runtime_val, qe->runtime_data);
|
||||
qe->func(qe->runtime_val, qe->runtime_data);
|
||||
/* free the timer */
|
||||
if (qe->name)
|
||||
Efree(qe->name);
|
||||
|
@ -142,22 +110,17 @@ RemoveTimerEvent(const char *name)
|
|||
Qentry *qe, *ptr, *pptr;
|
||||
|
||||
pptr = NULL;
|
||||
ptr = q_first;
|
||||
/* hunt through the queue */
|
||||
while (ptr)
|
||||
for (ptr = q_first; ptr; pptr = ptr, ptr = ptr->next)
|
||||
{
|
||||
/* if the name of a timer matches */
|
||||
qe = ptr;
|
||||
if (!strcmp(qe->name, name))
|
||||
{
|
||||
/* remove it form the queue */
|
||||
if (strcmp(qe->name, name))
|
||||
continue;
|
||||
|
||||
/* Match - remove it from the queue */
|
||||
if (pptr)
|
||||
pptr->next = qe->next;
|
||||
else
|
||||
q_first = qe->next;
|
||||
/* increase the time of the next timer accordingly */
|
||||
if (qe->next)
|
||||
qe->next->in_time += qe->in_time;
|
||||
/* free it */
|
||||
if (qe->name)
|
||||
Efree(qe->name);
|
||||
|
@ -166,10 +129,6 @@ RemoveTimerEvent(const char *name)
|
|||
/* done */
|
||||
return 1;
|
||||
}
|
||||
pptr = ptr;
|
||||
ptr = ptr->next;
|
||||
/* keep going through the queue */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue