diff --git a/lib/std/threads/os/thread_posix.c3 b/lib/std/threads/os/thread_posix.c3 index 5570d9a72..56512802b 100644 --- a/lib/std/threads/os/thread_posix.c3 +++ b/lib/std/threads/os/thread_posix.c3 @@ -1,7 +1,13 @@ module std::threads::os @if(env::POSIX); import std::os::posix; import libc; -def NativeMutex = Pthread_mutex_t; + +struct NativeMutex +{ + Pthread_mutex_t mutex; + bool initialized; +} + def NativeConditionVariable = Pthread_cond_t; def NativeThread = Pthread_t; def NativeOnceFlag = Pthread_once_t; @@ -19,12 +25,13 @@ fn void! NativeMutex.init(&self, MutexType type) { if (posix::pthread_mutexattr_settype(&attr, posix::PTHREAD_MUTEX_RECURSIVE)) return ThreadFault.INIT_FAILED?; } - if (posix::pthread_mutex_init(self, &attr)) return ThreadFault.INIT_FAILED?; + if (posix::pthread_mutex_init(&self.mutex, &attr)) return ThreadFault.INIT_FAILED?; + self.initialized = true; } fn bool NativeMutex.is_initialized(&self) { - return *self != NativeMutex {}; + return self.initialized; } /** @@ -33,8 +40,8 @@ fn bool NativeMutex.is_initialized(&self) **/ fn void! NativeMutex.destroy(&self) { - if (posix::pthread_mutex_destroy(self)) return ThreadFault.DESTROY_FAILED?; - *self = NativeMutex {}; + if (posix::pthread_mutex_destroy(&self.mutex)) return ThreadFault.DESTROY_FAILED?; + *self = {}; } /** @@ -42,17 +49,17 @@ fn void! NativeMutex.destroy(&self) **/ fn void! NativeMutex.lock(&self) { - if (posix::pthread_mutex_lock(self)) return ThreadFault.LOCK_FAILED?; + if (posix::pthread_mutex_lock(&self.mutex)) return ThreadFault.LOCK_FAILED?; } /** - * @require mtx.is_initialized() : "Mutex was not initialized" + * @require self.is_initialized() : "Mutex was not initialized" **/ -fn void! NativeMutex.lock_timeout(&mtx, ulong ms) +fn void! NativeMutex.lock_timeout(&self, ulong ms) { /* Try to acquire the lock and, if we fail, sleep for 5ms. */ Errno result; - while ((result = posix::pthread_mutex_trylock(mtx)) == errno::EBUSY) + while ((result = posix::pthread_mutex_trylock(&self.mutex)) == errno::EBUSY) { if (!ms) break; ulong sleep = min(5, ms); @@ -76,7 +83,7 @@ fn void! NativeMutex.lock_timeout(&mtx, ulong ms) **/ fn bool NativeMutex.try_lock(&self) { - return !posix::pthread_mutex_trylock(self); + return !posix::pthread_mutex_trylock(&self.mutex); } /** @@ -84,7 +91,7 @@ fn bool NativeMutex.try_lock(&self) **/ fn void! NativeMutex.unlock(&self) { - if (posix::pthread_mutex_unlock(self)) return ThreadFault.UNLOCK_FAILED?; + if (posix::pthread_mutex_unlock(&self.mutex)) return ThreadFault.UNLOCK_FAILED?; } fn void! NativeConditionVariable.init(&cond) @@ -107,18 +114,24 @@ fn void! NativeConditionVariable.broadcast(&cond) if (posix::pthread_cond_broadcast(cond)) return ThreadFault.SIGNAL_FAILED?; } +/** + * @require mtx.is_initialized() + **/ fn void! NativeConditionVariable.wait(&cond, NativeMutex* mtx) { - if (posix::pthread_cond_wait(cond, mtx)) return ThreadFault.WAIT_FAILED?; + if (posix::pthread_cond_wait(cond, &mtx.mutex)) return ThreadFault.WAIT_FAILED?; } +/** + * @require mtx.is_initialized() + **/ fn void! NativeConditionVariable.wait_timeout(&cond, NativeMutex* mtx, ulong ms) { TimeSpec now; if (libc::timespec_get(&now, libc::TIME_UTC) != libc::TIME_UTC) return ThreadFault.WAIT_FAILED?; now.s += (Time_t)(ms / 1000); now.ns += (CLong)((ms % 1000) * 1000_000); - switch (posix::pthread_cond_timedwait(cond, mtx, &now)) + switch (posix::pthread_cond_timedwait(cond, &mtx.mutex, &now)) { case errno::ETIMEDOUT: return ThreadFault.WAIT_TIMEOUT?; diff --git a/resources/testproject/hello_world.c3 b/resources/testproject/hello_world.c3 index 376c0ebe3..7f1437c22 100644 --- a/resources/testproject/hello_world.c3 +++ b/resources/testproject/hello_world.c3 @@ -11,5 +11,5 @@ fn int main() printf("Hello World!\n"); bar::test(); printf("Hello double: %d\n", test_doubler(11)); - return 17; + return 0; } \ No newline at end of file diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index ced04d284..cfb8cad13 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -513,6 +513,7 @@ void compiler_compile(void) printf("Launching %s...\n", output_exe); int ret = system(platform_target.os == OS_TYPE_WIN32 ? output_exe : str_printf("./%s", output_exe)); printf("Program finished with exit code %d.\n", ret); + if (ret != 0) exit(EXIT_FAILURE); } } else if (output_static) diff --git a/src/version.h b/src/version.h index 52ab74850..1e5afe518 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.4.636" \ No newline at end of file +#define COMPILER_VERSION "0.4.637" \ 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 33d6b0770..afcfc5ad0 100644 --- a/test/unit/stdlib/threads/simple_thread.c3 +++ b/test/unit/stdlib/threads/simple_thread.c3 @@ -15,18 +15,19 @@ fn void! testrun() @test assert(t.join()! == 10); } -Mutex m; + +Mutex m_global; fn void! testrun_mutex() @test { Thread[20] ts; a = 0; - m.init()!; + m_global.init()!; foreach (&t : ts) { t.create(fn int(void* arg) { - m.lock()!!; - defer m.unlock()!!; + m_global.lock()!!; + defer m_global.unlock()!!; a += 10; thread::sleep_ms(5); a *= 10; @@ -44,7 +45,7 @@ fn void! testrun_mutex() @test assert(t.join()! == 0); } assert(a == ts.len); - m.destroy()!; + m_global.destroy()!; } fn void! testrun_mutex_try() @test