? thread/PTHREAD/t Index: m3core.h =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/m3core.h,v retrieving revision 1.14 diff -u -r1.14 m3core.h --- m3core.h 10 Apr 2010 12:43:58 -0000 1.14 +++ m3core.h 11 Apr 2010 03:39:38 -0000 @@ -80,6 +80,7 @@ #include #include #include +#include #ifdef _WIN32 #ifndef WIN32 @@ -268,7 +269,6 @@ int __cdecl Usocket__getsockopt(int s, int level, int optname, void* optval, m3_socklen_t* plen); int __cdecl Usocket__recvfrom(int s, void* buf, size_t len, int flags, struct sockaddr* from, m3_socklen_t* plen); - #ifndef _WIN32 DIR* __cdecl Udir__opendir(const char* a); #endif @@ -300,18 +300,11 @@ } m3_timeval_t; typedef struct { -/* somewhat idealized, but ideally we'd use INT64 here */ - INTEGER sec; - INTEGER nsec; /* nanosec */ -} m3_timespec_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); @@ -330,7 +323,6 @@ 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); -int __cdecl Utime__nanosleep(const m3_timespec_t* m3req, m3_timespec_t* m3rem); 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); @@ -393,6 +385,33 @@ UINT32 __cdecl Uin__htonl(UINT32 x); UINT16 __cdecl Uin__htons(UINT16 x); +/* Support for translating Modula-3 to C. */ + +typedef double LONGREAL; + +/* http://www.cs.tut.fi/~jkorpela/round.html */ +#define ROUND(a) (((a) >= 0) ? ((a) + 0.5) : ((a) - 0.5)) + +#define FLOAT(value, type) ((type)value) +#define FLOOR floor +#define TRUNC(n) (n) + +/* Support for translating Modula-3 Time.T to Posix microtime or nanotime. */ + +typedef LONGREAL FloatSeconds, TimeT; +typedef struct timespec NanosecondsStruct_t; +typedef struct timeval MicrosecondsStruct_t; + +NanosecondsStruct_t* +__cdecl +TimePosix__FloatSecondsToNanosecondsStruct(FloatSeconds m3time, + NanosecondsStruct_t* nanotime); + +MicrosecondsStruct_t* +__cdecl +TimePosix__FloatSecondsToMicrosecondsStruct(FloatSeconds m3time, + MicrosecondsStruct_t* microtime); + #ifdef __cplusplus } /* extern "C" */ #endif Index: thread/PTHREAD/ThreadPThread.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/PTHREAD/ThreadPThread.i3,v retrieving revision 1.48 diff -u -r1.48 ThreadPThread.i3 --- thread/PTHREAD/ThreadPThread.i3 25 Feb 2010 08:31:35 -0000 1.48 +++ thread/PTHREAD/ThreadPThread.i3 11 Apr 2010 03:39:38 -0000 @@ -8,7 +8,6 @@ FROM Ctypes IMPORT int; FROM Cstddef IMPORT size_t; -FROM Utime IMPORT struct_timespec; TYPE (* These are opaque C references (not necessarily UNTRACED REF ADDRESS) *) @@ -117,7 +116,7 @@ <*EXTERNAL ThreadPThread__pthread_cond_timedwait*> PROCEDURE pthread_cond_timedwait(cond: pthread_cond_t; mutex: pthread_mutex_t; - READONLY abs: struct_timespec):int; + abs: LONGREAL(*Time.T*)):int; <*EXTERNAL ThreadPThread__pthread_cond_signal*> PROCEDURE pthread_cond_signal(cond: pthread_cond_t):int; @@ -128,7 +127,7 @@ (*---------------------------------------------------------------------------*) <*EXTERNAL "ThreadPThread__Nanosleep"*> -PROCEDURE Nanosleep (READONLY req: struct_timespec; VAR rem: struct_timespec): int; +PROCEDURE Nanosleep(nanoseconds: INTEGER); (*---------------------------------------------------------------------------*) @@ -147,4 +146,9 @@ (t: pthread_t; bottom, context: ADDRESS; p: PROCEDURE(start, limit: ADDRESS)); (*---------------------------------------------------------------------------*) +<*EXTERNAL ThreadPThread__select*> +PROCEDURE select(nfds: int; read, write, except: ADDRESS; timeout: LONGREAL): INTEGER; + +(*---------------------------------------------------------------------------*) + END ThreadPThread. Index: thread/PTHREAD/ThreadPThread.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/PTHREAD/ThreadPThread.m3,v retrieving revision 1.235 diff -u -r1.235 ThreadPThread.m3 --- thread/PTHREAD/ThreadPThread.m3 7 Apr 2010 17:34:45 -0000 1.235 +++ thread/PTHREAD/ThreadPThread.m3 11 Apr 2010 03:39:38 -0000 @@ -6,7 +6,7 @@ SchedulerPosix, RTOS, RTHooks, ThreadPThread; IMPORT Cerrno, FloatMode, MutexRep, RTCollectorSRC, RTError, RTHeapRep, RTIO, - RTParams, RTPerfTool, RTProcess, ThreadEvent, Time, Unix, Utime, Word, + RTParams, RTPerfTool, RTProcess, ThreadEvent, Time, Unix, Word, Usched, Uerror, Uexec; FROM Compiler IMPORT ThisFile, ThisLine; FROM Ctypes IMPORT int; @@ -15,8 +15,9 @@ (*----------------------------------------------------- types and globals ---*) CONST - WAIT_UNIT = 1000000; (* one million nanoseconds, one thousandth of a second *) - RETRY_INTERVAL = 10000000; (* 10 million nanoseconds, one hundredth of a second *) + MILLION = 1000 * 1000; + WAIT_UNIT = MILLION; (* one million nanoseconds, one thousandth of a second *) + RETRY_INTERVAL = 10 * MILLION; (* 10 million nanoseconds, one hundredth of a second *) REVEAL Mutex = MutexRep.Public BRANDED "Mutex Pthread-1.0" OBJECT @@ -531,27 +532,10 @@ (*---------------------------------------------------- Scheduling support ---*) -PROCEDURE CommonSleep() = - VAR wait, remaining: Utime.struct_timespec; - BEGIN - wait.tv_sec := 0; - wait.tv_nsec := WAIT_UNIT; - WHILE Nanosleep(wait, remaining) # 0 DO - wait := remaining; - END; - END CommonSleep; - -PROCEDURE ToNTime (n: LONGREAL; VAR ts: Utime.struct_timespec) = - BEGIN - ts.tv_sec := TRUNC(n); - ts.tv_nsec := ROUND((n - FLOAT(ts.tv_sec, LONGREAL)) * 1.0D9); - END ToNTime; - PROCEDURE XPause (self: Activation; n: LONGREAL; alertable: BOOLEAN) RAISES {Alerted} = - VAR until: Utime.struct_timespec; + VAR until := Time.Now() + n; BEGIN - ToNTime(Time.Now() + n, until); IF perfOn THEN PerfChanged(State.pausing) END; WITH r = pthread_mutex_lock(self.mutex) DO <*ASSERT r=0*> END; <*ASSERT self.waitingOn = NIL*> @@ -659,18 +643,18 @@ RETURN WaitResult.Timeout; END TestFDS; - PROCEDURE CallSelect (nfd: CARDINAL; timeout: UNTRACED REF UTime): INTEGER = + PROCEDURE CallSelect (nfd: CARDINAL; timeout: Time.T): INTEGER = TYPE FDSPtr = UNTRACED REF Unix.FDSet; VAR res: INTEGER; BEGIN FOR i := 0 TO fdindex 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, + LOOPHOLE (ADR(gReadFDS[0]), FDSPtr), + LOOPHOLE (ADR(gWriteFDS[0]), FDSPtr), + LOOPHOLE (ADR(gExceptFDS[0]), FDSPtr), + timeout); IF res > 0 THEN FOR i := 0 TO fdindex DO gExceptFDS[i] := gExceptFDS[i] + gReadFDS[i] + gWriteFDS[i]; @@ -699,14 +683,7 @@ ELSE gWriteFDS[fdindex] := fdset; END; - IF subInterval >= 0.0D0 THEN - VAR utimeout := UTimeFromTime(subInterval); - BEGIN - res := CallSelect(fd+1, ADR(utimeout)); - END; - ELSE - res := CallSelect(fd+1, NIL); - END; + res := CallSelect(fd+1, subInterval); IF alertable AND XTestAlert(self) THEN RAISE Alerted END; @@ -727,14 +704,6 @@ END; END XIOWait; -TYPE UTime = Utime.struct_timeval; - -PROCEDURE UTimeFromTime (time: Time.T): UTime = - VAR floor := FLOOR(time); - BEGIN - RETURN UTime{floor, FLOOR(1.0D6 * (time - FLOAT(floor, LONGREAL)))}; - END UTimeFromTime; - PROCEDURE WaitProcess (pid: int; VAR status: int): int = (* ThreadPThread.m3 and ThreadPosix.m3 are very similar. *) BEGIN @@ -855,7 +824,7 @@ INC(nLive); EXIT; END; - CommonSleep(); + Nanosleep(WAIT_UNIT); END; WHILE nLive > 0 DO <*ASSERT SIG_SUSPEND # 0*> @@ -876,7 +845,7 @@ END; wait_nsecs := RETRY_INTERVAL; ELSE - CommonSleep(); + Nanosleep(WAIT_UNIT); DEC(wait_nsecs, WAIT_UNIT); END; END; @@ -909,7 +878,7 @@ INC(nDead); EXIT; END; - CommonSleep(); + Nanosleep(WAIT_UNIT); END; WHILE nDead > 0 DO <*ASSERT SIG_SUSPEND # 0*> @@ -930,7 +899,7 @@ END; wait_nsecs := RETRY_INTERVAL; ELSE - CommonSleep(); + Nanosleep(WAIT_UNIT); DEC(wait_nsecs, WAIT_UNIT); END; END; @@ -1042,7 +1011,7 @@ act := act.next; END; IF NOT retry THEN EXIT END; - CommonSleep(); + Nanosleep(WAIT_UNIT); END; WHILE nLive > 0 DO <*ASSERT SIG_SUSPEND # 0*> @@ -1067,7 +1036,7 @@ END; wait_nsecs := RETRY_INTERVAL; ELSE - CommonSleep(); + Nanosleep(WAIT_UNIT); DEC(wait_nsecs, WAIT_UNIT); END; END; @@ -1124,7 +1093,7 @@ act := act.next; END; IF NOT retry THEN EXIT END; - CommonSleep(); + Nanosleep(WAIT_UNIT); END; WHILE nDead > 0 DO <*ASSERT SIG_SUSPEND # 0*> @@ -1149,7 +1118,7 @@ END; wait_nsecs := RETRY_INTERVAL; ELSE - CommonSleep(); + Nanosleep(WAIT_UNIT); DEC(wait_nsecs, WAIT_UNIT); END; END; Index: thread/PTHREAD/ThreadPThreadC.c =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/PTHREAD/ThreadPThreadC.c,v retrieving revision 1.124 diff -u -r1.124 ThreadPThreadC.c --- thread/PTHREAD/ThreadPThreadC.c 9 Apr 2010 09:28:39 -0000 1.124 +++ thread/PTHREAD/ThreadPThreadC.c 11 Apr 2010 03:39:38 -0000 @@ -330,29 +330,60 @@ free(p); } -int -ThreadPThread__Nanosleep(struct timespec *req, struct timespec *rem) +INTEGER +ThreadPThread__select(INTEGER nfds, + ADDRESS read, + ADDRESS write, + ADDRESS except, + LONGREAL timeout) +{ + MicrosecondsStruct_t utime = { 0 }; + ZeroMemory(&utime, sizeof(utime)); + return select(nfds, read, write, except, + (timeout >= 0) + ? TimePosix__FloatSecondsToMicrosecondsStruct(timeout, &utime) + : NULL); +} + +void +ThreadPThread__Nanosleep(INTEGER nanoseconds) { #ifdef __INTERIX - /* This is only an approximation. */ - if (rem != NULL) - memset(rem, 0, sizeof(*rem)); - if (req->tv_sec > 0) - sleep(req->tv_sec); - else - usleep(req->tv_nsec / 1000); - return 0; + usleep(nanoseconds / 1000); /* This is only an approximation. + * We don't try to complete the sleep + * if interrupted. + */ #else - return nanosleep(req, rem); + NanosecondsStruct_t wait = { 0 }; + NanosecondsStruct_t remaining = { 0 }; + + ZeroMemory(&wait, sizeof(wait)); + ZeroMemory(&remaining, sizeof(remaining)); + + wait.tv_sec = 0; + wait.tv_nsec = nanoseconds; + while (nanosleep(&wait, &remaining) == -1 && errno == EINTR) + wait = remaining; #endif } M3WRAP2(int, pthread_cond_wait, pthread_cond_t*, pthread_mutex_t*) -M3WRAP3(int, pthread_cond_timedwait, pthread_cond_t*, pthread_mutex_t*, const struct timespec*) M3WRAP1(int, pthread_cond_signal, pthread_cond_t*) M3WRAP1(int, pthread_cond_broadcast, pthread_cond_t*) int +ThreadPThread__pthread_cond_timedwait(pthread_cond_t* cond, + pthread_mutex_t* mutex, + LONGREAL m3abs) +{ + NanosecondsStruct_t uabs = { 0 }; + ZeroMemory(&uabs, sizeof(uabs)); + return pthread_cond_timedwait(cond, + mutex, + TimePosix__FloatSecondsToNanosecondsStruct(m3abs, &uabs)); +} + +int ThreadPThread__pthread_detach_self(void) { return pthread_detach(pthread_self()); Index: time/POSIX/TimePosixC.c =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/time/POSIX/TimePosixC.c,v retrieving revision 1.7 diff -u -r1.7 TimePosixC.c --- time/POSIX/TimePosixC.c 9 Apr 2010 09:28:40 -0000 1.7 +++ time/POSIX/TimePosixC.c 11 Apr 2010 03:39:38 -0000 @@ -14,6 +14,8 @@ extern "C" { #endif +#if 0 + typedef double T; #define Now Time__Now @@ -21,7 +23,7 @@ #define ToUtime TimePosix__ToUtime #define ComputeGrain Time__ComputeGrain -#define M (1000000) +#define MILLION (1000 * 1000) #if defined(__STDC__) || defined(__cplusplus) #define ANSI(x) x @@ -53,7 +55,7 @@ struct timeval tv; tv.tv_sec = (time_t)n; - tv.tv_usec = ((((INT64)n) * M) % M); + tv.tv_usec = ((((INT64)n) * MILLION) % MILLION); return tv; } @@ -61,7 +63,7 @@ T FromUtime(ANSI(const struct timeval*) tv) KR(const struct timeval* tv;) { - return ((T)tv->tv_sec) + ((T)tv->tv_usec) / (T)M; + return ((T)tv->tv_sec) + ((T)tv->tv_usec) / (T)MILLION; } static T ComputeGrainOnce(ANSI(void)) @@ -93,12 +95,36 @@ } } +#endif + +NanosecondsStruct_t* +__cdecl +TimePosix__FloatSecondsToNanosecondsStruct(FloatSeconds m3time, + NanosecondsStruct_t* nanotime) +{ +/* fairly direct conversion from the Modula-3 ThreadPThread.ToNTime */ + nanotime->tv_sec = TRUNC(m3time); + nanotime->tv_nsec = ROUND((m3time - FLOAT(nanotime->tv_sec, LONGREAL)) * 1.0E9); + return nanotime; +} + +MicrosecondsStruct_t* +__cdecl +TimePosix__FloatSecondsToMicrosecondsStruct(FloatSeconds m3time, + MicrosecondsStruct_t* microtime) +{ +/* fairly direct conversion from the Modula-3 ThreadPThread.UTimeFromTime */ + LONGINT sec = FLOOR(m3time); + microtime->tv_sec = sec; + microtime->tv_usec = FLOOR(1.0E6 * (m3time - FLOAT(sec, LONGREAL))); + return microtime; +} #ifdef __cplusplus } /* extern C */ #endif -#if 1 +#if 0 int main() { Index: time/POSIX/m3makefile =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/time/POSIX/m3makefile,v retrieving revision 1.29 diff -u -r1.29 m3makefile --- time/POSIX/m3makefile 6 Dec 2009 13:39:27 -0000 1.29 +++ time/POSIX/m3makefile 11 Apr 2010 03:39:38 -0000 @@ -28,3 +28,4 @@ implementation (_DateImpls {TARGET_OS}) end Module("TimePosix") +c_source("TimePosixC") Index: unix/Common/Utime.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/unix/Common/Utime.i3,v retrieving revision 1.21 diff -u -r1.21 Utime.i3 --- unix/Common/Utime.i3 20 Sep 2009 23:48:25 -0000 1.21 +++ unix/Common/Utime.i3 11 Apr 2010 03:39:38 -0000 @@ -28,13 +28,6 @@ tz_dsttime: int32_t; (* type of dst correction *) END; - struct_timespec = RECORD - (* somewhat idealized; this does not necessarily match - the underlying system; ideally we'd use LONGINT here. *) - tv_sec: INTEGER; (* seconds *) - tv_nsec: INTEGER; (* nanoseconds *) - END; - struct_itimerval = RECORD (* Every system defines this the same, and we assert it in UnixC.c *) it_interval: struct_timeval; (* timer interval *) @@ -60,7 +53,6 @@ <*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__nanosleep"*>PROCEDURE nanosleep (READONLY req: struct_timespec; VAR rem: struct_timespec): int32_t; <*EXTERNAL "Utime__get_timezone"*>PROCEDURE get_timezone(): time_t; <*EXTERNAL "Utime__get_altzone"*>PROCEDURE get_altzone(): time_t; Index: unix/Common/UtimeC.c =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/unix/Common/UtimeC.c,v retrieving revision 1.44 diff -u -r1.44 UtimeC.c --- unix/Common/UtimeC.c 9 Apr 2010 09:28:40 -0000 1.44 +++ unix/Common/UtimeC.c 11 Apr 2010 03:39:38 -0000 @@ -21,33 +21,6 @@ { typedef struct itimerval T; M3_STATIC_ASSERT(sizeof(T) == M3_FIELD_SIZE(T, it_value) + M3_FIELD_SIZE(T, it_interval)); } - /* verify timespec (nanotime) contains just the two fields we know about, in either order */ -/* OpenBSD/sparc64 has the unfortunate: -struct timespec -{ - int32 tv_sec; year 2038 bug - 4 bytes of padding - int64 tv_nsec; -} -*/ -#if defined(__OpenBSD__) && defined(__sparc64__) - { typedef struct timespec T1; - typedef struct { time_t tv_sec; long tv_nsec; } T2; - M3_STATIC_ASSERT(M3_FIELD_SIZE(T1, tv_sec ) == 4); - M3_STATIC_ASSERT(M3_FIELD_SIZE(T1, tv_nsec) == 8); - M3_STATIC_ASSERT(M3_FIELD_SIZE(T2, tv_sec ) == 4); - M3_STATIC_ASSERT(M3_FIELD_SIZE(T2, tv_nsec) == 8); - M3_STATIC_ASSERT(offsetof(T1, tv_sec ) == 0); - M3_STATIC_ASSERT(offsetof(T1, tv_nsec) == 8); - M3_STATIC_ASSERT(offsetof(T2, tv_sec ) == 0); - M3_STATIC_ASSERT(offsetof(T2, tv_nsec) == 8); - M3_STATIC_ASSERT(sizeof(T1) == 16); - M3_STATIC_ASSERT(sizeof(T2) == 16); - } -#else - { typedef struct timespec T; - M3_STATIC_ASSERT(sizeof(T) == M3_FIELD_SIZE(T, tv_sec) + M3_FIELD_SIZE(T, tv_nsec)); } -#endif /* verify timeval (microtime) contains just the two fields we know about, in either order */ #if defined(__APPLE__) && defined(__LP64__) /* AMD64_DARWIN has: @@ -138,23 +111,6 @@ #ifndef _WIN32 -static void timespec_to_m3(const struct timespec* t, m3_timespec_t* m) -{ - if (!m) return; - assert(t); - m->sec = t->tv_sec; - m->nsec = t->tv_nsec; -} - -static const struct timespec* timespec_from_m3(struct timespec* t, const m3_timespec_t* m) -{ - if (!m) return 0; - assert(t); - t->tv_sec = m->sec; - t->tv_nsec = m->nsec; - return t; -} - static void timeval_to_m3(const struct timeval* t, m3_timeval_t* m) { if (!m) return; @@ -261,15 +217,6 @@ #ifndef __INTERIX -int Utime__nanosleep(const m3_timespec_t* m3req, m3_timespec_t* m3rem) -{ - struct timespec req; - struct timespec rem; - int r = nanosleep(timespec_from_m3(&req, m3rem), m3rem ? &rem : 0); - timespec_to_m3(&rem, m3rem); - return r; -} - int Unix__utimes(const char* file, const m3_timeval_t* m3t) { struct timeval t;