Add tracing mutexes to debug.h.

/*
 * Tracing mutexes are a thin wrapper around the pthread_mutex_t 
 * datatype that tracks and reports when a mutex is locked or unlocked.
 * It also allows you to assert that a mutex has (or has not) been locked
 * by calling tracing_mutex_assert().
 */



git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@493 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7
This commit is contained in:
mheily 2011-04-29 03:28:07 +00:00
parent c4573236fa
commit e138f4a4c9
3 changed files with 90 additions and 3 deletions

View File

@ -18,11 +18,14 @@
#define _DEBUG_H
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
extern int DEBUG_ACTIVE;
extern char *DEBUG_IDENT;
#if defined(__linux__)
# include <sys/syscall.h>
# define THREAD_ID ((pid_t) syscall(__NR_gettid))
#elif defined(__sun)
# define THREAD_ID (pthread_self())
@ -32,7 +35,6 @@ extern char *DEBUG_IDENT;
# error Unsupported platform
#endif
#ifndef NDEBUG
#define dbg_puts(str) do { \
if (DEBUG_ACTIVE) \
@ -67,11 +69,46 @@ extern char *DEBUG_IDENT;
fprintf(stderr, "%s: [%d] %s(): %s: (WSALastError=%d)\n", \
DEBUG_IDENT, THREAD_ID, __func__, str, (int)WSAGetLastError()); \
} while (0)
# else
# define dbg_lasterror(str) ;
# define dbg_wsalasterror(str) ;
# endif
/*
* Tracing mutexes are a thin wrapper around the pthread_mutex_t
* datatype that tracks and reports when a mutex is locked or unlocked.
* It also allows you to assert that a mutex has (or has not) been locked
* by calling tracing_mutex_assert().
*/
# define MTX_UNLOCKED 0
# define MTX_LOCKED 1
typedef struct {
pthread_mutex_t mtx_lock;
int mtx_status;
} tracing_mutex_t;
# define tracing_mutex_init(mtx, attr) do { \
pthread_mutex_init(&(mtx)->mtx_lock, (attr)); \
(mtx)->mtx_status = MTX_UNLOCKED; \
} while (0)
# define tracing_mutex_assert(x,y) assert((x)->mtx_status == (y))
# define tracing_mutex_lock(x) do { \
dbg_printf("waiting for %s", #x); \
pthread_mutex_lock(&((x)->mtx_lock)); \
dbg_printf("locked %s", #x); \
(x)->mtx_status = MTX_LOCKED; \
} while (0)
# define tracing_mutex_unlock(x) do { \
(x)->mtx_status = MTX_UNLOCKED; \
pthread_mutex_unlock(&((x)->mtx_lock)); \
dbg_printf("unlocked %s", # x); \
} while (0)
#else /* NDEBUG */
# define dbg_puts(str) do {} while (0)
# define dbg_printf(fmt,...) do {} while (0)
@ -79,6 +116,13 @@ extern char *DEBUG_IDENT;
# define dbg_lasterror(str) do {} while (0)
# define dbg_wsalasterror(str) do {} while (0)
# define reset_errno() do {} while (0)
# define MTX_UNLOCKED
# define MTX_LOCKED
# define tracing_mutex_t pthread_mutex_t
# define tracing_mutex_init pthread_mutex_init
# define tracing_mutex_assert(x,y) do {} while (0)
# define tracing_mutex_lock pthread_mutex_lock
# define tracing_mutex_unlock pthread_mutex_unlock
#endif
#endif /* ! _DEBUG_H */

View File

@ -16,7 +16,10 @@
include config.mk
all: kqtest
all: kqtest lockstat
lockstat: lockstat.c
$(CC) -o lockstat $(CFLAGS) lockstat.c $(LDADD)
kqtest: $(SOURCES)
$(CC) -o kqtest $(CFLAGS) $(SOURCES) $(LDADD)
@ -56,5 +59,5 @@ edit:
$(EDITOR) *.[ch]
clean:
rm -f *.o *.a kqtest
rm -f *.o *.a kqtest lockstat
for x in libdispatch stress; do cd $$x && make clean && cd ..; done

40
test/lockstat.c Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2011 Mark Heily <mark@heily.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <pthread.h>
#include "../src/common/debug.h"
int DEBUG_ACTIVE = 1;
char * DEBUG_IDENT = "lockstat";
struct foo {
tracing_mutex_t foo_lock;
};
/*
* Test the lockstat.h API
*/
int main() {
struct foo x;
tracing_mutex_init(&x.foo_lock, NULL);
tracing_mutex_lock(&x.foo_lock);
tracing_mutex_assert(&x.foo_lock, MTX_LOCKED);
tracing_mutex_unlock(&x.foo_lock);
tracing_mutex_assert(&x.foo_lock, MTX_UNLOCKED);
return (0);
}