source: rtems-libbsd/rtemsbsd/src/rtems-bsd-sx.c @ 8420b94

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 8420b94 was 8420b94, checked in by Jennifer Averett <jennifer.averett@…>, on 05/08/12 at 14:14:42

Modified copyright on rtems-bsd-xxx files to be consistant with FreeBSD copyright.

  • Property mode set to 100644
File size: 8.6 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bsd_rtems
5 *
6 * @brief TODO.
7 */
8
9/*
10 * Copyright (c) 2009, 2010 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Obere Lagerstr. 30
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
40/* Necessary to obtain some internal functions */
41#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
42
43#include <freebsd/machine/rtems-bsd-config.h>
44
45#include <freebsd/sys/param.h>
46#include <freebsd/sys/types.h>
47#include <freebsd/sys/systm.h>
48#include <freebsd/sys/lock.h>
49#include <freebsd/sys/sx.h>
50
51#ifndef INVARIANTS
52#define _sx_assert(sx, what, file, line)
53#endif
54
55static void assert_sx(struct lock_object *lock, int what);
56static void lock_sx(struct lock_object *lock, int how);
57#ifdef KDTRACE_HOOKS
58static int  owner_sx(struct lock_object *lock, struct thread **owner);
59#endif
60static int  unlock_sx(struct lock_object *lock);
61
62struct lock_class lock_class_sx = {
63  .lc_name = "sx",
64  .lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE,
65  .lc_assert = assert_sx,
66#ifdef DDB
67  .lc_ddb_show = db_show_sx,
68#endif
69  .lc_lock = lock_sx,
70  .lc_unlock = unlock_sx,
71#ifdef KDTRACE_HOOKS
72  .lc_owner = owner_sx,
73#endif
74};
75
76RTEMS_CHAIN_DEFINE_EMPTY(rtems_bsd_sx_chain);
77
78void
79assert_sx(struct lock_object *lock, int what)
80{
81  sx_assert((struct sx *)lock, what);
82}
83
84void
85lock_sx(struct lock_object *lock, int how)
86{
87  struct sx *sx;
88
89  sx = (struct sx *)lock;
90  if (how)
91    sx_xlock(sx);
92  else
93    sx_slock(sx);
94}
95
96int
97unlock_sx(struct lock_object *lock)
98{
99  struct sx *sx;
100
101  sx = (struct sx *)lock;
102  sx_assert(sx, SA_LOCKED | SA_NOTRECURSED);
103  if (sx_xlocked(sx)) {
104    sx_xunlock(sx);
105    return (1);
106  } else {
107    sx_sunlock(sx);
108    return (0);
109  }
110}
111
112#ifdef KDTRACE_HOOKS
113int
114owner_sx(struct lock_object *lock, struct thread **owner)
115{
116        struct sx *sx = (struct sx *)lock;
117  uintptr_t x = sx->sx_lock;
118
119        *owner = (struct thread *)SX_OWNER(x);
120        return ((x & SX_LOCK_SHARED) != 0 ? (SX_SHARERS(x) != 0) :
121      (*owner != NULL));
122}
123#endif
124
125void
126sx_sysinit(void *arg)
127{
128        struct sx_args *sargs = arg;
129
130        sx_init(sargs->sa_sx, sargs->sa_desc);
131}
132
133void
134sx_init_flags(struct sx *sx, const char *description, int opts)
135{
136  struct lock_class *class;
137  int i;
138        rtems_status_code sc = RTEMS_SUCCESSFUL;
139        rtems_id id = RTEMS_ID_NONE;
140        rtems_attribute attr = RTEMS_LOCAL | RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE;
141
142        if ((opts & SX_RECURSE) != 0) {
143                /* FIXME */
144        }
145
146  class = &lock_class_sx;
147
148  /* Check for double-init and zero object. */
149  KASSERT(!lock_initalized(&sx->lock_object), ("lock \"%s\" %p already initialized", name, sx->lock_object));
150
151  /* Look up lock class to find its index. */
152  for (i = 0; i < LOCK_CLASS_MAX; i++)
153  {
154    if (lock_classes[i] == class)
155    {
156      sx->lock_object.lo_flags = i << LO_CLASSSHIFT;
157      break;
158    }
159  }
160  KASSERT(i < LOCK_CLASS_MAX, ("unknown lock class %p", class));
161
162        sc = rtems_semaphore_create(
163                rtems_build_name( '_', 'S', 'X', ' '),
164                1,
165                attr,
166                0,
167                &id
168        );
169        BSD_ASSERT_SC(sc);
170
171        sx->lock_object.lo_name = description;
172  sx->lock_object.lo_flags |= LO_INITIALIZED;
173  sx->lock_object.lo_id = id;
174
175        rtems_chain_append(&rtems_bsd_sx_chain, &sx->lock_object.lo_node);
176}
177
178void
179sx_destroy(struct sx *sx)
180{
181        rtems_status_code sc = RTEMS_SUCCESSFUL;
182
183        sc = rtems_semaphore_delete( sx->lock_object.lo_id);
184        BSD_ASSERT_SC(sc);
185
186        rtems_chain_extract(&sx->lock_object.lo_node);
187
188  sx->lock_object.lo_id = 0;
189  sx->lock_object.lo_flags &= ~LO_INITIALIZED;
190}
191
192int
193_sx_xlock(struct sx *sx, int opts, const char *file, int line)
194{
195        rtems_status_code sc = RTEMS_SUCCESSFUL;
196
197        BSD_ASSERT((opts & SX_INTERRUPTIBLE) == 0);
198
199        sc = rtems_semaphore_obtain( sx->lock_object.lo_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
200        BSD_ASSERT_SC(sc);
201
202        return 0;
203}
204
205int
206_sx_try_xlock(struct sx *sx, const char *file, int line)
207{
208        rtems_status_code sc = RTEMS_SUCCESSFUL;
209
210        sc = rtems_semaphore_obtain( sx->lock_object.lo_id, RTEMS_NO_WAIT, 0);
211        if (sc == RTEMS_SUCCESSFUL) {
212                return 1;
213        } else if (sc == RTEMS_UNSATISFIED) {
214                return 0;
215        } else {
216                BSD_ASSERT_SC(sc);
217
218                return 0;
219        }
220}
221
222void
223_sx_xunlock(struct sx *sx, const char *file, int line)
224{
225        rtems_status_code sc = RTEMS_SUCCESSFUL;
226
227        sc = rtems_semaphore_release( sx->lock_object.lo_id);
228        BSD_ASSERT_SC(sc);
229}
230
231int
232_sx_try_upgrade(struct sx *sx, const char *file, int line)
233{
234        return 1;
235}
236
237void
238_sx_downgrade(struct sx *sx, const char *file, int line)
239{
240        /* Do nothing */
241}
242
243#ifdef INVARIANT_SUPPORT
244#ifndef INVARIANTS
245#undef  _sx_assert
246#endif
247
248/*
249 * In the non-WITNESS case, sx_assert() can only detect that at least
250 * *some* thread owns an slock, but it cannot guarantee that *this*
251 * thread owns an slock.
252 */
253void
254_sx_assert(struct sx *sx, int what, const char *file, int line)
255{
256#ifndef WITNESS
257  int slocked = 0;
258#endif
259
260  if (panicstr != NULL)
261    return;
262  switch (what) {
263  case SA_SLOCKED:
264  case SA_SLOCKED | SA_NOTRECURSED:
265  case SA_SLOCKED | SA_RECURSED:
266#ifndef WITNESS
267    slocked = 1;
268    /* FALLTHROUGH */
269#endif
270  case SA_LOCKED:
271  case SA_LOCKED | SA_NOTRECURSED:
272  case SA_LOCKED | SA_RECURSED:
273#ifdef WITNESS
274    witness_assert(&sx->lock_object, what, file, line);
275#else
276    /*
277     * If some other thread has an exclusive lock or we
278     * have one and are asserting a shared lock, fail.
279     * Also, if no one has a lock at all, fail.
280     */
281    if (sx->sx_lock == SX_LOCK_UNLOCKED ||
282        (!(sx->sx_lock & SX_LOCK_SHARED) && (slocked ||
283        sx_xholder(sx) != curthread)))
284      panic("Lock %s not %slocked @ %s:%d\n",
285          sx->lock_object.lo_name, slocked ? "share " : "",
286          file, line);
287
288    if (!(sx->sx_lock & SX_LOCK_SHARED)) {
289      if (sx_recursed(sx)) {
290        if (what & SA_NOTRECURSED)
291          panic("Lock %s recursed @ %s:%d\n",
292              sx->lock_object.lo_name, file,
293              line);
294      } else if (what & SA_RECURSED)
295        panic("Lock %s not recursed @ %s:%d\n",
296            sx->lock_object.lo_name, file, line);
297    }
298#endif
299    break;
300  case SA_XLOCKED:
301  case SA_XLOCKED | SA_NOTRECURSED:
302  case SA_XLOCKED | SA_RECURSED:
303    if (sx_xholder(sx) != curthread)
304      panic("Lock %s not exclusively locked @ %s:%d\n",
305          sx->lock_object.lo_name, file, line);
306    if (sx_recursed(sx)) {
307      if (what & SA_NOTRECURSED)
308        panic("Lock %s recursed @ %s:%d\n",
309            sx->lock_object.lo_name, file, line);
310    } else if (what & SA_RECURSED)
311      panic("Lock %s not recursed @ %s:%d\n",
312          sx->lock_object.lo_name, file, line);
313    break;
314  case SA_UNLOCKED:
315#ifdef WITNESS
316    witness_assert(&sx->lock_object, what, file, line);
317#else
318    /*
319     * If we hold an exclusve lock fail.  We can't
320     * reliably check to see if we hold a shared lock or
321     * not.
322     */
323    if (sx_xholder(sx) == curthread)
324      panic("Lock %s exclusively locked @ %s:%d\n",
325          sx->lock_object.lo_name, file, line);
326#endif
327    break;
328  default:
329    panic("Unknown sx lock assertion: %d @ %s:%d", what, file,
330        line);
331  }
332}
333#endif  /* INVARIANT_SUPPORT */
334
335int
336sx_xlocked(struct sx *sx)
337{
338        Objects_Locations location;
339        Semaphore_Control *sema = _Semaphore_Get(sx->lock_object.lo_id, &location);
340
341        if (location == OBJECTS_LOCAL && !_Attributes_Is_counting_semaphore(sema->attribute_set)) {
342                int xlocked = sema->Core_control.mutex.holder_id == rtems_task_self();
343
344                _Thread_Enable_dispatch();
345
346                return xlocked;
347        } else {
348                _Thread_Enable_dispatch();
349
350                BSD_PANIC("unexpected semaphore location or attributes");
351        }
352}
Note: See TracBrowser for help on using the repository browser.