summaryrefslogtreecommitdiffstats
path: root/debug.h
blob: a9891d8434073d800d9f259bda0d93a82a1cea98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* debug.h
 *
 * Definitions for the debug and run-time analysis support module.
 * Contains a lot of macros.
 *
 * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
 *
 * This file is part of rsyslog.
 *
 * Rsyslog is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Rsyslog is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Rsyslog.  If not, see <http://www.gnu.org/licenses/>.
 *
 * A copy of the GPL can be found in the file "COPYING" in this distribution.
 */
#ifndef DEBUG_H_INCLUDED
#define DEBUG_H_INCLUDED

#include <pthread.h>

/* external static data elements (some time to be replaced) */
extern int Debug;		/* debug flag  - read-only after startup */
extern int debugging_on;	 /* read-only, except on sig USR1 */

/* data types */

/* the function database. It is used as a static var inside each function. That provides
 * us the fast access to it that we need to make the instrumentation work. It's address
 * also serves as a unique function identifier and can be used inside other structures
 * to refer to the function (e.g. for pretty-printing names).
 * rgerhards, 2008-01-24
 */
typedef struct dbgFuncDBmutInfoEntry_s {
	pthread_mutex_t *pmut;
	int lockLn; /* line where it was locked (inside our func): -1 means mutex is not locked */
	pthread_t thrd; /* thrd where the mutex was locked */
	unsigned long lInvocation; /* invocation (unique during program run!) of this function that locked the mutex */
} dbgFuncDBmutInfoEntry_t;
typedef struct dbgFuncDB_s {
	unsigned magic;
	unsigned long nTimesCalled;
	const char *func;
	const char *file;
	int line;
	dbgFuncDBmutInfoEntry_t mutInfo[5];
	/* remember to update the initializer if you add anything or change the order! */
} dbgFuncDB_t;
#define dbgFUNCDB_MAGIC 0xA1B2C3D4
#define dbgFuncDB_t_INITIALIZER \
	{ \
	.magic = dbgFUNCDB_MAGIC,\
	.nTimesCalled = 0,\
	.func = __func__, \
	.file = __FILE__, \
	.line = __LINE__ \
	}

/* the structure below was originally just the thread's call stack, but it has
 * a bit evolved over time. So we have now ended up with the fact that it 
 * all debug info we know about the thread.
 */
typedef struct dbgCallStack_s {
	pthread_t thrd;
	dbgFuncDB_t *callStack[500];
	int lastLine[500]; /* last line where code execution was seen */
	int stackPtr;
	int stackPtrMax;
	char *pszThrdName;
	struct dbgCallStack_s *pNext;
	struct dbgCallStack_s *pPrev;
} dbgThrdInfo_t;


/* prototypes */
rsRetVal dbgClassInit(void);
rsRetVal dbgClassExit(void);
void sigsegvHdlr(int signum);
void dbgprintf(char *fmt, ...) __attribute__((format(printf,1, 2)));
int dbgMutexLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
int dbgMutexUnlock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
int dbgCondWait(pthread_cond_t *cond, pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
int dbgCondTimedWait(pthread_cond_t *cond, pthread_mutex_t *pmut, const struct timespec *abstime, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
int dbgEntrFunc(dbgFuncDB_t *pFuncDB, int line);
void dbgExitFunc(dbgFuncDB_t *pFuncDB, int iStackPtrRestore);
void dbgSetExecLocation(int iStackPtr, int line);
void dbgSetThrdName(uchar *pszName);
void dbgPrintAllDebugInfo(void);

/* macros */
#ifdef RTINST
#	define BEGINfunc static dbgFuncDB_t dbgFuncDB=dbgFuncDB_t_INITIALIZER; int dbgCALLStaCK_POP_POINT = dbgEntrFunc(&dbgFuncDB,__LINE__);
#	define ENDfunc dbgExitFunc(&dbgFuncDB, dbgCALLStaCK_POP_POINT);
#else
#	define BEGINfunc
#	define ENDfunc
#endif
#ifdef RTINST
#	define RUNLOG dbgSetExecLocation(dbgCALLStaCK_POP_POINT, __LINE__); dbgprintf("%s:%d: %s: log point\n", __FILE__, __LINE__, __func__)
#	define RUNLOG_VAR(fmt, x) dbgSetExecLocation(dbgCALLStaCK_POP_POINT, __LINE__);\
	 		          dbgprintf("%s:%d: %s: var '%s'[%s]: " fmt "\n", __FILE__, __LINE__, __func__, #x, fmt, x)
#else
#	define RUNLOG
#	define RUNLOG_VAR(fmt, x)
#endif

/* mutex operations */
#define MUTOP_LOCKWAIT		1
#define MUTOP_LOCK		2
#define MUTOP_UNLOCK		3


/* debug aides */
#ifdef RTINST
#define d_pthread_mutex_lock(x)      dbgMutexLock(x, &dbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#define d_pthread_mutex_unlock(x)    dbgMutexUnlock(x, &dbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#define d_pthread_cond_wait(cond, mut)   dbgCondWait(cond, mut, &dbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#define d_pthread_cond_timedwait(cond, mut, to)   dbgCondTimedWait(cond, mut, to, &dbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#else
#define d_pthread_mutex_lock(x)     pthread_mutex_lock(x)
#define d_pthread_mutex_unlock(x)   pthread_mutex_unlock(x)
#define d_pthread_cond_wait(cond, mut)   pthread_cond_wait(cond, mut)
#define d_pthread_cond_timedwait(cond, mut, to)   pthread_cond_timedwait(cond, mut, to)
#endif
#endif /* #ifndef DEBUG_H_INCLUDED */