1/* 2 * Copyright 2003-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "DebugSupport.h" 8 9#include <errno.h> 10#include <fcntl.h> 11#include <stdarg.h> 12#include <stdio.h> 13#include <string.h> 14#include <unistd.h> 15 16#include <OS.h> 17 18 19/*! 20 \file Debug.cpp 21 \brief Defines debug output function with printf() signature printing 22 into a file. 23 24 \note The initialization is not thread safe! 25*/ 26 27 28// locking support 29static int32 init_counter = 0; 30static sem_id dbg_printf_sem = -1; 31static thread_id dbg_printf_thread = -1; 32static int dbg_printf_nesting = 0; 33 34 35#if DEBUG_PRINT 36static int out = -1; 37#endif 38 39 40status_t 41init_debugging() 42{ 43 status_t error = B_OK; 44 if (init_counter++ == 0) { 45 // open the file 46 #if DEBUG_PRINT 47 out = open(DEBUG_PRINT_FILE, O_RDWR | O_CREAT | O_TRUNC); 48 if (out < 0) { 49 error = errno; 50 init_counter--; 51 } 52 #endif // DEBUG_PRINT 53 // 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(__i386__) && 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