trace_model.cpp
trace_parser.cpp
trace_writer.cpp
+ trace_local_writer.cpp
trace_model_writer.cpp
image.cpp
image_bmp.cpp
def dump_arg_instance(self, function, arg):
# Dump shaders as strings
if function.name in ('CreateVertexShader', 'CreatePixelShader') and arg.name == 'pFunction':
- print ' DumpShader(__writer, %s);' % (arg.name)
+ print ' DumpShader(Trace::localWriter, %s);' % (arg.name)
return
DllTracer.dump_arg_instance(self, function, arg)
def dump_arg_instance(self, function, arg):
# Dump shaders as strings
if function.name in ('CreateVertexShader', 'CreatePixelShader') and arg.name == 'pFunction':
- print ' DumpShader(__writer, %s);' % (arg.name)
+ print ' DumpShader(Trace::localWriter, %s);' % (arg.name)
return
DllTracer.dump_arg_instance(self, function, arg)
# Emit a fake function
print ' {'
print ' static const Trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name
- print ' unsigned __call = __writer.beginEnter(&__sig);'
- print ' __writer.beginArg(0);'
+ print ' unsigned __call = Trace::localWriter.beginEnter(&__sig);'
+ print ' Trace::localWriter.beginArg(0);'
dump_instance(glapi.GLenum, enable_name)
- print ' __writer.endArg();'
- print ' __writer.endEnter();'
- print ' __writer.beginLeave(__call);'
- print ' __writer.endLeave();'
+ print ' Trace::localWriter.endArg();'
+ print ' Trace::localWriter.endEnter();'
+ print ' Trace::localWriter.beginLeave(__call);'
+ print ' Trace::localWriter.endLeave();'
print ' }'
print ' return;'
Tracer.dispatch_function(self, function)
def emit_memcpy(self, dest, src, length):
- print ' unsigned __call = __writer.beginEnter(&__memcpy_sig);'
- print ' __writer.beginArg(0);'
- print ' __writer.writeOpaque(%s);' % dest
- print ' __writer.endArg();'
- print ' __writer.beginArg(1);'
- print ' __writer.writeBlob(%s, %s);' % (src, length)
- print ' __writer.endArg();'
- print ' __writer.beginArg(2);'
- print ' __writer.writeUInt(%s);' % length
- print ' __writer.endArg();'
- print ' __writer.endEnter();'
- print ' __writer.beginLeave(__call);'
- print ' __writer.endLeave();'
+ print ' unsigned __call = Trace::localWriter.beginEnter(&__memcpy_sig);'
+ print ' Trace::localWriter.beginArg(0);'
+ print ' Trace::localWriter.writeOpaque(%s);' % dest
+ print ' Trace::localWriter.endArg();'
+ print ' Trace::localWriter.beginArg(1);'
+ print ' Trace::localWriter.writeBlob(%s, %s);' % (src, length)
+ print ' Trace::localWriter.endArg();'
+ print ' Trace::localWriter.beginArg(2);'
+ print ' Trace::localWriter.writeUInt(%s);' % length
+ print ' Trace::localWriter.endArg();'
+ print ' Trace::localWriter.endEnter();'
+ print ' Trace::localWriter.beginLeave(__call);'
+ print ' Trace::localWriter.endLeave();'
buffer_targets = [
'ARRAY_BUFFER',
print ' __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
print ' if (!__element_array_buffer) {'
if isinstance(arg.type, stdapi.Array):
- print ' __writer.beginArray(%s);' % arg.type.length
+ print ' Trace::localWriter.beginArray(%s);' % arg.type.length
print ' for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length
- print ' __writer.beginElement();'
- print ' __writer.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name)
- print ' __writer.endElement();'
+ print ' Trace::localWriter.beginElement();'
+ print ' Trace::localWriter.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name)
+ print ' Trace::localWriter.endElement();'
print ' }'
- print ' __writer.endArray();'
+ print ' Trace::localWriter.endArray();'
else:
- print ' __writer.writeBlob(%s, count*__gl_type_size(type));' % (arg.name)
+ print ' Trace::localWriter.writeBlob(%s, count*__gl_type_size(type));' % (arg.name)
print ' } else {'
Tracer.dump_arg_instance(self, function, arg)
print ' }'
print ' GLint __unpack_buffer = 0;'
print ' __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);'
print ' if (__unpack_buffer) {'
- print ' __writer.writeOpaque(%s);' % arg.name
+ print ' Trace::localWriter.writeOpaque(%s);' % arg.name
print ' } else {'
Tracer.dump_arg_instance(self, function, arg)
print ' }'
# Emit a fake function
self.array_trace_intermezzo(api, uppercase_name)
- print ' unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
+ print ' unsigned __call = Trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
for arg in function.args:
assert not arg.output
- print ' __writer.beginArg(%u);' % (arg.index,)
+ print ' Trace::localWriter.beginArg(%u);' % (arg.index,)
if arg.name != 'pointer':
dump_instance(arg.type, arg.name)
else:
- print ' __writer.writeBlob((const void *)%s, __size);' % (arg.name)
- print ' __writer.endArg();'
+ print ' Trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name)
+ print ' Trace::localWriter.endArg();'
- print ' __writer.endEnter();'
- print ' __writer.beginLeave(__call);'
- print ' __writer.endLeave();'
+ print ' Trace::localWriter.endEnter();'
+ print ' Trace::localWriter.beginLeave(__call);'
+ print ' Trace::localWriter.endLeave();'
print ' }'
print ' }'
self.array_epilog(api, uppercase_name)
print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
# Emit a fake function
- print ' unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
+ print ' unsigned __call = Trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
for arg in function.args:
assert not arg.output
- print ' __writer.beginArg(%u);' % (arg.index,)
+ print ' Trace::localWriter.beginArg(%u);' % (arg.index,)
if arg.name != 'pointer':
dump_instance(arg.type, arg.name)
else:
- print ' __writer.writeBlob((const void *)%s, __size);' % (arg.name)
- print ' __writer.endArg();'
+ print ' Trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name)
+ print ' Trace::localWriter.endArg();'
- print ' __writer.endEnter();'
- print ' __writer.beginLeave(__call);'
- print ' __writer.endLeave();'
+ print ' Trace::localWriter.endEnter();'
+ print ' Trace::localWriter.beginLeave(__call);'
+ print ' Trace::localWriter.endLeave();'
print ' }'
print ' }'
print ' }'
self.fake_call(function, [texture])
def fake_call(self, function, args):
- print ' unsigned __fake_call = __writer.beginEnter(&__%s_sig);' % (function.name,)
+ print ' unsigned __fake_call = Trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
for arg, instance in zip(function.args, args):
assert not arg.output
- print ' __writer.beginArg(%u);' % (arg.index,)
+ print ' Trace::localWriter.beginArg(%u);' % (arg.index,)
dump_instance(arg.type, instance)
- print ' __writer.endArg();'
- print ' __writer.endEnter();'
- print ' __writer.beginLeave(__fake_call);'
- print ' __writer.endLeave();'
+ print ' Trace::localWriter.endArg();'
+ print ' Trace::localWriter.endEnter();'
+ print ' Trace::localWriter.beginLeave(__fake_call);'
+ print ' Trace::localWriter.endLeave();'
void Abort(void);
-void CatchInterrupts(void (*func)(int));
+void SetExceptionCallback(void (*callback)(void));
+void ResetExceptionCallback(void);
} /* namespace OS */
**************************************************************************/
+#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
}
-struct Interrupts
-{
- Interrupts()
- : set(false),
- sig_int(NULL),
- sig_hup(NULL),
- sig_term(NULL),
- sig_segv(NULL),
- handler(NULL)
- {}
-
- bool set;
- void (*sig_int)(int);
- void (*sig_hup)(int);
- void (*sig_term)(int);
- void (*sig_segv)(int);
-
- void (*handler)(int);
-};
-static Interrupts interrupts;
-
-static void InterruptHandler(int sig)
+static void (*gCallback)(void) = NULL;
+
+#define NUM_SIGNALS 16
+
+struct sigaction old_actions[NUM_SIGNALS];
+
+static void signal_handler(int sig, siginfo_t *info, void *context)
{
- if (interrupts.set && interrupts.handler) {
- interrupts.handler(sig);
- }
- if (sig == SIGINT) {
- if (!interrupts.sig_int) {
- exit(sig);
- }
- interrupts.sig_int(sig);
- } else if (sig == SIGHUP) {
- if (!interrupts.sig_hup) {
- exit(sig);
- }
- interrupts.sig_hup(sig);
- } else if (sig == SIGTERM) {
- if (!interrupts.sig_term) {
- exit(sig);
+ static int recursion_count = 0;
+
+ fprintf(stderr, "signal_handler: sig = %i\n", sig);
+
+ if (recursion_count) {
+ fprintf(stderr, "recursion with sig %i\n", sig);
+ } else {
+ if (gCallback) {
+ ++recursion_count;
+ gCallback();
+ --recursion_count;
}
- interrupts.sig_term(sig);
- } else if (sig == SIGSEGV) {
- if (interrupts.sig_segv) {
- interrupts.sig_segv(sig);
+ }
+
+ struct sigaction *old_action;
+ if (sig >= NUM_SIGNALS) {
+ /* This should never happen */
+ fprintf(stderr, "Unexpected signal %i\n", sig);
+ raise(SIGKILL);
+ }
+ old_action = &old_actions[sig];
+
+ if (old_action->sa_flags & SA_SIGINFO) {
+ // Handler is in sa_sigaction
+ old_action->sa_sigaction(sig, info, context);
+ } else {
+ if (old_action->sa_handler == SIG_DFL) {
+ fprintf(stderr, "taking default action for signal %i\n", sig);
+
+#if 1
+ struct sigaction dfl_action;
+ dfl_action.sa_handler = SIG_DFL;
+ sigemptyset (&dfl_action.sa_mask);
+ dfl_action.sa_flags = 0;
+ sigaction(sig, &dfl_action, NULL);
+
+ raise(sig);
+#else
+ raise(SIGKILL);
+#endif
+ } else if (old_action->sa_handler == SIG_IGN) {
+ /* ignore */
+ } else {
+ /* dispatch to handler */
+ old_action->sa_handler(sig);
}
}
}
void
-CatchInterrupts(void (*func)(int))
+SetExceptionCallback(void (*callback)(void))
{
- interrupts.handler = func;
+ assert(!gCallback);
+ if (!gCallback) {
+ gCallback = callback;
- if (!interrupts.set) {
- struct sigaction new_action, old_action;
- new_action.sa_handler = InterruptHandler;
+ struct sigaction new_action;
+ new_action.sa_sigaction = signal_handler;
sigemptyset(&new_action.sa_mask);
- new_action.sa_flags = 0;
-#define SET_IF_NOT_IGNORED(sig, old_handler) \
- do { \
- sigaction(sig, NULL, &old_action); \
- if (old_action.sa_handler != SIG_IGN) { \
- old_handler = old_action.sa_handler; \
- sigaction(sig, &new_action, NULL); \
- } \
- } while (0)
-
- SET_IF_NOT_IGNORED(SIGINT, interrupts.sig_int);
- SET_IF_NOT_IGNORED(SIGHUP, interrupts.sig_hup);
- SET_IF_NOT_IGNORED(SIGTERM, interrupts.sig_term);
- SET_IF_NOT_IGNORED(SIGSEGV, interrupts.sig_segv);
-
- interrupts.set = true;
-#undef SET_IF_NOT_IGNORED
+ new_action.sa_flags = SA_SIGINFO | SA_RESTART;
+
+
+ for (int sig = 1; sig < NUM_SIGNALS; ++sig) {
+ // SIGKILL and SIGSTOP can't be handled
+ if (sig != SIGKILL && sig != SIGSTOP) {
+ if (sigaction(sig, NULL, &old_actions[sig]) >= 0) {
+ sigaction(sig, &new_action, NULL);
+ }
+ }
+ }
}
}
+void
+ResetExceptionCallback(void)
+{
+ gCallback = NULL;
+}
+
} /* namespace OS */
static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter = NULL;
-
-static void (*handler)(int) = NULL;
+static void (*gCallback)(void) = NULL;
static LONG WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
{
- if (handler) {
- int exceptionCode = 0;
- if (pExceptionInfo) {
- PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
- if (pExceptionRecord) {
- exceptionCode = pExceptionRecord->ExceptionCode;
- }
- }
-
- handler(exceptionCode);
+ if (gCallback) {
+ gCallback();
}
if (prevExceptionFilter) {
}
void
-CatchInterrupts(void (*func)(int))
+SetExceptionCallback(void (*callback)(void))
{
- assert(!handler);
- assert(!prevExceptionFilter);
+ assert(!gCallback);
- handler = func;
+ if (!gCallback) {
+ gCallback = callback;
- if (handler && !prevExceptionFilter) {
- prevExceptionFilter =
- SetUnhandledExceptionFilter(UnhandledExceptionFilter);
+ assert(!prevExceptionFilter);
+ prevExceptionFilter = SetUnhandledExceptionFilter(UnhandledExceptionFilter);
}
}
+void
+ResetExceptionCallback(void)
+{
+ gCallback = NULL;
+}
+
} /* namespace OS */
print ' static const Trace::StructSig sig = {'
print ' %u, "%s", %u, members' % (int(struct.id), struct.name, len(struct.members))
print ' };'
- print ' __writer.beginStruct(&sig);'
+ print ' Trace::localWriter.beginStruct(&sig);'
for type, name in struct.members:
dump_instance(type, 'value.%s' % (name,))
- print ' __writer.endStruct();'
+ print ' Trace::localWriter.endStruct();'
print '}'
print
print ' sig = &sig%u;' % i
print ' break;'
print ' default:'
- print ' __writer.writeSInt(value);'
+ print ' Trace::localWriter.writeSInt(value);'
print ' return;'
print ' }'
- print ' __writer.writeEnum(sig);'
+ print ' Trace::localWriter.writeEnum(sig);'
print '}'
print
'''Dump an instance.'''
def visit_literal(self, literal, instance):
- print ' __writer.write%s(%s);' % (literal.format, instance)
+ print ' Trace::localWriter.write%s(%s);' % (literal.format, instance)
def visit_string(self, string, instance):
if string.length is not None:
- print ' __writer.writeString((const char *)%s, %s);' % (instance, string.length)
+ print ' Trace::localWriter.writeString((const char *)%s, %s);' % (instance, string.length)
else:
- print ' __writer.writeString((const char *)%s);' % instance
+ print ' Trace::localWriter.writeString((const char *)%s);' % instance
def visit_const(self, const, instance):
self.visit(const.type, instance)
index = '__i' + array.type.id
print ' if (%s) {' % instance
print ' size_t %s = %s;' % (length, array.length)
- print ' __writer.beginArray(%s);' % length
+ print ' Trace::localWriter.beginArray(%s);' % length
print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
- print ' __writer.beginElement();'
+ print ' Trace::localWriter.beginElement();'
self.visit(array.type, '(%s)[%s]' % (instance, index))
- print ' __writer.endElement();'
+ print ' Trace::localWriter.endElement();'
print ' }'
- print ' __writer.endArray();'
+ print ' Trace::localWriter.endArray();'
print ' } else {'
- print ' __writer.writeNull();'
+ print ' Trace::localWriter.writeNull();'
print ' }'
def visit_blob(self, blob, instance):
- print ' __writer.writeBlob(%s, %s);' % (instance, blob.size)
+ print ' Trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
def visit_enum(self, enum, instance):
print ' __traceEnum%s(%s);' % (enum.id, instance)
def visit_bitmask(self, bitmask, instance):
- print ' __writer.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.id, instance)
+ print ' Trace::localWriter.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.id, instance)
def visit_pointer(self, pointer, instance):
print ' if (%s) {' % instance
- print ' __writer.beginArray(1);'
- print ' __writer.beginElement();'
+ print ' Trace::localWriter.beginArray(1);'
+ print ' Trace::localWriter.beginElement();'
dump_instance(pointer.type, "*" + instance)
- print ' __writer.endElement();'
- print ' __writer.endArray();'
+ print ' Trace::localWriter.endElement();'
+ print ' Trace::localWriter.endArray();'
print ' } else {'
- print ' __writer.writeNull();'
+ print ' Trace::localWriter.writeNull();'
print ' }'
def visit_handle(self, handle, instance):
self.visit(alias.type, instance)
def visit_opaque(self, opaque, instance):
- print ' __writer.writeOpaque((const void *)%s);' % instance
+ print ' Trace::localWriter.writeOpaque((const void *)%s);' % instance
def visit_interface(self, interface, instance):
- print ' __writer.writeOpaque((const void *)&%s);' % instance
+ print ' Trace::localWriter.writeOpaque((const void *)&%s);' % instance
dump_instance = DumpImplementer().visit
self.footer(api)
def header(self, api):
- print 'Trace::LocalWriter __writer;'
- print
+ pass
def footer(self, api):
pass
print
def trace_function_impl_body(self, function):
- print ' unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
+ print ' unsigned __call = Trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
for arg in function.args:
if not arg.output:
self.unwrap_arg(function, arg)
self.dump_arg(function, arg)
- print ' __writer.endEnter();'
+ print ' Trace::localWriter.endEnter();'
self.dispatch_function(function)
- print ' __writer.beginLeave(__call);'
+ print ' Trace::localWriter.beginLeave(__call);'
for arg in function.args:
if arg.output:
self.dump_arg(function, arg)
self.wrap_arg(function, arg)
if function.type is not stdapi.Void:
self.dump_ret(function, "__result")
- print ' __writer.endLeave();'
+ print ' Trace::localWriter.endLeave();'
def dispatch_function(self, function):
if function.type is stdapi.Void:
print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
def dump_arg(self, function, arg):
- print ' __writer.beginArg(%u);' % (arg.index,)
+ print ' Trace::localWriter.beginArg(%u);' % (arg.index,)
self.dump_arg_instance(function, arg)
- print ' __writer.endArg();'
+ print ' Trace::localWriter.endArg();'
def dump_arg_instance(self, function, arg):
dump_instance(arg.type, arg.name)
unwrap_instance(arg.type, arg.name)
def dump_ret(self, function, instance):
- print ' __writer.beginReturn();'
+ print ' Trace::localWriter.beginReturn();'
dump_instance(function.type, instance)
- print ' __writer.endReturn();'
+ print ' Trace::localWriter.endReturn();'
def wrap_ret(self, function, instance):
wrap_instance(function.type, instance)
print method.prototype(interface_wrap_name(interface) + '::' + method.name) + ' {'
print ' static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
print ' static const Trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (int(method.id), interface.name + '::' + method.name, len(method.args) + 1)
- print ' unsigned __call = __writer.beginEnter(&__sig);'
- print ' __writer.beginArg(0);'
- print ' __writer.writeOpaque((const void *)m_pInstance);'
- print ' __writer.endArg();'
+ print ' unsigned __call = Trace::localWriter.beginEnter(&__sig);'
+ print ' Trace::localWriter.beginArg(0);'
+ print ' Trace::localWriter.writeOpaque((const void *)m_pInstance);'
+ print ' Trace::localWriter.endArg();'
for arg in method.args:
if not arg.output:
self.unwrap_arg(method, arg)
else:
print ' %s __result;' % method.type
result = '__result = '
- print ' __writer.endEnter();'
+ print ' Trace::localWriter.endEnter();'
print ' %sm_pInstance->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
- print ' __writer.beginLeave(__call);'
+ print ' Trace::localWriter.beginLeave(__call);'
for arg in method.args:
if arg.output:
self.dump_arg(method, arg)
self.wrap_arg(method, arg)
if method.type is not stdapi.Void:
- print ' __writer.beginReturn();'
+ print ' Trace::localWriter.beginReturn();'
dump_instance(method.type, "__result")
- print ' __writer.endReturn();'
+ print ' Trace::localWriter.endReturn();'
wrap_instance(method.type, '__result')
- print ' __writer.endLeave();'
+ print ' Trace::localWriter.endLeave();'
if method.name == 'QueryInterface':
print ' if (ppvObj && *ppvObj) {'
print ' if (*ppvObj == m_pInstance) {'
#include "os.hpp"
#include <iostream>
-#include <set>
using namespace Trace;
#define SNAPPY_BYTE1 'a'
#define SNAPPY_BYTE2 't'
-static void cleanupHandler(int sig);
-
-class FileCleanup
-{
-public:
- FileCleanup()
- {
- OS::CatchInterrupts(cleanupHandler);
- }
-
- ~FileCleanup()
- {
- flush();
- m_files.clear();
- }
-
- void addFile(Trace::File *file)
- {
- m_files.insert(file);
- }
- void removeFile(Trace::File *file)
- {
- m_files.erase(file);
- }
-
- void flush()
- {
- std::set<Trace::File*>::const_iterator itr;
- for (itr = m_files.begin(); itr != m_files.end(); ++itr) {
- (*itr)->flush(File::FlushDeep);
- }
- }
-
-private:
- std::set<Trace::File*> m_files;
-};
-static FileCleanup s_cleaner;
-
-static void cleanupHandler(int sig)
-{
- s_cleaner.flush();
-}
-
File::File(const std::string &filename,
File::Mode mode)
: m_filename(filename),
m_isOpened = rawOpen(filename, mode);
m_mode = mode;
- if (m_isOpened) {
- s_cleaner.addFile(this);
- }
return m_isOpened;
}
if (m_isOpened) {
rawClose();
m_isOpened = false;
- s_cleaner.removeFile(this);
}
}
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2007-2011 VMware, Inc.
+ * 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 THE
+ * AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "os.hpp"
+#include "trace_file.hpp"
+#include "trace_writer.hpp"
+#include "trace_format.hpp"
+
+
+namespace Trace {
+
+
+static void exceptionCallback(void)
+{
+ OS::DebugMessage("apitrace: flushing trace due to an exception\n");
+ localWriter.flush();
+}
+
+
+LocalWriter::LocalWriter() :
+ acquired(0)
+{}
+
+LocalWriter::~LocalWriter()
+{
+ OS::ResetExceptionCallback();
+}
+
+void
+LocalWriter::open(void) {
+
+ static unsigned dwCounter = 0;
+
+ const char *szExtension = "trace";
+ char szFileName[PATH_MAX];
+ const char *lpFileName;
+
+ lpFileName = getenv("TRACE_FILE");
+ if (lpFileName) {
+ strncpy(szFileName, lpFileName, PATH_MAX);
+ }
+ else {
+ char szProcessName[PATH_MAX];
+ char szCurrentDir[PATH_MAX];
+ OS::GetProcessName(szProcessName, PATH_MAX);
+ OS::GetCurrentDir(szCurrentDir, PATH_MAX);
+
+ for (;;) {
+ FILE *file;
+
+ if (dwCounter)
+ snprintf(szFileName, PATH_MAX, "%s%c%s.%u.%s", szCurrentDir, PATH_SEP, szProcessName, dwCounter, szExtension);
+ else
+ snprintf(szFileName, PATH_MAX, "%s%c%s.%s", szCurrentDir, PATH_SEP, szProcessName, szExtension);
+
+ file = fopen(szFileName, "rb");
+ if (file == NULL)
+ break;
+
+ fclose(file);
+
+ ++dwCounter;
+ }
+ }
+
+ OS::DebugMessage("apitrace: tracing to %s\n", szFileName);
+
+ Writer::open(szFileName);
+
+ OS::SetExceptionCallback(exceptionCallback);
+
+#if 0
+ // For debugging the exception handler
+ *((int *)0) = 0;
+#endif
+}
+
+unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
+ OS::AcquireMutex();
+ ++acquired;
+
+ if (!m_file->isOpened()) {
+ open();
+ }
+
+ return Writer::beginEnter(sig);
+}
+
+void LocalWriter::endEnter(void) {
+ Writer::endEnter();
+ --acquired;
+ OS::ReleaseMutex();
+}
+
+void LocalWriter::beginLeave(unsigned call) {
+ OS::AcquireMutex();
+ ++acquired;
+ Writer::beginLeave(call);
+}
+
+void LocalWriter::endLeave(void) {
+ Writer::endLeave();
+ --acquired;
+ OS::ReleaseMutex();
+}
+
+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.
+ */
+
+ if (!acquired) {
+ OS::AcquireMutex();
+ if (m_file->isOpened()) {
+ m_file->flush();
+ }
+ OS::ReleaseMutex();
+ }
+}
+
+
+LocalWriter localWriter;
+
+
+} /* namespace Trace */
+
}
-void
-LocalWriter::open(void) {
-
- static unsigned dwCounter = 0;
-
- const char *szExtension = "trace";
- char szFileName[PATH_MAX];
- const char *lpFileName;
-
- lpFileName = getenv("TRACE_FILE");
- if (lpFileName) {
- strncpy(szFileName, lpFileName, PATH_MAX);
- }
- else {
- char szProcessName[PATH_MAX];
- char szCurrentDir[PATH_MAX];
- OS::GetProcessName(szProcessName, PATH_MAX);
- OS::GetCurrentDir(szCurrentDir, PATH_MAX);
-
- for (;;) {
- FILE *file;
-
- if (dwCounter)
- snprintf(szFileName, PATH_MAX, "%s%c%s.%u.%s", szCurrentDir, PATH_SEP, szProcessName, dwCounter, szExtension);
- else
- snprintf(szFileName, PATH_MAX, "%s%c%s.%s", szCurrentDir, PATH_SEP, szProcessName, szExtension);
-
- file = fopen(szFileName, "rb");
- if (file == NULL)
- break;
-
- fclose(file);
-
- ++dwCounter;
- }
- }
-
- OS::DebugMessage("apitrace: tracing to %s\n", szFileName);
-
- Writer::open(szFileName);
-}
-
-unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
- OS::AcquireMutex();
-
- if (!m_file->isOpened()) {
- open();
- }
-
- return Writer::beginEnter(sig);
-}
-
-void LocalWriter::endEnter(void) {
- Writer::endEnter();
- OS::ReleaseMutex();
-}
-
-void LocalWriter::beginLeave(unsigned call) {
- OS::AcquireMutex();
- Writer::beginLeave(call);
-}
-
-void LocalWriter::endLeave(void) {
- Writer::endLeave();
- m_file->flush();
- OS::ReleaseMutex();
-}
-
-
} /* namespace Trace */
*/
class LocalWriter : public Writer {
protected:
+ int acquired;
+
public:
+ /**
+ * Should never called directly -- use localWriter singleton below instead.
+ */
+ LocalWriter();
+ ~LocalWriter();
+
void open(void);
unsigned beginEnter(const FunctionSig *sig);
void beginLeave(unsigned call);
void endLeave(void);
+
+ void flush(void);
};
+
+ /**
+ * Singleton.
+ */
+ extern LocalWriter localWriter;
}
#endif /* _TRACE_WRITER_HPP_ */