void mutex_lock(struct mutex *mutex) { assert(mutex->name); SLOG(LOG_DEBUG, "Locking %s", mutex_name(mutex)); uint64_t const start = bench_event_start(); # ifdef WITH_BENCH int err = pthread_mutex_trylock(&mutex->mutex); switch (err) { case 0: bench_event_fire(&mutex->lock_for_free); break; case EBUSY: err = pthread_mutex_lock(&mutex->mutex); break; default: // other errors (for lock and trylock) handled below break; } # else // This was found to be noticably faster (-1% cpu load) int err = pthread_mutex_lock(&mutex->mutex); # endif if (! err) { bench_event_stop(&mutex->acquiring_lock, start); SLOG(LOG_DEBUG, "Locked %s", mutex_name(mutex)); } else { SLOG(LOG_ERR, "Cannot lock %s: %s", mutex_name(mutex), strerror(err)); // so be it } }
void mutex_unlock(struct mutex *mutex) { assert(mutex->name); SLOG(LOG_DEBUG, "Unlocking %s", mutex_name(mutex)); int err = pthread_mutex_unlock(&mutex->mutex); if (err) { SLOG(LOG_ERR, "Cannot unlock %s : %s", mutex_name(mutex), strerror(err)); } }
void mutex_unlock(struct mutex *mutex) { assert(mutex->name); SLOG(LOG_DEBUG, "Unlocking %s", mutex_name(mutex)); int const err = pthread_mutex_unlock(&mutex->mutex); // Call directly pthread_mutex_unlock to avoid the logs in mutex_unlock if (! err) { SLOG(LOG_DEBUG, "Unlocked %s", mutex_name(mutex)); } else { SLOG(LOG_ERR, "Cannot unlock %s: %s", mutex_name(mutex), strerror(err)); } }
void mutex_dtor(struct mutex *mutex) { assert(mutex->name); SLOG(LOG_DEBUG, "Destruct mutex %s", mutex_name(mutex)); (void)pthread_mutex_destroy(&mutex->mutex); mutex->name = NULL; }
DECLARE_TEST(mutex, basic) { mutex_t* mutex; mutex = mutex_allocate(STRING_CONST("test")); EXPECT_CONSTSTRINGEQ(mutex_name(mutex), string_const(STRING_CONST("test"))); EXPECT_TRUE(mutex_try_lock(mutex)); EXPECT_TRUE(mutex_lock(mutex)); EXPECT_TRUE(mutex_try_lock(mutex)); EXPECT_TRUE(mutex_lock(mutex)); EXPECT_TRUE(mutex_unlock(mutex)); EXPECT_TRUE(mutex_unlock(mutex)); EXPECT_TRUE(mutex_unlock(mutex)); EXPECT_TRUE(mutex_unlock(mutex)); log_set_suppress(0, ERRORLEVEL_WARNING); EXPECT_FALSE(mutex_unlock(mutex)); log_set_suppress(0, ERRORLEVEL_INFO); mutex_signal(mutex); thread_yield(); EXPECT_TRUE(mutex_try_wait(mutex, 1)); EXPECT_TRUE(mutex_unlock(mutex)); mutex_signal(mutex); thread_yield(); EXPECT_TRUE(mutex_wait(mutex)); EXPECT_TRUE(mutex_unlock(mutex)); log_set_suppress(0, ERRORLEVEL_WARNING); EXPECT_FALSE(mutex_try_wait(mutex, 100)); EXPECT_FALSE(mutex_unlock(mutex)); log_set_suppress(0, ERRORLEVEL_INFO); mutex_signal(mutex); thread_yield(); EXPECT_TRUE(mutex_try_wait(mutex, 1)); log_set_suppress(0, ERRORLEVEL_WARNING); EXPECT_FALSE(mutex_try_wait(mutex, 100)); EXPECT_TRUE(mutex_unlock(mutex)); EXPECT_FALSE(mutex_unlock(mutex)); log_set_suppress(0, ERRORLEVEL_INFO); mutex_deallocate(mutex); return 0; }