diff --git a/src/add-ons/kernel/file_systems/packagefs/DebugSupport.cpp b/src/add-ons/kernel/file_systems/packagefs/DebugSupport.cpp new file mode 100644 index 0000000000..8377cf340c --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/DebugSupport.cpp @@ -0,0 +1,150 @@ +/* + * Copyright 2003-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "DebugSupport.h" + +#include +#include +#include +#include +#include +#include + +#include + + +/*! + \file Debug.cpp + \brief Defines debug output function with printf() signature printing + into a file. + + \note The initialization is not thread safe! +*/ + + +// locking support +static int32 init_counter = 0; +static sem_id dbg_printf_sem = -1; +static thread_id dbg_printf_thread = -1; +static int dbg_printf_nesting = 0; + + +#if DEBUG_PRINT +static int out = -1; +#endif + + +status_t +init_debugging() +{ + status_t error = B_OK; + if (init_counter++ == 0) { + // open the file + #if DEBUG_PRINT + out = open(DEBUG_PRINT_FILE, O_RDWR | O_CREAT | O_TRUNC); + if (out < 0) { + error = errno; + init_counter--; + } + #endif // DEBUG_PRINT + // allocate the semaphore + if (error == B_OK) { + dbg_printf_sem = create_sem(1, "dbg_printf"); + if (dbg_printf_sem < 0) + error = dbg_printf_sem; + } + if (error == B_OK) { + #if DEBUG + __out("##################################################\n"); + #endif + } else + exit_debugging(); + } + return error; +} + + +status_t +exit_debugging() +{ + status_t error = B_OK; + if (--init_counter == 0) { + #if DEBUG_PRINT + close(out); + out = -1; + #endif // DEBUG_PRINT + delete_sem(dbg_printf_sem); + } else + error = B_NO_INIT; + return error; +} + + +static inline bool +dbg_printf_lock() +{ + thread_id thread = find_thread(NULL); + if (thread != dbg_printf_thread) { + if (acquire_sem(dbg_printf_sem) != B_OK) + return false; + dbg_printf_thread = thread; + } + dbg_printf_nesting++; + return true; +} + + +static inline void +dbg_printf_unlock() +{ + thread_id thread = find_thread(NULL); + if (thread != dbg_printf_thread) + return; + dbg_printf_nesting--; + if (dbg_printf_nesting == 0) { + dbg_printf_thread = -1; + release_sem(dbg_printf_sem); + } +} + + +void +dbg_printf_begin() +{ + dbg_printf_lock(); +} + + +void +dbg_printf_end() +{ + dbg_printf_unlock(); +} + + +#if DEBUG_PRINT + +void +dbg_printf(const char *format,...) +{ + if (!dbg_printf_lock()) + return; + char buffer[1024]; + va_list args; + va_start(args, format); + // no vsnprintf() on PPC and in kernel + #if defined(__INTEL__) && USER + vsnprintf(buffer, sizeof(buffer) - 1, format, args); + #else + vsprintf(buffer, format, args); + #endif + va_end(args); + buffer[sizeof(buffer) - 1] = '\0'; + write(out, buffer, strlen(buffer)); + dbg_printf_unlock(); +} + +#endif // DEBUG_PRINT diff --git a/src/add-ons/kernel/file_systems/packagefs/DebugSupport.h b/src/add-ons/kernel/file_systems/packagefs/DebugSupport.h new file mode 100644 index 0000000000..76987397c6 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/DebugSupport.h @@ -0,0 +1,146 @@ +/* + * Copyright 2003-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 200?, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DEBUG_SUPPORT_H +#define DEBUG_SUPPORT_H + + +#include + + +#if !USER +# include +#endif +#include +#include + + +// define all macros we work with -- undefined macros are set to defaults +#ifndef USER +# define USER 0 +#endif +#ifndef DEBUG +# define DEBUG 0 +#endif +#if !DEBUG +# undef DEBUG_PRINT +# define DEBUG_PRINT 0 +#endif +#ifndef DEBUG_PRINT +# define DEBUG_PRINT 0 +#endif +#ifndef DEBUG_APP +# define DEBUG_APP "packagefs" +#endif +#ifndef DEBUG_PRINT_FILE +# define DEBUG_PRINT_FILE "/var/log/" DEBUG_APP ".log" +#endif + + +// define the debug output function +#if USER +# include +# if DEBUG_PRINT +# define __out dbg_printf +# else +# define __out printf +# endif +#else +# include +# include +# if DEBUG_PRINT +# define __out dbg_printf +# else +# define __out dprintf +# endif +#endif + + +// define the PANIC() macro +#ifndef PANIC +# if USER +# define PANIC(str) debugger(str) +# else +# define PANIC(str) panic(str) +# endif +#endif + + +// functions exported by this module +status_t init_debugging(); +status_t exit_debugging(); +void dbg_printf_begin(); +void dbg_printf_end(); +#if DEBUG_PRINT + void dbg_printf(const char *format,...); +#else + static inline void dbg_printf(const char *,...) {} +#endif + + +// Short overview over the debug output macros: +// PRINT() +// is for general messages that very unlikely should appear in a release build +// FATAL() +// this is for fatal messages, when something has really gone wrong +// INFORM() +// general information, as disk size, etc. +// REPORT_ERROR(status_t) +// prints out error information +// RETURN_ERROR(status_t) +// calls REPORT_ERROR() and return the value +// D() +// the statements in D() are only included if DEBUG is defined + + +#define DEBUG_THREAD find_thread(NULL) +#define DEBUG_CONTEXT(x) { dbg_printf_begin(); __out(DEBUG_APP " [%Ld: %5ld] ", system_time(), DEBUG_THREAD); x; dbg_printf_end(); } +#define DEBUG_CONTEXT_FUNCTION(prefix, x) { dbg_printf_begin(); __out(DEBUG_APP " [%Ld: %5ld] %s()" prefix, system_time(), DEBUG_THREAD, __FUNCTION__); x; dbg_printf_end(); } +#define DEBUG_CONTEXT_LINE(x) { dbg_printf_begin(); __out(DEBUG_APP " [%Ld: %5ld] %s():%d: ", system_time(), DEBUG_THREAD, __FUNCTION__, __LINE__); x; dbg_printf_end(); } + +#define TPRINT(x...) DEBUG_CONTEXT( __out(x) ) +#define TREPORT_ERROR(status) DEBUG_CONTEXT_LINE( __out("%s\n", strerror(status)) ) +#define TRETURN_ERROR(err) { status_t _status = err; if (_status < B_OK) TREPORT_ERROR(_status); return _status;} +#define TSET_ERROR(var, err) { status_t _status = err; if (_status < B_OK) TREPORT_ERROR(_status); var = _status; } +#define TFUNCTION(x...) DEBUG_CONTEXT_FUNCTION( ": ", __out(x) ) +#define TFUNCTION_START() DEBUG_CONTEXT_FUNCTION( "\n", ) +#define TFUNCTION_END() DEBUG_CONTEXT_FUNCTION( " done\n", ) + +#if DEBUG + #define PRINT(x...) TPRINT(x) + #define REPORT_ERROR(status) TREPORT_ERROR(status) + #define RETURN_ERROR(err) TRETURN_ERROR(err) + #define SET_ERROR(var, err) TSET_ERROR(var, err) + #define FATAL(x...) DEBUG_CONTEXT( __out(x) ) + #define ERROR(x...) DEBUG_CONTEXT( __out(x) ) + #define WARN(x...) DEBUG_CONTEXT( __out(x) ) + #define INFORM(x...) DEBUG_CONTEXT( __out(x) ) + #define FUNCTION(x...) TFUNCTION(x) + #define FUNCTION_START() TFUNCTION_START() + #define FUNCTION_END() TFUNCTION_END() + #define DARG(x) x + #define D(x) {x;}; +#else + #define PRINT(x...) ; + #define REPORT_ERROR(status) ; + #define RETURN_ERROR(status) return status; + #define SET_ERROR(var, err) var = err; + #define FATAL(x...) DEBUG_CONTEXT( __out(x) ) + #define ERROR(x...) DEBUG_CONTEXT( __out(x) ) + #define WARN(x...) DEBUG_CONTEXT( __out(x) ) + #define INFORM(x...) DEBUG_CONTEXT( __out(x) ) + #define FUNCTION(x...) ; + #define FUNCTION_START() ; + #define FUNCTION_END() ; + #define DARG(x) + #define D(x) ; +#endif + +#ifndef TOUCH +#define TOUCH(var) (void)var +#endif + + +#endif // DEBUG_SUPPORT_H