xref: /haiku/src/servers/package/DebugSupport.cpp (revision 5ffbe7d778424c9c59f00b37a3baff5c4c648790)
126296b0aSIngo Weinhold /*
226296b0aSIngo Weinhold  * Copyright 2003-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
326296b0aSIngo Weinhold  * Distributed under the terms of the MIT License.
426296b0aSIngo Weinhold  */
526296b0aSIngo Weinhold 
626296b0aSIngo Weinhold 
726296b0aSIngo Weinhold #include "DebugSupport.h"
826296b0aSIngo Weinhold 
926296b0aSIngo Weinhold #include <errno.h>
1026296b0aSIngo Weinhold #include <fcntl.h>
1126296b0aSIngo Weinhold #include <stdarg.h>
1226296b0aSIngo Weinhold #include <stdio.h>
1326296b0aSIngo Weinhold #include <string.h>
1426296b0aSIngo Weinhold #include <unistd.h>
1526296b0aSIngo Weinhold 
1626296b0aSIngo Weinhold #include <OS.h>
1726296b0aSIngo Weinhold 
1826296b0aSIngo Weinhold 
1926296b0aSIngo Weinhold /*!
2026296b0aSIngo Weinhold 	\file Debug.cpp
2126296b0aSIngo Weinhold 	\brief Defines debug output function with printf() signature printing
2226296b0aSIngo Weinhold 		   into a file.
2326296b0aSIngo Weinhold 
2426296b0aSIngo Weinhold 	\note The initialization is not thread safe!
2526296b0aSIngo Weinhold */
2626296b0aSIngo Weinhold 
2726296b0aSIngo Weinhold 
2826296b0aSIngo Weinhold // locking support
2926296b0aSIngo Weinhold static int32 init_counter = 0;
3026296b0aSIngo Weinhold static sem_id dbg_printf_sem = -1;
3126296b0aSIngo Weinhold static thread_id dbg_printf_thread = -1;
3226296b0aSIngo Weinhold static int dbg_printf_nesting = 0;
3326296b0aSIngo Weinhold 
3426296b0aSIngo Weinhold 
3526296b0aSIngo Weinhold #if DEBUG_PRINT
3626296b0aSIngo Weinhold static int out = -1;
3726296b0aSIngo Weinhold #endif
3826296b0aSIngo Weinhold 
3926296b0aSIngo Weinhold 
4026296b0aSIngo Weinhold status_t
init_debugging()4126296b0aSIngo Weinhold init_debugging()
4226296b0aSIngo Weinhold {
4326296b0aSIngo Weinhold 	status_t error = B_OK;
4426296b0aSIngo Weinhold 	if (init_counter++ == 0) {
4526296b0aSIngo Weinhold 		// open the file
4626296b0aSIngo Weinhold 		#if DEBUG_PRINT
4726296b0aSIngo Weinhold 			out = open(DEBUG_PRINT_FILE, O_RDWR | O_CREAT | O_TRUNC);
4826296b0aSIngo Weinhold 			if (out < 0) {
4926296b0aSIngo Weinhold 				error = errno;
5026296b0aSIngo Weinhold 				init_counter--;
5126296b0aSIngo Weinhold 			}
5226296b0aSIngo Weinhold 		#endif	// DEBUG_PRINT
5326296b0aSIngo Weinhold 		// allocate the semaphore
5426296b0aSIngo Weinhold 		if (error == B_OK) {
5526296b0aSIngo Weinhold 			dbg_printf_sem = create_sem(1, "dbg_printf");
5626296b0aSIngo Weinhold 			if (dbg_printf_sem < 0)
5726296b0aSIngo Weinhold 				error = dbg_printf_sem;
5826296b0aSIngo Weinhold 		}
5926296b0aSIngo Weinhold 		if (error == B_OK) {
6026296b0aSIngo Weinhold 			#if DEBUG
6126296b0aSIngo Weinhold 				__out("##################################################\n");
6226296b0aSIngo Weinhold 			#endif
6326296b0aSIngo Weinhold 		} else
6426296b0aSIngo Weinhold 			exit_debugging();
6526296b0aSIngo Weinhold 	}
6626296b0aSIngo Weinhold 	return error;
6726296b0aSIngo Weinhold }
6826296b0aSIngo Weinhold 
6926296b0aSIngo Weinhold 
7026296b0aSIngo Weinhold status_t
exit_debugging()7126296b0aSIngo Weinhold exit_debugging()
7226296b0aSIngo Weinhold {
7326296b0aSIngo Weinhold 	status_t error = B_OK;
7426296b0aSIngo Weinhold 	if (--init_counter == 0) {
7526296b0aSIngo Weinhold 		#if DEBUG_PRINT
7626296b0aSIngo Weinhold 			close(out);
7726296b0aSIngo Weinhold 			out = -1;
7826296b0aSIngo Weinhold 		#endif	// DEBUG_PRINT
7926296b0aSIngo Weinhold 		delete_sem(dbg_printf_sem);
8026296b0aSIngo Weinhold 	} else
8126296b0aSIngo Weinhold 		error = B_NO_INIT;
8226296b0aSIngo Weinhold 	return error;
8326296b0aSIngo Weinhold }
8426296b0aSIngo Weinhold 
8526296b0aSIngo Weinhold 
8626296b0aSIngo Weinhold static inline bool
dbg_printf_lock()8726296b0aSIngo Weinhold dbg_printf_lock()
8826296b0aSIngo Weinhold {
8926296b0aSIngo Weinhold 	thread_id thread = find_thread(NULL);
9026296b0aSIngo Weinhold 	if (thread != dbg_printf_thread) {
9126296b0aSIngo Weinhold 		if (acquire_sem(dbg_printf_sem) != B_OK)
9226296b0aSIngo Weinhold 			return false;
9326296b0aSIngo Weinhold 		dbg_printf_thread = thread;
9426296b0aSIngo Weinhold 	}
9526296b0aSIngo Weinhold 	dbg_printf_nesting++;
9626296b0aSIngo Weinhold 	return true;
9726296b0aSIngo Weinhold }
9826296b0aSIngo Weinhold 
9926296b0aSIngo Weinhold 
10026296b0aSIngo Weinhold static inline void
dbg_printf_unlock()10126296b0aSIngo Weinhold dbg_printf_unlock()
10226296b0aSIngo Weinhold {
10326296b0aSIngo Weinhold 	thread_id thread = find_thread(NULL);
10426296b0aSIngo Weinhold 	if (thread != dbg_printf_thread)
10526296b0aSIngo Weinhold 		return;
10626296b0aSIngo Weinhold 	dbg_printf_nesting--;
10726296b0aSIngo Weinhold 	if (dbg_printf_nesting == 0) {
10826296b0aSIngo Weinhold 		dbg_printf_thread = -1;
10926296b0aSIngo Weinhold 		release_sem(dbg_printf_sem);
11026296b0aSIngo Weinhold 	}
11126296b0aSIngo Weinhold }
11226296b0aSIngo Weinhold 
11326296b0aSIngo Weinhold 
11426296b0aSIngo Weinhold void
dbg_printf_begin()11526296b0aSIngo Weinhold dbg_printf_begin()
11626296b0aSIngo Weinhold {
11726296b0aSIngo Weinhold 	dbg_printf_lock();
11826296b0aSIngo Weinhold }
11926296b0aSIngo Weinhold 
12026296b0aSIngo Weinhold 
12126296b0aSIngo Weinhold void
dbg_printf_end()12226296b0aSIngo Weinhold dbg_printf_end()
12326296b0aSIngo Weinhold {
12426296b0aSIngo Weinhold 	dbg_printf_unlock();
12526296b0aSIngo Weinhold }
12626296b0aSIngo Weinhold 
12726296b0aSIngo Weinhold 
12826296b0aSIngo Weinhold #if DEBUG_PRINT
12926296b0aSIngo Weinhold 
13026296b0aSIngo Weinhold void
dbg_printf(const char * format,...)13126296b0aSIngo Weinhold dbg_printf(const char *format,...)
13226296b0aSIngo Weinhold {
13326296b0aSIngo Weinhold 	if (!dbg_printf_lock())
13426296b0aSIngo Weinhold 		return;
13526296b0aSIngo Weinhold 	char buffer[1024];
13626296b0aSIngo Weinhold 	va_list args;
13726296b0aSIngo Weinhold 	va_start(args, format);
13826296b0aSIngo Weinhold 	// no vsnprintf() on PPC and in kernel
139*5ffbe7d7SAugustin Cavalier 	#if defined(__i386__) && USER
14026296b0aSIngo Weinhold 		vsnprintf(buffer, sizeof(buffer) - 1, format, args);
14126296b0aSIngo Weinhold 	#else
14226296b0aSIngo Weinhold 		vsprintf(buffer, format, args);
14326296b0aSIngo Weinhold 	#endif
14426296b0aSIngo Weinhold 	va_end(args);
14526296b0aSIngo Weinhold 	buffer[sizeof(buffer) - 1] = '\0';
14626296b0aSIngo Weinhold 	write(out, buffer, strlen(buffer));
14726296b0aSIngo Weinhold 	dbg_printf_unlock();
14826296b0aSIngo Weinhold }
14926296b0aSIngo Weinhold 
15026296b0aSIngo Weinhold #endif	// DEBUG_PRINT
151