thread.c 1.85 KB
Newer Older
1 2 3 4 5 6
/*
 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
 * Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
7
 * of the GNU General Public License version 2.
8
 */
9 10 11

#include "lock_dlm.h"

12
static inline int no_work(struct gdlm_ls *ls)
13 14 15 16
{
	int ret;

	spin_lock(&ls->async_lock);
17
	ret = list_empty(&ls->submit);
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
	spin_unlock(&ls->async_lock);

	return ret;
}

static inline int check_drop(struct gdlm_ls *ls)
{
	if (!ls->drop_locks_count)
		return 0;

	if (time_after(jiffies, ls->drop_time + ls->drop_locks_period * HZ)) {
		ls->drop_time = jiffies;
		if (ls->all_locks_count >= ls->drop_locks_count)
			return 1;
	}
	return 0;
}

36
static int gdlm_thread(void *data)
37 38 39 40 41
{
	struct gdlm_ls *ls = (struct gdlm_ls *) data;
	struct gdlm_lock *lp = NULL;

	while (!kthread_should_stop()) {
42
		wait_event_interruptible(ls->thread_wait,
43
				!no_work(ls) || kthread_should_stop());
44 45 46

		spin_lock(&ls->async_lock);

47
		if (!list_empty(&ls->submit)) {
48 49 50
			lp = list_entry(ls->submit.next, struct gdlm_lock,
					delay_list);
			list_del_init(&lp->delay_list);
51
			spin_unlock(&ls->async_lock);
52
			gdlm_do_lock(lp);
53 54 55 56 57
			spin_lock(&ls->async_lock);
		}
		/* Does this ever happen these days? I hope not anyway */
		if (check_drop(ls)) {
			spin_unlock(&ls->async_lock);
Steven Whitehouse's avatar
Steven Whitehouse committed
58
			ls->fscb(ls->sdp, LM_CB_DROPLOCKS, NULL);
59 60 61
			spin_lock(&ls->async_lock);
		}
		spin_unlock(&ls->async_lock);
62 63 64 65 66 67 68 69 70 71
	}

	return 0;
}

int gdlm_init_threads(struct gdlm_ls *ls)
{
	struct task_struct *p;
	int error;

72
	p = kthread_run(gdlm_thread, ls, "lock_dlm");
73 74
	error = IS_ERR(p);
	if (error) {
75
		log_error("can't start lock_dlm thread %d", error);
76 77
		return error;
	}
78
	ls->thread = p;
79 80 81 82 83 84

	return 0;
}

void gdlm_release_threads(struct gdlm_ls *ls)
{
85
	kthread_stop(ls->thread);
86 87
}