" Vermeulen) (10/25/90)
Since we run X on a System V box, several toolkit clients, like xload, xclock etc. started to consume far more CPU than they used to do on a BSD box. It seemed like the 'select' system call was called a lot. The problem is in the dispatching of timer events, which in done in the file 'NextEvent.c'. First we block till an event occurs. In the routine '_XtwaitForSomething' the code calculates the timeout interval to be used in the 'select' that follows. When the 'select' breaks, it is *at* the time of the timer event (given that no other events occured). Then we try to process the event. In 'DoOtherSources' (and in other event processing routines) the timer event will be processed *after* the time of the timer event. On System V, that has a time granularity of a second, this means that the 'select' breaks *at* the time, yet the dispatching is not done till *after* the time. Until that time, the code loops around and starts calling 'select' with a zero timeout value (effectively polling). So, for up to a second the code is looping through 'XtAppNextEvent' as fast as it can. When I checked this on the BSD box, it had the same problem, yet because of the higher time granularity it only looped for a fraction of a second (as far as I understand it, the time is updated in units of micro-seconds whenever the OS has a chance). I looked at several possibilities of solving this problem. The correct solution seems to dispatch the timer events *at* the time of the timer event. I would very much like to hear what other people think about this, and make sure I chose the right solution that will not cause problems elsewhere. I added a context diff for people that like to look at the code. Thanks, -Jaap- -- Jaap Vermeulen +--------------------------+ | Sequent Computer Systems | Internet : jaap@sequent.com | Beaverton, Oregon | Uucp : ...uunet!sequent!jaap +--------------------------+ *** NextEvent.c.orig Wed Oct 24 20:55:37 1990 --- NextEvent.c Wed Oct 24 21:01:39 1990 *************** *** 89,94 #define IS_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \ || (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec > (t1).tv_usec))) static void QueueTimerEvent(app, ptr) XtAppContext app; TimerEventRec *ptr; --- 89,97 ----- #define IS_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \ || (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec > (t1).tv_usec))) + #define IS_AT_OR_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \ + || (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec >= (t1).tv_usec))) + static void QueueTimerEvent(app, ptr) XtAppContext app; TimerEventRec *ptr; *************** *** 602,608 if (app->timerQueue != NULL) { /* check timeout queue */ (void) gettimeofday (&cur_time, NULL); FIXUP_TIMEVAL(cur_time); ! while(IS_AFTER (app->timerQueue->te_timer_value, cur_time)) { te_ptr = app->timerQueue; app->timerQueue = te_ptr->te_next; te_ptr->te_next = NULL; --- 605,611 ----- if (app->timerQueue != NULL) { /* check timeout queue */ (void) gettimeofday (&cur_time, NULL); FIXUP_TIMEVAL(cur_time); ! while(IS_AT_OR_AFTER (app->timerQueue->te_timer_value, cur_time)) { te_ptr = app->timerQueue; app->timerQueue = te_ptr->te_next; te_ptr->te_next = NULL; *************** *** 727,733 if (mask & XtIMTimer && app->timerQueue != NULL) { (void) gettimeofday (&cur_time, NULL); FIXUP_TIMEVAL(cur_time); ! if (IS_AFTER(app->timerQueue->te_timer_value, cur_time)) { TimerEventRec *te_ptr = app->timerQueue; app->timerQueue = app->timerQueue->te_next; te_ptr->te_next = NULL; --- 730,736 ----- if (mask & XtIMTimer && app->timerQueue != NULL) { (void) gettimeofday (&cur_time, NULL); FIXUP_TIMEVAL(cur_time); ! if (IS_AT_OR_AFTER(app->timerQueue->te_timer_value, cur_time)) { TimerEventRec *te_ptr = app->timerQueue; app->timerQueue = app->timerQueue->te_next; te_ptr->te_next = NULL; *************** *** 828,834 if (app->timerQueue != NULL) { /* check timeout queue */ (void) gettimeofday (&cur_time, NULL); FIXUP_TIMEVAL(cur_time); ! if ((IS_AFTER(app->timerQueue->te_timer_value, cur_time)) && (app->timerQueue->te_proc != 0)) { ret |= XtIMTimer; } --- 831,837 ----- if (app->timerQueue != NULL) { /* check timeout queue */ (void) gettimeofday (&cur_time, NULL); FIXUP_TIMEVAL(cur_time); ! if ((IS_AT_OR_AFTER(app->timerQueue->te_timer_value, cur_time)) && (app->timerQueue->te_proc != 0)) { ret |= XtIMTimer; } *************** *** 864,870 if (app->timerQueue != NULL) { /* check timeout queue */ (void) gettimeofday (&cur_time, NULL); FIXUP_TIMEVAL(cur_time); ! if (IS_AFTER (app->timerQueue->te_timer_value, cur_time)) return TRUE; } return FALSE; --- 867,874 ----- if (app->timerQueue != NULL) { /* check timeout queue */ (void) gettimeofday (&cur_time, NULL); FIXUP_TIMEVAL(cur_time); ! if (IS_AT_OR_AFTER (app->timerQueue->te_timer_value, cur_time)) ! return TRUE; } return FALSE;