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

Started by gregben, August 11, 2004, 12:44:13 AM

Previous topic - Next topic

gregben

I'm running Newlisp on Solaris 8 and when I run the following

program:


#!/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.

nigelbrown

#1
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

Lutz

#2
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

Lutz

#3
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

nigelbrown

#4
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

gregben

#5
Quote from: "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


This worked fine. Thank you.

uname -a on my machine shows:

SunOS carbon 5.8 Generic_108528-17 sun4u sparc SUNW,Ultra-2