spinlock_test.c 2.3 KB
Newer Older
D
David Daney 已提交
1 2 3 4 5
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/hrtimer.h>
#include <linux/fs.h>
#include <linux/debugfs.h>
6
#include <linux/export.h>
D
David Daney 已提交
7
#include <linux/spinlock.h>
8
#include <asm/debug.h>
D
David Daney 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

static int ss_get(void *data, u64 *val)
{
	ktime_t start, finish;
	int loops;
	int cont;
	DEFINE_RAW_SPINLOCK(ss_spin);

	loops = 1000000;
	cont = 1;

	start = ktime_get();

	while (cont) {
		raw_spin_lock(&ss_spin);
		loops--;
		if (loops == 0)
			cont = 0;
		raw_spin_unlock(&ss_spin);
	}

	finish = ktime_get();

	*val = ktime_us_delta(finish, start);

	return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(fops_ss, ss_get, NULL, "%llu\n");



struct spin_multi_state {
	raw_spinlock_t lock;
	atomic_t start_wait;
	atomic_t enter_wait;
	atomic_t exit_wait;
	int loops;
};

struct spin_multi_per_thread {
	struct spin_multi_state *state;
	ktime_t start;
};

static int multi_other(void *data)
{
	int loops;
	int cont;
	struct spin_multi_per_thread *pt = data;
	struct spin_multi_state *s = pt->state;

	loops = s->loops;
	cont = 1;

	atomic_dec(&s->enter_wait);

	while (atomic_read(&s->enter_wait))
		; /* spin */

	pt->start = ktime_get();

	atomic_dec(&s->start_wait);

	while (atomic_read(&s->start_wait))
		; /* spin */

	while (cont) {
		raw_spin_lock(&s->lock);
		loops--;
		if (loops == 0)
			cont = 0;
		raw_spin_unlock(&s->lock);
	}

	atomic_dec(&s->exit_wait);
	while (atomic_read(&s->exit_wait))
		; /* spin */
	return 0;
}

static int multi_get(void *data, u64 *val)
{
	ktime_t finish;
	struct spin_multi_state ms;
	struct spin_multi_per_thread t1, t2;

	ms.lock = __RAW_SPIN_LOCK_UNLOCKED("multi_get");
	ms.loops = 1000000;

	atomic_set(&ms.start_wait, 2);
	atomic_set(&ms.enter_wait, 2);
	atomic_set(&ms.exit_wait, 2);
	t1.state = &ms;
	t2.state = &ms;

	kthread_run(multi_other, &t2, "multi_get");

	multi_other(&t1);

	finish = ktime_get();

	*val = ktime_us_delta(finish, t1.start);

	return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(fops_multi, multi_get, NULL, "%llu\n");

static int __init spinlock_test(void)
{
	struct dentry *d;

	if (!mips_debugfs_dir)
		return -ENODEV;

	d = debugfs_create_file("spin_single", S_IRUGO,
				mips_debugfs_dir, NULL,
				&fops_ss);
	if (!d)
		return -ENOMEM;

	d = debugfs_create_file("spin_multi", S_IRUGO,
				mips_debugfs_dir, NULL,
				&fops_multi);
	if (!d)
		return -ENOMEM;

	return 0;
}
device_initcall(spinlock_test);