source: rtems-libbsd/rtemsbsd/rtems/rtems-bsd-sx.c @ 150d4d6

4.115-freebsd-12freebsd-9.3
Last change on this file since 150d4d6 was 150d4d6, checked in by Sebastian Huber <sebastian.huber@…>, on Oct 24, 2013 at 9:11:32 AM

Move content to new <machine/rtems-bsd-support.h>

  • Property mode set to 100644
File size: 8.7 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bsd_rtems
5 *
6 * @brief TODO.
7 */
8
9/*
10 * Copyright (c) 2009-2013 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 * 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#include <machine/rtems-bsd-config.h>
41#include <machine/rtems-bsd-support.h>
42
43#include <rtems/score/objectimpl.h>
44#include <rtems/rtems/attrimpl.h>
45#include <rtems/rtems/semimpl.h>
46
47#include <rtems/bsd/sys/param.h>
48#include <rtems/bsd/sys/types.h>
49#include <sys/systm.h>
50#include <rtems/bsd/sys/lock.h>
51#include <sys/sx.h>
52
53#ifndef INVARIANTS
54#define _sx_assert(sx, what, file, line)
55#endif
56
57static void assert_sx(struct lock_object *lock, int what);
58static void lock_sx(struct lock_object *lock, int how);
59#ifdef KDTRACE_HOOKS
60static int  owner_sx(struct lock_object *lock, struct thread **owner);
61#endif
62static int  unlock_sx(struct lock_object *lock);
63
64struct lock_class lock_class_sx = {
65  .lc_name = "sx",
66  .lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE,
67  .lc_assert = assert_sx,
68#ifdef DDB
69  .lc_ddb_show = db_show_sx,
70#endif
71  .lc_lock = lock_sx,
72  .lc_unlock = unlock_sx,
73#ifdef KDTRACE_HOOKS
74  .lc_owner = owner_sx,
75#endif
76};
77
78RTEMS_CHAIN_DEFINE_EMPTY(rtems_bsd_sx_chain);
79
80void
81assert_sx(struct lock_object *lock, int what)
82{
83  sx_assert((struct sx *)lock, what);
84}
85
86void
87lock_sx(struct lock_object *lock, int how)
88{
89  struct sx *sx;
90
91  sx = (struct sx *)lock;
92  if (how)
93    sx_xlock(sx);
94  else
95    sx_slock(sx);
96}
97
98int
99unlock_sx(struct lock_object *lock)
100{
101  struct sx *sx;
102
103  sx = (struct sx *)lock;
104  sx_assert(sx, SA_LOCKED | SA_NOTRECURSED);
105  if (sx_xlocked(sx)) {
106    sx_xunlock(sx);
107    return (1);
108  } else {
109    sx_sunlock(sx);
110    return (0);
111  }
112}
113
114#ifdef KDTRACE_HOOKS
115int
116owner_sx(struct lock_object *lock, struct thread **owner)
117{
118        struct sx *sx = (struct sx *)lock;
119  uintptr_t x = sx->sx_lock;
120
121        *owner = (struct thread *)SX_OWNER(x);
122        return ((x & SX_LOCK_SHARED) != 0 ? (SX_SHARERS(x) != 0) :
123      (*owner != NULL));
124}
125#endif
126
127void
128sx_sysinit(void *arg)
129{
130        struct sx_args *sargs = arg;
131
132        sx_init(sargs->sa_sx, sargs->sa_desc);
133}
134
135void
136sx_init_flags(struct sx *sx, const char *description, int opts)
137{
138  struct lock_class *class;
139  int i;
140        rtems_status_code sc = RTEMS_SUCCESSFUL;
141        rtems_id id = RTEMS_ID_NONE;
142        rtems_attribute attr = RTEMS_LOCAL | RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE;
143
144        if ((opts & SX_RECURSE) != 0) {
145                /* FIXME */
146        }
147
148  class = &lock_class_sx;
149
150  /* Check for double-init and zero object. */
151  KASSERT(!lock_initalized(&sx->lock_object), ("lock \"%s\" %p already initialized", name, sx->lock_object));
152
153  /* Look up lock class to find its index. */
154  for (i = 0; i < LOCK_CLASS_MAX; i++)
155  {
156    if (lock_classes[i] == class)
157    {
158      sx->lock_object.lo_flags = i << LO_CLASSSHIFT;
159      break;
160    }
161  }
162  KASSERT(i < LOCK_CLASS_MAX, ("unknown lock class %p", class));
163
164        sc = rtems_semaphore_create(
165                rtems_build_name( '_', 'S', 'X', ' '),
166                1,
167                attr,
168                0,
169                &id
170        );
171        BSD_ASSERT_SC(sc);
172
173        sx->lock_object.lo_name = description;
174  sx->lock_object.lo_flags |= LO_INITIALIZED;
175  sx->lock_object.lo_id = id;
176
177        rtems_chain_append(&rtems_bsd_sx_chain, &sx->lock_object.lo_node);
178}
179
180void
181sx_destroy(struct sx *sx)
182{
183        rtems_status_code sc = RTEMS_SUCCESSFUL;
184
185        sc = rtems_semaphore_delete( sx->lock_object.lo_id);
186        BSD_ASSERT_SC(sc);
187
188        rtems_chain_extract(&sx->lock_object.lo_node);
189
190  sx->lock_object.lo_id = 0;
191  sx->lock_object.lo_flags &= ~LO_INITIALIZED;
192}
193
194int
195_sx_xlock(struct sx *sx, int opts, const char *file, int line)
196{
197        rtems_status_code sc = RTEMS_SUCCESSFUL;
198
199        #warning "SX_INTERRUPTIBLE NOT SUPPORTED YET"
200        /* BSD_ASSERT((opts & SX_INTERRUPTIBLE) == 0); */
201        BSD_ASSERT(!rtems_interrupt_is_in_progress());
202       
203        sc = rtems_semaphore_obtain( sx->lock_object.lo_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
204        BSD_ASSERT_SC(sc);
205
206        return 0;
207}
208
209int
210_sx_try_xlock(struct sx *sx, const char *file, int line)
211{
212        rtems_status_code sc = RTEMS_SUCCESSFUL;
213
214        sc = rtems_semaphore_obtain( sx->lock_object.lo_id, RTEMS_NO_WAIT, 0);
215        if (sc == RTEMS_SUCCESSFUL) {
216                return 1;
217        } else if (sc == RTEMS_UNSATISFIED) {
218                return 0;
219        } else {
220                BSD_ASSERT_SC(sc);
221
222                return 0;
223        }
224}
225
226void
227_sx_xunlock(struct sx *sx, const char *file, int line)
228{
229        rtems_status_code sc = RTEMS_SUCCESSFUL;
230
231        sc = rtems_semaphore_release( sx->lock_object.lo_id);
232        BSD_ASSERT_SC(sc);
233}
234
235int
236_sx_try_upgrade(struct sx *sx, const char *file, int line)
237{
238        return 1;
239}
240
241void
242_sx_downgrade(struct sx *sx, const char *file, int line)
243{
244        /* Do nothing */
245}
246
247#ifdef INVARIANT_SUPPORT
248#ifndef INVARIANTS
249#undef  _sx_assert
250#endif
251
252/*
253 * In the non-WITNESS case, sx_assert() can only detect that at least
254 * *some* thread owns an slock, but it cannot guarantee that *this*
255 * thread owns an slock.
256 */
257void
258_sx_assert(struct sx *sx, int what, const char *file, int line)
259{
260#ifndef WITNESS
261  int slocked = 0;
262#endif
263
264  if (panicstr != NULL)
265    return;
266  switch (what) {
267  case SA_SLOCKED:
268  case SA_SLOCKED | SA_NOTRECURSED:
269  case SA_SLOCKED | SA_RECURSED:
270#ifndef WITNESS
271    slocked = 1;
272    /* FALLTHROUGH */
273#endif
274  case SA_LOCKED:
275  case SA_LOCKED | SA_NOTRECURSED:
276  case SA_LOCKED | SA_RECURSED:
277#ifdef WITNESS
278    witness_assert(&sx->lock_object, what, file, line);
279#else
280    /*
281     * If some other thread has an exclusive lock or we
282     * have one and are asserting a shared lock, fail.
283     * Also, if no one has a lock at all, fail.
284     */
285    if (sx->sx_lock == SX_LOCK_UNLOCKED ||
286        (!(sx->sx_lock & SX_LOCK_SHARED) && (slocked ||
287        sx_xholder(sx) != curthread)))
288      panic("Lock %s not %slocked @ %s:%d\n",
289          sx->lock_object.lo_name, slocked ? "share " : "",
290          file, line);
291
292    if (!(sx->sx_lock & SX_LOCK_SHARED)) {
293      if (sx_recursed(sx)) {
294        if (what & SA_NOTRECURSED)
295          panic("Lock %s recursed @ %s:%d\n",
296              sx->lock_object.lo_name, file,
297              line);
298      } else if (what & SA_RECURSED)
299        panic("Lock %s not recursed @ %s:%d\n",
300            sx->lock_object.lo_name, file, line);
301    }
302#endif
303    break;
304  case SA_XLOCKED:
305  case SA_XLOCKED | SA_NOTRECURSED:
306  case SA_XLOCKED | SA_RECURSED:
307    if (sx_xholder(sx) != curthread)
308      panic("Lock %s not exclusively locked @ %s:%d\n",
309          sx->lock_object.lo_name, file, line);
310    if (sx_recursed(sx)) {
311      if (what & SA_NOTRECURSED)
312        panic("Lock %s recursed @ %s:%d\n",
313            sx->lock_object.lo_name, file, line);
314    } else if (what & SA_RECURSED)
315      panic("Lock %s not recursed @ %s:%d\n",
316          sx->lock_object.lo_name, file, line);
317    break;
318  case SA_UNLOCKED:
319#ifdef WITNESS
320    witness_assert(&sx->lock_object, what, file, line);
321#else
322    /*
323     * If we hold an exclusve lock fail.  We can't
324     * reliably check to see if we hold a shared lock or
325     * not.
326     */
327    if (sx_xholder(sx) == curthread)
328      panic("Lock %s exclusively locked @ %s:%d\n",
329          sx->lock_object.lo_name, file, line);
330#endif
331    break;
332  default:
333    panic("Unknown sx lock assertion: %d @ %s:%d", what, file,
334        line);
335  }
336}
337#endif  /* INVARIANT_SUPPORT */
338
339int
340sx_xlocked(struct sx *sx)
341{
342        Objects_Locations location;
343        Semaphore_Control *sema = _Semaphore_Get(sx->lock_object.lo_id, &location);
344
345        if (location == OBJECTS_LOCAL && !_Attributes_Is_counting_semaphore(sema->attribute_set)) {
346                int xlocked = sema->Core_control.mutex.holder_id == rtems_task_self();
347
348                _Thread_Enable_dispatch();
349
350                return xlocked;
351        } else {
352                _Thread_Enable_dispatch();
353
354                BSD_PANIC("unexpected semaphore location or attributes");
355        }
356}
Note: See TracBrowser for help on using the repository browser.