Page 1 of 1

Bug in (sleep) on Solaris 8 (Newlisp v8.1.0)

Posted: Wed Aug 11, 2004 7:44 am
by gregben
I'm running Newlisp on Solaris 8 and when I run the following
program:

Code: Select all

#!/usr/local/bin/newlisp
# 
# Demonstrate bug in (sleep) on Solaris 8


(println "\n(sleep 999) interval is too short.")
(dotimes (i 10)

 (println (format "%02d " i) (date (apply date-value (now))))
 (sleep 999)

)


(println "\n(sleep 1000) is correct.")
(dotimes (i 10)

 (println (format "%02d " i) (date (apply date-value (now))))
 (sleep 1000)

)

(exit)
I get the following results:
  • ca1$ date_clock

    (sleep 999) interval is too short.
    00 Wed Aug 11 00:34:11 2004
    01 Wed Aug 11 00:34:11 2004
    02 Wed Aug 11 00:34:11 2004
    03 Wed Aug 11 00:34:11 2004
    04 Wed Aug 11 00:34:11 2004
    05 Wed Aug 11 00:34:11 2004
    06 Wed Aug 11 00:34:11 2004
    07 Wed Aug 11 00:34:11 2004
    08 Wed Aug 11 00:34:11 2004
    09 Wed Aug 11 00:34:11 2004

    (sleep 1000) is correct.
    00 Wed Aug 11 00:34:11 2004
    01 Wed Aug 11 00:34:12 2004
    02 Wed Aug 11 00:34:13 2004
    03 Wed Aug 11 00:34:14 2004
    04 Wed Aug 11 00:34:15 2004
    05 Wed Aug 11 00:34:16 2004
    06 Wed Aug 11 00:34:17 2004
    07 Wed Aug 11 00:34:18 2004
    08 Wed Aug 11 00:34:19 2004
    09 Wed Aug 11 00:34:20 2004
    ca1$
If I can do anything to help track this down, please let me know.
Thanks.

Posted: Wed Aug 11, 2004 10:45 am
by nigelbrown
Looking at the source nl-filesys.c the section involved seems to be
void mySleep(UINT ms)
{
#ifdef NANOSLEEP
struct timespec tm;

tm.tv_sec = ms/1000;
tm.tv_nsec = (ms - tm.tv_sec * 1000) * 1000000;
nanosleep(&tm, 0);

#else

#ifdef MINGW
_sleep(ms);
#else
sleep(ms/1000);
#endif

#endif
}

Is nanosleep used on Sol8?
if not the code is
sleep(ms/1000);
with ms UINT so I guess integer division is giving
999/1000=0

If nanosleep is enabled someone else will need to comment on that section.

Nigel

Posted: Wed Aug 11, 2004 12:36 pm
by Lutz
NANOSLEEP is not enabled for Solaris compiles (see makefile_solaris) and most likely not available on your machine.

For that reason (sleep milliseconds) has only 1 second resolution on your machine.

If you happen to know how to do a 'sleep' with finer resolution on your platform, let me know and I can build it in.

Lutz

Posted: Wed Aug 11, 2004 2:16 pm
by Lutz
On Solaris 5.9 nanosleep() is available, use the following changes in the makefile:

in CFLAGS include -DNANOSLEEP

CFLAGS = -Wall -pedantic -Wno-uninitialized -c -O2 -g -DNANOSLEEP -DSOLARIS -DOPSYS=4

in the compile line include the library -lrt

$(CC) $(OBJS) -g -lm -ldl -lrt -lsocket -lnsl -o newlisp

I just tried in on a X86 with Solaris 5.9 and it gives you millisec resolution. This option will be included in the next makefile_solaris as default, if it works for you. Perhaps HPW has also a feedback on this from his Solaris people running on a Sparc station.

Lutz

Posted: Wed Aug 11, 2004 2:24 pm
by nigelbrown
Perhaps for any non-NANOSLEEP situation the code
sleep(ms/1000);
with ms UINT so I guess integer division is giving
999/1000=0

could be
sleep((ms + 500)/1000);
to round to the nearest second rather than truncate?

Nigel

Posted: Wed Aug 11, 2004 11:00 pm
by gregben
Lutz wrote:On Solaris 5.9 nanosleep() is available, use the following changes in the makefile:

in CFLAGS include -DNANOSLEEP

CFLAGS = -Wall -pedantic -Wno-uninitialized -c -O2 -g -DNANOSLEEP -DSOLARIS -DOPSYS=4

in the compile line include the library -lrt

$(CC) $(OBJS) -g -lm -ldl -lrt -lsocket -lnsl -o newlisp

I just tried in on a X86 with Solaris 5.9 and it gives you millisec resolution. This option will be included in the next makefile_solaris as default, if it works for you. Perhaps HPW has also a feedback on this from his Solaris people running on a Sparc station.

Lutz
This worked fine. Thank you.
uname -a on my machine shows:
SunOS carbon 5.8 Generic_108528-17 sun4u sparc SUNW,Ultra-2