1351290Sdim/* 2351290Sdim * Copyright 2003-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3351290Sdim * Distributed under the terms of the MIT License. 4351290Sdim */ 5351290Sdim 6351290Sdim 7351290Sdim#include "DebugSupport.h" 8351290Sdim 9351290Sdim#include <errno.h> 10351290Sdim#include <fcntl.h> 11351290Sdim#include <stdarg.h> 12351290Sdim#include <stdio.h> 13351290Sdim#include <string.h> 14351290Sdim#include <unistd.h> 15351290Sdim 16351290Sdim#include <OS.h> 17351290Sdim 18351290Sdim 19351290Sdim/*! 20351290Sdim \file DebugSupport.cpp 21351290Sdim \brief Defines debug output function with printf() signature printing 22351290Sdim into a file. 23351290Sdim 24351290Sdim \note The initialization is not thread safe! 25351290Sdim*/ 26351290Sdim 27351290Sdim 28351290Sdim// locking support 29351290Sdimstatic int32 init_counter = 0; 30351290Sdimstatic sem_id dbg_printf_sem = -1; 31351290Sdimstatic thread_id dbg_printf_thread = -1; 32351290Sdimstatic int dbg_printf_nesting = 0; 33351290Sdim 34351290Sdim 35351290Sdim#if DEBUG_PRINT 36351290Sdimstatic int out = -1; 37351290Sdim#endif 38351290Sdim 39351290Sdim 40360784Sdimstatus_t 41360784Sdiminit_debugging() 42360784Sdim{ 43360784Sdim status_t error = B_OK; 44360784Sdim if (init_counter++ == 0) { 45360784Sdim // open the file 46360784Sdim #if DEBUG_PRINT 47351290Sdim out = open(DEBUG_PRINT_FILE, O_RDWR | O_CREAT | O_TRUNC); 48351290Sdim if (out < 0) { 49351290Sdim error = errno; 50351290Sdim init_counter--; 51351290Sdim } 52351290Sdim #endif // DEBUG_PRINT 53351290Sdim // allocate the semaphore 54 if (error == B_OK) { 55 dbg_printf_sem = create_sem(1, "dbg_printf"); 56 if (dbg_printf_sem < 0) 57 error = dbg_printf_sem; 58 } 59 if (error == B_OK) { 60 #if DEBUG 61 __out("##################################################\n"); 62 #endif 63 } else 64 exit_debugging(); 65 } 66 return error; 67} 68 69 70status_t 71exit_debugging() 72{ 73 status_t error = B_OK; 74 if (--init_counter == 0) { 75 #if DEBUG_PRINT 76 close(out); 77 out = -1; 78 #endif // DEBUG_PRINT 79 delete_sem(dbg_printf_sem); 80 } else 81 error = B_NO_INIT; 82 return error; 83} 84 85 86static inline bool 87dbg_printf_lock() 88{ 89 thread_id thread = find_thread(NULL); 90 if (thread != dbg_printf_thread) { 91 if (acquire_sem(dbg_printf_sem) != B_OK) 92 return false; 93 dbg_printf_thread = thread; 94 } 95 dbg_printf_nesting++; 96 return true; 97} 98 99 100static inline void 101dbg_printf_unlock() 102{ 103 thread_id thread = find_thread(NULL); 104 if (thread != dbg_printf_thread) 105 return; 106 dbg_printf_nesting--; 107 if (dbg_printf_nesting == 0) { 108 dbg_printf_thread = -1; 109 release_sem(dbg_printf_sem); 110 } 111} 112 113 114void 115dbg_printf_begin() 116{ 117 dbg_printf_lock(); 118} 119 120 121void 122dbg_printf_end() 123{ 124 dbg_printf_unlock(); 125} 126 127 128#if DEBUG_PRINT 129 130void 131dbg_printf(const char *format,...) 132{ 133 if (!dbg_printf_lock()) 134 return; 135 char buffer[1024]; 136 va_list args; 137 va_start(args, format); 138 // no vsnprintf() on PPC and in kernel 139 #if defined(__INTEL__) && USER 140 vsnprintf(buffer, sizeof(buffer) - 1, format, args); 141 #else 142 vsprintf(buffer, format, args); 143 #endif 144 va_end(args); 145 buffer[sizeof(buffer) - 1] = '\0'; 146 write(out, buffer, strlen(buffer)); 147 dbg_printf_unlock(); 148} 149 150#endif // DEBUG_PRINT 151