1// Debug.cpp 2// 3// Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de) 4// 5// This program is free software; you can redistribute it and/or modify 6// it under the terms of the GNU General Public License as published by 7// the Free Software Foundation; either version 2 of the License, or 8// (at your option) any later version. 9// 10// This program is distributed in the hope that it will be useful, 11// but WITHOUT ANY WARRANTY; without even the implied warranty of 12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13// GNU General Public License for more details. 14// 15// You should have received a copy of the GNU General Public License 16// along with this program; if not, write to the Free Software 17// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18// 19// You can alternatively use *this file* under the terms of the the MIT 20// license included in this package. 21 22#include <errno.h> 23#include <fcntl.h> 24#include <stdarg.h> 25#include <stdio.h> 26#include <string.h> 27#include <unistd.h> 28 29#include <OS.h> 30 31#include "Debug.h" 32 33/*! 34 \file Debug.cpp 35 \brief Defines debug output function with printf() signature printing 36 into a file. 37 38 \note The initialization is not thread safe! 39*/ 40 41// no need to define it, if not used 42#if DEBUG_PRINT 43 44static int32 init_counter = 0; 45static int out = -1; 46static sem_id dbg_printf_sem = -1; 47static thread_id dbg_printf_thread = -1; 48static int dbg_printf_nesting = 0; 49 50// init_debugging 51status_t 52init_debugging() 53{ 54 status_t error = B_OK; 55 if (init_counter++ == 0) { 56 // open the file 57 out = open(DEBUG_PRINT_FILE, O_RDWR | O_CREAT | O_TRUNC); 58 if (out < 0) { 59 error = errno; 60 init_counter--; 61 } else { 62 dbg_printf("##################################################\n"); 63 dbg_printf_sem = create_sem(1, "dbg_printf"); 64 } 65 } 66 return error; 67} 68 69// exit_debugging 70status_t 71exit_debugging() 72{ 73 status_t error = B_OK; 74 if (out >= 0) { 75 if (--init_counter == 0) { 76 close(out); 77 out = -1; 78 delete_sem(dbg_printf_sem); 79 } 80 } else 81 error = B_NO_INIT; 82 return error; 83} 84 85// dbg_printf_lock 86static inline 87bool 88dbg_printf_lock() 89{ 90 thread_id thread = find_thread(NULL); 91 if (thread != dbg_printf_thread) { 92 if (acquire_sem(dbg_printf_sem) != B_OK) 93 return false; 94 dbg_printf_thread = thread; 95 } 96 dbg_printf_nesting++; 97 return true; 98} 99 100// dbg_printf_unlock 101static inline 102void 103dbg_printf_unlock() 104{ 105 thread_id thread = find_thread(NULL); 106 if (thread != dbg_printf_thread) 107 return; 108 dbg_printf_nesting--; 109 if (dbg_printf_nesting == 0) { 110 dbg_printf_thread = -1; 111 release_sem(dbg_printf_sem); 112 } 113} 114 115// dbg_printf 116void 117dbg_printf(const char *format,...) 118{ 119 if (!dbg_printf_lock()) 120 return; 121 char buffer[1024]; 122 va_list args; 123 va_start(args, format); 124 // no vsnprintf() on PPC and in kernel 125 #if defined(__INTEL__) && USER 126 vsnprintf(buffer, sizeof(buffer) - 1, format, args); 127 #else 128 vsprintf(buffer, format, args); 129 #endif 130 va_end(args); 131 buffer[sizeof(buffer) - 1] = '\0'; 132 write(out, buffer, strlen(buffer)); 133 dbg_printf_unlock(); 134} 135 136// dbg_printf_begin 137void 138dbg_printf_begin() 139{ 140 dbg_printf_lock(); 141} 142 143// dbg_printf_end 144void 145dbg_printf_end() 146{ 147 dbg_printf_unlock(); 148} 149 150#endif // DEBUG_PRINT 151