linux/arch/mips/kernel/spinlock_test.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <linux/init.h>
   3#include <linux/kthread.h>
   4#include <linux/hrtimer.h>
   5#include <linux/fs.h>
   6#include <linux/debugfs.h>
   7#include <linux/export.h>
   8#include <linux/spinlock.h>
   9#include <asm/debug.h>
  10
  11static int ss_get(void *data, u64 *val)
  12{
  13        ktime_t start, finish;
  14        int loops;
  15        int cont;
  16        DEFINE_RAW_SPINLOCK(ss_spin);
  17
  18        loops = 1000000;
  19        cont = 1;
  20
  21        start = ktime_get();
  22
  23        while (cont) {
  24                raw_spin_lock(&ss_spin);
  25                loops--;
  26                if (loops == 0)
  27                        cont = 0;
  28                raw_spin_unlock(&ss_spin);
  29        }
  30
  31        finish = ktime_get();
  32
  33        *val = ktime_us_delta(finish, start);
  34
  35        return 0;
  36}
  37
  38DEFINE_DEBUGFS_ATTRIBUTE(fops_ss, ss_get, NULL, "%llu\n");
  39
  40
  41
  42struct spin_multi_state {
  43        raw_spinlock_t lock;
  44        atomic_t start_wait;
  45        atomic_t enter_wait;
  46        atomic_t exit_wait;
  47        int loops;
  48};
  49
  50struct spin_multi_per_thread {
  51        struct spin_multi_state *state;
  52        ktime_t start;
  53};
  54
  55static int multi_other(void *data)
  56{
  57        int loops;
  58        int cont;
  59        struct spin_multi_per_thread *pt = data;
  60        struct spin_multi_state *s = pt->state;
  61
  62        loops = s->loops;
  63        cont = 1;
  64
  65        atomic_dec(&s->enter_wait);
  66
  67        while (atomic_read(&s->enter_wait))
  68                ; /* spin */
  69
  70        pt->start = ktime_get();
  71
  72        atomic_dec(&s->start_wait);
  73
  74        while (atomic_read(&s->start_wait))
  75                ; /* spin */
  76
  77        while (cont) {
  78                raw_spin_lock(&s->lock);
  79                loops--;
  80                if (loops == 0)
  81                        cont = 0;
  82                raw_spin_unlock(&s->lock);
  83        }
  84
  85        atomic_dec(&s->exit_wait);
  86        while (atomic_read(&s->exit_wait))
  87                ; /* spin */
  88        return 0;
  89}
  90
  91static int multi_get(void *data, u64 *val)
  92{
  93        ktime_t finish;
  94        struct spin_multi_state ms;
  95        struct spin_multi_per_thread t1, t2;
  96
  97        ms.lock = __RAW_SPIN_LOCK_UNLOCKED("multi_get");
  98        ms.loops = 1000000;
  99
 100        atomic_set(&ms.start_wait, 2);
 101        atomic_set(&ms.enter_wait, 2);
 102        atomic_set(&ms.exit_wait, 2);
 103        t1.state = &ms;
 104        t2.state = &ms;
 105
 106        kthread_run(multi_other, &t2, "multi_get");
 107
 108        multi_other(&t1);
 109
 110        finish = ktime_get();
 111
 112        *val = ktime_us_delta(finish, t1.start);
 113
 114        return 0;
 115}
 116
 117DEFINE_DEBUGFS_ATTRIBUTE(fops_multi, multi_get, NULL, "%llu\n");
 118
 119static int __init spinlock_test(void)
 120{
 121        debugfs_create_file_unsafe("spin_single", S_IRUGO, mips_debugfs_dir, NULL,
 122                            &fops_ss);
 123        debugfs_create_file_unsafe("spin_multi", S_IRUGO, mips_debugfs_dir, NULL,
 124                            &fops_multi);
 125        return 0;
 126}
 127device_initcall(spinlock_test);
 128