From e55b11b33446feeac54c095683f60c47556dd19b Mon Sep 17 00:00:00 2001 From: Terraneo Federico <fede.tft@miosix.org> Date: Sun, 26 Mar 2023 17:48:04 +0200 Subject: [PATCH] Add tests for condition variable timedwait --- miosix/_tools/testsuite/testsuite.cpp | 114 ++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 8 deletions(-) diff --git a/miosix/_tools/testsuite/testsuite.cpp b/miosix/_tools/testsuite/testsuite.cpp index cc6d54a4..5d2b3303 100644 --- a/miosix/_tools/testsuite/testsuite.cpp +++ b/miosix/_tools/testsuite/testsuite.cpp @@ -2257,6 +2257,12 @@ void t15_p2(void *argv) } } +void t15_p3(void *argv) +{ + Thread::sleep(30); + t15_c1.signal(); +} + static void test_15() { test_name("Condition variables"); @@ -2306,6 +2312,26 @@ static void test_15() Thread::sleep(10); if(Thread::exists(p1) || Thread::exists(p2)) fail("Threads not deleted (2)"); + + //testing timedWait + long long b,a=getTime()+10000000; //10ms + { + Lock<Mutex> l(t15_m1); + if(t15_c1.timedWait(l,a)!=TimedWaitResult::Timeout) fail("timedwait (1)"); + b=getTime(); + } + //iprintf("delta=%lld\n",b-a); + if(llabs(b-a)>200000) fail("timedwait (2)"); + Thread::create(t15_p3,STACK_SMALL,0); + a=getTime()+100000000; //100ms + { + Lock<Mutex> l(t15_m1); + if(t15_c1.timedWait(l,a)!=TimedWaitResult::NoTimeout) fail("timedwait (1)"); + b=getTime(); + } + //iprintf("delta=%lld\n",b-a); + if(llabs(b-a+70000000)>500000) fail("timedwait (4)"); + Thread::sleep(10); pass(); } @@ -2344,6 +2370,25 @@ inline Thread *toThread(pthread_t t) return reinterpret_cast<Thread*>(t); } +static constexpr int nsPerSec = 1000000000; + +inline long long timespec2ll(const struct timespec *tp) +{ + return static_cast<long long>(tp->tv_sec) * nsPerSec + tp->tv_nsec; +} + +void timespecAdd(struct timespec *t, long long ns) +{ + long long x=timespec2ll(t)+ns; + t->tv_sec = x / nsPerSec; + t->tv_nsec = static_cast<long>(x % nsPerSec); +} + +long long timespecDelta(struct timespec *a, struct timespec *b) +{ + return timespec2ll(a)-timespec2ll(b); +} + void *t16_p1(void *argv) { toThread(pthread_self())->wait(); @@ -2392,17 +2437,17 @@ void *t16_p4(void *argv) return NULL; } -int a=0; +int t16_v2=0; void t16_f1() { - a++; + t16_v2++; } void t16_f2() { Thread::sleep(200); - a++; + t16_v2++; } pthread_once_t t16_o1=PTHREAD_ONCE_INIT; @@ -2576,6 +2621,29 @@ static void test_16() pthread_join(thread,NULL); Thread::sleep(10); if(pthread_cond_destroy(&t16_c2)!=0) fail("cond destroy"); + //testing pthread_cond_timedwait + timespec a,b; + clock_gettime(CLOCK_MONOTONIC,&a); + timespecAdd(&a,10000000); //10ms + if(pthread_mutex_lock(&t16_m1)!=0) fail("mutex lock (7)"); //<--- + if(pthread_cond_timedwait(&t16_c1,&t16_m1,&a)!=ETIMEDOUT) fail("timedwait (1)"); + clock_gettime(CLOCK_MONOTONIC,&b); + if(pthread_mutex_unlock(&t16_m1)!=0) fail("mutex unlock (7)"); //<--- + //iprintf("delta=%lld\n",timespecDelta(&b,&a)); + if(llabs(timespecDelta(&b,&a))>200000) fail("timedwait (2)"); + if(pthread_create(&thread,NULL,t16_p3,NULL)!=0) fail("pthread_create (10)"); + clock_gettime(CLOCK_MONOTONIC,&a); + timespecAdd(&a,100000000); //100ms + if(pthread_mutex_lock(&t16_m1)!=0) fail("mutex lock (8)"); //<--- + t16_v1=false; + if(pthread_cond_timedwait(&t16_c1,&t16_m1,&a)!=0) fail("timedwait (3)"); + clock_gettime(CLOCK_MONOTONIC,&b); + if(t16_v1==false) fail("did not really wait"); + if(pthread_mutex_unlock(&t16_m1)!=0) fail("mutex unlock (8)"); //<--- + //iprintf("delta=%lld\n",timespecDelta(&b,&a)); + if(llabs(timespecDelta(&b,&a)+70000000)>500000) fail("timedwait (4)"); + pthread_join(thread,NULL); + Thread::sleep(10); // // Testing pthread_once // @@ -2583,17 +2651,17 @@ static void test_16() //pthread_once, it wouldn't be possible to run the test more than once ;) if(t16_o1.init_executed) t16_o1.init_executed=0; if(t16_o2.init_executed) t16_o2.init_executed=0; - a=0; + t16_v2=0; if(pthread_once(&t16_o1,t16_f1)!=0) fail("pthread_once 1"); - if(a!=1) fail("pthread_once 2"); + if(t16_v2!=1) fail("pthread_once 2"); if(pthread_once(&t16_o1,t16_f1)!=0) fail("pthread_once 2"); - if(a!=1) fail("pthread_once 3"); + if(t16_v2!=1) fail("pthread_once 3"); if(sizeof(pthread_once_t)!=2) fail("pthread_once 4"); - a=0; + t16_v2=0; Thread::create(t16_p5,STACK_MIN); Thread::sleep(50); if(pthread_once(&t16_o2,t16_f2)!=0) fail("pthread_once 5"); - if(a!=1) fail("pthread_once does not wait"); + if(t16_v2!=1) fail("pthread_once does not wait"); pass(); } @@ -4046,6 +4114,36 @@ static void test_25() auto b=chrono::steady_clock::now().time_since_epoch().count(); if(llabs(b-a-100000000)>5000000) fail("sleep_until"); } + // + // Testing condition_variable timed wait + // + { + unique_lock<mutex> l(t25_m1); + auto a=chrono::steady_clock::now().time_since_epoch().count(); + if(t25_c1.wait_for(l,10ms)!=cv_status::timeout) fail("timedwait (1)"); + auto b=chrono::steady_clock::now().time_since_epoch().count(); + //iprintf("delta=%lld\n",b-a-10000000); + if(llabs(b-a-10000000)>200000) fail("timedwait (2)"); + } + { + unique_lock<mutex> l(t25_m1); + auto start=chrono::steady_clock::now(); + auto a=start.time_since_epoch().count(); + if(t25_c1.wait_until(l,start+10ms)!=cv_status::timeout) fail("timedwait (3)"); + auto b=chrono::steady_clock::now().time_since_epoch().count(); + //iprintf("delta=%lld\n",b-a-10000000); + if(llabs(b-a-10000000)>200000) fail("timedwait (4)"); + } + { + thread t([]{ this_thread::sleep_for(30ms); t25_c1.notify_one(); }); + auto a=chrono::steady_clock::now().time_since_epoch().count(); + unique_lock<mutex> l(t25_m1); + if(t25_c1.wait_for(l,100ms)!=cv_status::no_timeout) fail("timedwait (5)"); + auto b=chrono::steady_clock::now().time_since_epoch().count(); + //iprintf("delta=%lld\n",b-a-30000000); + if(llabs(b-a-30000000)>500000) fail("timedwait (6)"); + t.join(); + } pass(); Thread::setPriority(0); } -- GitLab