source: rtems-libbsd/rtemsbsd/rtems/rtems-bsd-rwlock.c @ de3ef24

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since de3ef24 was e599318, checked in by Sebastian Huber <sebastian.huber@…>, on 10/09/13 at 20:52:54

Update files to match FreeBSD layout

Add compatibility with Newlib header files. Some FreeBSD header files
are mapped by the translation script:

o rtems/bsd/sys/_types.h
o rtems/bsd/sys/errno.h
o rtems/bsd/sys/lock.h
o rtems/bsd/sys/param.h
o rtems/bsd/sys/resource.h
o rtems/bsd/sys/time.h
o rtems/bsd/sys/timespec.h
o rtems/bsd/sys/types.h
o rtems/bsd/sys/unistd.h

It is now possible to include <sys/socket.h> directly for example.

Generate one Makefile which builds everything including tests.

  • Property mode set to 100644
File size: 9.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bsd_rtems
5 *
6 * @brief TODO.
7 */
8
9/*
10 * Copyright (c) 2011 OPTI Medical.  All rights reserved.
11 *
12 *  OPTI Medical
13 *  235 Hembree Park Drive
14 *  Roswell, GA 30076
15 *  USA
16 *  <kevin.kirspel@optimedical.com>
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
42#include <rtems/score/objectimpl.h>
43#include <rtems/posix/rwlockimpl.h>
44
45#include <rtems/bsd/sys/param.h>
46#include <rtems/bsd/sys/types.h>
47#include <sys/systm.h>
48#include <rtems/bsd/sys/lock.h>
49#include <sys/rwlock.h>
50
51#ifndef INVARIANTS
52#define _rw_assert(rw, what, file, line)
53#endif
54
55static void assert_rw(struct lock_object *lock, int what);
56static void lock_rw(struct lock_object *lock, int how);
57#ifdef KDTRACE_HOOKS
58static int  owner_rw(struct lock_object *lock, struct thread **owner);
59#endif
60static int  unlock_rw(struct lock_object *lock);
61
62struct lock_class lock_class_rw = {
63  .lc_name = "rw",
64  .lc_flags = LC_SLEEPLOCK | LC_RECURSABLE | LC_UPGRADABLE,
65  .lc_assert = assert_rw,
66#ifdef DDB
67  .lc_ddb_show = db_show_rwlock,
68#endif
69  .lc_lock = lock_rw,
70  .lc_unlock = unlock_rw,
71#ifdef KDTRACE_HOOKS
72  .lc_owner = owner_rw,
73#endif
74};
75
76RTEMS_CHAIN_DEFINE_EMPTY(rtems_bsd_rwlock_chain);
77
78void
79assert_rw(struct lock_object *lock, int what)
80{
81  rw_assert((struct rwlock *)lock, what);
82}
83
84void
85lock_rw(struct lock_object *lock, int how)
86{
87  struct rwlock *rw;
88
89  rw = (struct rwlock *)lock;
90  if (how)
91    rw_wlock(rw);
92  else
93    rw_rlock(rw);
94}
95
96int
97unlock_rw(struct lock_object *lock)
98{
99  struct rwlock *rw;
100
101  rw = (struct rwlock *)lock;
102  rw_assert(rw, RA_LOCKED | LA_NOTRECURSED);
103  if (rw->rw_lock & RW_LOCK_READ) {
104    rw_runlock(rw);
105    return (0);
106  } else {
107    rw_wunlock(rw);
108    return (1);
109  }
110}
111
112#ifdef KDTRACE_HOOKS
113int
114owner_rw(struct lock_object *lock, struct thread **owner)
115{
116  struct rwlock *rw = (struct rwlock *)lock;
117  uintptr_t x = rw->rw_lock;
118
119  *owner = rw_wowner(rw);
120  return ((x & RW_LOCK_READ) != 0 ?  (RW_READERS(x) != 0) :
121      (*owner != NULL));
122}
123#endif
124
125void
126rw_init_flags(struct rwlock *rw, const char *name, int opts)
127{
128  struct lock_class *class;
129  int i;
130  pthread_rwlock_t lock;
131  int iret;
132
133  if ((opts & RW_RECURSE) != 0) {
134    /* FIXME */
135  }
136
137  class = &lock_class_rw;
138
139  /* Check for double-init and zero object. */
140  KASSERT(!lock_initalized(&rw->lock_object), ("lock \"%s\" %p already initialized", name, rw->lock_object));
141
142  /* Look up lock class to find its index. */
143  for (i = 0; i < LOCK_CLASS_MAX; i++)
144  {
145    if (lock_classes[i] == class)
146    {
147      rw->lock_object.lo_flags = i << LO_CLASSSHIFT;
148      break;
149    }
150  }
151  KASSERT(i < LOCK_CLASS_MAX, ("unknown lock class %p", class));
152
153  iret = pthread_rwlock_init( &lock, NULL );
154  BSD_ASSERT( iret == 0 );
155
156  rw->lock_object.lo_name = name;
157  rw->lock_object.lo_flags |= LO_INITIALIZED;
158  rw->lock_object.lo_id = lock;
159
160  rtems_chain_append(&rtems_bsd_rwlock_chain, &rw->lock_object.lo_node);
161}
162
163void
164rw_destroy(struct rwlock *rw)
165{
166  int iret;
167  pthread_rwlock_destroy( rw->lock_object.lo_id );
168  BSD_ASSERT( iret == 0 );
169  rtems_chain_extract( &rw->lock_object.lo_node );
170  rw->lock_object.lo_id = 0;
171  rw->lock_object.lo_flags &= ~LO_INITIALIZED;
172}
173
174void
175rw_sysinit(void *arg)
176{
177  struct rw_args *args = arg;
178
179  rw_init(args->ra_rw, args->ra_desc);
180}
181
182void
183rw_sysinit_flags(void *arg)
184{
185  struct rw_args_flags *args = arg;
186
187  rw_init_flags(args->ra_rw, args->ra_desc, args->ra_flags);
188}
189
190/* XXX add pthread_rwlock_is_wlocked_np( id, &wlocked )
191 * XXX    returns 0 or -1 w/error
192 * XXX    wlocked = 1 if write locked
193 * XXX
194/* XXX add pthread_rwlock_is_rlocked_np( id, &wlocked )
195 * XXX    similar behavior
196 * XXX probably want to add "unlocked" state to RTEMS SuperCore rwlock
197 * XXX
198 * XXX Rationale: This violates the API layering BADLY!!!!!
199 * XXX Consider: Adding pthread_np.h to hold np methods like FreeBSD
200 * XXX           This would avoid polluting pthread.h
201 */
202int
203rw_wowned(struct rwlock *rw)
204{
205  int                   is_locked_for_write = 0;
206  Objects_Locations     location;
207  POSIX_RWLock_Control *the_rwlock;
208
209  the_rwlock = _POSIX_RWLock_Get(&rw->lock_object.lo_id, &location);
210  switch ( location ) {
211
212    case OBJECTS_LOCAL:
213      if (the_rwlock->RWLock.current_state == CORE_RWLOCK_LOCKED_FOR_WRITING)
214        is_locked_for_write = 1;
215      _Thread_Enable_dispatch();
216      return is_locked_for_write;
217
218#if defined(RTEMS_MULTIPROCESSING)
219    case OBJECTS_REMOTE:
220#endif
221    case OBJECTS_ERROR:
222      break;
223  }
224  _Thread_Enable_dispatch();
225
226  BSD_PANIC("unexpected semaphore location or attributes");
227}
228
229void
230_rw_wlock(struct rwlock *rw, const char *file, int line)
231{
232  int iret;
233
234  iret = pthread_rwlock_wrlock( &rw->lock_object.lo_id );
235  BSD_ASSERT( iret == 0 );
236
237  return 0;
238}
239
240int
241_rw_try_wlock(struct rwlock *rw, const char *file, int line)
242{
243  int iret;
244
245  iret = pthread_rwlock_trywrlock( &rw->lock_object.lo_id );
246  if (iret == 0) {
247    return 1;
248  } else {
249    return 0;
250  }
251}
252
253void
254_rw_wunlock(struct rwlock *rw, const char *file, int line)
255{
256  int iret;
257
258  iret = pthread_rwlock_unlock( &rw->lock_object.lo_id );
259  BSD_ASSERT( iret == 0 );
260}
261
262void
263_rw_rlock(struct rwlock *rw, const char *file, int line)
264{
265  int iret;
266
267  iret = pthread_rwlock_rdlock( &rw->lock_object.lo_id );
268  BSD_ASSERT( iret == 0 );
269}
270
271int
272_rw_try_rlock(struct rwlock *rw, const char *file, int line)
273{
274  int iret;
275
276  iret = pthread_rwlock_tryrdlock( &rw->lock_object.lo_id );
277  if (iret == 0) {
278    return 1;
279  } else {
280    return 0;
281  }
282}
283
284void
285_rw_runlock(struct rwlock *rw, const char *file, int line)
286{
287  int iret;
288
289  iret = pthread_rwlock_unlock( &rw->lock_object.lo_id );
290  BSD_ASSERT( iret == 0 );
291}
292
293/*
294 * Attempt to do a non-blocking upgrade from a read lock to a write
295 * lock.  This will only succeed if this thread holds a single read
296 * lock.  Returns true if the upgrade succeeded and false otherwise.
297 */
298int
299_rw_try_upgrade(struct rwlock *rw, const char *file, int line)
300{
301  return 0; /* XXX */
302}
303
304/*
305 * Downgrade a write lock into a single read lock.
306 */
307void
308_rw_downgrade(struct rwlock *rw, const char *file, int line)
309{
310  /* XXX */
311}
312
313#ifdef INVARIANT_SUPPORT
314#ifndef INVARIANTS
315#undef _rw_assert
316#endif
317
318/*
319 * In the non-WITNESS case, rw_assert() can only detect that at least
320 * *some* thread owns an rlock, but it cannot guarantee that *this*
321 * thread owns an rlock.
322 */
323void
324_rw_assert(struct rwlock *rw, int what, const char *file, int line)
325{
326
327  if (panicstr != NULL)
328    return;
329  switch (what) {
330  case RA_LOCKED:
331  case RA_LOCKED | RA_RECURSED:
332  case RA_LOCKED | RA_NOTRECURSED:
333  case RA_RLOCKED:
334#ifdef WITNESS
335    witness_assert(&rw->lock_object, what, file, line);
336#else
337    /*
338     * If some other thread has a write lock or we have one
339     * and are asserting a read lock, fail.  Also, if no one
340     * has a lock at all, fail.
341     */
342    if (rw->rw_lock == RW_UNLOCKED ||
343        (!(rw->rw_lock & RW_LOCK_READ) && (what == RA_RLOCKED ||
344        rw_wowner(rw) != curthread)))
345      panic("Lock %s not %slocked @ %s:%d\n",
346          rw->lock_object.lo_name, (what == RA_RLOCKED) ?
347          "read " : "", file, line);
348
349    if (!(rw->rw_lock & RW_LOCK_READ)) {
350      if (rw_recursed(rw)) {
351        if (what & RA_NOTRECURSED)
352          panic("Lock %s recursed @ %s:%d\n",
353              rw->lock_object.lo_name, file,
354              line);
355      } else if (what & RA_RECURSED)
356        panic("Lock %s not recursed @ %s:%d\n",
357            rw->lock_object.lo_name, file, line);
358    }
359#endif
360    break;
361  case RA_WLOCKED:
362  case RA_WLOCKED | RA_RECURSED:
363  case RA_WLOCKED | RA_NOTRECURSED:
364    if (rw_wowner(rw) != curthread)
365      panic("Lock %s not exclusively locked @ %s:%d\n",
366          rw->lock_object.lo_name, file, line);
367    if (rw_recursed(rw)) {
368      if (what & RA_NOTRECURSED)
369        panic("Lock %s recursed @ %s:%d\n",
370            rw->lock_object.lo_name, file, line);
371    } else if (what & RA_RECURSED)
372      panic("Lock %s not recursed @ %s:%d\n",
373          rw->lock_object.lo_name, file, line);
374    break;
375  case RA_UNLOCKED:
376#ifdef WITNESS
377    witness_assert(&rw->lock_object, what, file, line);
378#else
379    /*
380     * If we hold a write lock fail.  We can't reliably check
381     * to see if we hold a read lock or not.
382     */
383    if (rw_wowner(rw) == curthread)
384      panic("Lock %s exclusively locked @ %s:%d\n",
385          rw->lock_object.lo_name, file, line);
386#endif
387    break;
388  default:
389    panic("Unknown rw lock assertion: %d @ %s:%d", what, file,
390        line);
391  }
392}
393#endif /* INVARIANT_SUPPORT */
Note: See TracBrowser for help on using the repository browser.