Index: m3core.h =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/m3core.h,v retrieving revision 1.15 diff -u -r1.15 m3core.h --- m3core.h 11 Apr 2010 03:40:41 -0000 1.15 +++ m3core.h 11 Apr 2010 15:41:20 -0000 @@ -299,12 +299,6 @@ INTEGER usec; /* microsec */ } m3_timeval_t; -typedef struct { -/* This is what all systems do, but without the "m3_". */ - m3_timeval_t interval; - m3_timeval_t value; -} m3_itimerval_t; - #ifndef _WIN32 m3_time_t __cdecl Utime__get_timezone(void); m3_time_t __cdecl Utime__get_altzone(void); @@ -312,7 +306,6 @@ int __cdecl Utime__get_daylight(void); const char* __cdecl Utime__get_tzname(unsigned a); int __cdecl Utime__gettimeofday(m3_timeval_t* m3t); -int __cdecl Utime__getitimer(int which, m3_itimerval_t* m3t); #ifndef _WIN32 m3_time_t __cdecl Utime__time(m3_time_t* tloc); m3_time_t __cdecl Utime__mktime(struct tm* tm); @@ -322,7 +315,6 @@ struct tm* __cdecl Utime__localtime_r(const m3_time_t* clock, struct tm* result); struct tm* __cdecl Utime__gmtime_r(const m3_time_t* clock, struct tm* result); #endif -int __cdecl Utime__setitimer(int which, const m3_itimerval_t* m3new, m3_itimerval_t* m3old); void __cdecl Utime__tzset(void); int __cdecl Unix__utimes(const char* file, const m3_timeval_t* tvp); int __cdecl Unix__select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, m3_timeval_t* timeout); Index: thread/POSIX/ThreadPosix.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/POSIX/ThreadPosix.i3,v retrieving revision 1.14 diff -u -r1.14 ThreadPosix.i3 --- thread/POSIX/ThreadPosix.i3 11 Apr 2010 13:32:24 -0000 1.14 +++ thread/POSIX/ThreadPosix.i3 11 Apr 2010 15:41:20 -0000 @@ -5,6 +5,7 @@ INTERFACE ThreadPosix; FROM Thread IMPORT Alerted; +FROM Ctypes IMPORT int; TYPE SignalHandler1 = PROCEDURE(signo: int) RAISES {Alerted}; @@ -30,4 +31,27 @@ PROCEDURE ProcessContext(c, bottom, top: ADDRESS; p: PROCEDURE(start, limit: ADDRESS)); +(*---------------------------------------------------------------------------*) + +<*EXTERNAL ThreadPosix__SetVirtualTimer*> +PROCEDURE SetVirtualTimer(): int; +(* Thin wrapper around setitimer. *) + +(*---------------------------------------------------------------------------*) + +(* Model a set of integers of arbitrary size? *) + +CONST FDSetSize = BITSIZE(INTEGER); + +TYPE FDSet = SET OF [0 .. FDSetSize-1]; + FDS = REF ARRAY OF FDSet; + +<*EXTERNAL ThreadPosix__Select*> +PROCEDURE Select(nfds: int; VAR read, write, except: FDSet; + timeout: LONGREAL(*Time.T*)): int; +(* Thin wrapper around select. *) + +(*---------------------------------------------------------------------------*) + + END ThreadPosix. Index: thread/POSIX/ThreadPosix.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/POSIX/ThreadPosix.m3,v retrieving revision 1.68 diff -u -r1.68 ThreadPosix.m3 --- thread/POSIX/ThreadPosix.m3 11 Apr 2010 15:40:46 -0000 1.68 +++ thread/POSIX/ThreadPosix.m3 11 Apr 2010 15:41:21 -0000 @@ -15,8 +15,7 @@ IMPORT Cerrno, Cstring, FloatMode, MutexRep, RTHeapRep, RTCollectorSRC, RTError, RTParams, RTPerfTool, RTProcedureSRC, - RTProcess, RTIO, ThreadEvent, Time, TimePosix, - Unix, Utime, Uexec, RuntimeError; + RTProcess, RTIO, ThreadEvent, Time, Uexec, RuntimeError; FROM Compiler IMPORT ThisFile, ThisLine; FROM Ctypes IMPORT int; @@ -49,7 +48,7 @@ read: BOOLEAN := FALSE; waitResult: WaitResult := WaitResult.Ready; (* fields relevant for new and old implementation *) - timeout := UTime{0, 0}; + timeout: Time.T := 0.0D0; hasTimeout: BOOLEAN := FALSE; errno: INTEGER := 0; index: CARDINAL := 0; @@ -95,7 +94,7 @@ waitingForMutex: Mutex; (* if state = pausing, the time at which we can restart *) - waitingForTime : UTime; + waitingForTime: Time.T; (* true if we are waiting during an AlertWait or AlertJoin or AlertPause *) @@ -132,66 +131,18 @@ is disabled. We *ASSUME* that "INC(inCritical)" and "DEC(inCritical)" generate code that is atomic with respect to Unix signal delivery. *) -(*------------------------------------------------------- Unix time hack! ---*) - -TYPE - UTime = Utime.struct_timeval; - -PROCEDURE UTimeNow (): UTime = - VAR tv: UTime; - BEGIN - EVAL Utime.gettimeofday (tv); - RETURN tv; - END UTimeNow; - -PROCEDURE Time_Add (READONLY t1, t2: UTime): UTime = - VAR res: UTime; - BEGIN - res.tv_sec := t1.tv_sec + t2.tv_sec; - res.tv_usec := t1.tv_usec + t2.tv_usec; - IF res.tv_usec > 1000000 THEN - DEC (res.tv_usec, 1000000); - INC (res.tv_sec, 1); - END; - RETURN res; - END Time_Add; - -PROCEDURE Time_Subtract (READONLY t1, t2: UTime): UTime = - VAR res: UTime; - BEGIN - res.tv_sec := t1.tv_sec - t2.tv_sec; - res.tv_usec := t1.tv_usec - t2.tv_usec; - IF res.tv_usec < 0 THEN - INC (res.tv_usec, 1000000); - DEC (res.tv_sec, 1); - END; - RETURN res; - END Time_Subtract; - -PROCEDURE Time_Compare (READONLY t1, t2: UTime): [-1 .. 1] = - BEGIN - IF t1.tv_sec > t2.tv_sec THEN RETURN 1; - ELSIF t1.tv_sec < t2.tv_sec THEN RETURN -1; - ELSIF t1.tv_usec = t2.tv_usec THEN RETURN 0; - ELSIF t1.tv_usec > t2.tv_usec THEN RETURN 1; - ELSE RETURN -1; - END; - END Time_Compare; - (*--------------------------------------------------------------- globals ---*) VAR preemption: BOOLEAN; - (* this is really a constant, but we need to take its address *) - ZeroTimeout := UTime{0, 0}; +CONST ZeroTimeout = 0.0D0; VAR (* we start the heavy machinery only when we have more than one thread *) multipleThreads: BOOLEAN := FALSE; pausedThreads : T; - selected_interval:= UTime{0, 100 * 1000}; defaultStackSize := 3000; @@ -556,18 +507,18 @@ PROCEDURE Pause(n: LONGREAL)= <*FATAL Alerted*> - VAR until := TimePosix.ToUtime (n + Time.Now ()); + VAR until := n + Time.Now (); BEGIN XPause(until, FALSE); END Pause; PROCEDURE AlertPause(n: LONGREAL) RAISES {Alerted}= - VAR until := TimePosix.ToUtime (n + Time.Now ()); + VAR until := n + Time.Now (); BEGIN XPause(until, TRUE); END AlertPause; -PROCEDURE XPause (READONLY until: UTime; alertable := FALSE) RAISES {Alerted} = +PROCEDURE XPause (READONLY until: Time.T; alertable := FALSE) RAISES {Alerted} = BEGIN INC (inCritical); self.waitingForTime := until; @@ -577,12 +528,6 @@ InternalYield (); END XPause; -CONST FDSetSize = BITSIZE(INTEGER); - -TYPE - FDSet = SET OF [0 .. FDSetSize-1]; - FDS = REF ARRAY OF FDSet; - VAR gMaxActiveFDSet, gMaxFDSet: CARDINAL; gReadFDS, gWriteFDS, gExceptFDS: FDS; @@ -635,13 +580,7 @@ THEN gReadFDS[fdindex] := fdset; ELSE gWriteFDS[fdindex] := fdset; END; - IF interval >= 0.0D0 THEN - VAR utimeout := UTimeFromTime(interval); BEGIN - res := CallSelect(fd + 1, ADR(utimeout)); - END; - ELSE - res := CallSelect(fd + 1, NIL); - END; + res := CallSelect(fd + 1, interval); IF res > 0 THEN RETURN TestFDS(fdindex, fdset, read); ELSIF res = 0 THEN RETURN WaitResult.Timeout; ELSE RETURN WaitResult.Error; @@ -672,8 +611,7 @@ self.select.set := fdset; self.select.hasTimeout := (interval >= 0.0D0); IF interval >= 0.0D0 THEN - self.select.timeout := - Time_Add(UTimeNow(), UTimeFromTime(interval)); + self.select.timeout := Time.Now() + interval; END; ICannotRun (State.blocking); DEC (inCritical); @@ -726,16 +664,13 @@ RETURN WaitResult.Timeout; END TestFDS; -PROCEDURE CallSelect(nfd: CARDINAL; timeout: UNTRACED REF UTime): INTEGER = - TYPE FDSPtr = UNTRACED REF Unix.FDSet; - VAR res: INTEGER; +PROCEDURE CallSelect(nfd: CARDINAL; timeout: Time.T): int = + VAR res: int; BEGIN FOR i := 0 TO gMaxActiveFDSet - 1 DO gExceptFDS[i] := gReadFDS[i] + gWriteFDS[i]; END; - res := Unix.select(nfd, LOOPHOLE (ADR(gReadFDS[0]), FDSPtr), - LOOPHOLE (ADR(gWriteFDS[0]), FDSPtr), - LOOPHOLE (ADR(gExceptFDS[0]), FDSPtr), timeout); + res := Select(nfd, gReadFDS[0], gWriteFDS[0], gExceptFDS[0], timeout); IF res > 0 THEN FOR i := 0 TO gMaxActiveFDSet - 1 DO gExceptFDS[i] := gExceptFDS[i] + gReadFDS[i] + gWriteFDS[i]; @@ -744,13 +679,6 @@ RETURN res; END CallSelect; -PROCEDURE UTimeFromTime(time: Time.T): UTime = - VAR floor := FLOOR(time); - BEGIN - RETURN UTime{floor, FLOOR(1.0D6 * (time - FLOAT(floor, LONGREAL)))}; - END UTimeFromTime; - - (*------------------------------------------------ timer-based preemption ---*) PROCEDURE DisableSwitching () = @@ -766,13 +694,10 @@ PROCEDURE StartSwitching () = (* set the SIGVTALRM timer and handler; can be called to change the switching interval *) - VAR it, oit: Utime.struct_itimerval; BEGIN IF preemption THEN setup_sigvtalrm (switch_thread); - it.it_interval := selected_interval; - it.it_value := selected_interval; - IF Utime.setitimer (Utime.ITIMER_VIRTUAL, it, oit) # 0 THEN + IF SetVirtualTimer() # 0 THEN RAISE InternalError; END; allow_sigvtalrm (); @@ -815,8 +740,8 @@ INVARIANT: scanned OR (selectResult = 0) *) somePausing, someBlocking: BOOLEAN; - now : UTime; - earliest : UTime; + now : Time.T; + earliest : Time.T; selectResult := 0; do_alert : BOOLEAN; did_delete : BOOLEAN; @@ -827,7 +752,7 @@ <*ASSERT heapState.inCritical = 0 *> from := self.next; (* remember where we started *) - now := UTimeNow (); + now := Time.Now (); LOOP t := from; @@ -859,7 +784,7 @@ CanRun (t); EXIT; - ELSIF Time_Compare (t.waitingForTime, now) <= 0 THEN + ELSIF t.waitingForTime <= now THEN CanRun (t); EXIT; @@ -867,7 +792,7 @@ earliest := t.waitingForTime; somePausing := TRUE; - ELSIF Time_Compare (t.waitingForTime, earliest) < 0 THEN + ELSIF t.waitingForTime < earliest THEN earliest := t.waitingForTime; END; | State.blocking => @@ -893,7 +818,7 @@ ELSE gWriteFDS[t.select.index] := t.select.set; END; - VAR n := CallSelect(t.select.fd + 1, ADR(ZeroTimeout)); BEGIN + VAR n := CallSelect(t.select.fd + 1, ZeroTimeout); BEGIN IF n > 0 THEN t.select.waitResult := TestFDS(t.select.index, t.select.set, t.select.read); @@ -919,8 +844,7 @@ END; (* Not runnable, but its timer may have expired *) - IF t.select.hasTimeout - AND Time_Compare (t.select.timeout, now) <= 0 THEN + IF t.select.hasTimeout AND t.select.timeout <= now THEN t.select.errno := 0; t.select.waitResult := WaitResult.Timeout; CanRun (t); @@ -932,7 +856,7 @@ IF NOT somePausing THEN earliest := t.select.timeout; somePausing := TRUE; - ELSIF Time_Compare (t.select.timeout, earliest) < 0 THEN + ELSIF t.select.timeout < earliest THEN earliest := t.select.timeout; END END @@ -989,17 +913,17 @@ ELSIF somePausing OR someBlocking THEN IF perfOn THEN PerfRunning (-1); END; - IF t.state = State.alive OR - somePausing AND Time_Compare(earliest, now) <= 0 THEN - selectResult := CallSelect(blockingNfds, ADR(ZeroTimeout)); + (* Some parens please to disambiguate. *) + IF t.state = State.alive OR somePausing AND earliest <= now THEN + selectResult := CallSelect(blockingNfds, ZeroTimeout); ELSIF somePausing THEN - VAR timeout := Time_Subtract (earliest, now); BEGIN - selectResult := CallSelect(blockingNfds, ADR(timeout)); + VAR timeout := earliest - now; BEGIN + selectResult := CallSelect(blockingNfds, timeout); END; ELSE - selectResult := CallSelect(blockingNfds, NIL); + selectResult := CallSelect(blockingNfds, -1.0D0 (* NIL *)); END; - IF selectResult <= 0 THEN now := UTimeNow(); END; + IF selectResult <= 0 THEN now := Time.Now(); END; scanned := TRUE ELSE IF perfOn THEN PerfRunning (-1); END; Index: thread/POSIX/ThreadPosixC.c =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/POSIX/ThreadPosixC.c,v retrieving revision 1.40 diff -u -r1.40 ThreadPosixC.c --- thread/POSIX/ThreadPosixC.c 11 Apr 2010 15:36:35 -0000 1.40 +++ thread/POSIX/ThreadPosixC.c 11 Apr 2010 15:41:21 -0000 @@ -305,6 +305,38 @@ #endif } +int +__cdecl +ThreadPosix__SetVirtualTimer(void) +{ + struct timeval selected_interval; + struct itimerval it; + + ZERO_MEMORY(selected_interval); + ZERO_MEMORY(it); + selected_interval.tv_sec = 0; + selected_interval.tv_usec = 100 * 1000; + it.it_interval = selected_interval; + it.it_value = selected_interval; + return setitimer(ITIMER_VIRTUAL, &it, NULL); +} + +int +__cdecl +ThreadPosix__Select(int nfds, + ADDRESS read, + ADDRESS write, + ADDRESS except, + LONGREAL/*Time.T*/ timeout) +{ + MicrosecondsStruct_t utime; + ZERO_MEMORY(utime); + return select(nfds, read, write, except, + (timeout >= 0) + ? TimePosix__FloatSecondsToMicrosecondsStruct(timeout, &utime) + : NULL); +} + #ifdef __cplusplus } /* extern "C" */ #endif Index: unix/Common/Uconstants.c =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/unix/Common/Uconstants.c,v retrieving revision 1.44 diff -u -r1.44 Uconstants.c --- unix/Common/Uconstants.c 16 Jan 2010 10:46:13 -0000 1.44 +++ unix/Common/Uconstants.c 11 Apr 2010 15:41:21 -0000 @@ -677,13 +677,6 @@ #undef X -#define X(x) const int Utime__##x = x; -#ifndef _WIN32 -X(ITIMER_REAL) -X(ITIMER_VIRTUAL) -#endif - -#undef X #define X(x) const int Umman__##x = x; #ifndef _WIN32 Index: unix/Common/Utime.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/unix/Common/Utime.i3,v retrieving revision 1.22 diff -u -r1.22 Utime.i3 --- unix/Common/Utime.i3 11 Apr 2010 03:41:05 -0000 1.22 +++ unix/Common/Utime.i3 11 Apr 2010 15:41:21 -0000 @@ -9,10 +9,6 @@ FROM Cstdint IMPORT int32_t; IMPORT Usysdep; -(*CONST*) -<*EXTERNAL "Utime__ITIMER_VIRTUAL"*> -VAR ITIMER_VIRTUAL: int; (* virtual time intervals *) - TYPE struct_timeval = RECORD @@ -28,19 +24,12 @@ tz_dsttime: int32_t; (* type of dst correction *) END; - struct_itimerval = RECORD - (* Every system defines this the same, and we assert it in UnixC.c *) - it_interval: struct_timeval; (* timer interval *) - it_value: struct_timeval; (* current value *) - END; - struct_tm_star = UNTRACED REF struct_tm; struct_tm = Usysdep.struct_tm; time_t = Utypes.time_t; <*EXTERNAL "Utime__gettimeofday"*>PROCEDURE gettimeofday (VAR t: struct_timeval): int32_t; -<*EXTERNAL "Utime__getitimer"*>PROCEDURE getitimer (which: int32_t; VAR value: struct_itimerval): int32_t; <*EXTERNAL "Utime__time"*>PROCEDURE time (tloc: UNTRACED REF time_t): time_t; <*EXTERNAL "Utime__mktime"*>PROCEDURE mktime (tm: struct_tm_star): time_t; @@ -52,8 +41,6 @@ <*EXTERNAL "Utime__localtime_r"*>PROCEDURE localtime_r (READONLY clock: time_t; result: struct_tm_star): struct_tm_star; <*EXTERNAL "Utime__gmtime_r"*>PROCEDURE gmtime_r (READONLY clock: time_t; result: struct_tm_star): struct_tm_star; -<*EXTERNAL "Utime__setitimer"*>PROCEDURE setitimer (which: int32_t; VAR (*const*) new_value, old_value: struct_itimerval): int32_t; - <*EXTERNAL "Utime__get_timezone"*>PROCEDURE get_timezone(): time_t; <*EXTERNAL "Utime__get_altzone"*>PROCEDURE get_altzone(): time_t; <*EXTERNAL "Utime__get_daylight"*>PROCEDURE get_daylight(): int32_t; Index: unix/Common/UtimeC.c =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/unix/Common/UtimeC.c,v retrieving revision 1.46 diff -u -r1.46 UtimeC.c --- unix/Common/UtimeC.c 11 Apr 2010 15:38:28 -0000 1.46 +++ unix/Common/UtimeC.c 11 Apr 2010 15:41:21 -0000 @@ -17,10 +17,6 @@ /* Basically no 32bit system has a 64bit time_t, unfortunate. */ M3_STATIC_ASSERT(sizeof(time_t) <= sizeof(void*)); - /* verify itimerval contains just the two fields we know about, in either order */ - { typedef struct itimerval T; - M3_STATIC_ASSERT(sizeof(T) == M3_FIELD_SIZE(T, it_value) + M3_FIELD_SIZE(T, it_interval)); } - /* verify timeval (microtime) contains just the two fields we know about, in either order */ #if defined(__APPLE__) && defined(__LP64__) /* AMD64_DARWIN has: @@ -128,23 +124,6 @@ return t; } -static void itimerval_to_m3(const struct itimerval* t, m3_itimerval_t* m) -{ - if (!m) return; - assert(t); - timeval_to_m3(&t->it_interval, &m->interval); - timeval_to_m3(&t->it_value, &m->value); -} - -static struct itimerval* itimerval_from_m3(struct itimerval* t, const m3_itimerval_t* m) -{ - if (!m) return 0; - assert(t); - timeval_from_m3(&t->it_interval, &m->interval); - timeval_from_m3(&t->it_value, &m->value); - return t; -} - int Utime__gettimeofday(m3_timeval_t* m3t) { struct timeval t; @@ -154,14 +133,6 @@ return r; } -int Utime__getitimer(int which, m3_itimerval_t* m3t) -{ - struct itimerval t; - int r = getitimer(which, m3t ? &t : 0); - itimerval_to_m3(&t, m3t); - return r; -} - m3_time_t Utime__time(m3_time_t* tloc) { time_t b = tloc ? (time_t)*tloc : 0; @@ -205,15 +176,6 @@ return gmtime_r(m3t ? &t : 0, result); } -int Utime__setitimer(int which, const m3_itimerval_t* m3new, m3_itimerval_t* m3old) -{ - struct itimerval ne; - struct itimerval old; - int r = setitimer(which, itimerval_from_m3(&ne, m3new), m3old ? &old : 0); - itimerval_to_m3(&old, m3old); - return r; -} - #ifndef __INTERIX int Unix__utimes(const char* file, const m3_timeval_t* m3t)