📄 nap.c
字号:
/* CHK=0x24D1 *//*+------------------------------------------------------------------------- nap.c - nap() support wht@n4hgf.Mt-Park.GA.US--------------------------------------------------------------------------*//*+:EDITS:*//*:09-10-1992-14:00-wht@n4hgf-ECU release 3.20 *//*:08-22-1992-15:39-wht@n4hgf-ECU release 3.20 BETA *//*:08-10-1992-03:04-wht@n4hgf-add init_Nap *//*:07-17-1992-18:19-wht@n4hgf-creation of common module for all binaries */#include "ecu.h"#undef NULL /* some stdio and param.h define these differently */#include <sys/param.h>#ifndef NULL /* fake usual sys/param.h value */#define NULL 0#endifint hz; /* HZ from environ or sys/param.h */ulong hzmsec; /* clock period in msec rounded up *//*+------------------------------------------------------------------------- Nap(msec) - wrapper for nap()early/most ISC and SCO UNIX nap() misbehave. This kludge doesn't return theproper value (the actual time slept), but at least it does not makea mockery of the manual page. It says: NAP(S) UNIX System V NAP(S) Name nap - suspends execution for a short interval Syntax long nap(period) long period; Description The current process is suspended from execution for at least the number of milliseconds specified by period, or until a signal is received. Return Value On successful completion, a long integer indicating the number of milliseconds actually slept is returned. If the process received a signal while napping, the return value will be -1, and errno will be set to EINTR. See Also sleep(S) Notes This function is driven by the system clock, which in most cases has a granularity of tens of milliseconds. This function must be linked with the linker option -lx.It appears nap() under UNIX 3.2.x has departed virtually entirely fromthe manual page. I'm beginning to look rather silly in severalmilleus since I keep telling people SCO UNIX is a viable upgrade fromXENIX. But process control people need some kind of timing capabilityless than one second and we can't do it with nap or select.nap(msec) is supposed to nap *at least* msec milliseconds. However,if msec is specified less than 1000/HZ + 1, it will not nap at all.This was true for 3.2.0 and 3.2.1.It is supposed to return the number of milliseconds it actuallyslept. Instead, it appears to "save up" the values and return them inlots of 1000. This behavior is true for 3.2.2.As it is nap() is nearly useless for accurate timing. I believeselect() suffers from the same deficiency (< 1000 msec timeoutbecomes 1000 msec) but I haven't "proven" it yet. [[ It was laterproven for SCO 3.2v2 at least ... see READMEs and *HISTORY ]]On systems with a working select(), we use a relatively complex selectarrangement to accomplish the nap requirement, but with an improvement.The "nap" survives any EINTR except for SIGINT (as indicated by sigintgetting set). On SIGINT, the nap is aborted.A "working select" means1. the system tries to support it (all but XENIX 286)2. it is in libc.a (all but XENIX; see directory xsel386 to fix XENIX 386)3. it is not broken (XENIX 386 select fails on ttys, but can be fixed: see xsel386; even an "unfixed" XENIX select would work here because we are only interested in timeouts)4. it times out properly (SCO UNIX 3.2.[1-2] screws up by ROUNDING timeouts UP to ONE SECOND).select() and nap() works very well on SCO 3.2v4--------------------------------------------------------------------------*/longNap(msec)long msec;{#if defined(M_XENIX) || defined(SCO32v4) || defined(WORKING_NAP) return(nap(msec));#else#if defined(WORKING_SELECT)/* precision guard */#define SECDELTA 684300000L /* sometime in 9/91 *//* * Compute A -= B for timeval structs A, B (thanks to ping.c) */#ifdef USE_GETTIMEOFDAY#define tvsub(A, B) \ if(1) { \ (A)->tv_sec -= (B)->tv_sec ;\ if (((A)->tv_usec -= (B)->tv_usec) < 0)\ { (A)->tv_sec--; (A)->tv_usec += 1000000; } \ } else /* ; supplied by invocation */ struct timeval timer; struct timeval start; struct timeval now; struct timezone trash; gettimeofday(&start,&trash); start.tv_sec -= SECDELTA; timer.tv_sec = msec / 1000; timer.tv_usec = (msec % 1000L) * 1000L; while(((timer.tv_sec * 1000000) + timer.tv_usec) > 0) { if(!select(0,0,0,0,&timer)) break; if(errno != EINTR) break; if(sigint) /* if SIGINT posted, exit now */ return(-1); gettimeofday(&now,&trash); now.tv_sec -= SECDELTA; tvsub(&now,&start); timer.tv_sec = msec / 1000; timer.tv_usec = (msec % 1000L) * 1000L; tvsub(&timer,&now); } gettimeofday(&now,&trash); now.tv_sec -= SECDELTA; tvsub(&now,&start); msec = (now.tv_sec * 1000) + (now.tv_usec / 1000);#else#define tbsub(t, t0) \ if(1) { \ register long delta_msec = ((((t)->time * 1000L) + ( t)->millitm) - \ (((t0)->time * 1000L) + (t0)->millitm)); \ (t)->time = delta_msec / 1000; \ (t)->millitm = delta_msec % 1000; \ } else /* ; supplied by invoker */ struct timeb timer; struct timeb start; struct timeb now; ftime(&start); start.time -= SECDELTA; timer.time = msec / 1000; timer.millitm = msec % 1000; while(((timer.time * 1000) + timer.millitm) > 0) { struct timeval tval; tval.tv_sec = timer.time; tval.tv_usec = timer.millitm * 1000; if(!select(0,0,0,0,&tval)) break; if(errno != EINTR) break; if(sigint) /* if SIGINT posted, exit now */ return(-1); ftime(&now); now.time -= SECDELTA; tbsub(&now,&start); timer.time = msec / 1000; timer.millitm = msec % 1000; tbsub(&timer,&now); } ftime(&now); now.time -= SECDELTA; tbsub(&now,&start); msec = (now.time * 1000) + now.millitm;#endif /* USE_GETTIMEOFDAY */ return(msec);#else#if defined(M_UNIX) || defined(ISC) if(msec < hzmsec) msec = hzmsec; if(nap(msec) < 0) return(-1); return(msec);#elseporting_attention_needed_here;#endif /* use hacked nap */#endif /* WORKING_SELECT */#endif /* working nap */} /* end of Nap *//*+------------------------------------------------------------------------- init_Nap()--------------------------------------------------------------------------*/voidinit_Nap(){ /* * learn tick rate for various timers */ if(getenv("HZ")) hz = (ulong)atoi(getenv("HZ")); else hz = HZ; hzmsec = (ulong)(1000 / hz) + 2;} /* end of init_Nap *//* vi: set tabstop=4 shiftwidth=4: *//* end of nap.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -