From d83f591184f9d24f5c801c98eae5efd69894e5d2 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 12 Aug 2023 11:54:54 +0200 Subject: [PATCH] Check for mutex initialization. Fix missing check on optional for certain macro situations. --- lib/std/threads/os/thread_posix.c3 | 46 ++++++++++++++++++----- lib/std/threads/thread.c3 | 2 +- src/compiler/sema_expr.c | 2 +- src/version.h | 2 +- test/unit/stdlib/threads/simple_thread.c3 | 8 ++-- 5 files changed, 43 insertions(+), 17 deletions(-) diff --git a/lib/std/threads/os/thread_posix.c3 b/lib/std/threads/os/thread_posix.c3 index 3647287af..b312507b0 100644 --- a/lib/std/threads/os/thread_posix.c3 +++ b/lib/std/threads/os/thread_posix.c3 @@ -6,7 +6,11 @@ def NativeConditionVariable = Pthread_cond_t; def NativeThread = Pthread_t; def NativeOnceFlag = Pthread_once_t; -fn void! NativeMutex.init(&mtx, MutexType type) +/** + * @require !self.is_initialized() : "Mutex is already initialized" + * @ensure self.is_initialized() + **/ +fn void! NativeMutex.init(&self, MutexType type) { Pthread_mutexattr_t attr; if (posix::pthread_mutexattr_init(&attr)) return ThreadFault.INIT_FAILED?; @@ -15,19 +19,35 @@ fn void! NativeMutex.init(&mtx, MutexType type) { if (posix::pthread_mutexattr_settype(&attr, posix::PTHREAD_MUTEX_RECURSIVE)) return ThreadFault.INIT_FAILED?; } - if (posix::pthread_mutex_init(mtx, &attr)) return ThreadFault.INIT_FAILED?; + if (posix::pthread_mutex_init(self, &attr)) return ThreadFault.INIT_FAILED?; } -fn void! NativeMutex.destroy(&mtx) +fn bool NativeMutex.is_initialized(&self) { - if (posix::pthread_mutex_destroy(mtx)) return ThreadFault.DESTROY_FAILED?; + return *self != NativeMutex {}; } -fn void! NativeMutex.lock(&mtx) +/** + * @require self.is_initialized() : "Mutex was not initialized" + * @ensure !self.is_initialized() + **/ +fn void! NativeMutex.destroy(&self) { - if (posix::pthread_mutex_lock(mtx)) return ThreadFault.LOCK_FAILED?; + if (posix::pthread_mutex_destroy(self)) return ThreadFault.DESTROY_FAILED?; + *self = NativeMutex {}; } +/** + * @require self.is_initialized() : "Mutex was not initialized" + **/ +fn void! NativeMutex.lock(&self) +{ + if (posix::pthread_mutex_lock(self)) return ThreadFault.LOCK_FAILED?; +} + +/** + * @require mtx.is_initialized() : "Mutex was not initialized" + **/ fn void! NativeMutex.lock_timeoutout(&mtx, ulong ms) { /* Try to acquire the lock and, if we fail, sleep for 5ms. */ @@ -51,14 +71,20 @@ fn void! NativeMutex.lock_timeoutout(&mtx, ulong ms) } } -fn bool NativeMutex.try_lock(&mtx) +/** + * @require self.is_initialized() : "Mutex was not initialized" + **/ +fn bool NativeMutex.try_lock(&self) { - return !posix::pthread_mutex_trylock(mtx); + return !posix::pthread_mutex_trylock(self); } -fn void! NativeMutex.unlock(&mtx) +/** + * @require self.is_initialized() : "Mutex was not initialized" + **/ +fn void! NativeMutex.unlock(&self) { - if (posix::pthread_mutex_unlock(mtx)) return ThreadFault.UNLOCK_FAILED?; + if (posix::pthread_mutex_unlock(self)) return ThreadFault.UNLOCK_FAILED?; } fn void! NativeConditionVariable.init(&cond) diff --git a/lib/std/threads/thread.c3 b/lib/std/threads/thread.c3 index a4ac36a53..d98e266bf 100644 --- a/lib/std/threads/thread.c3 +++ b/lib/std/threads/thread.c3 @@ -30,7 +30,7 @@ fault ThreadFault INTERRUPTED, } -macro void! Mutex.init(&mutex, MutexType type) => NativeMutex.init((NativeMutex*)mutex, type); +macro void! Mutex.init(&mutex, MutexType type = MUTEX_PLAIN) => NativeMutex.init((NativeMutex*)mutex, type); macro void! Mutex.destroy(&mutex) => NativeMutex.destroy((NativeMutex*)mutex); macro void! Mutex.lock(&mutex) => NativeMutex.lock((NativeMutex*)mutex); macro void! Mutex.lock_timeout(&mutex, ulong ms) => NativeMutex.lock((NativeMutex*)mutex, ms); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 66b92e344..43ad781fc 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -2006,7 +2006,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s assert(call_expr->type); bool must_use = false; - if (rtype != type_void) + if (rtype != type_void || optional_return) { must_use = sig->attrs.nodiscard || (optional_return && !sig->attrs.maydiscard); } diff --git a/src/version.h b/src/version.h index 94e7eb4f3..07bbc889e 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.4.604" \ No newline at end of file +#define COMPILER_VERSION "0.4.605" \ No newline at end of file diff --git a/test/unit/stdlib/threads/simple_thread.c3 b/test/unit/stdlib/threads/simple_thread.c3 index 9249ae0ca..13d6249fe 100644 --- a/test/unit/stdlib/threads/simple_thread.c3 +++ b/test/unit/stdlib/threads/simple_thread.c3 @@ -5,7 +5,7 @@ fn void! testrun() @test { Thread t; a = 0; - t.create(fn int(void* arg) { a++; return 0; }, null); + t.create(fn int(void* arg) { a++; return 0; }, null)!; assert(t.join()! == 0); assert(a == 1); } @@ -16,11 +16,11 @@ fn void! testrun_mutex() @test { Thread[100] ts; a = 0; - m.init(thread::MUTEX_PLAIN); + m.init(thread::MUTEX_PLAIN)!; foreach (&t : ts) { t.create(fn int(void* arg) { - m.lock(); + m.lock()!!; defer m.unlock()!!; a += 10; thread::sleep_ms(5); @@ -32,7 +32,7 @@ fn void! testrun_mutex() @test thread::sleep_ms(5); a++; return 0; - }, null); + }, null)!; } foreach (i, &t : ts) {