Better solution [was: Re: [BUG][Linux] VM2.8 port eats processor cycles]

Stephan Rudlof sr at evolgo.de
Thu Jun 29 16:10:50 UTC 2000


Below there is described a better solution for sleeping parts of seconds
in the idle process.

I wrote:
> 
> Tim Rowledge wrote:
> >
> > In message <395A8532.6272A67E at evolgo.de> you wrote:
> >
> > > There is a bug somewhere. Possibly I have found the origin, see below.
> > [snip]
> > > There is a socketPollFunction, which has to be set by
> > > setSocketPollFunction( int spf), because it is initialized to 0;
> > > grep'ing for setSocketPollFunction() reveals:
> > >
> > > sr at Klaus:~/Squeak/2.8/src > grep setSocketPollFunction *.c *.h
> > > ../interp.c
> > > sqXWindow.c:void setSocketPollFunction( int spf) {
> > >
> > > . It won't be called! So ioRelinquishProcessorForMicroseconds() returns
> > > *very* fast and the idle process doesn't give processor cycles to the
> > > OS.
> > Well, sorta.
> > The setSocketPollFunction is called by the socket plugin (remember, you
> > have to grep _all_ the sources)
> 
> Ooops, sorry, I have missed this.
> 
> > in its initialiseModule() code. So if
> > you haven't done a socket call, then yes I guess you never go to sleep.
> 
> That's it.
> 
> > Hmm, anyone know how to handle something like this? Is there a sleep
> > type of call that will do partial seconds? Seems kind of poor to require
> > people to do a socket call in order to sleep!
> 
> Solution:
> 
> Just evaluate
>         NetNameResolver resolverError
> (shouldn't do too much ;-) ) and the module will be initialized:
>  initialiseModule() -> socketInit() -> setSocketPollFunction()
> .
> 
> This is a workaround!


A better solution is desribed in the following.


This C-function allows sleeping partial seconds:

NANOSLEEP(2)        Linux Programmer's Manual        NANOSLEEP(2)


NAME
       nanosleep - pause execution for a specified time

SYNOPSIS
       #include <time.h>

       int  nanosleep(const struct timespec *req, struct timespec
       *rem);

DESCRIPTION
       nanosleep delays the execution of the program for at least
       the  time specified in *req.  The function can return ear­
       lier if a signal has been delivered  to  the  process.  In
       this  case, it returns -1, sets errno to EINTR, and writes
       the remaining time into the structure pointed  to  by  rem
       unless rem is NULL.  The value of *rem can then be used to
       call nanosleep again and complete the specified pause.

       The structure timespec is used  to  specify  intervals  of
       time   with  nanosecond  precision.  It  is  specified  in
       <time.h> and has the form

              struct timespec
              {
                      time_t  tv_sec;         /* seconds */
                      long    tv_nsec;        /* nanoseconds */
              };

       The value of the nanoseconds field must be in the range  0
       to 999 999 999.

       Compared  to  sleep(3)  and  usleep(3),  nanosleep has the
       advantage of not affecting any signals, it is standardized
       by  POSIX,  it  provides  higher timing resolution, and it
       allows to continue a sleep that has been interrupted by  a
       signal more easily.

...

BUGS
       The current implementation of nanosleep is  based  on  the
       normal  kernel  timer mechanism, which has a resolution of



Linux 1.3.85                1996-04-10                          1





NANOSLEEP(2)        Linux Programmer's Manual        NANOSLEEP(2)


       1/HZ s (i.e, 10 ms on Linux/i386 and 1 ms on Linux/Alpha).
       Therefore, nanosleep pauses always for at least the speci­
       fied time, however it can take up to  10  ms  longer  than
       specified  until  the  process becomes runnable again. For
       the same reason, the value returned in case of a delivered
       signal  in *rem is usually rounded to the next larger mul­
       tiple of 1/HZ s.
...

Probably a 10 ms resolution is sufficient.

sqXWindow.c ioRelinquishProcessorForMicroseconds() could be changed from

int ioRelinquishProcessorForMicroseconds(int microSeconds)
{
  /* sleep in select() for immediate response to socket i/o */
#ifdef HEADLESS
  if ( socketPollFunction ) { socketPollFunction(microSeconds,0);}
  /* aioPollForIO(microSeconds, 0); */
#else
  if ( socketPollFunction ) { socketPollFunction(microSeconds,stXfd);}
  /* aioPollForIO(microSeconds, stXfd); */
#endif
        return microSeconds;
}

to

int ioRelinquishProcessorForMicroseconds(int microSeconds)
{
  if ( socketPollFunction ) {
	/* sleep in select() for immediate response to socket i/o */
#ifdef HEADLESS
	socketPollFunction(microSeconds,0);
	/* aioPollForIO(microSeconds, 0); */
#else
	socketPollFunction(microSeconds,stXfd);
	/* aioPollForIO(microSeconds, stXfd); */
#endif
  }
  else {
	struct timespec  sleepTime, reminderTime;
	sleepTime.tv_sec = microSeconds / 1000000;
	sleepTime.tv_nsec = microSeconds % 1000000 * 1000;
	nanosleep(&sleepTime, &reminderTime);
  }
  return microSeconds; "BTW: What's the sense of this return here? [sr]"
}


Stephan

> Greetings,
> 
> Stephan
> 
> >
> > tim
> >
> > --
> > Tim Rowledge, tim at sumeru.stanford.edu, http://sumeru.stanford.edu/tim
> > Useful Latin Phrases:- Ventis secundis, tene cursum. = Go with the flow.
> 
> --
> Stephan Rudlof (sr at evolgo.de)
>    "Genius doesn't work on an assembly line basis.
>     You can't simply say, 'Today I will be brilliant.'"
>     -- Kirk, "The Ultimate Computer", stardate 4731.3

-- 
Stephan Rudlof (sr at evolgo.de)
   "Genius doesn't work on an assembly line basis.
    You can't simply say, 'Today I will be brilliant.'"
    -- Kirk, "The Ultimate Computer", stardate 4731.3





More information about the Squeak-dev mailing list