diff --git a/mio/lib/mio-cmn.h b/mio/lib/mio-cmn.h index 8810443..8862af2 100644 --- a/mio/lib/mio-cmn.h +++ b/mio/lib/mio-cmn.h @@ -478,11 +478,18 @@ struct mio_ptl_t #define MIO_SEC_TO_USEC(sec) ((sec) * MIO_USECS_PER_SEC) #define MIO_USEC_TO_SEC(usec) ((usec) / MIO_USECS_PER_SEC) +#if defined(MIO_SIZEOF_INT64_T) && (MIO_SIZEOF_INT64_T > 0) +typedef mio_int64_t mio_ntime_sec_t; +#else +typedef mio_int32_t mio_ntime_sec_t; +#endif +typedef mio_int32_t mio_ntime_nsec_t; + typedef struct mio_ntime_t mio_ntime_t; struct mio_ntime_t { - mio_intptr_t sec; - mio_int32_t nsec; /* nanoseconds */ + mio_ntime_sec_t sec; + mio_ntime_nsec_t nsec; /* nanoseconds */ }; #define MIO_INIT_NTIME(c,s,ns) (((c)->sec = (s)), ((c)->nsec = (ns))) diff --git a/mio/lib/mio-prv.h b/mio/lib/mio-prv.h index 1954b4d..5cfe4cb 100644 --- a/mio/lib/mio-prv.h +++ b/mio/lib/mio-prv.h @@ -130,9 +130,15 @@ void mio_firetmrjobs ( ); +/** + * The mio_gettmrtmout() function gets the remaining time until the first + * scheduled job is to be triggered. It stores in \a tmout the difference between + * the given time \a tm and the scheduled time and returns 1. If there is no + * job scheduled, it returns 0. + */ int mio_gettmrtmout ( mio_t* mio, - const mio_ntime_t* tmbase, + const mio_ntime_t* tm, mio_ntime_t* tmout ); diff --git a/mio/lib/mio-utl.h b/mio/lib/mio-utl.h index c3c4fce..c8ae4bc 100644 --- a/mio/lib/mio-utl.h +++ b/mio/lib/mio-utl.h @@ -763,6 +763,35 @@ MIO_EXPORT mio_oow_t mio_utf8_to_uc ( mio_uch_t* uc ); +/* ========================================================================= + * TIME CALCULATION WITH OVERFLOW/UNDERFLOW DETECTION + * ========================================================================= */ + +/** + * The mio_add_ntime() function adds two time structures pointed to by \a x and \a y + * and stores the result in the structure pointed to by \a z. If it detects overflow/ + * underflow, it stores the largest/least possible value respectively. + * You may use the MIO_ADD_NTIME() macro if overflow/underflow check isn't needed. + */ +MIO_EXPORT void mio_add_ntime ( + mio_ntime_t* z, + const mio_ntime_t* x, + const mio_ntime_t* y +); + +/** + * The mio_sub_ntime() function subtracts the time value \a y from the time value \a x + * and stores the result in the structure pointed to by \a z. If it detects overflow/ + * underflow, it stores the largest/least possible value respectively. + * You may use the MIO_SUB_NTIME() macro if overflow/underflow check isn't needed. + */ +MIO_EXPORT void mio_sub_ntime ( + mio_ntime_t* z, + const mio_ntime_t* x, + const mio_ntime_t* y +); + + /* ========================================================================= * BIT SWAP * ========================================================================= */ diff --git a/mio/lib/mio.c b/mio/lib/mio.c index 67ee9fd..d18c332 100644 --- a/mio/lib/mio.c +++ b/mio/lib/mio.c @@ -757,7 +757,7 @@ int mio_exec (mio_t* mio) /* wait on the multiplexer only if there is at least 1 active device */ mio_ntime_t tmout; - if (mio_gettmrtmout(mio, MIO_NULL, &tmout) <= -1) + if (mio_gettmrtmout(mio, MIO_NULL, &tmout) <= 0) { /* defaults to 0 or 1 second if timeout can't be acquired. * if this timeout affects how fast the halted device will get killed. diff --git a/mio/lib/tmr.c b/mio/lib/tmr.c index 10a174a..80a41d1 100644 --- a/mio/lib/tmr.c +++ b/mio/lib/tmr.c @@ -190,11 +190,7 @@ int mio_gettmrtmout (mio_t* mio, const mio_ntime_t* tm, mio_ntime_t* tmout) mio_ntime_t now; /* time-out can't be calculated when there's no job scheduled */ - if (mio->tmr.size <= 0) - { - mio_seterrbfmt (mio, MIO_ENOENT, "unable to compute timeout as no job is scheduled"); - return -1; - } + if (mio->tmr.size <= 0) return 0; /* no scheduled job */ /* if the current time is not specified, get it from the system */ if (tm) now = *tm; @@ -202,8 +198,7 @@ int mio_gettmrtmout (mio_t* mio, const mio_ntime_t* tm, mio_ntime_t* tmout) MIO_SUB_NTIME (tmout, &mio->tmr.jobs[0].when, &now); if (tmout->sec < 0) MIO_CLEAR_NTIME (tmout); - - return 0; + return 1; /* tmout is set */ } mio_tmrjob_t* mio_gettmrjob (mio_t* mio, mio_tmridx_t index) diff --git a/mio/lib/utl.c b/mio/lib/utl.c index f1dd72a..5e82130 100644 --- a/mio/lib/utl.c +++ b/mio/lib/utl.c @@ -2103,3 +2103,113 @@ mio_bch_t* mio_dupbcstrs (mio_t* mio, const mio_bch_t* bcs[], mio_oow_t* bcslen) return ptr; } /* ========================================================================= */ + +void mio_add_ntime (mio_ntime_t* z, const mio_ntime_t* x, const mio_ntime_t* y) +{ + mio_ntime_sec_t xs, ys; + mio_ntime_nsec_t ns; + + /*MIO_ASSERT (x->nsec >= 0 && x->nsec < MIO_NSECS_PER_SEC); + MIO_ASSERT (y->nsec >= 0 && y->nsec < MIO_NSECS_PER_SEC);*/ + + ns = x->nsec + y->nsec; + if (ns >= MIO_NSECS_PER_SEC) + { + ns = ns - MIO_NSECS_PER_SEC; + if (x->sec == MIO_TYPE_MAX(mio_ntime_sec_t)) + { + if (y->sec >= 0) goto overflow; + xs = x->sec; + ys = y->sec + 1; /* this won't overflow */ + } + else + { + xs = x->sec + 1; /* this won't overflow */ + ys = y->sec; + } + } + else + { + xs = x->sec; + ys = y->sec; + } + + if ((ys >= 1 && xs > MIO_TYPE_MAX(mio_ntime_sec_t) - ys) || + (ys <= -1 && xs < MIO_TYPE_MIN(mio_ntime_sec_t) - ys)) + { + if (xs >= 0) + { + overflow: + xs = MIO_TYPE_MAX(mio_ntime_sec_t); + ns = MIO_NSECS_PER_SEC - 1; + } + else + { + xs = MIO_TYPE_MIN(mio_ntime_sec_t); + ns = 0; + } + } + else + { + xs = xs + ys; + } + + z->sec = xs; + z->nsec = ns; +} + +void mio_sub_ntime (mio_ntime_t* z, const mio_ntime_t* x, const mio_ntime_t* y) +{ + mio_ntime_sec_t xs, ys; + mio_ntime_nsec_t ns; + + /*MIO_ASSERT (x->nsec >= 0 && x->nsec < MIO_NSECS_PER_SEC); + MIO_ASSERT (y->nsec >= 0 && y->nsec < MIO_NSECS_PER_SEC);*/ + + ns = x->nsec - y->nsec; + if (ns < 0) + { + ns = ns + MIO_NSECS_PER_SEC; + if (x->sec == MIO_TYPE_MIN(mio_ntime_sec_t)) + { + if (y->sec <= 0) goto underflow; + xs = x->sec; + ys = y->sec - 1; /* this won't underflow */ + } + else + { + xs = x->sec - 1; /* this won't underflow */ + ys = y->sec; + } + } + else + { + xs = x->sec; + ys = y->sec; + } + + if ((ys >= 1 && xs < MIO_TYPE_MIN(mio_ntime_sec_t) + ys) || + (ys <= -1 && xs > MIO_TYPE_MAX(mio_ntime_sec_t) + ys)) + { + if (xs >= 0) + { + xs = MIO_TYPE_MAX(mio_ntime_sec_t); + ns = MIO_NSECS_PER_SEC - 1; + } + else + { + underflow: + xs = MIO_TYPE_MIN(mio_ntime_sec_t); + ns = 0; + } + } + else + { + xs = xs - ys; + } + + z->sec = xs; + z->nsec = ns; +} + +/* ========================================================================= */