1
by Tim Gardner
Import upstream version 4.2.0 |
1 |
/*
|
2 |
* Specialised local-global spinlock. Can only be declared as global variables
|
|
3 |
* to avoid overhead and keep things simple (and we don't want to start using
|
|
4 |
* these inside dynamically allocated structures).
|
|
5 |
*
|
|
6 |
* "local/global locks" (lglocks) can be used to:
|
|
7 |
*
|
|
8 |
* - Provide fast exclusive access to per-CPU data, with exclusive access to
|
|
9 |
* another CPU's data allowed but possibly subject to contention, and to
|
|
10 |
* provide very slow exclusive access to all per-CPU data.
|
|
11 |
* - Or to provide very fast and scalable read serialisation, and to provide
|
|
12 |
* very slow exclusive serialisation of data (not necessarily per-CPU data).
|
|
13 |
*
|
|
14 |
* Brlocks are also implemented as a short-hand notation for the latter use
|
|
15 |
* case.
|
|
16 |
*
|
|
17 |
* Copyright 2009, 2010, Nick Piggin, Novell Inc.
|
|
18 |
*/
|
|
19 |
#ifndef __LINUX_LGLOCK_H
|
|
20 |
#define __LINUX_LGLOCK_H
|
|
21 |
||
22 |
#include <linux/spinlock.h> |
|
23 |
#include <linux/lockdep.h> |
|
24 |
#include <linux/percpu.h> |
|
25 |
#include <linux/cpu.h> |
|
26 |
#include <linux/notifier.h> |
|
27 |
||
28 |
#ifdef CONFIG_SMP
|
|
29 |
||
30 |
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
31 |
#define LOCKDEP_INIT_MAP lockdep_init_map
|
|
32 |
#else
|
|
33 |
#define LOCKDEP_INIT_MAP(a, b, c, d)
|
|
34 |
#endif
|
|
35 |
||
36 |
struct lglock { |
|
37 |
arch_spinlock_t __percpu *lock; |
|
38 |
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
39 |
struct lock_class_key lock_key; |
|
40 |
struct lockdep_map lock_dep_map; |
|
41 |
#endif
|
|
42 |
};
|
|
43 |
||
44 |
#define DEFINE_LGLOCK(name) \
|
|
45 |
static DEFINE_PER_CPU(arch_spinlock_t, name ## _lock) \
|
|
46 |
= __ARCH_SPIN_LOCK_UNLOCKED; \
|
|
47 |
struct lglock name = { .lock = &name ## _lock }
|
|
48 |
||
49 |
#define DEFINE_STATIC_LGLOCK(name) \
|
|
50 |
static DEFINE_PER_CPU(arch_spinlock_t, name ## _lock) \
|
|
51 |
= __ARCH_SPIN_LOCK_UNLOCKED; \
|
|
52 |
static struct lglock name = { .lock = &name ## _lock }
|
|
53 |
||
54 |
void lg_lock_init(struct lglock *lg, char *name); |
|
55 |
||
56 |
void lg_local_lock(struct lglock *lg); |
|
57 |
void lg_local_unlock(struct lglock *lg); |
|
58 |
void lg_local_lock_cpu(struct lglock *lg, int cpu); |
|
59 |
void lg_local_unlock_cpu(struct lglock *lg, int cpu); |
|
60 |
||
61 |
void lg_double_lock(struct lglock *lg, int cpu1, int cpu2); |
|
62 |
void lg_double_unlock(struct lglock *lg, int cpu1, int cpu2); |
|
63 |
||
64 |
void lg_global_lock(struct lglock *lg); |
|
65 |
void lg_global_unlock(struct lglock *lg); |
|
66 |
||
67 |
#else
|
|
68 |
/* When !CONFIG_SMP, map lglock to spinlock */
|
|
69 |
#define lglock spinlock
|
|
70 |
#define DEFINE_LGLOCK(name) DEFINE_SPINLOCK(name)
|
|
71 |
#define DEFINE_STATIC_LGLOCK(name) static DEFINE_SPINLOCK(name)
|
|
72 |
#define lg_lock_init(lg, name) spin_lock_init(lg)
|
|
73 |
#define lg_local_lock spin_lock
|
|
74 |
#define lg_local_unlock spin_unlock
|
|
75 |
#define lg_local_lock_cpu(lg, cpu) spin_lock(lg)
|
|
76 |
#define lg_local_unlock_cpu(lg, cpu) spin_unlock(lg)
|
|
77 |
#define lg_global_lock spin_lock
|
|
78 |
#define lg_global_unlock spin_unlock
|
|
79 |
#endif
|
|
80 |
||
81 |
#endif
|