source: rtems-libbsd/rtemsbsd/src/rtems-bsd-sx.c @ 6ad03bf

4.115-freebsd-12freebsd-9.3
Last change on this file since 6ad03bf was 6ad03bf, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 8, 2012 at 4:31:56 PM

Remove rtems/ from includes of RTEMS specific files

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