1/*
2 * Copyright 2003-2013, 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#ifdef __HAIKU__
17
18#include <OS.h>
19
20
21/*!
22	\file Debug.cpp
23	\brief Defines debug output function with printf() signature printing
24		   into a file.
25
26	\note The initialization is not thread safe!
27*/
28
29
30// locking support
31static int32 init_counter = 0;
32static sem_id dbg_printf_sem = -1;
33static thread_id dbg_printf_thread = -1;
34static int dbg_printf_nesting = 0;
35
36
37#if DEBUG_PRINT
38static int out = -1;
39#endif
40
41
42status_t
43init_debugging()
44{
45	status_t error = B_OK;
46	if (init_counter++ == 0) {
47		// open the file
48		#if DEBUG_PRINT
49			out = open(DEBUG_PRINT_FILE, O_RDWR | O_CREAT | O_TRUNC);
50			if (out < 0) {
51				error = errno;
52				init_counter--;
53			}
54		#endif	// DEBUG_PRINT
55		// allocate the semaphore
56		if (error == B_OK) {
57			dbg_printf_sem = create_sem(1, "dbg_printf");
58			if (dbg_printf_sem < 0)
59				error = dbg_printf_sem;
60		}
61		if (error == B_OK) {
62			#if DEBUG
63				__out("##################################################\n");
64			#endif
65		} else
66			exit_debugging();
67	}
68	return error;
69}
70
71
72status_t
73exit_debugging()
74{
75	status_t error = B_OK;
76	if (--init_counter == 0) {
77		#if DEBUG_PRINT
78			close(out);
79			out = -1;
80		#endif	// DEBUG_PRINT
81		delete_sem(dbg_printf_sem);
82	} else
83		error = B_NO_INIT;
84	return error;
85}
86
87
88static inline bool
89dbg_printf_lock()
90{
91	thread_id thread = find_thread(NULL);
92	if (thread != dbg_printf_thread) {
93		if (acquire_sem(dbg_printf_sem) != B_OK)
94			return false;
95		dbg_printf_thread = thread;
96	}
97	dbg_printf_nesting++;
98	return true;
99}
100
101
102static inline void
103dbg_printf_unlock()
104{
105	thread_id thread = find_thread(NULL);
106	if (thread != dbg_printf_thread)
107		return;
108	dbg_printf_nesting--;
109	if (dbg_printf_nesting == 0) {
110		dbg_printf_thread = -1;
111		release_sem(dbg_printf_sem);
112	}
113}
114
115#else
116
117status_t
118init_debugging()
119{
120	status_t error = B_OK;
121	return error;
122}
123status_t
124exit_debugging()
125{
126	status_t error = B_OK;
127	return error;
128}
129static inline bool
130dbg_printf_lock()
131{
132	return true;
133}
134static inline void
135dbg_printf_unlock(){}
136
137#endif
138
139
140void
141dbg_printf_begin()
142{
143	dbg_printf_lock();
144}
145
146
147void
148dbg_printf_end()
149{
150	dbg_printf_unlock();
151}
152
153
154#if DEBUG_PRINT
155
156
157void
158dbg_vprintf(const char* format, va_list args)
159{
160	if (!dbg_printf_lock())
161		return;
162
163	char buffer[1024];
164	vsnprintf(buffer, sizeof(buffer) - 1, format, args);
165	write(out, buffer, strlen(buffer));
166
167	dbg_printf_unlock();
168}
169
170
171void
172dbg_printf(const char* format,...)
173{
174	va_list args;
175	va_start(args, format);
176	dbg_vprintf(format, args);
177	va_end(args);
178}
179
180
181#endif	// DEBUG_PRINT
182