#include <pthread.h>
#include "lock.h"
-
+#include <stdio.h>
void cleanup_lock (void * data)
{
- unlock((pthread_mutex_t *)data);
+ unlock ((*(struct mutex_lock *)data));
}
#ifndef _LOCK_H
#define _LOCK_H
+/*
+ * Wrapper for the mutex. Includes a ref-count to keep
+ * track of how many there are out-standing threads blocking
+ * on a mutex. */
+struct mutex_lock {
+ pthread_mutex_t *mutex;
+ int depth;
+};
+
#ifdef LCKDBG
#define lock(a) \
- fprintf(stderr, "%s:%s(%i) lock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
- pthread_mutex_lock(a)
+ fprintf(stderr, "%s:%s(%i) lock %p depth: %d (%ld)\n", __FILE__, __FUNCTION__, __LINE__, a.mutex, a.depth, pthread_self()); \
+ a.depth++; pthread_mutex_lock(a.mutex)
#define unlock(a) \
- fprintf(stderr, "%s:%s(%i) unlock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
- pthread_mutex_unlock(a)
+ fprintf(stderr, "%s:%s(%i) unlock %p depth: %d (%ld)\n", __FILE__, __FUNCTION__, __LINE__, a.mutex, a.depth, pthread_self()); \
+ a.depth--; pthread_mutex_unlock(a.mutex)
#define lock_cleanup_pop(a) \
- fprintf(stderr, "%s:%s(%i) unlock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
- pthread_cleanup_pop(1);
+ fprintf(stderr, "%s:%s(%i) unlock %p depth: %d (%ld)\n", __FILE__, __FUNCTION__, __LINE__, a.mutex, a.depth, pthread_self()); \
+ pthread_cleanup_pop(1);
#else
-#define lock(a) pthread_mutex_lock(a)
-#define unlock(a) pthread_mutex_unlock(a)
+#define lock(a) a.depth++; pthread_mutex_lock(a.mutex)
+#define unlock(a) a.depth--; pthread_mutex_unlock(a.mutex)
#define lock_cleanup_pop(a) pthread_cleanup_pop(1);
#endif
#ifndef _STRUCTS_VEC_H
#define _STRUCTS_VEC_H
+#include "lock.h"
+/*
+struct mutex_lock {
+ pthread_mutex_t *mutex;
+ int depth;
+}; */
struct vectors {
- pthread_mutex_t *lock;
+ struct mutex_lock lock; /* defined in lock.h */
vector pathvec;
vector mpvec;
};
*/
wp->mpp->waiter = NULL;
else
- condlog(3, "free_waiter, mpp freed before wp=%p,", wp);
+ /*
+ * This is OK condition during shutdown.
+ */
+ condlog(3, "free_waiter, mpp freed before wp=%p (%s).", wp, wp->mapname);
unlock(wp->vecs->lock);
void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs)
{
struct event_thread *wp = (struct event_thread *)mpp->waiter;
+ pthread_t thread;
if (!wp) {
condlog(3, "%s: no waiter thread", mpp->alias);
return;
}
- condlog(2, "%s: stop event checker thread", wp->mapname);
- pthread_kill((pthread_t)wp->thread, SIGUSR1);
+ thread = wp->thread;
+ condlog(2, "%s: stop event checker thread (%lu)", wp->mapname, thread);
+
+ pthread_kill(thread, SIGUSR1);
}
static sigset_t unblock_signals(void)
* 4) a path reinstate : nothing to do
* 5) a switch group : nothing to do
*/
- pthread_cleanup_push(cleanup_lock, waiter->vecs->lock);
+ pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock);
lock(waiter->vecs->lock);
r = update_multipath(waiter->vecs, waiter->mapname);
lock_cleanup_pop(waiter->vecs->lock);
condlog(3, "restart multipath configuration process");
out:
+
sysfs_cleanup();
dm_lib_release();
dm_lib_exit();
*len = 0;
vecs = (struct vectors *)trigger_data;
- pthread_cleanup_push(cleanup_lock, vecs->lock);
+ pthread_cleanup_push(cleanup_lock, &vecs->lock);
lock(vecs->lock);
r = parse_cmd(str, reply, len, vecs);
condlog(3, "unlink pidfile");
unlink(DEFAULT_PIDFILE);
- lock(&exit_mutex);
+ pthread_mutex_lock(&exit_mutex);
pthread_cond_signal(&exit_cond);
- unlock(&exit_mutex);
+ pthread_mutex_unlock(&exit_mutex);
return status;
}
}
while (1) {
- pthread_cleanup_push(cleanup_lock, vecs->lock);
+ pthread_cleanup_push(cleanup_lock, &vecs->lock);
lock(vecs->lock);
condlog(4, "tick");
if (!vecs)
return NULL;
- vecs->lock =
+ vecs->lock.mutex =
(pthread_mutex_t *)MALLOC(sizeof(pthread_mutex_t));
- if (!vecs->lock)
+ if (!vecs->lock.mutex)
goto out;
- pthread_mutex_init(vecs->lock, NULL);
+ pthread_mutex_init(vecs->lock.mutex, NULL);
+ vecs->lock.depth = 0;
return vecs;
condlog(0, "failure during configuration");
exit(1);
}
-
/*
* start threads
*/
free_polls();
unlock(vecs->lock);
- pthread_mutex_destroy(vecs->lock);
- FREE(vecs->lock);
- vecs->lock = NULL;
+ /* Now all the waitevent threads will start rushing in. */
+ while (vecs->lock.depth > 0) {
+ sleep (1); /* This is weak. */
+ condlog(3,"Have %d wait event checkers threads to de-alloc, waiting..\n", vecs->lock.depth);
+ }
+ pthread_mutex_destroy(vecs->lock.mutex);
+ FREE(vecs->lock.mutex);
+ vecs->lock.depth = 0;
+ vecs->lock.mutex = NULL;
FREE(vecs);
vecs = NULL;