Skip to content

Commit

Permalink
Basic implementation of threaded traces
Browse files Browse the repository at this point in the history
The very simple implementation improves performance of tracing by
about 3x.
  • Loading branch information
zackr committed Aug 1, 2011
1 parent 8067fe0 commit 94ee9b3
Show file tree
Hide file tree
Showing 6 changed files with 418 additions and 17 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ add_library (common
trace_parser.cpp
trace_writer.cpp
trace_model_writer.cpp
ringbuffer.cpp
image.cpp
image_bmp.cpp
image_pnm.cpp
Expand Down Expand Up @@ -323,6 +324,7 @@ else ()
glcaps.cpp
glsnapshot.cpp
trace_writer.cpp
ringbuffer.cpp
image.cpp
image_png.cpp
os_posix.cpp
Expand Down
187 changes: 187 additions & 0 deletions os_thread.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/**************************************************************************
*
* Copyright 1999-2006 Brian Paul
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/


/**
* @file
*
* Thread, mutex, condition variable.
*/


#ifndef OS_THREAD_H_
#define OS_THREAD_H_

namespace OS {

#if defined _WIN32
#include <windows.h>
typedef HANDLE Thread;
typedef CRITICAL_SECTION Mutex;
typedef CONDITION_VARIABLE Condvar;
#else
#include <pthread.h> /* POSIX threads headers */
#include <stdio.h> /* for perror() */
#include <signal.h>
typedef pthread_t Thread;
typedef pthread_mutex_t Mutex;
typedef pthread_cond_t Condvar;
#endif

#if defined _WIN32
#define THREAD_ROUTINE( name, param ) \
void * WINAPI name( void *param )

static inline Thread ThreadCreate(void *(WINAPI * routine)(void *),
void *param)
{
DWORD id;
return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) routine,
param, 0, &id);
}

static inline int ThreadWait(Thread thread)
{
if (WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0)
return 0;
return -1;
}

static inline int ThreadDestroy(Thread thread)
{
if (CloseHandle(thread))
return 0;
return -1;
}

/* http://locklessinc.com/articles/pthreads_on_windows/ */
#define MutexStatic(mutex) \
static Mutex mutex = {(PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0}

#define MutexInit(mutex) \
InitializeCriticalSection(&mutex)

#define MutexDestroy(mutex) \
DeleteCriticalSection(&mutex)

#define MutexLock(mutex) \
EnterCriticalSection(&mutex)

#define MutexUnlock(mutex) \
LeaveCriticalSection(&mutex)

/* CONDITION_VARIABLE is only available on newer versions of Windows
* (Server 2008/Vista or later).
* http://msdn.microsoft.com/en-us/library/ms682052(VS.85).aspx
*/

#define CondvarStatic(cond) \
/*static*/ Condvar cond = CONDITION_VARIABLE_INIT

#define CondvarInit(cond) \
InitializeConditionVariable(&(cond))

#define CondvarDestroy(cond) \
(void) cond /* nothing to do */

#define CondvarWait(cond, mutex) \
SleepConditionVariableCS(&(cond), &(mutex), INFINITE)

#define CondvarSignal(cond) \
WakeConditionVariable(&(cond))

#define CondvarBroadcast(cond) \
WakeAllConditionVariable(&(cond))

#else

#define THREAD_ROUTINE( name, param ) \
void *name( void *param )

static inline Thread ThreadCreate(void *(* routine)( void *),
void *param)
{
Thread thread;
sigset_t saved_set, new_set;
int ret;

sigfillset(&new_set);
pthread_sigmask(SIG_SETMASK, &new_set, &saved_set);
ret = pthread_create( &thread, NULL, routine, param );
pthread_sigmask(SIG_SETMASK, &saved_set, NULL);
if (ret)
return 0;
return thread;
}

static inline int ThreadWait(Thread thread)
{
return pthread_join(thread, NULL);
}

static inline int ThreadDestroy(Thread thread)
{
return pthread_detach(thread);
}

#define MutexStatic(mutex) \
static Mutex mutex = PTHREAD_MUTEX_INITIALIZER

#define MutexInit(mutex) \
(void) pthread_mutex_init(&(mutex), NULL)

#define MutexDestroy(mutex) \
pthread_mutex_destroy(&(mutex))

#define MutexLock(mutex) \
(void) pthread_mutex_lock(&(mutex))

#define MutexUnlock(mutex) \
(void) pthread_mutex_unlock(&(mutex))

#define CondvarStatic(mutex) \
static Condvar mutex = PTHREAD_COND_INITIALIZER

#define CondvarInit(cond) \
pthread_cond_init(&(cond), NULL)

#define CondvarDestroy(cond) \
pthread_cond_destroy(&(cond))

#define CondvarWait(cond, mutex) \
pthread_cond_wait(&(cond), &(mutex))

#define CondvarSignal(cond) \
pthread_cond_signal(&(cond))

#define CondvarBroadcast(cond) \
pthread_cond_broadcast(&(cond))

#endif


}

#endif /* OS_THREAD_H_ */
70 changes: 70 additions & 0 deletions ringbuffer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include <string.h>
#include <assert.h>

#include "ringbuffer.hpp"

using namespace OS;

Ringbuffer::Ringbuffer(long size)
: m_size(size)
{
m_buffer = new char[m_size];
m_writePtr = m_buffer;
m_readPtr = m_buffer;

MutexInit(m_mutex);
}

Ringbuffer::~Ringbuffer()
{
MutexDestroy(m_mutex);
delete [] m_buffer;
}

long Ringbuffer::size() const
{
return m_size;
}

int Ringbuffer::sizeToWrite() const
{
if (m_writePtr > m_readPtr) {
return m_size - (m_writePtr - m_readPtr);
} else if (m_writePtr == m_readPtr) {
return m_size - (m_writePtr - m_buffer);
} else {
return m_readPtr - m_writePtr;
}
}

int Ringbuffer::sizeToRead() const
{
return m_size - sizeToWrite();
}

void Ringbuffer::write(char *buffer, int size)
{
if (size >= this->size()) {
assert(0);
return;
}
MutexLock(m_mutex);
memcpy(m_writePtr, buffer, size);
m_writePtr += size;
MutexUnlock(m_mutex);
}

void Ringbuffer::read(char *buffer, int size)
{
MutexLock(m_mutex);
memcpy(buffer, m_readPtr, size);
m_readPtr += size;
MutexUnlock(m_mutex);
}

void OS::Ringbuffer::reset()
{
m_writePtr = m_buffer;
m_readPtr = m_buffer;
}

36 changes: 36 additions & 0 deletions ringbuffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef OS_RINGBUFFER_HPP
#define OS_RINGBUFFER_HPP

#include "os_thread.hpp"

namespace OS {

class Ringbuffer
{
public:
Ringbuffer(long size = 32 * 1024 * 1024);
~Ringbuffer();

long size() const;

int sizeToWrite() const;
int sizeToRead() const;

void write(char *buffer, int size);
void read(char *buffer, int size);

void reset();

private:
char *m_buffer;
long m_size;

char *m_writePtr;
char *m_readPtr;

OS::Mutex m_mutex;
};

}

#endif
Loading

0 comments on commit 94ee9b3

Please sign in to comment.