source: rtems-libbsd/rtemsbsd/rtems/rtems-kernel-rwlockimpl.c @ 97a98f6

55-freebsd-126-freebsd-12
Last change on this file since 97a98f6 was 97a98f6, checked in by Sebastian Huber <sebastian.huber@…>, on 11/14/17 at 11:57:01

RWLOCK(9): Add reader/writer lock implementation

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bsd_rtems
5 *
6 * @brief TODO.
7 */
8
9/*
10 * Copyright (c) 2017 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-kernel-space.h>
41#include <machine/rtems-bsd-rwlockimpl.h>
42
43#include <rtems/score/schedulerimpl.h>
44
45void
46rtems_bsd_rwlock_wlock_more(const struct lock_object *lock,
47    rtems_bsd_rwlock *rw, Thread_Control *executing,
48    rtems_bsd_rwlock_context *context)
49{
50        Thread_Control *wowner;
51
52        wowner = rtems_bsd_rwlock_wowner(rw);
53
54        if (wowner == executing) {
55                BSD_ASSERT(lock->lo_flags & LO_RECURSABLE);
56                ++rw->nest_level;
57
58                _Thread_queue_Release(&rw->writer_queue, &context->writer);
59        } else {
60                _Thread_queue_Context_set_thread_state(&context->writer,
61                    STATES_WAITING_FOR_RWLOCK);
62                _Thread_queue_Context_set_enqueue_do_nothing_extra(
63                    &context->writer);
64                _Thread_queue_Context_set_deadlock_callout(&context->writer,
65                    _Thread_queue_Deadlock_fatal);
66                _Thread_queue_Enqueue(&rw->writer_queue.Queue,
67                    &_Thread_queue_Operations_priority, executing,
68                    &context->writer);
69        }
70}
71
72static Thread_Control *
73rtems_bsd_rwlock_flush_reader_filter(Thread_Control *reader,
74    Thread_queue_Queue *queue, Thread_queue_Context *queue_context)
75{
76        rtems_bsd_rwlock *rw;
77
78        rw = RTEMS_CONTAINER_OF(queue, rtems_bsd_rwlock, reader_queue.Queue);
79        ++rw->readers;
80        _Thread_Resource_count_increment(reader);
81        return (reader);
82}
83
84static void
85rtems_bsd_rwlock_flush_reader_post_release(Thread_queue_Queue *queue,
86    Thread_queue_Context *queue_context)
87{
88        rtems_bsd_rwlock *rw;
89        rtems_bsd_rwlock_context *context;
90
91        rw = RTEMS_CONTAINER_OF(queue, rtems_bsd_rwlock, reader_queue.Queue);
92        context = RTEMS_CONTAINER_OF(queue_context, rtems_bsd_rwlock_context,
93            reader);
94        _Thread_queue_Release(&rw->writer_queue, &context->writer);
95}
96
97void
98rtems_bsd_rwlock_wunlock_more(rtems_bsd_rwlock *rw, Thread_Control *wowner,
99    rtems_bsd_rwlock_context *context)
100{
101
102        if (!_Thread_queue_Is_empty(&rw->reader_queue.Queue)) {
103                BSD_ASSERT(rw->readers == 0);
104                rtems_bsd_rwlock_ready_waiting_readers(rw, context);
105        } else {
106                BSD_ASSERT(!_Thread_queue_Is_empty(&rw->writer_queue.Queue));
107                _Thread_queue_Surrender(&rw->writer_queue.Queue,
108                    rw->writer_queue.Queue.heads, wowner, &context->writer,
109                    &_Thread_queue_Operations_priority);
110        }
111}
112
113static void
114rtems_bsd_rwlock_reader_enqueue(Thread_queue_Queue *queue,
115    Thread_Control *executing, Per_CPU_Control *cpu_self,
116    Thread_queue_Context *queue_context
117)
118{
119        rtems_bsd_rwlock *rw;
120        rtems_bsd_rwlock_context *context;
121
122        rw = RTEMS_CONTAINER_OF(queue, rtems_bsd_rwlock, reader_queue.Queue);
123        context = RTEMS_CONTAINER_OF(queue_context, rtems_bsd_rwlock_context,
124            reader);
125        _Thread_queue_Release(&rw->writer_queue, &context->writer);
126}
127
128void
129rtems_bsd_rwlock_rlock_more(rtems_bsd_rwlock *rw,
130    rtems_bsd_rwlock_context *context)
131{
132        Thread_Control *executing;
133
134        executing = _Thread_Executing;
135
136        _Thread_queue_Context_initialize(&context->reader);
137        _Thread_queue_Context_set_thread_state(&context->reader,
138            STATES_WAITING_FOR_RWLOCK);
139        _Thread_queue_Context_set_enqueue_callout(
140            &context->reader, rtems_bsd_rwlock_reader_enqueue);
141        _Thread_queue_Context_set_deadlock_callout(&context->reader,
142            _Thread_queue_Deadlock_fatal);
143        _Thread_queue_Acquire(&rw->reader_queue, &context->reader);
144        _Thread_queue_Enqueue(&rw->reader_queue.Queue,
145            &_Thread_queue_Operations_FIFO, executing, &context->reader);
146}
147
148void
149rtems_bsd_rwlock_runlock_more(rtems_bsd_rwlock *rw,
150    rtems_bsd_rwlock_context *context)
151{
152
153        if (!_Thread_queue_Is_empty(&rw->writer_queue.Queue)) {
154                BSD_ASSERT(rw->readers == 0);
155
156                _Thread_queue_Surrender(&rw->writer_queue.Queue,
157                    rw->writer_queue.Queue.heads, NULL, &context->writer,
158                    &_Thread_queue_Operations_priority);
159        } else {
160                BSD_ASSERT(!_Thread_queue_Is_empty(&rw->reader_queue.Queue));
161                rtems_bsd_rwlock_ready_waiting_readers(rw, context);
162        }
163}
164
165void
166rtems_bsd_rwlock_ready_waiting_readers(rtems_bsd_rwlock *rw,
167    rtems_bsd_rwlock_context *context)
168{
169
170        _Thread_queue_Context_initialize(&context->reader);
171        _Thread_queue_Acquire(&rw->reader_queue, &context->reader);
172        _Thread_queue_Flush_critical(&rw->reader_queue.Queue,
173            &_Thread_queue_Operations_FIFO,
174            rtems_bsd_rwlock_flush_reader_filter,
175            rtems_bsd_rwlock_flush_reader_post_release,
176            &context->reader);
177}
Note: See TracBrowser for help on using the repository browser.