#pragma once #include #include #include #include #include #define CHECKED(x) { int err = x; if( err != 0 ) { std::cerr << "KERNEL ERROR: Operation \"" #x "\" return error " << err << " - " << strerror(err) << std::endl; std::abort(); } } struct __bin_sem_t { pthread_mutex_t lock; pthread_cond_t cond; int val; __bin_sem_t() { // Create the mutex with error checking pthread_mutexattr_t mattr; pthread_mutexattr_init( &mattr ); pthread_mutexattr_settype( &mattr, PTHREAD_MUTEX_ERRORCHECK_NP); pthread_mutex_init(&lock, &mattr); pthread_cond_init (&cond, nullptr); val = 0; } ~__bin_sem_t() { CHECKED( pthread_mutex_destroy(&lock) ); CHECKED( pthread_cond_destroy (&cond) ); } void wait() { CHECKED( pthread_mutex_lock(&lock) ); while(val < 1) { pthread_cond_wait(&cond, &lock); } val -= 1; CHECKED( pthread_mutex_unlock(&lock) ); } bool post() { bool needs_signal = false; CHECKED( pthread_mutex_lock(&lock) ); if(val < 1) { val += 1; pthread_cond_signal(&cond); needs_signal = true; } CHECKED( pthread_mutex_unlock(&lock) ); return needs_signal; } }; #undef CHECKED #if defined(__cforall) || defined(__cpluplus) extern "C" { #endif //-------------------- // Basic types struct pthread_runner_t { pthread_t handle; __bin_sem_t sem; }; typedef pthread_runner_t * thread_t; //-------------------- // Basic thread support thread_t thrdlib_create( void (*main)( thread_t ) ) { thread_t thrd = new pthread_runner_t(); int r = pthread_create( &thrd->handle, nullptr, (void *(*)(void *))main, thrd ); if( r != 0 ) std::abort(); return thrd; } void thrdlib_join( thread_t handle ) { void * ret; int r = pthread_join( handle->handle, &ret ); if( r != 0 ) std::abort(); delete handle; } void thrdlib_park( thread_t handle ) { handle->sem.wait(); } void thrdlib_unpark( thread_t handle ) { handle->sem.post(); } void thrdlib_yield( void ) { int r = pthread_yield(); if( r != 0 ) std::abort(); } //-------------------- // Basic kernel features void thrdlib_init( int ) {} void thrdlib_clean( void ) {} #if defined(__cforall) || defined(__cpluplus) } #endif