source: rtems-libbsd/rtemsbsd/rtems/rtems-kernel-sx.c @ cc7a8d8

55-freebsd-126-freebsd-12
Last change on this file since cc7a8d8 was cc7a8d8, checked in by Sebastian Huber <sebastian.huber@…>, on 11/15/17 at 10:49:09

SX(9): Implement with reader/writer lock

  • Property mode set to 100644
File size: 6.4 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bsd_rtems
5 *
6 * @brief TODO.
7 */
8
9/*
10 * Copyright (c) 2009, 2017 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * Copyright (c) 2006 John Baldwin <jhb@FreeBSD.org>
19 * All rights reserved.
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
23 * are met:
24 * 1. Redistributions of source code must retain the above copyright
25 *    notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 *    notice, this list of conditions and the following disclaimer in the
28 *    documentation and/or other materials provided with the distribution.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 */
42
43#include <machine/rtems-bsd-kernel-space.h>
44#include <machine/rtems-bsd-rwlockimpl.h>
45#include <machine/rtems-bsd-thread.h>
46
47#include <sys/param.h>
48#include <sys/types.h>
49#include <sys/systm.h>
50#include <sys/lock.h>
51#include <sys/sx.h>
52
53static void     assert_sx(const struct lock_object *lock, int what);
54static void     lock_sx(struct lock_object *lock, uintptr_t how);
55static uintptr_t unlock_sx(struct lock_object *lock);
56
57struct lock_class lock_class_sx = {
58        .lc_name = "sx",
59        .lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE,
60        .lc_assert = assert_sx,
61        .lc_lock = lock_sx,
62        .lc_unlock = unlock_sx,
63};
64
65#define sx_xholder(sx) rtems_bsd_rwlock_wowner(&(sx)->rwlock)
66
67#define sx_recursed(sx) rtems_bsd_rwlock_recursed(&(sx)->rwlock)
68
69void
70assert_sx(const struct lock_object *lock, int what)
71{
72
73        sx_assert((const struct sx *)lock, what);
74}
75
76void
77lock_sx(struct lock_object *lock, uintptr_t how)
78{
79        struct sx *sx;
80
81        sx = (struct sx *)lock;
82        if (how)
83                sx_slock(sx);
84        else
85                sx_xlock(sx);
86}
87
88uintptr_t
89unlock_sx(struct lock_object *lock)
90{
91        struct sx *sx;
92
93        sx = (struct sx *)lock;
94        sx_assert(sx, SA_LOCKED | SA_NOTRECURSED);
95        if (sx->rwlock.readers > 0) {
96                sx_sunlock(sx);
97                return (1);
98        } else {
99                sx_xunlock(sx);
100                return (0);
101        }
102}
103
104void
105sx_sysinit(void *arg)
106{
107        struct sx_args *sargs = arg;
108
109        sx_init(sargs->sa_sx, sargs->sa_desc);
110}
111
112void
113sx_init_flags(struct sx *sx, const char *description, int opts)
114{
115        int flags;
116
117        flags = LO_SLEEPABLE | LO_UPGRADABLE;
118        if (opts & SX_RECURSE)
119                flags |= LO_RECURSABLE;
120
121        rtems_bsd_rwlock_init(&sx->lock_object, &sx->rwlock, &lock_class_sx,
122            description, NULL, flags);
123}
124
125void
126sx_destroy(struct sx *sx)
127{
128
129        rtems_bsd_rwlock_destroy(&sx->lock_object, &sx->rwlock);
130}
131
132int
133_sx_xlock(struct sx *sx, int opts, const char *file, int line)
134{
135
136        rtems_bsd_rwlock_wlock(&sx->lock_object, &sx->rwlock);
137        return (0);
138}
139
140int
141sx_try_xlock_(struct sx *sx, const char *file, int line)
142{
143
144        return (rtems_bsd_rwlock_try_wlock(&sx->lock_object, &sx->rwlock));
145}
146
147void
148_sx_xunlock(struct sx *sx, const char *file, int line)
149{
150
151        rtems_bsd_rwlock_wunlock(&sx->rwlock);
152}
153
154int
155sx_try_upgrade_(struct sx *sx, const char *file, int line)
156{
157
158        return (rtems_bsd_rwlock_try_upgrade(&sx->rwlock));
159}
160
161void
162sx_downgrade_(struct sx *sx, const char *file, int line)
163{
164
165        rtems_bsd_rwlock_downgrade(&sx->rwlock);
166}
167
168int
169_sx_slock(struct sx *sx, int opts, const char *file, int line)
170{
171
172        rtems_bsd_rwlock_rlock(&sx->lock_object, &sx->rwlock);
173        return (0);
174}
175
176int
177sx_try_slock_(struct sx *sx, const char *file, int line)
178{
179
180        return (rtems_bsd_rwlock_try_rlock(&sx->lock_object, &sx->rwlock));
181}
182
183void
184_sx_sunlock(struct sx *sx, const char *file, int line)
185{
186
187        rtems_bsd_rwlock_runlock(&sx->rwlock);
188}
189
190#ifdef INVARIANT_SUPPORT
191/*
192 * In the non-WITNESS case, sx_assert() can only detect that at least
193 * *some* thread owns an slock, but it cannot guarantee that *this*
194 * thread owns an slock.
195 */
196void
197_sx_assert(const struct sx *sx, int what, const char *file, int line)
198{
199        const char *name = rtems_bsd_rwlock_name(&sx->rwlock);
200        int slocked = 0;
201
202        switch (what) {
203        case SA_SLOCKED:
204        case SA_SLOCKED | SA_NOTRECURSED:
205        case SA_SLOCKED | SA_RECURSED:
206                slocked = 1;
207                /* FALLTHROUGH */
208        case SA_LOCKED:
209        case SA_LOCKED | SA_NOTRECURSED:
210        case SA_LOCKED | SA_RECURSED:
211                /*
212                 * If some other thread has an exclusive lock or we
213                 * have one and are asserting a shared lock, fail.
214                 * Also, if no one has a lock at all, fail.
215                 */
216                if ((sx->rwlock.readers == 0 && sx_xholder(sx) == NULL) ||
217                    (sx->rwlock.readers == 0 && (slocked ||
218                    sx_xholder(sx) != _Thread_Get_executing())))
219                        panic("Lock %s not %slocked @ %s:%d\n",
220                            name, slocked ? "share " : "",
221                            file, line);
222
223                if (sx->rwlock.readers == 0) {
224                        if (sx_recursed(sx)) {
225                                if (what & SA_NOTRECURSED)
226                                        panic("Lock %s recursed @ %s:%d\n",
227                                            name, file,
228                                            line);
229                        } else if (what & SA_RECURSED)
230                                panic("Lock %s not recursed @ %s:%d\n",
231                                    name, file, line);
232                }
233                break;
234        case SA_XLOCKED:
235        case SA_XLOCKED | SA_NOTRECURSED:
236        case SA_XLOCKED | SA_RECURSED:
237                if (sx_xholder(sx) != _Thread_Get_executing())
238                        panic("Lock %s not exclusively locked @ %s:%d\n",
239                            name, file, line);
240                if (sx_recursed(sx)) {
241                        if (what & SA_NOTRECURSED)
242                                panic("Lock %s recursed @ %s:%d\n",
243                                    name, file, line);
244                } else if (what & SA_RECURSED)
245                        panic("Lock %s not recursed @ %s:%d\n",
246                            name, file, line);
247                break;
248        case SA_UNLOCKED:
249                /*
250                 * If we hold an exclusve lock fail.  We can't
251                 * reliably check to see if we hold a shared lock or
252                 * not.
253                 */
254                if (sx_xholder(sx) == _Thread_Get_executing())
255                        panic("Lock %s exclusively locked @ %s:%d\n",
256                            name, file, line);
257                break;
258        default:
259                panic("Unknown sx lock assertion: %d @ %s:%d", what, file,
260                    line);
261        }
262}
263#endif  /* INVARIANT_SUPPORT */
264
265int
266sx_xlocked(struct sx *sx)
267{
268
269        return (rtems_bsd_rwlock_wowned(&sx->rwlock));
270}
Note: See TracBrowser for help on using the repository browser.