From 7731ca80a0e7d473fc1e8ec0d65bd71ad41a8b9d Mon Sep 17 00:00:00 2001 From: stefanocasazza Date: Wed, 25 Nov 2015 18:28:45 +0100 Subject: [PATCH] some fix --- include/ulib/debug/macro.h | 46 ++-- include/ulib/debug/trace.h | 9 +- include/ulib/event/event_time.h | 255 ++++++++++++------ include/ulib/internal/objectIO.h | 4 +- include/ulib/timer.h | 12 +- include/ulib/timeval.h | 30 +-- src/ulib/debug/trace.cpp | 3 +- src/ulib/event/event_time.cpp | 13 +- src/ulib/notifier.cpp | 55 ++-- src/ulib/timer.cpp | 92 ++++--- .../FrameworkBenchmarks/ULib/README.md | 12 +- tests/examples/tsa_rpc.test | 3 +- tests/ulib/test_thread.cpp | 5 +- 13 files changed, 309 insertions(+), 230 deletions(-) diff --git a/include/ulib/debug/macro.h b/include/ulib/debug/macro.h index dd07b300..599a9c78 100644 --- a/include/ulib/debug/macro.h +++ b/include/ulib/debug/macro.h @@ -17,21 +17,21 @@ // Design by contract - if (expr == false) then stop #ifdef DEBUG -# define U_ASSERT(expr) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT(expr); UTrace::resume(_status_); } -# define U_ASSERT_MINOR(a,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MINOR(a,b); UTrace::resume(_status_); } -# define U_ASSERT_MAJOR(a,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MAJOR(a,b); UTrace::resume(_status_); } -# define U_ASSERT_EQUALS(a,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_EQUALS(a,b); UTrace::resume(_status_); } -# define U_ASSERT_DIFFERS(a,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_DIFFERS(a,b); UTrace::resume(_status_); } -# define U_ASSERT_POINTER(ptr) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_POINTER(ptr); UTrace::resume(_status_); } -# define U_ASSERT_RANGE(a,x,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_RANGE(a,x,b); UTrace::resume(_status_); } +# define U_ASSERT(expr) { UTrace::suspend(); U_INTERNAL_ASSERT(expr); UTrace::resume(); } +# define U_ASSERT_MINOR(a,b) { UTrace::suspend(); U_INTERNAL_ASSERT_MINOR(a,b); UTrace::resume(); } +# define U_ASSERT_MAJOR(a,b) { UTrace::suspend(); U_INTERNAL_ASSERT_MAJOR(a,b); UTrace::resume(); } +# define U_ASSERT_EQUALS(a,b) { UTrace::suspend(); U_INTERNAL_ASSERT_EQUALS(a,b); UTrace::resume(); } +# define U_ASSERT_DIFFERS(a,b) { UTrace::suspend(); U_INTERNAL_ASSERT_DIFFERS(a,b); UTrace::resume(); } +# define U_ASSERT_POINTER(ptr) { UTrace::suspend(); U_INTERNAL_ASSERT_POINTER(ptr); UTrace::resume(); } +# define U_ASSERT_RANGE(a,x,b) { UTrace::suspend(); U_INTERNAL_ASSERT_RANGE(a,x,b); UTrace::resume(); } -# define U_ASSERT_MSG(expr,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MSG(expr,info); UTrace::resume(_status_); } -# define U_ASSERT_MINOR_MSG(a,b,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MINOR_MSG(a,b,info); UTrace::resume(_status_); } -# define U_ASSERT_MAJOR_MSG(a,b,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MAJOR_MSG(a,b,info); UTrace::resume(_status_); } -# define U_ASSERT_EQUALS_MSG(a,b,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_EQUALS_MSG(a,b,info); UTrace::resume(_status_); } -# define U_ASSERT_DIFFERS_MSG(a,b,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_DIFFERS_MSG(a,b,info); UTrace::resume(_status_); } -# define U_ASSERT_POINTER_MSG(ptr,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_POINTER_MSG(ptr,info); UTrace::resume(_status_); } -# define U_ASSERT_RANGE_MSG(a,x,b,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_RANGE_MSG(a,x,b,info); UTrace::resume(_status_); } +# define U_ASSERT_MSG(expr,info) { UTrace::suspend(); U_INTERNAL_ASSERT_MSG(expr,info); UTrace::resume(); } +# define U_ASSERT_MINOR_MSG(a,b,info) { UTrace::suspend(); U_INTERNAL_ASSERT_MINOR_MSG(a,b,info); UTrace::resume(); } +# define U_ASSERT_MAJOR_MSG(a,b,info) { UTrace::suspend(); U_INTERNAL_ASSERT_MAJOR_MSG(a,b,info); UTrace::resume(); } +# define U_ASSERT_EQUALS_MSG(a,b,info) { UTrace::suspend(); U_INTERNAL_ASSERT_EQUALS_MSG(a,b,info); UTrace::resume(); } +# define U_ASSERT_DIFFERS_MSG(a,b,info) { UTrace::suspend(); U_INTERNAL_ASSERT_DIFFERS_MSG(a,b,info); UTrace::resume(); } +# define U_ASSERT_POINTER_MSG(ptr,info) { UTrace::suspend(); U_INTERNAL_ASSERT_POINTER_MSG(ptr,info); UTrace::resume(); } +# define U_ASSERT_RANGE_MSG(a,x,b,info) { UTrace::suspend(); U_INTERNAL_ASSERT_RANGE_MSG(a,x,b,info); UTrace::resume(); } #elif defined(U_TEST) # define U_ASSERT(expr) U_INTERNAL_ASSERT(expr) # define U_ASSERT_MINOR(a,b) U_INTERNAL_ASSERT_MINOR(a,b) @@ -85,20 +85,20 @@ // NB: U_DUMP, U_SYSCALL() and U_RETURN() depend on presence of U_TRACE() -# define U_INTERNAL_DUMP(args...) { if (utr.active[0]) u_trace_dump(args); } -# define U_DUMP(args...) { if (utr.active[0]) { int _status_ = UTrace::suspend(); u_trace_dump(args); UTrace::resume(_status_); } } - -# define U_SYSCALL(name,format,args...) (utr.trace_syscall("::"#name"(" format ")" , ##args), \ - utr.trace_sysreturn_type(::name(args))) +# define U_INTERNAL_DUMP(args...) { if (utr.active[0]) u_trace_dump(args); } +# define U_DUMP(args...) { if (utr.active[0]) { UTrace::suspend(); u_trace_dump(args); UTrace::resume(); } } # define U_SYSCALL_NO_PARAM(name) (utr.trace_syscall("::"#name"()",0), \ utr.trace_sysreturn_type(::name())) -# define U_SYSCALL_VOID(name,format,args...) {utr.trace_syscall("::"#name"(" format ")" , ##args); \ - name(args); utr.trace_sysreturn(false,0);} +# define U_SYSCALL_VOID_NO_PARAM(name) { utr.trace_syscall("::"#name"()",0); \ + name(); utr.trace_sysreturn(false,0); } -# define U_SYSCALL_VOID_NO_PARAM(name) {utr.trace_syscall("::"#name"()",0); \ - name(); utr.trace_sysreturn(false,0);} +# define U_SYSCALL(name,format,args...) (UTrace::suspend(), utr.trace_syscall("::"#name"(" format ")" , ##args), \ + UTrace::resume(), utr.trace_sysreturn_type(::name(args))) + +# define U_SYSCALL_VOID(name,format,args...) { UTrace::suspend(); utr.trace_syscall("::"#name"(" format ")" , ##args); \ + UTrace::resume(); ::name(args); utr.trace_sysreturn(false,0); } # define U_RETURN(r) return (utr.trace_return_type((r))) # define U_RETURN_STRING(str) {U_INTERNAL_ASSERT((str).invariant()); return (utr.trace_return("%V",(str).rep),(str));} diff --git a/include/ulib/debug/trace.h b/include/ulib/debug/trace.h index 63ed1062..24fc8bf7 100644 --- a/include/ulib/debug/trace.h +++ b/include/ulib/debug/trace.h @@ -51,6 +51,8 @@ typedef const unsigned char* pcuchar_t; // typedef int (*x11error_t) (void*, void*); // typedef int (*x11IOerror_t)(void*); +class UCrono; + class U_EXPORT UTrace { public: @@ -121,13 +123,16 @@ public: U_MANAGE_SYSRETURN_VALUE(tdbdata_t, "%J", false) #endif - static int suspend() { int status = u_trace_suspend; u_trace_suspend = 1; return status; } - static void resume(int status) { u_trace_suspend = status; } + static void resume() { u_trace_suspend = status; } + static void suspend() { status = u_trace_suspend; u_trace_suspend = 1; } private: char buffer_trace[1019], buffer_syscall[1019]; uint32_t buffer_trace_len, buffer_syscall_len; + static int status; + static UCrono* time_syscall_read_or_write; + void set(int level) U_NO_EXPORT; }; diff --git a/include/ulib/event/event_time.h b/include/ulib/event/event_time.h index 747d6257..c9997aad 100644 --- a/include/ulib/event/event_time.h +++ b/include/ulib/event/event_time.h @@ -16,6 +16,8 @@ #include +class UTimer; +class UNotifier; #ifdef USE_LIBEVENT template class UTimerEv; #endif @@ -25,48 +27,24 @@ public: struct timeval ctime; - void reset() { ctime.tv_sec = ctime.tv_usec = 0L; } - - UEventTime(long sec = 0L, long usec = 1L); + UEventTime(long sec = 0L, long micro_sec = 1L); virtual ~UEventTime(); bool operator<(const UEventTime& t) const __pure; // SERVICES - void setTime(long timeoutMS) + bool isExpired() const __pure { - U_TRACE(0, "UEventTime::setTime(%ld)", timeoutMS) - - setCurrentTime(); - - UTimeVal::setMilliSecond(timeoutMS); - } - - void setCurrentTime() - { - U_TRACE_NO_PARAM(1, "UEventTime::setCurrentTime()") + U_TRACE_NO_PARAM(0, "UEventTime::isExpired()") U_CHECK_MEMORY - (void) U_SYSCALL(gettimeofday, "%p,%p", &ctime, 0); - - U_INTERNAL_DUMP("ctime = { %ld %6ld }", ctime.tv_sec, ctime.tv_usec) - } - - time_t expire() const { return (ctime.tv_sec + tv_sec); } - - bool isExpired(long tolerance) const __pure - { - U_TRACE(0, "UEventTime::isExpired(%ld)", tolerance) - - U_CHECK_MEMORY - - long t1 = expire(), - diff1 = t1 - u_now->tv_sec, + long diff1 = ctime.tv_sec + tv_sec - u_now->tv_sec, diff2 = ctime.tv_usec + tv_usec - u_now->tv_usec; - U_INTERNAL_DUMP("this = { %ld %6ld }, diff1 = %ld diff2 = %ld", t1, ctime.tv_usec + tv_usec, diff1, diff2) + U_INTERNAL_DUMP("this = { %ld %6ld }, diff1 = %ld diff2 = %ld", ctime.tv_sec + tv_sec, + ctime.tv_usec + tv_usec, diff1, diff2) if ( diff1 < 0 || (diff1 == 0 && @@ -75,71 +53,31 @@ public: U_RETURN(true); } - long diff = (diff1 * 1000L) + - (diff2 / 1000L); + ms = (diff1 * 1000L) + + (diff2 / 1000L); - U_INTERNAL_DUMP("diff = %ld", diff) + U_INTERNAL_DUMP("ms = %ld", ms) - if (diff <= tolerance) U_RETURN(true); + U_ASSERT(checkMilliSecond()) U_RETURN(false); } - bool isOld() const __pure { return isExpired(0); } - bool isExpired() const __pure { return isExpired(UTimeVal::getTolerance()); } - - void setTimerVal(struct timeval* it_value) + bool isExpiredWithTolerance() const __pure { - U_TRACE(0, "UEventTime::setTimerVal(%p)", it_value) + U_TRACE_NO_PARAM(0, "UEventTime::isExpiredWithTolerance()") - U_CHECK_MEMORY + if (isExpired() == false) + { + U_ASSERT(checkTolerance()) - it_value->tv_sec = ctime.tv_sec + tv_sec - u_now->tv_sec; - it_value->tv_usec = ctime.tv_usec + tv_usec - u_now->tv_usec; + if (ms > tolerance) U_RETURN(false); + } - UTimeVal::adjust(&(it_value->tv_sec), &(it_value->tv_usec)); - - U_INTERNAL_DUMP("it_value = { %ld %6ld }", it_value->tv_sec, it_value->tv_usec) - - U_INTERNAL_ASSERT(it_value->tv_sec >= 0) - U_INTERNAL_ASSERT(it_value->tv_usec >= 0) + U_RETURN(true); } - long getTimerVal() - { - U_TRACE_NO_PARAM(0, "UEventTime::getTimerVal()") - - U_CHECK_MEMORY - - long ms = ((ctime.tv_sec + tv_sec - u_now->tv_sec) * 1000L) + - ((ctime.tv_usec + tv_usec - u_now->tv_usec) / 1000L); - - U_RETURN(ms); - } - - struct timespec* getTimerValSpec() - { - U_TRACE_NO_PARAM(0, "UEventTime::getTimerValSpec()") - - U_CHECK_MEMORY - - /** - * struct timespec { - * time_t tv_sec; // seconds - * long tv_nsec; // nanoseconds - * }; - */ - - long ns = ((ctime.tv_sec + tv_sec - u_now->tv_sec) * 1000000000L) + - ((ctime.tv_usec + tv_usec - u_now->tv_usec) * 1000L); - - timeout.tv_sec = ns / 1000000000L; - timeout.tv_nsec = ns % 1000000000L; - - U_INTERNAL_DUMP("timeout = { %ld %9ld }", timeout.tv_sec, timeout.tv_nsec) - - U_RETURN_POINTER(&timeout, struct timespec); - } + time_t expire() const { return (ctime.tv_sec + tv_sec); } // ------------------------------------------- // method VIRTUAL to define @@ -158,19 +96,162 @@ public: #ifdef U_STDCPP_ENABLE friend U_EXPORT ostream& operator<<(ostream& os, const UEventTime& t); -# ifdef DEBUG +# ifdef DEBUG const char* dump(bool reset) const; -# endif +# endif #endif -private: - static struct timespec timeout; +protected: + long tolerance; + static long ms; + static struct timeval timeout1; + static struct timespec timeout2; + + void setCurrentTime() + { + U_TRACE_NO_PARAM(1, "UEventTime::setCurrentTime()") + + U_CHECK_MEMORY + + (void) U_SYSCALL(gettimeofday, "%p,%p", &ctime, 0); + + U_INTERNAL_DUMP("ctime = { %ld %6ld }", ctime.tv_sec, ctime.tv_usec) + } + + void setTime(long timeoutMS) + { + U_TRACE(0, "UEventTime::setTime(%ld)", timeoutMS) + + setCurrentTime(); + + UTimeVal::setMilliSecond(ms = timeoutMS); + } + + void setMilliSecond() + { + U_TRACE_NO_PARAM(0, "UEventTime::setMilliSecond()") + + ms = ((ctime.tv_sec + tv_sec - u_now->tv_sec) * 1000L) + + ((ctime.tv_usec + tv_usec - u_now->tv_usec) / 1000L); + + U_ASSERT(checkTolerance()) + } + + bool checkMilliSecond() const + { + U_TRACE_NO_PARAM(0, "UEventTime::checkMilliSecond()") + + U_INTERNAL_DUMP("ms = %ld", ms) + + long ms_calculated = ((ctime.tv_sec + tv_sec - u_now->tv_sec) * 1000L) + + ((ctime.tv_usec + tv_usec - u_now->tv_usec) / 1000L); + + if (ms == ms_calculated) U_RETURN(true); + + U_INTERNAL_DUMP("ms_calculated = %ld", ms_calculated) + + U_RETURN(false); + } + + void setTolerance() + { + U_TRACE_NO_PARAM(0, "UEventTime::setTolerance()") + + tolerance = ((tv_sec * 1000L) + + (tv_usec / 1000L)) / 128; + + U_INTERNAL_DUMP("tolerance = %ld", tolerance) + } + + bool checkTolerance() const + { + U_TRACE_NO_PARAM(0, "UEventTime::checkTolerance()") + + U_ASSERT(checkMilliSecond()) + + U_INTERNAL_DUMP("tolerance = %ld", tolerance) + + long tolerance_calculated = ((tv_sec * 1000L) + + (tv_usec / 1000L)) / 128; + + if (tolerance == tolerance_calculated) U_RETURN(true); + + U_INTERNAL_DUMP("tolerance_calculated = %ld", tolerance_calculated) + + U_RETURN(false); + } + + static long getMilliSecond(UEventTime* ptimeout) + { + U_TRACE(0, "UEventTime::getMilliSecond(%p)", ptimeout) + + if (ptimeout == 0) U_RETURN(-1); + + U_ASSERT(ptimeout->checkMilliSecond()) + + U_RETURN(ms); + } + + static struct timeval* getTimeVal(UEventTime* ptimeout) + { + U_TRACE(0, "UEventTime::getTimeVal(%p)", ptimeout) + + if (ptimeout == 0) U_RETURN_POINTER(0, struct timeval); + + U_ASSERT(ptimeout->checkMilliSecond()) + + /** + * struct timeval { + * long tv_sec; // seconds + * long tv_usec; // microseconds + * }; + */ + + long us = ms * 1000L; + + timeout1.tv_sec = us / 1000000L; + timeout1.tv_usec = us % 1000000L; + + U_INTERNAL_DUMP("timeout1 = { %ld %9ld }", timeout1.tv_sec, timeout1.tv_usec) + + U_RETURN_POINTER(&timeout1, struct timeval); + } + + static struct timespec* getTimeSpec(UEventTime* ptimeout) + { + U_TRACE(0, "UEventTime::getTimeSpec(%p)", ptimeout) + + if (ptimeout == 0) U_RETURN_POINTER(0, struct timespec); + + U_ASSERT(ptimeout->checkMilliSecond()) + + /** + * struct timespec { + * time_t tv_sec; // seconds + * long tv_nsec; // nanoseconds + * }; + */ + + long ns = ms * 1000000L; + + timeout2.tv_sec = ns / 1000000000L; + timeout2.tv_nsec = ns % 1000000000L; + + U_INTERNAL_DUMP("timeout2 = { %ld %9ld }", timeout2.tv_sec, timeout2.tv_nsec) + + U_RETURN_POINTER(&timeout2, struct timespec); + } + +private: #ifdef U_COMPILER_DELETE_MEMBERS UEventTime& operator=(const UEventTime&) = delete; #else UEventTime& operator=(const UEventTime&) { return *this; } #endif + + friend class UTimer; + friend class UNotifier; }; #endif diff --git a/include/ulib/internal/objectIO.h b/include/ulib/internal/objectIO.h index a8c2a8b1..fe5048fa 100644 --- a/include/ulib/internal/objectIO.h +++ b/include/ulib/internal/objectIO.h @@ -120,7 +120,7 @@ template inline char* U_OBJECT_TO_TRACE(T& object) U_INTERNAL_TRACE("U_OBJECT_TO_TRACE(%p)", &object) #ifdef DEBUG - bool status = UTrace::suspend(); + UTrace::suspend(); #endif char* str = UObject2String(object); @@ -128,7 +128,7 @@ template inline char* U_OBJECT_TO_TRACE(T& object) str = strndup(str, UObjectIO::buffer_output_len); #ifdef DEBUG - UTrace::resume(status); + UTrace::resume(); #endif return str; diff --git a/include/ulib/timer.h b/include/ulib/timer.h index ae032115..035c4d02 100644 --- a/include/ulib/timer.h +++ b/include/ulib/timer.h @@ -85,15 +85,15 @@ public: // run the list of timers. Your main program needs to call this every so often, or as indicated by getTimeout() - static bool run(); + static void run(); static void setTimer(); static UEventTime* getTimeout() // returns a timeout indicating how long until the next timer triggers { U_TRACE_NO_PARAM(0, "UTimer::getTimeout()") - if (first && - run()) + if ( first && + (run(), first)) { U_RETURN_POINTER(first->alarm, UEventTime); } @@ -129,12 +129,12 @@ public: // DEBUG -# ifdef DEBUG +# ifdef DEBUG static void printInfo(ostream& os); void outputEntry(ostream& os) const U_NO_EXPORT; const char* dump(bool reset) const; -# endif +# endif #endif protected: @@ -145,7 +145,7 @@ protected: static UTimer* pool; // free list static UTimer* first; // active list - static bool callHandlerTimeout(); + static void callHandlerTimeout(); #ifdef DEBUG static bool invariant(); diff --git a/include/ulib/timeval.h b/include/ulib/timeval.h index e7b799cc..c08278a1 100644 --- a/include/ulib/timeval.h +++ b/include/ulib/timeval.h @@ -149,15 +149,6 @@ public: void setSecond(long sec) { tv_sec = sec; } void setMicroSecond(long micro_sec) { tv_usec = micro_sec; } - void setMilliSecond(long timeoutMS) - { - U_TRACE(0, "UTimeVal::setMilliSecond(%ld)", timeoutMS) - - tv_usec = timeoutMS * 1000L; - - adjust(); - } - long getSecond() const { U_TRACE_NO_PARAM(0, "UTimeVal::getSecond()") @@ -181,15 +172,6 @@ public: U_RETURN(ms); } - long getTolerance() const - { - U_TRACE_NO_PARAM(0, "UTimeVal::getTolerance()") - - long ms = getMilliSecond() / 128; - - U_RETURN(ms); - } - double getMicroSecond() const { U_TRACE_NO_PARAM(0, "UTimeVal::getMicroSecond()") @@ -199,6 +181,18 @@ public: U_RETURN(micro_sec); } + void setMilliSecond(long timeoutMS) + { + U_TRACE(0, "UTimeVal::setMilliSecond(%ld)", timeoutMS) + + tv_sec = 0L; + tv_usec = timeoutMS * 1000L; + + adjust(); + + U_ASSERT_EQUALS(timeoutMS, getMilliSecond()) + } + // OPERATOR int operator !() const { return isZero(); } diff --git a/src/ulib/debug/trace.cpp b/src/ulib/debug/trace.cpp index 506a6c63..ca8f6a2f 100644 --- a/src/ulib/debug/trace.cpp +++ b/src/ulib/debug/trace.cpp @@ -23,7 +23,8 @@ #include -static UCrono* time_syscall_read_or_write; +int UTrace::status; +UCrono* UTrace::time_syscall_read_or_write; U_NO_EXPORT void UTrace::set(int level) { diff --git a/src/ulib/event/event_time.cpp b/src/ulib/event/event_time.cpp index 7b661261..c5f007e6 100644 --- a/src/ulib/event/event_time.cpp +++ b/src/ulib/event/event_time.cpp @@ -17,13 +17,18 @@ # include #endif -struct timespec UEventTime::timeout; +long UEventTime::ms; +struct timeval UEventTime::timeout1; +struct timespec UEventTime::timeout2; -UEventTime::UEventTime(long sec, long usec) : UTimeVal(sec, usec) +UEventTime::UEventTime(long sec, long micro_sec) : UTimeVal(sec, micro_sec) { - U_TRACE_REGISTER_OBJECT(0, UEventTime, "%ld,%ld", sec, usec) + U_TRACE_REGISTER_OBJECT(0, UEventTime, "%ld,%ld", sec, micro_sec) - reset(); + setTolerance(); + + ctime.tv_sec = + ctime.tv_usec = 0L; #ifdef USE_LIBEVENT if (u_ev_base == 0) u_ev_base = (struct event_base*) U_SYSCALL_NO_PARAM(event_init); diff --git a/src/ulib/notifier.cpp b/src/ulib/notifier.cpp index 76540b1f..6c4ffed3 100644 --- a/src/ulib/notifier.cpp +++ b/src/ulib/notifier.cpp @@ -22,11 +22,11 @@ # include #endif -#ifdef HAVE_POLL_H +#ifndef HAVE_POLL_H +UEventTime* UNotifier::time_obj; +#else # include struct pollfd UNotifier::fds[1]; -#else -UEventTime* UNotifier::time_obj; #endif #include @@ -728,37 +728,24 @@ int UNotifier::waitForEvent(int fd_max, fd_set* read_set, fd_set* write_set, UEv #else int result; # ifdef HAVE_EPOLL_WAIT - int timeoutMS = (ptimeout ? ptimeout->getTimerVal() : -1); - - result = U_SYSCALL(epoll_wait, "%d,%p,%u,%d", epollfd, events, max_connection, timeoutMS); + result = U_SYSCALL(epoll_wait, "%d,%p,%u,%d", epollfd, events, max_connection, UEventTime::getMilliSecond(ptimeout)); # elif defined(HAVE_KQUEUE) - struct timespec* timeout = (ptimeout ? ptimeout->getTimerValSpec() : 0); - - result = U_SYSCALL(kevent, "%d,%p,%d,%p,%d,%p", kq, kqevents, nkqevents, kqrevents, max_connection, timeout); + result = U_SYSCALL(kevent, "%d,%p,%d,%p,%d,%p", kq, kqevents, nkqevents, kqrevents, max_connection, UEventTime::getTimeSpec(ptimeout)); nkqevents = 0; # else - static struct timeval tmp; - struct timeval* ptmp; + // If both fields of the timeval structure are zero, then select() returns immediately. + // (This is useful for polling). If ptimeout is NULL (no timeout), select() can block indefinitely... + // + // On Linux, the function select modifies timeout to reflect the amount of time not slept; most other implementations do not do this. + // This causes problems both when Linux code which reads timeout is ported to other operating systems, and when code is ported to Linux + // that reuses a struct timeval for multiple selects in a loop without reinitializing it. Consider timeout to be undefined after select returns # if defined(DEBUG) && !defined(_MSWINDOWS_) if ( read_set) U_INTERNAL_DUMP(" read_set = %B", __FDS_BITS( read_set)[0]) if (write_set) U_INTERNAL_DUMP("write_set = %B", __FDS_BITS(write_set)[0]) # endif - if (ptimeout == 0) ptmp = 0; - else - { - // On Linux, the function select modifies timeout to reflect the amount of time not slept; most other implementations do not do this. - // This causes problems both when Linux code which reads timeout is ported to other operating systems, and when code is ported to Linux - // that reuses a struct timeval for multiple selects in a loop without reinitializing it. Consider timeout to be undefined after select returns - - ptimeout->setTimerVal(ptmp = &tmp); - } - - // If both fields of the timeval structure are zero, then select() returns immediately. - // (This is useful for polling). If ptmp is NULL (no timeout), select() can block indefinitely... - - result = U_SYSCALL(select, "%d,%p,%p,%p,%p", fd_max, read_set, write_set, 0, ptmp); + result = U_SYSCALL(select, "%d,%p,%p,%p,%p", fd_max, read_set, write_set, 0, UEventTime::getTimeVal(ptimeout)); # if defined(DEBUG) && !defined(_MSWINDOWS_) if ( read_set) U_INTERNAL_DUMP(" read_set = %B", __FDS_BITS( read_set)[0]) @@ -793,9 +780,7 @@ loop: ptimeout); # elif defined(HAVE_KQUEUE) loop: - struct timespec* timeout = (ptimeout ? ptimeout->getTimerValSpec() : 0); - - nfd_ready = U_SYSCALL(kevent, "%d,%p,%d,%p,%d,%p", kq, kqevents, nkqevents, kqrevents, max_connection, timeout); + nfd_ready = U_SYSCALL(kevent, "%d,%p,%d,%p,%d,%p", kq, kqevents, nkqevents, kqrevents, max_connection, UEventTime::getTimeSpec(ptimeout)); # ifdef DEBUG if (nfd_ready == -1 && errno == EINVAL) @@ -806,9 +791,7 @@ loop: nkqevents = 0; # else loop: - int timeoutMS = (ptimeout ? ptimeout->getTimerVal() : -1); - - nfd_ready = U_SYSCALL(epoll_wait, "%d,%p,%u,%d", epollfd, events, max_connection, timeoutMS); + nfd_ready = U_SYSCALL(epoll_wait, "%d,%p,%u,%d", epollfd, events, max_connection, UEventTime::getMilliSecond(ptimeout)); # endif if (nfd_ready > 0) @@ -1045,11 +1028,11 @@ loop: waitForEvent(ptimeout = UTimer::getTimeout()); if (nfd_ready == 0 && - ptimeout) + ptimeout != 0) { U_INTERNAL_ASSERT_EQUALS(UTimer::first->alarm, ptimeout) - (void) UTimer::callHandlerTimeout(); + UTimer::callHandlerTimeout(); goto loop; } @@ -1322,7 +1305,7 @@ int UNotifier::waitForRead(int fd, int timeoutMS) # endif // If both fields of the timeval structure are zero, then select() returns immediately. - // (This is useful for polling). If ptmp is NULL (no timeout), select() can block indefinitely... + // (This is useful for polling). If ptime is NULL (no timeout), select() can block indefinitely... UEventTime* ptime; @@ -1377,9 +1360,9 @@ int UNotifier::waitForWrite(int fd, int timeoutMS) } #else -# ifdef _MSWINDOWS_ +# ifdef _MSWINDOWS_ if (is_pipe(fd) != INVALID_HANDLE_VALUE) U_RETURN(1); -# endif +# endif // If both fields of the timeval structure are zero, then select() returns immediately. // (This is useful for polling). If ptmp is NULL (no timeout), select() can block indefinitely... diff --git a/src/ulib/timer.cpp b/src/ulib/timer.cpp index a3493fd2..e5ecf574 100644 --- a/src/ulib/timer.cpp +++ b/src/ulib/timer.cpp @@ -41,7 +41,7 @@ void UTimer::init(Type _mode) U_NO_EXPORT void UTimer::insertEntry() { - U_TRACE_NO_PARAM(1, "UTimer::insertEntry()") + U_TRACE_NO_PARAM(0, "UTimer::insertEntry()") U_CHECK_MEMORY @@ -70,7 +70,7 @@ U_NO_EXPORT void UTimer::insertEntry() U_ASSERT(invariant()) } -bool UTimer::callHandlerTimeout() +void UTimer::callHandlerTimeout() { U_TRACE_NO_PARAM(0, "UTimer::callHandlerTimeout()") @@ -87,73 +87,83 @@ bool UTimer::callHandlerTimeout() item->insertEntry(); - U_RETURN(true); + item->alarm->setMilliSecond(); } + else + { + // put it on the free list - // put it on the free list - - item->alarm = 0; - item->next = pool; - pool = item; - - U_RETURN(false); + item->alarm = 0; + item->next = pool; + pool = item; + } } -bool UTimer::run() +void UTimer::run() { U_TRACE_NO_PARAM(1, "UTimer::run()") - U_INTERNAL_ASSERT_POINTER(first) - (void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0); - U_INTERNAL_DUMP("u_now = { %ld %6ld }", u_now->tv_sec, u_now->tv_usec) + U_INTERNAL_DUMP("u_now = { %ld %6ld } first = %p", u_now->tv_sec, u_now->tv_usec, first) + + UTimer* item = first; + bool bnosignal = (mode == NOSIGNAL), bexpired; loop: - if ((mode == NOSIGNAL ? first->alarm->isOld() - : first->alarm->isExpired())) - { - if (callHandlerTimeout() || - first) - { - goto loop; - } +#ifdef DEBUG + U_INTERNAL_DUMP("item = %p item->next = %p", item, item->next) - U_RETURN(false); + U_INTERNAL_ASSERT_POINTER(item) + + if (item->next) U_INTERNAL_ASSERT(*item <= *(item->next)) +#endif + + bexpired = (bnosignal ? item->alarm->isExpired() + : item->alarm->isExpiredWithTolerance()); + + if (bexpired) + { + item = item->next; + + callHandlerTimeout(); + + if (item) goto loop; } U_INTERNAL_DUMP("first = %p", first) - - if (first) U_RETURN(true); - - U_RETURN(false); } void UTimer::setTimer() { U_TRACE_NO_PARAM(1, "UTimer::setTimer()") - U_INTERNAL_ASSERT_POINTER(first) U_INTERNAL_ASSERT_DIFFERS(mode, NOSIGNAL) - if (run()) - { - U_INTERNAL_ASSERT_POINTER(first) + run(); - first->alarm->setTimerVal(&UInterrupt::timerval.it_value); - } - else + if (first == 0) { - U_INTERNAL_ASSERT_EQUALS(first, 0) - UInterrupt::timerval.it_value.tv_sec = UInterrupt::timerval.it_value.tv_usec = 0L; } + else + { + UEventTime* item = first->alarm; - // NB: can happen that setitimer() produce immediatly a signal because the interval is very short (< 10ms)... + UInterrupt::timerval.it_value.tv_sec = item->ctime.tv_sec + item->tv_sec - u_now->tv_sec; + UInterrupt::timerval.it_value.tv_usec = item->ctime.tv_usec + item->tv_usec - u_now->tv_usec; + + UTimeVal::adjust(&(UInterrupt::timerval.it_value.tv_sec), &(UInterrupt::timerval.it_value.tv_usec)); + } + + // NB: it can happen that setitimer() produce immediatly a signal because the interval is very short (< 10ms)... U_INTERNAL_DUMP("UInterrupt::timerval.it_value = { %ld %6ld }", UInterrupt::timerval.it_value.tv_sec, UInterrupt::timerval.it_value.tv_usec) + U_INTERNAL_ASSERT(UInterrupt::timerval.it_value.tv_sec >= 0 && + UInterrupt::timerval.it_value.tv_usec >= 0) + (void) U_SYSCALL(setitimer, "%d,%p,%p", ITIMER_REAL, &UInterrupt::timerval, 0); } @@ -161,7 +171,7 @@ void UTimer::insert(UEventTime* a) { U_TRACE(0, "UTimer::insert(%p,%b)", a) - // set an alarm to more than 2 month is very strange... + // set an alarm to more than 2 month is very suspect... U_INTERNAL_ASSERT_MINOR(a->tv_sec, 60L * U_ONE_DAY_IN_SECOND) // 60 gg (2 month) @@ -210,14 +220,14 @@ void UTimer::erase(UEventTime* a) void UTimer::clear() { - U_TRACE_NO_PARAM(0, "UTimer::clear()") + U_TRACE_NO_PARAM(1, "UTimer::clear()") U_INTERNAL_DUMP("mode = %d first = %p pool = %p", mode, first, pool) if (mode != NOSIGNAL) { UInterrupt::timerval.it_value.tv_sec = - UInterrupt::timerval.it_value.tv_usec = 0; + UInterrupt::timerval.it_value.tv_usec = 0L; (void) U_SYSCALL(setitimer, "%d,%p,%p", ITIMER_REAL, &UInterrupt::timerval, 0); } @@ -252,7 +262,7 @@ bool UTimer::invariant() { for (UTimer* item = first; item->next; item = item->next) { - U_INTERNAL_ASSERT(*item <= *(item->next)) + if (item->next) U_INTERNAL_ASSERT(*item <= *(item->next)) } } diff --git a/tests/examples/benchmark/FrameworkBenchmarks/ULib/README.md b/tests/examples/benchmark/FrameworkBenchmarks/ULib/README.md index 0cbc812a..ccf468be 100644 --- a/tests/examples/benchmark/FrameworkBenchmarks/ULib/README.md +++ b/tests/examples/benchmark/FrameworkBenchmarks/ULib/README.md @@ -45,7 +45,7 @@ HTTP/1.1 200 OK Date: Thu, 03 Jul 2014 10:11:10 GMT Server: ULib Content-Length: 27 -Content-Type: application/json; charset=UTF-8 +Content-Type: application/json {"message":"Hello, World!"} ``` @@ -57,7 +57,7 @@ HTTP/1.1 200 OK Date: Thu, 03 Jul 2014 10:14:51 GMT Server: ULib Content-Length: 31 -Content-Type: application/json; charset=UTF-8 +Content-Type: application/json {"id":6227,"randomNumber":8489} ``` @@ -69,7 +69,7 @@ HTTP/1.1 200 OK Date: Thu, 03 Jul 2014 10:14:51 GMT Server: ULib Content-Length: 320 -Content-Type: application/json; charset=UTF-8 +Content-Type: application/json [{"id":6851,"randomNumber":7598},{"id":3968,"randomNumber":7325},{"id":8159,"randomNumber":348},{"id":9560,"randomNumber":7333},{"id":9938,"randomNumber":9080},{"id":1598,"randomNumber":1623},{"id":3280,"randomNumber":8707},{"id":4521,"randomNumber":6063},{"id":8173,"randomNumber":3690},{"id":3648,"randomNumber":8803}] ``` @@ -80,7 +80,7 @@ Content-Type: application/json; charset=UTF-8 HTTP/1.1 200 OK Date: Thu, 03 Jul 2014 10:14:51 GMT Server: ULib -Content-Type: text/html; charset=UTF-8 +Content-Type: text/html Content-Length: 1227 Fortunes
idmessage
11<script>alert("This should not be displayed in a browser alert box.");</script>
4A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1
5A computer program does what you tell it to do, not what you want it to do.
2A computer scientist is someone who fixes things that aren't broken.
8A list is only as strong as its weakest link. — Donald Knuth
0Additional fortune added at request time.
3After enough decimal places, nobody gives a damn.
7Any program that runs right is obsolete.
10Computers make very fast, very accurate mistakes.
6Emacs is a nice operating system, but I prefer UNIX. — Tom Christaensen
9Feature: A bug with seniority.
1fortune: No such file or directory
12フレームワークのベンチマーク
@@ -93,7 +93,7 @@ HTTP/1.1 200 OK Date: Thu, 03 Jul 2014 10:14:51 GMT Server: ULib Content-Length: 319 -Content-Type: application/json; charset=UTF-8 +Content-Type: application/json [{"id":7171,"randomNumber":351},{"id":6019,"randomNumber":9725},{"id":8118,"randomNumber":4023},{"id":7965,"randomNumber":1388},{"id":7797,"randomNumber":2249},{"id":112,"randomNumber":1108},{"id":6127,"randomNumber":4323},{"id":2597,"randomNumber":7509},{"id":2978,"randomNumber":7883},{"id":1111,"randomNumber":2228}] ``` @@ -104,7 +104,7 @@ Content-Type: application/json; charset=UTF-8 HTTP/1.1 200 OK Date: Thu, 03 Jul 2014 10:14:51 GMT Server: ULib -Content-Type: text/plain; charset=UTF-8 +Content-Type: text/plain Content-Length: 13 Hello, World! diff --git a/tests/examples/tsa_rpc.test b/tests/examples/tsa_rpc.test index f090c901..4d4dada6 100755 --- a/tests/examples/tsa_rpc.test +++ b/tests/examples/tsa_rpc.test @@ -7,9 +7,10 @@ start_msg tsa_rpc #UTRACE="0 50M 0" +#UTRACE_SIGNAL="0 10M -1" #UOBJDUMP="0 1M 100" #USIMERR="error.sim" - export UTRACE UOBJDUMP USIMERR +export UTRACE UOBJDUMP USIMERR UTRACE_SIGNAL DOC_ROOT=TSA diff --git a/tests/ulib/test_thread.cpp b/tests/ulib/test_thread.cpp index c2816f5f..7d7d8686 100644 --- a/tests/ulib/test_thread.cpp +++ b/tests/ulib/test_thread.cpp @@ -10,7 +10,6 @@ #define TEST_CHANGE(b) {if(!TestChange(b))return 1;} -static bool status; static volatile int n; static int time_to_sleep = 5; @@ -83,7 +82,7 @@ public: if (WaitNValue(2)) // wait for main thread { # ifdef DEBUG - status = UTrace::suspend(); + UTrace::suspend(); # endif while (true) @@ -261,7 +260,7 @@ int U_EXPORT main(int argc, char* argv[]) time_to_sleep = 5000; #ifdef DEBUG - UTrace::resume(status); + UTrace::resume(); #endif // Test child thread destroying before father