Annotation of sys/sys/mplock.h, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: mplock.h,v 1.8 2005/06/17 22:33:34 niklas Exp $ */
2:
3: /*
4: * Copyright (c) 2004 Niklas Hallqvist. All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27: #ifndef _MPLOCK_H_
28: #define _MPLOCK_H_
29:
30: /*
31: * Really simple spinlock implementation with recursive capabilities.
32: * Correctness is paramount, no fancyness allowed.
33: */
34:
35: struct __mp_lock {
36: __cpu_simple_lock_t mpl_lock;
37: cpuid_t mpl_cpu;
38: int mpl_count;
39: };
40:
41: static __inline void __mp_lock_init(struct __mp_lock *);
42: static __inline void __mp_lock(struct __mp_lock *);
43: static __inline void __mp_unlock(struct __mp_lock *);
44: static __inline int __mp_release_all(struct __mp_lock *);
45: static __inline void __mp_acquire_count(struct __mp_lock *, int);
46: static __inline int __mp_lock_held(struct __mp_lock *);
47:
48: /*
49: * XXX Simplelocks macros used at "trusted" places.
50: */
51: #define SIMPLELOCK __mp_lock
52: #define SIMPLE_LOCK_INIT __mp_lock_init
53: #define SIMPLE_LOCK __mp_lock
54: #define SIMPLE_UNLOCK __mp_unlock
55:
56: static __inline void
57: __mp_lock_init(struct __mp_lock *lock)
58: {
59: __cpu_simple_lock_init(&lock->mpl_lock);
60: lock->mpl_cpu = LK_NOCPU;
61: lock->mpl_count = 0;
62: }
63:
64: #if defined(MP_LOCKDEBUG)
65: #ifndef DDB
66: #error "MP_LOCKDEBUG requires DDB"
67: #endif
68:
69: extern void Debugger(void);
70: extern int db_printf(const char *, ...)
71: __attribute__((__format__(__kprintf__,1,2)));
72:
73: /* CPU-dependent timing, needs this to be settable from ddb. */
74: extern int __mp_lock_spinout;
75: #endif
76:
77: static __inline void
78: __mp_lock(struct __mp_lock *lock)
79: {
80: int s = spllock();
81:
82: if (lock->mpl_cpu != cpu_number()) {
83: #ifndef MP_LOCKDEBUG
84: __cpu_simple_lock(&lock->mpl_lock);
85: #else
86: {
87: int got_it;
88: do {
89: int ticks = __mp_lock_spinout;
90:
91: do {
92: got_it = __cpu_simple_lock_try(
93: &lock->mpl_lock);
94: } while (!got_it && ticks-- > 0);
95: if (!got_it) {
96: db_printf(
97: "__mp_lock(0x%x): lock spun out",
98: lock);
99: Debugger();
100: }
101: } while (!got_it);
102: }
103: #endif
104: lock->mpl_cpu = cpu_number();
105: }
106: lock->mpl_count++;
107: splx(s);
108: }
109:
110: /*
111: * Try to acquire the lock, if another cpu has it, fill it in the
112: * call-by-reference cpu parameter. Return true if acquired.
113: */
114: static __inline int
115: __mp_lock_try(struct __mp_lock *lock, cpuid_t *cpu)
116: {
117: int s = spllock();
118:
119: if (lock->mpl_cpu != cpu_number()) {
120: if (!__cpu_simple_lock_try(&lock->mpl_lock)) {
121: *cpu = lock->mpl_cpu;
122: splx(s);
123: return 0;
124: }
125: lock->mpl_cpu = cpu_number();
126: }
127: lock->mpl_count++;
128: splx(s);
129: return 1;
130: }
131:
132: static __inline void
133: __mp_unlock(struct __mp_lock *lock)
134: {
135: int s = spllock();
136:
137: #ifdef MP_LOCKDEBUG
138: if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) {
139: db_printf("__mp_unlock(0x%x): releasing not locked lock\n",
140: lock);
141: Debugger();
142: }
143: #endif
144:
145: if (--lock->mpl_count == 0) {
146: lock->mpl_cpu = LK_NOCPU;
147: __cpu_simple_unlock(&lock->mpl_lock);
148: }
149: splx(s);
150: }
151:
152: static __inline int
153: __mp_release_all(struct __mp_lock *lock) {
154: int s = spllock();
155: int rv = lock->mpl_count;
156:
157: #ifdef MP_LOCKDEBUG
158: if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) {
159: db_printf(
160: "__mp_release_all(0x%x): releasing not locked lock\n",
161: lock);
162: Debugger();
163: }
164: #endif
165:
166: lock->mpl_cpu = LK_NOCPU;
167: lock->mpl_count = 0;
168: __cpu_simple_unlock(&lock->mpl_lock);
169: splx(s);
170: return (rv);
171: }
172:
173: static __inline int
174: __mp_release_all_but_one(struct __mp_lock *lock) {
175: int s = spllock();
176: int rv = lock->mpl_count - 1;
177:
178: #ifdef MP_LOCKDEBUG
179: if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) {
180: db_printf(
181: "__mp_release_all_but_one(0x%x): releasing not locked lock\n",
182: lock);
183: Debugger();
184: }
185: #endif
186:
187: lock->mpl_count = 1;
188: splx(s);
189: return (rv);
190: }
191:
192: static __inline void
193: __mp_acquire_count(struct __mp_lock *lock, int count) {
194: int s = spllock();
195:
196: while (count--)
197: __mp_lock(lock);
198: splx(s);
199: }
200:
201: static __inline int
202: __mp_lock_held(struct __mp_lock *lock) {
203: return lock->mpl_count && lock->mpl_cpu == cpu_number();
204: }
205:
206: extern struct __mp_lock kernel_lock;
207:
208: #endif /* !_MPLOCK_H */
CVSweb