1 /* 2 * Copyright 2003-2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * IngoWeinhold <bonefish@cs.tu-berlin.de> 7 */ 8 9 #include "Debug.h" 10 11 #include <errno.h> 12 #include <fcntl.h> 13 #include <stdarg.h> 14 #include <stdio.h> 15 #include <string.h> 16 #include <unistd.h> 17 18 #include <OS.h> 19 20 /*! 21 \file Debug.cpp 22 \brief Defines debug output function with printf() signature printing 23 into a file. 24 25 \note The initialization is not thread safe! 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 #if DEBUG_PRINT 35 static int out = -1; 36 #endif 37 38 // init_debugging 39 status_t 40 init_debugging() 41 { 42 status_t error = B_OK; 43 if (init_counter++ == 0) { 44 // open the file 45 #if DEBUG_PRINT 46 out = open(DEBUG_PRINT_FILE, O_RDWR | O_CREAT | O_TRUNC); 47 if (out < 0) { 48 error = errno; 49 init_counter--; 50 } 51 #endif // DEBUG_PRINT 52 // allocate the semaphore 53 if (error == B_OK) { 54 dbg_printf_sem = create_sem(1, "dbg_printf"); 55 if (dbg_printf_sem < 0) 56 error = dbg_printf_sem; 57 } 58 if (error == B_OK) { 59 #if DEBUG 60 __out("##################################################\n"); 61 #endif 62 } else 63 exit_debugging(); 64 } 65 return error; 66 } 67 68 // exit_debugging 69 status_t 70 exit_debugging() 71 { 72 status_t error = B_OK; 73 if (--init_counter == 0) { 74 #if DEBUG_PRINT 75 close(out); 76 out = -1; 77 #endif // DEBUG_PRINT 78 delete_sem(dbg_printf_sem); 79 } else 80 error = B_NO_INIT; 81 return error; 82 } 83 84 // dbg_printf_lock 85 static inline 86 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 // dbg_printf_unlock 100 static inline 101 void 102 dbg_printf_unlock() 103 { 104 thread_id thread = find_thread(NULL); 105 if (thread != dbg_printf_thread) 106 return; 107 dbg_printf_nesting--; 108 if (dbg_printf_nesting == 0) { 109 dbg_printf_thread = -1; 110 release_sem(dbg_printf_sem); 111 } 112 } 113 114 // dbg_printf_begin 115 void 116 dbg_printf_begin() 117 { 118 dbg_printf_lock(); 119 } 120 121 // dbg_printf_end 122 void 123 dbg_printf_end() 124 { 125 dbg_printf_unlock(); 126 } 127 128 #if DEBUG_PRINT 129 130 // dbg_printf 131 void 132 dbg_printf(const char *format,...) 133 { 134 if (!dbg_printf_lock()) 135 return; 136 char buffer[1024]; 137 va_list args; 138 va_start(args, format); 139 // no vsnprintf() on PPC and in kernel 140 #if defined(__i386__) && USER 141 vsnprintf(buffer, sizeof(buffer) - 1, format, args); 142 #else 143 vsprintf(buffer, format, args); 144 #endif 145 va_end(args); 146 buffer[sizeof(buffer) - 1] = '\0'; 147 write(out, buffer, strlen(buffer)); 148 dbg_printf_unlock(); 149 } 150 151 #endif // DEBUG_PRINT 152