summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--debug.c52
-rw-r--r--debug.h36
2 files changed, 59 insertions, 29 deletions
diff --git a/debug.c b/debug.c
index 32bfab7c..4605eec8 100644
--- a/debug.c
+++ b/debug.c
@@ -51,6 +51,7 @@
/* forward definitions */
static void dbgGetThrdName(char *pszBuf, size_t lenBuf, pthread_t thrd, int bIncludeNumID);
+static dbgThrdInfo_t *dbgGetThrdInfo(void);
/* static data (some time to be replaced) */
int Debug; /* debug flag - read-only after startup */
@@ -92,19 +93,6 @@ static dbgMutLog_t *dbgMutLogListLast = NULL;
static pthread_mutex_t mutMutLog = PTHREAD_MUTEX_INITIALIZER;
-/* 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 stackPtr;
- int stackPtrMax;
- char *pszThrdName;
- struct dbgCallStack_s *pNext;
- struct dbgCallStack_s *pPrev;
-} dbgThrdInfo_t;
static dbgThrdInfo_t *dbgCallStackListRoot = NULL;
static dbgThrdInfo_t *dbgCallStackListLast = NULL;
static pthread_mutex_t mutCallStack = PTHREAD_MUTEX_INITIALIZER;
@@ -150,6 +138,17 @@ static void dbgMutexCancelCleanupHdlr(void *pmut)
}
+/* handler to update the last execution location seen
+ * rgerhards, 2008-01-28
+ */
+static inline void
+dbgRecordExecLocation(int iStackPtr, int line)
+{
+ dbgThrdInfo_t *pThrd = dbgGetThrdInfo();
+ pThrd->lastLine[iStackPtr] = line;
+}
+
+
/* ------------------------- mutex tracking code ------------------------- */
/* ------------------------- FuncDB utility functions ------------------------- */
@@ -482,10 +481,11 @@ static inline void dbgMutexUnlockLog(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB
/* wrapper for pthread_mutex_lock() */
-int dbgMutexLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln)
+int dbgMutexLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr)
{
int ret;
+ dbgRecordExecLocation(iStackPtr, ln);
dbgMutexPreLockLog(pmut, pFuncDB, ln);
ret = pthread_mutex_lock(pmut);
if(ret == 0) {
@@ -500,9 +500,10 @@ int dbgMutexLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln)
/* wrapper for pthread_mutex_unlock() */
-int dbgMutexUnlock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln)
+int dbgMutexUnlock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr)
{
int ret;
+ dbgRecordExecLocation(iStackPtr, ln);
dbgMutexUnlockLog(pmut, pFuncDB, ln);
ret = pthread_mutex_unlock(pmut);
return ret;
@@ -510,9 +511,10 @@ int dbgMutexUnlock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln)
/* wrapper for pthread_cond_wait() */
-int dbgCondWait(pthread_cond_t *cond, pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln)
+int dbgCondWait(pthread_cond_t *cond, pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr)
{
int ret;
+ dbgRecordExecLocation(iStackPtr, ln);
dbgMutexUnlockLog(pmut, pFuncDB, ln);
dbgprintf("%s:%d:%s: mutex %p waiting on condition %p\n", pFuncDB->file, pFuncDB->line, pFuncDB->func, (void*)pmut, (void*)cond);
dbgMutexPreLockLog(pmut, pFuncDB, ln);
@@ -522,9 +524,10 @@ int dbgCondWait(pthread_cond_t *cond, pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD
/* wrapper for pthread_cond_timedwait() */
-int dbgCondTimedWait(pthread_cond_t *cond, pthread_mutex_t *pmut, const struct timespec *abstime, dbgFuncDB_t *pFuncDB, int ln)
+int dbgCondTimedWait(pthread_cond_t *cond, pthread_mutex_t *pmut, const struct timespec *abstime, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr)
{
int ret;
+ dbgRecordExecLocation(iStackPtr, ln);
dbgMutexUnlockLog(pmut, pFuncDB, ln);
dbgMutexPreLockLog(pmut, pFuncDB, ln);
dbgprintf("%s:%d:%s: mutex %p waiting on condition %p (with timeout)\n", pFuncDB->file, pFuncDB->line, pFuncDB->func,
@@ -633,7 +636,7 @@ static void dbgCallStackPrint(dbgThrdInfo_t *pThrd)
dbgprintf("\n");
dbgprintf("Recorded Call Order for Thread '%s':\n", pszThrdName);
for(i = 0 ; i < pThrd->stackPtr ; i++) {
- dbgprintf("%d: %s:%s\n", i, pThrd->callStack[i]->func, pThrd->callStack[i]->file);
+ dbgprintf("%d: %s:%d:%s:\n", i, pThrd->callStack[i]->file, pThrd->lastLine[i], pThrd->callStack[i]->func);
}
dbgprintf("maximum number of nested calls for this thread: %d.\n", pThrd->stackPtrMax);
dbgprintf("NOTE: not all calls may have been recorded, code does not currently guarantee that!\n");
@@ -760,7 +763,7 @@ ENDfunc
/* handler called when a function is entered
*/
-int dbgEntrFunc(dbgFuncDB_t *pFuncDB)
+int dbgEntrFunc(dbgFuncDB_t *pFuncDB, int line)
{
int iStackPtr;
dbgThrdInfo_t *pThrd = dbgGetThrdInfo();
@@ -805,6 +808,7 @@ int dbgEntrFunc(dbgFuncDB_t *pFuncDB)
if(pThrd->stackPtr > pThrd->stackPtrMax)
pThrd->stackPtrMax = pThrd->stackPtr;
pThrd->callStack[iStackPtr] = pFuncDB;
+ pThrd->lastLine[iStackPtr] = line;
}
return iStackPtr;
@@ -832,6 +836,16 @@ void dbgExitFunc(dbgFuncDB_t *pFuncDB, int iStackPtrRestore)
}
+/* externally-callable handler to record the last exec location. We use a different function
+ * so that the internal one can be inline.
+ */
+void
+dbgSetExecLocation(int iStackPtr, int line)
+{
+ dbgRecordExecLocation(iStackPtr, line);
+}
+
+
void dbgPrintAllDebugInfo(void)
{
dbgCallStackPrintAll();
diff --git a/debug.h b/debug.h
index c25fd6f9..35ba8c80 100644
--- a/debug.h
+++ b/debug.h
@@ -64,24 +64,40 @@ typedef struct dbgFuncDB_s {
.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 lnB);
-int dbgMutexUnlock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int lnB);
-int dbgCondWait(pthread_cond_t *cond, pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int lnB);
-int dbgCondTimedWait(pthread_cond_t *cond, pthread_mutex_t *pmut, const struct timespec *abstime, dbgFuncDB_t *pFuncD, int lnB);
-int dbgEntrFunc(dbgFuncDB_t *pFuncDB);
+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 */
#if 1 /* DEV debug: set to 1 to get a rough call trace -- rgerhards, 2008-01-13 */
-# define BEGINfunc static dbgFuncDB_t dbgFuncDB=dbgFuncDB_t_INITIALIZER; int dbgCALLStaCK_POP_POINT = dbgEntrFunc(&dbgFuncDB);
+# 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
@@ -103,10 +119,10 @@ void dbgPrintAllDebugInfo(void);
/* debug aides */
#if 1
-#define d_pthread_mutex_lock(x) dbgMutexLock(x, &dbgFuncDB, __LINE__)
-#define d_pthread_mutex_unlock(x) dbgMutexUnlock(x, &dbgFuncDB, __LINE__)
-#define d_pthread_cond_wait(cond, mut) dbgCondWait(cond, mut, &dbgFuncDB, __LINE__)
-#define d_pthread_cond_timedwait(cond, mut, to) dbgCondTimedWait(cond, mut, to, &dbgFuncDB, __LINE__)
+#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)