1 /* mutexDebug.c - NeonServ v5.6
2 * Copyright (C) 2011-2012 Philipp Kreil (pk910)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "mutexDebug.h"
20 #ifdef ENABLE_MUTEX_DEBUG
22 struct MutexLockEvent {
26 struct MutexLockEvent *next;
32 struct MutexLockEvent *first_event, *last_event;
33 struct MutexLock *prev, *next;
37 pthread_mutex_t *mutex;
38 struct MutexLock *first_lock, *last_lock;
39 struct MutexNode *next;
42 static pthread_mutex_t synchronized;
43 static struct MutexNode *mutex_nodes = NULL;
45 static struct MutexNode *getMutexNode(pthread_mutex_t *mutex, int create);
46 static void lockMutex(struct MutexNode *node, const char *file, unsigned int line);
47 static void unlockMutex(struct MutexNode *node, const char *file, unsigned int line);
48 static void mutex_replay(struct MutexNode *node);
50 void xmutex(int lock, pthread_mutex_t *mutex, const char *file, unsigned int line) {
51 pthread_mutex_lock(&synchronized);
52 struct MutexNode *node = getMutexNode(mutex, 1);
54 lockMutex(node, file, line);
56 unlockMutex(node, file, line);
57 pthread_mutex_unlock(&synchronized);
60 void initMutexDebug() {
61 THREAD_MUTEX_INIT(synchronized);
64 static struct MutexNode *getMutexNode(pthread_mutex_t *mutex, int create) {
65 struct MutexNode *node;
66 for(node = mutex_nodes; node; node = node->next) {
67 if(node->mutex == mutex)
72 node = malloc(sizeof(*node));
73 node->first_lock = NULL;
74 node->last_lock = NULL;
76 node->next = mutex_nodes;
81 static void lockMutex(struct MutexNode *node, const char *file, unsigned int line) {
82 struct MutexLock *lock;
83 int thread = getCurrentThreadID();
84 for(lock = node->first_lock; lock; lock = lock->next) {
85 if(lock->thread == thread)
89 lock = malloc(sizeof(*lock));
90 lock->thread = thread;
92 lock->first_event = NULL;
93 lock->last_event = NULL;
94 lock->prev = node->last_lock;
96 node->last_lock = lock;
98 node->first_lock = lock;
102 struct MutexLockEvent *event = malloc(sizeof(*event));
107 if(lock->last_event) {
108 lock->last_event->next = event;
109 lock->last_event = event;
111 lock->first_event = event;
112 lock->last_event = event;
116 static void unlockMutex(struct MutexNode *node, const char *file, unsigned int line) {
117 struct MutexLock *lock;
118 int thread = getCurrentThreadID();
119 for(lock = node->first_lock; lock; lock = lock->next) {
120 if(lock->thread == thread)
126 if(lock->count <= 0) {
129 lock->prev->next = lock->next;
131 node->first_lock = lock->next;
133 lock->next->prev = lock->prev;
135 node->last_lock = lock->prev;
136 //recursive free all events
137 struct MutexLockEvent *event, *next_event;
138 for(event = lock->first_event; event; event = next_event) {
139 next_event = event->next;
145 struct MutexLockEvent *event = malloc(sizeof(*event));
150 if(lock->last_event) {
151 lock->last_event->next = event;
152 lock->last_event = event;
154 lock->first_event = event;
155 lock->last_event = event;
160 void mutex_debug(pthread_mutex_t *mutex) {
161 //replay mutex events to stdout
162 struct MutexNode *node;
164 node = getMutexNode(mutex, 0);
166 printf("[MUTEX_DEBUG] unknown mutex!\n");
171 for(node = mutex_nodes; node; node = node->next) {
175 printf("[MUTEX_DEBUG] end of mutex replay.\n");
178 static void mutex_replay(struct MutexNode *node) {
179 printf("[MUTEX_DEBUG] mutex replay:\n");
180 struct MutexLock *lock;
181 struct MutexLockEvent *event;
182 for(lock = node->first_lock; lock; lock = lock->next) {
183 printf("[MUTEX_DEBUG] THREAD %d (%d locks):\n", lock->thread, lock->count);
184 for(event = lock->first_event; event; event = event->next) {
185 printf("[MUTEX_DEBUG] %s in %s:%d\n", (event->locked ? "lock " : "unlock"), event->file, event->line);