namespace os {
-void acquireMutex(void);
-
-void releaseMutex(void);
-
void log(const char *format, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 1, 2)))
#include <unistd.h>
#include <sys/time.h>
#include <sys/wait.h>
-#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
namespace os {
-static pthread_mutex_t
-mutex = PTHREAD_MUTEX_INITIALIZER;
-
-
-void
-acquireMutex(void)
-{
- pthread_mutex_lock(&mutex);
-}
-
-
-void
-releaseMutex(void)
-{
- pthread_mutex_unlock(&mutex);
-}
-
-
String
getProcessName(void)
{
#ifndef _OS_THREAD_HPP_
#define _OS_THREAD_HPP_
+
#ifdef _WIN32
#include <windows.h>
#else
namespace os {
+ class recursive_mutex
+ {
+ public:
+#ifdef _WIN32
+ typedef CRITICAL_SECTION native_handle_type;
+#else
+ typedef pthread_mutex_t native_handle_type;
+#endif
+
+ recursive_mutex(void) {
+#ifdef _WIN32
+ InitializeCriticalSection(&_native_handle);
+#else
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&_native_handle, NULL);
+ pthread_mutexattr_destroy(&attr);
+#endif
+ }
+
+ ~recursive_mutex() {
+#ifdef _WIN32
+ DeleteCriticalSection(&_native_handle);
+#else
+ pthread_mutex_destroy(&_native_handle);
+#endif
+ }
+
+ inline void
+ lock(void) {
+#ifdef _WIN32
+ EnterCriticalSection(&_native_handle);
+#else
+ pthread_mutex_lock(&_native_handle);
+#endif
+ }
+
+ inline void
+ unlock(void) {
+#ifdef _WIN32
+ LeaveCriticalSection(&_native_handle);
+#else
+ pthread_mutex_unlock(&_native_handle);
+#endif
+ }
+
+ private:
+ native_handle_type _native_handle;
+ };
+
+
template <typename T>
class thread_specific_ptr
{
namespace os {
-/*
- * Trick from http://locklessinc.com/articles/pthreads_on_windows/
- */
-static CRITICAL_SECTION
-criticalSection = {
- (PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0
-};
-
-
-void
-acquireMutex(void)
-{
- EnterCriticalSection(&criticalSection);
-}
-
-
-void
-releaseMutex(void)
-{
- LeaveCriticalSection(&criticalSection);
-}
-
-
String
getProcessName(void)
{
static os::thread_specific_ptr<unsigned> thread_id_specific_ptr;
unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
- os::acquireMutex();
+ mutex.lock();
++acquired;
if (!m_file->isOpened()) {
void LocalWriter::endEnter(void) {
Writer::endEnter();
--acquired;
- os::releaseMutex();
+ mutex.unlock();
}
void LocalWriter::beginLeave(unsigned call) {
- os::acquireMutex();
+ mutex.lock();
++acquired;
Writer::beginLeave(call);
}
void LocalWriter::endLeave(void) {
Writer::endLeave();
--acquired;
- os::releaseMutex();
+ mutex.unlock();
}
void LocalWriter::flush(void) {
/*
* Do nothing if the mutex is already acquired (e.g., if a segfault happen
- * while writing the file) to prevent dead-lock.
+ * while writing the file) as state could be inconsistent, therefore yield
+ * inconsistent trace files and/or repeated segfaults till infinity.
*/
- os::acquireMutex();
+ mutex.lock();
if (acquired) {
os::log("apitrace: ignoring exception while tracing\n");
} else {
}
--acquired;
}
- os::releaseMutex();
+ mutex.unlock();
}
#define _TRACE_WRITER_LOCAL_HPP_
+#include "os_thread.hpp"
#include "trace_writer.hpp"
*/
class LocalWriter : public Writer {
protected:
+ /**
+ * We need a recursive mutex so that it doesn't dead lock when a segfault happens when the mutex is held.
+ */
+ os::recursive_mutex mutex;
int acquired;
public: