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