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 29 static int32 init_counter = 0; 30 static sem_id dbg_printf_sem = -1; 31 static thread_id dbg_printf_thread = -1; 32 static int dbg_printf_nesting = 0; 33 34 35 #if DEBUG_PRINT 36 static int out = -1; 37 #endif 38 39 40 status_t 41 init_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 70 status_t 71 exit_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 86 static inline bool 87 dbg_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 100 static inline void 101 dbg_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 114 void 115 dbg_printf_begin() 116 { 117 dbg_printf_lock(); 118 } 119 120 121 void 122 dbg_printf_end() 123 { 124 dbg_printf_unlock(); 125 } 126 127 128 #if DEBUG_PRINT 129 130 void 131 dbg_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