summaryrefslogtreecommitdiff
path: root/include/linux/rwsem-spinlock.h
blob: 6608521725f4fc44f9963d9e02fc902ce4049878 (plain) (blame)
1
2
3
4
5
6
7
8
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
/* rwsem-spinlock.h: fallback C implementation
 *
 * Copyright (c) 2001   David Howells (dhowells@redhat.com).
 * - Derived partially from ideas by Andrea Arcangeli <andrea@suse.de>
 * - Derived also from comments by Linus
 */

#ifndef _LINUX_RWSEM_SPINLOCK_H
#define _LINUX_RWSEM_SPINLOCK_H

#ifndef _LINUX_RWSEM_H
#error "please don't include linux/rwsem-spinlock.h directly, use linux/rwsem.h instead"
#endif

#include <linux/spinlock.h>
#include <linux/list.h>

#ifdef __KERNEL__

#include <linux/types.h>

struct rwsem_waiter;

/*
 * the rw-anon-semaphore definition
 * - if activity is 0 then there are no active readers or writers
 * - if activity is +ve then that is the number of active readers
 * - if activity is -1 then there is one active writer
 * - if wait_list is not empty, then there are processes waiting for the semaphore
 *
 * the anon in the name documents that the semaphore has no full
 * restrictions versus owner ship.
 */
struct rw_anon_semaphore {
	__s32			activity;
	raw_spinlock_t		wait_lock;
	struct list_head	wait_list;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
	struct lockdep_map dep_map;
#endif
};

#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define __RWSEM_ANON_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
#else
# define __RWSEM_ANON_DEP_MAP_INIT(lockname)
#endif

#define __RWSEM_ANON_INITIALIZER(name) \
{ 0, __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock), LIST_HEAD_INIT((name).wait_list) \
  __RWSEM_ANON_DEP_MAP_INIT(name) }

#define DECLARE_ANON_RWSEM(name) \
	struct rw_anon_semaphore name = __RWSEM_ANON_INITIALIZER(name)

extern void __init_anon_rwsem(struct rw_anon_semaphore *sem, const char *name,
			      struct lock_class_key *key);

#define init_anon_rwsem(sem)					\
do {								\
	static struct lock_class_key __key;			\
								\
	__init_anon_rwsem((sem), #sem, &__key);			\
} while (0)

extern void __down_read(struct rw_anon_semaphore *sem);
extern int __down_read_trylock(struct rw_anon_semaphore *sem);
extern void __down_write(struct rw_anon_semaphore *sem);
extern void __down_write_nested(struct rw_anon_semaphore *sem, int subclass);
extern int __down_write_trylock(struct rw_anon_semaphore *sem);
extern void __up_read(struct rw_anon_semaphore *sem);
extern void __up_write(struct rw_anon_semaphore *sem);
extern void __downgrade_write(struct rw_anon_semaphore *sem);
 extern int anon_rwsem_is_locked(struct rw_anon_semaphore *sem);

#ifndef CONFIG_PREEMPT_RT
/*
 * Non preempt-rt implementation of rw_semaphore. Same as above, but
 * restricted vs. ownership. i.e. ownerless locked state and non owner
 * release not allowed.
 */

/*
 * the rw-semaphore definition
 * - if activity is 0 then there are no active readers or writers
 * - if activity is +ve then that is the number of active readers
 * - if activity is -1 then there is one active writer
 * - if wait_list is not empty, then there are processes waiting for the semaphore
 */
struct rw_semaphore {
	__s32			activity;
	raw_spinlock_t		wait_lock;
	struct list_head	wait_list;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
	struct lockdep_map dep_map;
#endif
};

#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
#else
# define __RWSEM_DEP_MAP_INIT(lockname)
#endif

#define __RWSEM_INITIALIZER(name) \
{ 0, __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock), LIST_HEAD_INIT((name).wait_list) \
  __RWSEM_DEP_MAP_INIT(name) }

#define DECLARE_RWSEM(name) \
	struct rw_semaphore name = __RWSEM_INITIALIZER(name)

static inline void __init_rwsem(struct rw_semaphore *sem, const char *name,
				struct lock_class_key *key)
{
	__init_anon_rwsem((struct rw_anon_semaphore *)sem, name, key);
}

#define init_rwsem(sem)						\
do {								\
	static struct lock_class_key __key;			\
								\
	__init_rwsem((sem), #sem, &__key);			\
} while (0)

static inline int rwsem_is_locked(struct rw_semaphore *sem)
{
	return anon_rwsem_is_locked((struct rw_anon_semaphore *)sem);
}
#endif /* !PREEMPT_RT */

#endif /* __KERNEL__ */
#endif /* _LINUX_RWSEM_SPINLOCK_H */