source: rtems-libbsd/rtemsbsd/rtems/rtems-bsd-mutex.c @ ab415f9

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since ab415f9 was ab415f9, checked in by Sebastian Huber <sebastian.huber@…>, on 10/09/13 at 06:56:49

Use extension to attach a struct thread to threads

Add test thread01.

  • Property mode set to 100644
File size: 8.0 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-thread.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/mutex.h>
52#include <sys/proc.h>
53
54static void assert_mtx(struct lock_object *lock, int what);
55static void lock_mtx(struct lock_object *lock, int how);
56static void lock_spin(struct lock_object *lock, int how);
57#ifdef KDTRACE_HOOKS
58static int  owner_mtx(struct lock_object *lock, struct thread **owner);
59#endif
60static int  unlock_mtx(struct lock_object *lock);
61static int  unlock_spin(struct lock_object *lock);
62
63RTEMS_CHAIN_DEFINE_EMPTY(rtems_bsd_mtx_chain);
64
65/*
66 * Lock classes for sleep and spin mutexes.
67 */
68struct lock_class lock_class_mtx_sleep = {
69  .lc_name = "sleep mutex",
70  .lc_flags = LC_SLEEPLOCK | LC_RECURSABLE,
71  .lc_assert = assert_mtx,
72#ifdef DDB
73  .lc_ddb_show = db_show_mtx,
74#endif
75  .lc_lock = lock_mtx,
76  .lc_unlock = unlock_mtx,
77#ifdef KDTRACE_HOOKS
78  .lc_owner = owner_mtx,
79#endif
80};
81
82struct lock_class lock_class_mtx_spin = {
83  .lc_name = "spin mutex",
84  .lc_flags = LC_SPINLOCK | LC_RECURSABLE,
85  .lc_assert = assert_mtx,
86#ifdef DDB
87  .lc_ddb_show = db_show_mtx,
88#endif
89  .lc_lock = lock_spin,
90  .lc_unlock = unlock_spin,
91#ifdef KDTRACE_HOOKS
92  .lc_owner = owner_mtx,
93#endif
94};
95
96struct mtx Giant;
97
98void
99assert_mtx(struct lock_object *lock, int what)
100{
101  mtx_assert((struct mtx *)lock, what);
102}
103
104void
105lock_mtx(struct lock_object *lock, int how)
106{
107
108  mtx_lock((struct mtx *)lock);
109}
110
111void
112lock_spin(struct lock_object *lock, int how)
113{
114
115  panic("spin locks can only use msleep_spin");
116}
117
118int
119unlock_mtx(struct lock_object *lock)
120{
121  struct mtx *m;
122
123  m = (struct mtx *)lock;
124  mtx_assert(m, MA_OWNED | MA_NOTRECURSED);
125  mtx_unlock(m);
126  return (0);
127}
128
129int
130unlock_spin(struct lock_object *lock)
131{
132
133  panic("spin locks can only use msleep_spin");
134}
135
136#ifdef KDTRACE_HOOKS
137int
138owner_mtx(struct lock_object *lock, struct thread **owner)
139{
140  struct mtx *m = (struct mtx *)lock;
141
142  *owner = mtx_owner(m);
143  return (mtx_unowned(m) == 0);
144}
145#endif
146
147void
148mtx_init(struct mtx *m, const char *name, const char *type, int opts)
149{
150  struct lock_class *class;
151  int i;
152        rtems_status_code sc = RTEMS_SUCCESSFUL;
153        rtems_id id = RTEMS_ID_NONE;
154        /* rtems_attribute attr = RTEMS_LOCAL | RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY_CEILING; */
155  rtems_attribute attr = RTEMS_LOCAL | RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE;
156
157  if ((opts & MTX_RECURSE) != 0 )
158  {
159    /*FIXME*/
160  }
161
162  /* Determine lock class and lock flags. */
163  if (opts & MTX_SPIN)
164    class = &lock_class_mtx_spin;
165  else
166    class = &lock_class_mtx_sleep;
167
168  /* Check for double-init and zero object. */
169  KASSERT(!lock_initalized(&m->lock_object), ("lock \"%s\" %p already initialized", name, m->lock_object));
170
171  /* Look up lock class to find its index. */
172  for (i = 0; i < LOCK_CLASS_MAX; i++)
173  {
174    if (lock_classes[i] == class)
175    {
176      m->lock_object.lo_flags = i << LO_CLASSSHIFT;
177      break;
178    }
179  }
180  KASSERT(i < LOCK_CLASS_MAX, ("unknown lock class %p", class));
181
182        sc = rtems_semaphore_create(
183                rtems_build_name('_', 'M', 'T', 'X'),
184                1,
185                attr,
186                BSD_TASK_PRIORITY_RESOURCE_OWNER,
187                &id
188        );
189        BSD_ASSERT_SC(sc);
190
191        m->lock_object.lo_name = name;
192  m->lock_object.lo_flags |= LO_INITIALIZED;
193  m->lock_object.lo_id = id;
194
195        rtems_chain_append(&rtems_bsd_mtx_chain, &m->lock_object.lo_node);
196}
197
198void
199_mtx_lock_flags(struct mtx *m, int opts, const char *file, int line)
200{
201        rtems_status_code sc = RTEMS_SUCCESSFUL;
202
203        sc = rtems_semaphore_obtain(m->lock_object.lo_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
204        BSD_ASSERT_SC(sc);
205}
206
207int
208_mtx_trylock(struct mtx *m, int opts, const char *file, int line)
209{
210        rtems_status_code sc = RTEMS_SUCCESSFUL;
211
212        sc = rtems_semaphore_obtain(m->lock_object.lo_id, RTEMS_NO_WAIT, 0);
213        if (sc == RTEMS_SUCCESSFUL) {
214                return 1;
215        } else if (sc == RTEMS_UNSATISFIED) {
216                return 0;
217        } else {
218                BSD_ASSERT_SC(sc);
219
220                return 0;
221        }
222}
223
224void
225_mtx_unlock_flags(struct mtx *m, int opts, const char *file, int line)
226{
227        rtems_status_code sc = RTEMS_SUCCESSFUL;
228
229        sc = rtems_semaphore_release(m->lock_object.lo_id);
230        BSD_ASSERT_SC(sc);
231}
232
233/*
234 * The backing function for the INVARIANTS-enabled mtx_assert()
235 */
236#ifdef INVARIANT_SUPPORT
237void
238_mtx_assert(struct mtx *m, int what, const char *file, int line)
239{
240
241  if (panicstr != NULL || dumping)
242    return;
243  switch (what) {
244  case MA_OWNED:
245  case MA_OWNED | MA_RECURSED:
246  case MA_OWNED | MA_NOTRECURSED:
247    if (!mtx_owned(m))
248      panic("mutex %s not owned at %s:%d",
249          m->lock_object.lo_name, file, line);
250    if (mtx_recursed(m)) {
251      if ((what & MA_NOTRECURSED) != 0)
252        panic("mutex %s recursed at %s:%d",
253            m->lock_object.lo_name, file, line);
254    } else if ((what & MA_RECURSED) != 0) {
255      panic("mutex %s unrecursed at %s:%d",
256          m->lock_object.lo_name, file, line);
257    }
258    break;
259  case MA_NOTOWNED:
260    if (mtx_owned(m))
261      panic("mutex %s owned at %s:%d",
262          m->lock_object.lo_name, file, line);
263    break;
264  default:
265    panic("unknown mtx_assert at %s:%d", file, line);
266  }
267}
268#endif
269
270int mtx_owned(struct mtx *m)
271{
272        Objects_Locations location;
273        Semaphore_Control *sema = _Semaphore_Get(m->lock_object.lo_id, &location);
274
275        if (location == OBJECTS_LOCAL && !_Attributes_Is_counting_semaphore(sema->attribute_set)) {
276                int owned = sema->Core_control.mutex.holder_id == rtems_task_self();
277
278                _Thread_Enable_dispatch();
279
280                return owned;
281        } else {
282                _Thread_Enable_dispatch();
283
284                BSD_PANIC("unexpected semaphore location or attributes");
285        }
286}
287
288int mtx_recursed(struct mtx *m)
289{
290        Objects_Locations location;
291        Semaphore_Control *sema = _Semaphore_Get(m->lock_object.lo_id, &location);
292
293        if (location == OBJECTS_LOCAL && !_Attributes_Is_counting_semaphore(sema->attribute_set)) {
294                int recursed = sema->Core_control.mutex.nest_count != 0;
295
296                _Thread_Enable_dispatch();
297
298                return recursed;
299        } else {
300                _Thread_Enable_dispatch();
301
302                BSD_PANIC("unexpected semaphore location or attributes");
303        }
304}
305
306void
307mtx_sysinit(void *arg)
308{
309        struct mtx_args *margs = arg;
310
311        mtx_init(margs->ma_mtx, margs->ma_desc, NULL, margs->ma_opts);
312}
313
314void
315mtx_destroy(struct mtx *m)
316{
317        rtems_status_code sc = RTEMS_SUCCESSFUL;
318
319        sc = rtems_semaphore_delete(m->lock_object.lo_id);
320        BSD_ASSERT_SC(sc);
321
322        rtems_chain_extract(&m->lock_object.lo_node);
323
324  m->lock_object.lo_id = 0;
325  m->lock_object.lo_flags &= ~LO_INITIALIZED;
326}
327
328void
329mutex_init(void)
330{
331        mtx_init(&Giant, "Giant", NULL, MTX_DEF | MTX_RECURSE);
332}
Note: See TracBrowser for help on using the repository browser.