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