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
init_debugging()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
exit_debugging()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
dbg_printf_lock()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
dbg_printf_unlock()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
dbg_printf_begin()115 dbg_printf_begin()
116 {
117 dbg_printf_lock();
118 }
119
120
121 void
dbg_printf_end()122 dbg_printf_end()
123 {
124 dbg_printf_unlock();
125 }
126
127
128 #if DEBUG_PRINT
129
130 void
dbg_printf(const char * format,...)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(__i386__) && 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