source: rtems/cpukit/score/src/corerwlockrelease.c @ 21275b58

5
Last change on this file since 21275b58 was 89fc9345, checked in by Sebastian Huber <sebastian.huber@…>, on 09/21/17 at 13:42:45

posix: Implement self-contained POSIX rwlocks

POSIX rwlocks are now available in all configurations and no longer
depend on --enable-posix.

Update #2514.
Update #3115.

  • Property mode set to 100644
File size: 3.1 KB
Line 
1/**
2 * @file
3 *
4 * @brief Releases the RWLock
5 *
6 * @ingroup ScoreRWLock
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2006.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <rtems/score/corerwlockimpl.h>
23#include <rtems/score/assert.h>
24
25static bool _CORE_RWLock_Is_waiting_for_reading(
26  const Thread_Control *the_thread
27)
28{
29  if ( the_thread->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_READ ) {
30    return true;
31  } else {
32    _Assert( the_thread->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_WRITE );
33    return false;
34  }
35}
36
37static Thread_Control *_CORE_RWLock_Flush_filter(
38  Thread_Control       *the_thread,
39  Thread_queue_Queue   *queue,
40  Thread_queue_Context *queue_context
41)
42{
43  CORE_RWLock_Control *the_rwlock;
44
45  the_rwlock = RTEMS_CONTAINER_OF(
46    queue,
47    CORE_RWLock_Control,
48    Queue.Queue
49  );
50
51  switch ( the_rwlock->current_state ) {
52    case CORE_RWLOCK_LOCKED_FOR_READING:
53      if ( _CORE_RWLock_Is_waiting_for_reading( the_thread ) ) {
54        the_rwlock->number_of_readers += 1;
55      } else {
56        the_thread = NULL;
57      }
58      break;
59    case CORE_RWLOCK_LOCKED_FOR_WRITING:
60      the_thread = NULL;
61      break;
62    default:
63      _Assert( the_rwlock->current_state == CORE_RWLOCK_UNLOCKED );
64      if ( _CORE_RWLock_Is_waiting_for_reading( the_thread ) ) {
65        the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING;
66        the_rwlock->number_of_readers = 1;
67      } else {
68        the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
69      }
70      break;
71  }
72
73  return the_thread;
74}
75
76Status_Control _CORE_RWLock_Surrender( CORE_RWLock_Control *the_rwlock )
77{
78  Thread_queue_Context queue_context;
79
80  /*
81   *  If unlocked, then OK to read.
82   *  Otherwise, we have to block.
83   *  If locked for reading and no waiters, then OK to read.
84   *  If any thread is waiting, then we wait.
85   */
86
87  _Thread_queue_Context_initialize( &queue_context );
88  _CORE_RWLock_Acquire( the_rwlock, &queue_context );
89
90  if ( the_rwlock->current_state == CORE_RWLOCK_UNLOCKED){
91    /* This is an error at the caller site */
92    _CORE_RWLock_Release( the_rwlock, &queue_context );
93    return STATUS_SUCCESSFUL;
94  }
95
96  if ( the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_READING ) {
97    the_rwlock->number_of_readers -= 1;
98
99    if ( the_rwlock->number_of_readers != 0 ) {
100      /* must be unlocked again */
101      _CORE_RWLock_Release( the_rwlock, &queue_context );
102      return STATUS_SUCCESSFUL;
103    }
104  }
105
106  _Assert(
107    the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_WRITING
108      || ( the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_READING
109        && the_rwlock->number_of_readers == 0 )
110  );
111
112  /*
113   * Implicitly transition to "unlocked" and find another thread interested
114   * in obtaining this rwlock.
115   */
116  the_rwlock->current_state = CORE_RWLOCK_UNLOCKED;
117
118  _Thread_queue_Flush_critical(
119    &the_rwlock->Queue.Queue,
120    CORE_RWLOCK_TQ_OPERATIONS,
121    _CORE_RWLock_Flush_filter,
122    &queue_context
123  );
124  return STATUS_SUCCESSFUL;
125}
Note: See TracBrowser for help on using the repository browser.