source: rtems-libbsd/rtemsbsd/include/machine/rtems-bsd-muteximpl.h @ 62c8ca0

55-freebsd-126-freebsd-12
Last change on this file since 62c8ca0 was 62c8ca0, checked in by Sebastian Huber <sebastian.huber@…>, on May 18, 2017 at 7:35:46 AM

Fix INVARIANTS support

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bsd_machine
5 *
6 * @brief Implementation of a mutex with a simple priority inheritance
7 * protocol.
8 */
9
10/*
11 * Copyright (c) 2014, 2017 embedded brains GmbH.  All rights reserved.
12 *
13 *  embedded brains GmbH
14 *  Dornierstr. 4
15 *  82178 Puchheim
16 *  Germany
17 *  <rtems@embedded-brains.de>
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 *    notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 *    notice, this list of conditions and the following disclaimer in the
26 *    documentation and/or other materials provided with the distribution.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 */
40
41#ifndef _RTEMS_BSD_MACHINE_RTEMS_BSD_MUTEXIMPL_H_
42#define _RTEMS_BSD_MACHINE_RTEMS_BSD_MUTEXIMPL_H_
43
44#include <machine/rtems-bsd-mutex.h>
45#include <machine/rtems-bsd-support.h>
46
47#include <sys/types.h>
48#include <sys/lock.h>
49
50#include <rtems/score/threadimpl.h>
51#include <rtems/score/threadqimpl.h>
52
53#ifdef __cplusplus
54extern "C" {
55#endif /* __cplusplus */
56
57#define RTEMS_BSD_MUTEX_TQ_OPERATIONS \
58    &_Thread_queue_Operations_priority_inherit
59
60static inline void
61rtems_bsd_mutex_init(struct lock_object *lock, rtems_bsd_mutex *m,
62    struct lock_class *class, const char *name, const char *type, int flags)
63{
64        _Thread_queue_Initialize(&m->queue, name);
65        m->nest_level = 0;
66
67        lock_init(lock, class, name, type, flags);
68}
69
70void rtems_bsd_mutex_lock_more(struct lock_object *lock, rtems_bsd_mutex *m,
71    Thread_Control *owner, Thread_Control *executing,
72    Thread_queue_Context *queue_context);
73
74#define rtems_bsd_mutex_isr_disable(isr_level, queue_context)   \
75do {                                                            \
76        _ISR_Local_disable(isr_level);                          \
77        _ISR_lock_ISR_disable_profile(                          \
78              &(queue_context)->Lock_context.Lock_context)      \
79} while (0)
80
81static inline void
82rtems_bsd_mutex_acquire_critical(rtems_bsd_mutex *m,
83    Thread_queue_Context *queue_context)
84{
85
86        _Thread_queue_Queue_acquire_critical(&m->queue.Queue,
87            &m->queue.Lock_stats, &queue_context->Lock_context.Lock_context);
88#if defined(RTEMS_SMP) && defined(RTEMS_DEBUG)
89        m->queue.owner = _SMP_lock_Who_am_I();
90#endif
91}
92
93static inline void
94rtems_bsd_mutex_release(rtems_bsd_mutex *m, ISR_Level isr_level,
95    Thread_queue_Context *queue_context)
96{
97
98#if defined(RTEMS_SMP) && defined(RTEMS_DEBUG)
99        _Assert( _Thread_queue_Is_lock_owner( &m->queue ) );
100        m->queue.owner = SMP_LOCK_NO_OWNER;
101#endif
102        _Thread_queue_Queue_release_critical(&m->queue.Queue,
103            &queue_context->Lock_context.Lock_context);
104        _ISR_Local_enable(isr_level);
105}
106
107static inline void
108rtems_bsd_mutex_set_isr_level(Thread_queue_Context *queue_context,
109    ISR_Level isr_level)
110{
111
112        _ISR_lock_Context_set_level(&queue_context->Lock_context.Lock_context,
113            isr_level);
114}
115
116static inline void
117rtems_bsd_mutex_lock(struct lock_object *lock, rtems_bsd_mutex *m)
118{
119        ISR_Level isr_level;
120        Thread_queue_Context queue_context;
121        Thread_Control *executing;
122        Thread_Control *owner;
123
124        _Thread_queue_Context_initialize(&queue_context);
125        rtems_bsd_mutex_isr_disable(isr_level, &queue_context);
126        executing = _Thread_Executing;
127        rtems_bsd_mutex_acquire_critical(m, &queue_context);
128
129        owner = m->queue.Queue.owner;
130
131        if (__predict_true(owner == NULL)) {
132                m->queue.Queue.owner = executing;
133                _Thread_Resource_count_increment(executing);
134                rtems_bsd_mutex_release(m, isr_level, &queue_context);
135        } else {
136                rtems_bsd_mutex_set_isr_level(&queue_context, isr_level);
137                rtems_bsd_mutex_lock_more(lock, m, owner, executing,
138                    &queue_context);
139        }
140}
141
142static inline int
143rtems_bsd_mutex_trylock(struct lock_object *lock, rtems_bsd_mutex *m)
144{
145        int success;
146        ISR_Level isr_level;
147        Thread_queue_Context queue_context;
148        Thread_Control *executing;
149        Thread_Control *owner;
150
151        _Thread_queue_Context_initialize(&queue_context);
152        rtems_bsd_mutex_isr_disable(isr_level, &queue_context);
153        executing = _Thread_Executing;
154        rtems_bsd_mutex_acquire_critical(m, &queue_context);
155
156        owner = m->queue.Queue.owner;
157
158        if (owner == NULL) {
159                m->queue.Queue.owner = executing;
160                _Thread_Resource_count_increment(executing);
161                success = 1;
162        } else if (owner == executing) {
163                BSD_ASSERT(lock->lo_flags & LO_RECURSABLE);
164                ++m->nest_level;
165                success = 1;
166        } else {
167                success = 0;
168        }
169
170        rtems_bsd_mutex_release(m, isr_level, &queue_context);
171
172        return (success);
173}
174
175static inline void
176rtems_bsd_mutex_unlock(rtems_bsd_mutex *m)
177{
178        ISR_Level isr_level;
179        Thread_queue_Context queue_context;
180        Thread_Control *owner;
181        int nest_level;
182
183        _Thread_queue_Context_initialize(&queue_context);
184        rtems_bsd_mutex_isr_disable(isr_level, &queue_context);
185        rtems_bsd_mutex_acquire_critical(m, &queue_context);
186
187        nest_level = m->nest_level;
188        owner = m->queue.Queue.owner;
189
190        BSD_ASSERT(owner == _Thread_Executing);
191
192        if (__predict_true(nest_level == 0)) {
193                Thread_queue_Heads *heads;
194
195                heads = m->queue.Queue.heads;
196                m->queue.Queue.owner = NULL;
197                _Thread_Resource_count_decrement(owner);
198
199                if (__predict_true(heads == NULL)) {
200                        rtems_bsd_mutex_release(m, isr_level, &queue_context);
201                } else {
202                        rtems_bsd_mutex_set_isr_level(&queue_context, isr_level);
203                        _Thread_queue_Surrender(&m->queue.Queue, heads, owner,
204                            &queue_context, RTEMS_BSD_MUTEX_TQ_OPERATIONS);
205                }
206        } else {
207                m->nest_level = nest_level - 1;
208                rtems_bsd_mutex_release(m, isr_level, &queue_context);
209        }
210}
211
212static inline Thread_Control *
213rtems_bsd_mutex_owner(const rtems_bsd_mutex *m)
214{
215
216        return (m->queue.Queue.owner);
217}
218
219static inline int
220rtems_bsd_mutex_owned(const rtems_bsd_mutex *m)
221{
222
223        return (rtems_bsd_mutex_owner(m) == _Thread_Get_executing());
224}
225
226static inline int
227rtems_bsd_mutex_recursed(const rtems_bsd_mutex *m)
228{
229
230        return (m->nest_level != 0);
231}
232
233static inline const char *
234rtems_bsd_mutex_name(const rtems_bsd_mutex *m)
235{
236
237        return (m->queue.Queue.name);
238}
239
240static inline void
241rtems_bsd_mutex_destroy(struct lock_object *lock, rtems_bsd_mutex *m)
242{
243        BSD_ASSERT(m->queue.Queue.heads == NULL);
244
245        if (rtems_bsd_mutex_owned(m)) {
246                m->nest_level = 0;
247                rtems_bsd_mutex_unlock(m);
248        }
249
250        _Thread_queue_Destroy(&m->queue);
251        lock_destroy(lock);
252}
253
254#ifdef __cplusplus
255}
256#endif /* __cplusplus */
257
258#endif /* _RTEMS_BSD_MACHINE_RTEMS_BSD_MUTEXIMPL_H_ */
Note: See TracBrowser for help on using the repository browser.