Skip to content

Instantly share code, notes, and snippets.

@simonwagner
Created April 16, 2015 22:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simonwagner/1c029272905371be852b to your computer and use it in GitHub Desktop.
Save simonwagner/1c029272905371be852b to your computer and use it in GitHub Desktop.
Broken recursive_timed_mutex in libstdc++ for GCC 4.8
#include <cstdint>
#ifdef MAKE_IT_WORK
#undef _GLIBCXX_USE_CLOCK_MONOTONIC //if this is undefined, the 'correct' clock will be used
#endif
#include <mutex>
extern "C" {
using mutex = std::recursive_timed_mutex;
mutex* make_lock() {
return new mutex();
}
void lock_lock(mutex* lock) {
lock->lock();
}
void lock_unlock(mutex* lock) {
lock->unlock();
}
uint32_t lock_try_lock(mutex* lock) {
return lock->try_lock();
}
uint32_t lock_try_lock_for(mutex* lock, uint32_t us) {
return lock->try_lock_for(std::chrono::microseconds(us));
}
}
#include <thread>
#include <chrono>
#include <iostream>
int main() {
//print which clock we are using
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
std::cout << "using chrono::steady_clock" << std::endl;
#else
std::cout << "using chrono::high_resolution_clock" << std::endl;
#endif
//try_lock_for basically will call pthread_mutex_timedlock behind the scenes
//now, because of the code introduced in https://github.com/gcc-mirror/gcc/commit/ec0b1c28a851cf10f39624709487fbdb5e4c8505
//pthread_mutex_timedlock would basically be called with the wrong clock
//This was fixed with https://github.com/gcc-mirror/gcc/commit/4ca82f859dc0bfda63f5bcc16d0219ae25b5e351
//(As far as I can wrap my head around it, it is fixed with https://github.com/gcc-mirror/gcc/commit/4ca82f859dc0bfda63f5bcc16d0219ae25b5e351#diff-a8a8079e66b9d73a8c1c74a4bfa7ed8cL246 which will do the clock conversion)
//The really bad thing is that it is assumed that time_since_epoch would return UNIX time - this is not guaranteed and just works by chance
auto now_hrc = std::chrono::high_resolution_clock::now();
auto now_steady = std::chrono::steady_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::seconds>(now_hrc.time_since_epoch() - now_steady.time_since_epoch());
std::cout << "pthread_mutex_timedlock does use CLOCK_REALTIME, not monotonic" << std::endl;
std::cout << "The difference is " << diff.count() << " seconds" << std::endl;
auto mutex = make_lock();
lock_lock(mutex);
std::thread([&mutex]() {
auto start = std::chrono::system_clock::now();
auto locked = lock_try_lock_for(mutex, 1000 * 1000 * 5);
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - start);
std::cout << locked << " " << elapsed.count() << std::endl;
}).join();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment