xref: /haiku/src/add-ons/kernel/file_systems/userlandfs/shared/Debug.cpp (revision 1acbe440b8dd798953bec31d18ee589aa3f71b73)
1 // Debug.cpp
2 //
3 // Copyright (c) 2003-2004, Ingo Weinhold (bonefish@cs.tu-berlin.de)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
22 //
23 // Except as contained in this notice, the name of a copyright holder shall
24 // not be used in advertising or otherwise to promote the sale, use or other
25 // dealings in this Software without prior written authorization of the
26 // copyright holder.
27 
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <unistd.h>
34 
35 #include <OS.h>
36 
37 #include "Debug.h"
38 
39 /*!
40 	\file Debug.cpp
41 	\brief Defines debug output function with printf() signature printing
42 		   into a file.
43 
44 	\note The initialization is not thread safe!
45 */
46 
47 // locking support
48 static int32 init_counter = 0;
49 static sem_id dbg_printf_sem = -1;
50 static thread_id dbg_printf_thread = -1;
51 static int dbg_printf_nesting = 0;
52 
53 #if DEBUG_PRINT
54 static int out = -1;
55 #endif
56 
57 // init_debugging
58 status_t
59 init_debugging()
60 {
61 	status_t error = B_OK;
62 	if (init_counter++ == 0) {
63 		// open the file
64 		#if DEBUG_PRINT
65 			out = open(DEBUG_PRINT_FILE, O_RDWR | O_CREAT | O_TRUNC);
66 			if (out < 0) {
67 				error = errno;
68 				init_counter--;
69 			}
70 		#endif	// DEBUG_PRINT
71 		// allocate the semaphore
72 		if (error == B_OK) {
73 			dbg_printf_sem = create_sem(1, "dbg_printf");
74 			if (dbg_printf_sem < 0)
75 				error = dbg_printf_sem;
76 		}
77 		if (error == B_OK) {
78 			#if DEBUG
79 				__out("##################################################\n");
80 			#endif
81 		} else
82 			exit_debugging();
83 	}
84 	return error;
85 }
86 
87 // exit_debugging
88 status_t
89 exit_debugging()
90 {
91 	status_t error = B_OK;
92 	if (--init_counter == 0) {
93 		#if DEBUG_PRINT
94 			close(out);
95 			out = -1;
96 		#endif	// DEBUG_PRINT
97 		delete_sem(dbg_printf_sem);
98 	} else
99 		error = B_NO_INIT;
100 	return error;
101 }
102 
103 // dbg_printf_lock
104 static inline
105 bool
106 dbg_printf_lock()
107 {
108 	thread_id thread = find_thread(NULL);
109 	if (thread != dbg_printf_thread) {
110 		if (acquire_sem(dbg_printf_sem) != B_OK)
111 			return false;
112 		dbg_printf_thread = thread;
113 	}
114 	dbg_printf_nesting++;
115 	return true;
116 }
117 
118 // dbg_printf_unlock
119 static inline
120 void
121 dbg_printf_unlock()
122 {
123 	thread_id thread = find_thread(NULL);
124 	if (thread != dbg_printf_thread)
125 		return;
126 	dbg_printf_nesting--;
127 	if (dbg_printf_nesting == 0) {
128 		dbg_printf_thread = -1;
129 		release_sem(dbg_printf_sem);
130 	}
131 }
132 
133 // dbg_printf_begin
134 void
135 dbg_printf_begin()
136 {
137 	dbg_printf_lock();
138 }
139 
140 // dbg_printf_end
141 void
142 dbg_printf_end()
143 {
144 	dbg_printf_unlock();
145 }
146 
147 #if DEBUG_PRINT
148 
149 // dbg_printf
150 void
151 dbg_printf(const char *format,...)
152 {
153 	if (!dbg_printf_lock())
154 		return;
155 	char buffer[1024];
156 	va_list args;
157 	va_start(args, format);
158 	// no vsnprintf() on PPC and in kernel
159 	#if defined(__INTEL__) && USER
160 		vsnprintf(buffer, sizeof(buffer) - 1, format, args);
161 	#else
162 		vsprintf(buffer, format, args);
163 	#endif
164 	va_end(args);
165 	buffer[sizeof(buffer) - 1] = '\0';
166 	write(out, buffer, strlen(buffer));
167 	dbg_printf_unlock();
168 }
169 
170 #endif	// DEBUG_PRINT
171