Date: Tue, 05 Aug 1997 11:09:41 -0400 (EDT) From: "Mark J. Taylor" <mtaylor@cybernet.com> To: "Jamil J. Weatherbee" <jamil@counterintelligence.ml.org>, freebsd-hackers@FreeBSD.ORG Cc: freebsd-realtime@FreeBSD.ORG Subject: RE: ?? The right way to do a microsecond resolution wait Message-ID: <XFMail.970805110941.mtaylor@cybernet.com> In-Reply-To: <Pine.BSF.3.96.970805013644.501A-100000@counterintelligence.ml.org>
next in thread | previous in thread | raw e-mail | index | archive | help
I've had compatibility problems with this kind of code in a 'real-time' environment. There are all kinds of signals going on. Some systems don't restart after an interrupted system call (even if you set the signal up as such). And many systems use the itimer for other things (like alarm()). Having it yanked out from under you is kinda annoying. I wrote a sleeper routine using select(), as the man page for usleep() suggests. It does not take any 'extra' system resources (like a valuable timer channel). For the SGI/IRIX version, I used nanosleep(). If you are interested in the 'select()' version of usleep(), here it is (free of charge and worth every penny): double timeGetTime(void) { struct timeval tv; double now; gettimeofday(&tv, NULL); now = (double) tv.tv_sec*1000L+(double) tv.tv_usec/1000; return(now); } void Sleep(long sleep_msec) { #if !defined(vxworks) && !defined(sgi) struct timeval tv; #else struct timespec tv; #endif /* !vxworks */ double wakeup_msec, now_msec; now_msec = timeGetTime(); wakeup_msec = now_msec + sleep_msec; while (now_msec=timeGetTime(), now_msec < wakeup_msec) { tv.tv_sec = (wakeup_msec - now_msec)/1000L; #if !defined(vxworks) && !defined(sgi) tv.tv_usec = ((wakeup_msec-now_msec)-(tv.tv_sec*1000L))*1000L; select(0 , NULL, NULL, NULL, &tv); #else tv.tv_nsec = ((wakeup_msec-now_msec)-(tv.tv_sec*1000L))*1000000L; nanosleep(&tv, NULL); #endif /* !vxworks */ } } On 05-Aug-97 "Jamil J. Weatherbee" wrote: > >Is this the best way to do a microsecond resolution wait under freebsd >(usleep only appears good to 10,000 microseconds). Doing small waits is an >important part of realtime software -- something that it would be >interesting to see addressed, particularily making a usleep that actually >sleeps microseconds. > > >With the following (unless i am off my rocker) i can get a 4 microsecond >wait on a ppro 180, a 25 microsecond wait on a pentium 100, and a 12 >microsecond wait on a nexgen-100. > >What I want to know is this the best way to get a highly accurate wait in >a thread of execution, is this even doing what I think it is, and why >doesnt usleep do something like this? I guess I could use it to output a >square wave on a paralell pin and look at that with an oscilliscope. For >the application I use it for the usleeps for the significant portion of >the time bring the cpu% down from 99% to about 1.5% pretty significant. > > > >#define USLEEP_RESOLUTION 10000 > >/* Don't use for times > 2000 seconds */ >void rsleep (long usecs) >{ > struct timeval begin_time, cur_time; > long elapsed, utm; > > gettimeofday (&begin_time, NULL); /* record the starting time */ > > if (utm = (usecs / USLEEP_RESOLUTION)*USLEEP_RESOLUTION) usleep (utm); > > do gettimeofday (&cur_time, NULL); /* get the current time */ > while (((cur_time.tv_sec - begin_time.tv_sec) * 1000000 + > (cur_time.tv_usec - begin_time.tv_usec)) < usecs); > } -------------------------------------------------------------------- Mark J. Taylor Network R&D Manager Cybernet Systems mtaylor@cybernet.com 727 Airport Blvd. PHONE (313) 668-2567 Ann Arbor, MI 48108 FAX (313) 668-8780 --------------------------------------------------------------------
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?XFMail.970805110941.mtaylor>