From 05e6d71f6f98ebb49f69cbf8d7d99fb640c3927c Mon Sep 17 00:00:00 2001 From: fpagliughi Date: Mon, 13 Jan 2025 09:43:49 -0500 Subject: [PATCH 1/3] Fixed condition variable timed wait. Updated thread test for current implementation. --- src/Thread.c | 25 +++++++++++++++---------- test/thread.c | 22 ++++++++++++---------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/Thread.c b/src/Thread.c index f4d43fb6..f8b5279f 100644 --- a/src/Thread.c +++ b/src/Thread.c @@ -51,6 +51,8 @@ #include "OsWrapper.h" +#define NSEC_PER_SEC 1000000000L + /** * Start a new thread * @param fn the function to run, must be of the correct signature @@ -443,12 +445,8 @@ int Thread_wait_cond(cond_type condvar, int timeout_ms) { int rc = 0; struct timespec cond_timeout; - struct timespec interval; FUNC_ENTRY; - interval.tv_sec = timeout_ms / 1000; - interval.tv_nsec = (timeout_ms % 1000) * 1000000L; - #if defined(__APPLE__) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 /* for older versions of MacOS */ struct timeval cur_time; gettimeofday(&cur_time, NULL); @@ -458,13 +456,20 @@ int Thread_wait_cond(cond_type condvar, int timeout_ms) clock_gettime(CLOCK_REALTIME, &cond_timeout); #endif - cond_timeout.tv_sec += interval.tv_sec; - cond_timeout.tv_nsec += (timeout_ms % 1000) * 1000000L; + if (timeout_ms > 0) { + struct timespec interval; - if (cond_timeout.tv_nsec >= 1000000000L) - { - cond_timeout.tv_sec++; - cond_timeout.tv_nsec += (cond_timeout.tv_nsec - 1000000000L); + interval.tv_sec = timeout_ms / 1000; + interval.tv_nsec = (timeout_ms % 1000) * 1000000L; + + cond_timeout.tv_sec += interval.tv_sec; + cond_timeout.tv_nsec += interval.tv_nsec; + + while (cond_timeout.tv_nsec >= NSEC_PER_SEC) + { + cond_timeout.tv_sec++; + cond_timeout.tv_nsec -= NSEC_PER_SEC; + } } pthread_mutex_lock(&condvar->mutex); diff --git a/test/thread.c b/test/thread.c index 9e6de963..5f91cff3 100644 --- a/test/thread.c +++ b/test/thread.c @@ -244,7 +244,7 @@ static thread_return_type WINAPI sem_secondary(void* n) duration = elapsed(start); assert("rc 0 from lock mutex", rc == 0, "rc was %d", rc); MyLog(LOGA_INFO, "Lock duration was %ld", duration); - assert("duration is 2s", duration >= 2000L, "duration was %ld", duration); + assert("duration is 2s", duration >= 1999L && duration < 2050L, "duration was %ld", duration); MyLog(LOGA_DEBUG, "Secondary thread ending"); return 0; @@ -288,10 +288,14 @@ int test_sem(struct Options options) assert("rc 0 from post_sem", rc == 0, "rc was %d\n", rc); } + rc = Thread_check_sem(sem); + assert("rc 1 from check_sem", rc == 1, "rc was %d", rc); + + // Binary sem, so additional checks should be zero for (i = 0; i < 10; ++i) { rc = Thread_check_sem(sem); - assert("rc 1 from check_sem", rc == 1, "rc was %d", rc); + assert("rc 0 from check_sem", rc == 0, "rc was %d", rc); } rc = Thread_check_sem(sem); assert("rc 0 from check_sem", rc == 0, "rc was %d", rc); @@ -300,7 +304,7 @@ int test_sem(struct Options options) start = start_clock(); rc = Thread_wait_sem(sem, 1500); duration = elapsed(start); - assert("rc ETIMEDOUT from lock mutex", rc == ETIMEDOUT, "rc was %d", rc); + assert("rc ETIMEDOUT from lock mutex", rc == ETIMEDOUT || rc == EAGAIN, "rc was %d", rc); MyLog(LOGA_INFO, "Lock duration was %ld", duration); assert("duration is 2s", duration >= 1500L, "duration was %ld", duration); @@ -310,7 +314,7 @@ int test_sem(struct Options options) mysleep(2); MyLog(LOGA_DEBUG, "post secondary"); rc = Thread_post_sem(sem); - assert("rc 1 from post_sem", rc == 1, "rc was %d", rc); + assert("rc 0 from post_sem", rc == 0, "rc was %d", rc); mysleep(1); @@ -333,10 +337,10 @@ thread_return_type cond_secondary(void* n) MyLog(LOGA_DEBUG, "This will time out"); start = start_clock(); - rc = Thread_wait_cond(cond, 1); + rc = Thread_wait_cond(cond, 1000); duration = elapsed(start); MyLog(LOGA_INFO, "Lock duration was %ld", duration); - assert("duration is about 1s", duration >= 1000L && duration <= 1050L, "duration was %ld", duration); + assert("duration is about 1s", duration >= 999L && duration <= 1050L, "duration was %ld", duration); assert("rc non 0 from wait_cond", rc == ETIMEDOUT, "rc was %d", rc); MyLog(LOGA_DEBUG, "This should hang around a few seconds"); @@ -370,11 +374,11 @@ int test_cond(struct Options options) MyLog(LOGA_DEBUG, "Check timeout"); start = start_clock(); - rc = Thread_wait_cond(cond, 2); + rc = Thread_wait_cond(cond, 2000); duration = elapsed(start); assert("rc ETIMEDOUT from lock mutex", rc == ETIMEDOUT, "rc was %d", rc); MyLog(LOGA_INFO, "Lock duration was %ld", duration); - assert("duration is 2s", duration >= 2000L, "duration was %ld", duration); + assert("duration is 2s", duration >= 1999L && duration < 2050L, "duration was %ld", duration); /* multiple posts */ for (i = 0; i < 10; ++i) @@ -389,8 +393,6 @@ int test_cond(struct Options options) rc = Thread_wait_cond(cond, 0); assert("rc non-zero from wait_cond", rc == ETIMEDOUT, "rc was %d", rc); } - rc = Thread_wait_cond(cond, 0); - assert("rc non-zero from wait_cond", rc == ETIMEDOUT, "rc was %d", rc); MyLog(LOGA_DEBUG, "Post secondary but it will time out"); rc = Thread_signal_cond(cond); From cd28c9870084407730c31e9e5a5cf434c2419f90 Mon Sep 17 00:00:00 2001 From: Ian Craggs <10279016+icraggs@users.noreply.github.com> Date: Thu, 14 Aug 2025 13:54:01 +0100 Subject: [PATCH 2/3] Update Thread.c - fix MacOS build warning --- src/Thread.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Thread.c b/src/Thread.c index f8b5279f..28b410aa 100644 --- a/src/Thread.c +++ b/src/Thread.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2023 IBM Corp. and Ian Craggs + * Copyright (c) 2009, 2025 IBM Corp. and Ian Craggs * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 @@ -51,7 +51,9 @@ #include "OsWrapper.h" +#if !defined(NSEC_PER_SEC) #define NSEC_PER_SEC 1000000000L +#endif /** * Start a new thread From 8e0029a5b6dbbbac26337a210152796cf4e373ee Mon Sep 17 00:00:00 2001 From: Ian Craggs <10279016+icraggs@users.noreply.github.com> Date: Thu, 14 Aug 2025 14:09:45 +0100 Subject: [PATCH 3/3] Update thread.c - fix Windows build where EAGAIN is not defined --- test/thread.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/thread.c b/test/thread.c index 5f91cff3..f9089c68 100644 --- a/test/thread.c +++ b/test/thread.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2024 IBM Corp. + * Copyright (c) 2009, 2025 IBM Corp. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 @@ -304,7 +304,11 @@ int test_sem(struct Options options) start = start_clock(); rc = Thread_wait_sem(sem, 1500); duration = elapsed(start); - assert("rc ETIMEDOUT from lock mutex", rc == ETIMEDOUT || rc == EAGAIN, "rc was %d", rc); + #if defined(EAGAIN) + assert("rc ETIMEDOUT from lock mutex", rc == ETIMEDOUT || rc == EAGAIN, "rc was %d", rc); + #else + assert("rc ETIMEDOUT from lock mutex", rc == ETIMEDOUT, "rc was %d", rc); + #endif MyLog(LOGA_INFO, "Lock duration was %ld", duration); assert("duration is 2s", duration >= 1500L, "duration was %ld", duration);