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 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#if DEBUG_PRINT 35static int out = -1; 36#endif 37 38// init_debugging 39status_t 40init_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 69status_t 70exit_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 85static inline 86bool 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// dbg_printf_unlock 100static inline 101void 102dbg_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 115void 116dbg_printf_begin() 117{ 118 dbg_printf_lock(); 119} 120 121// dbg_printf_end 122void 123dbg_printf_end() 124{ 125 dbg_printf_unlock(); 126} 127 128#if DEBUG_PRINT 129 130// dbg_printf 131void 132dbg_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