source: rtems-libbsd/rtemsbsd/include/machine/rtems-bsd-muteximpl.h @ 8b0bcb8

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 8b0bcb8 was 8b0bcb8, checked in by Sebastian Huber <sebastian.huber@…>, on 11/09/16 at 07:53:20

rtems-bsd-mutex: Optimize

Inline SMP lock acquire/release. Avoid stack frame for hot path.

  • Property mode set to 100644
File size: 6.4 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, 2016 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 <rtems/bsd/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);
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}
89
90static inline void
91rtems_bsd_mutex_release(rtems_bsd_mutex *m, ISR_Level isr_level,
92    Thread_queue_Context *queue_context)
93{
94
95        _Thread_queue_Queue_release_critical(&m->queue.Queue,
96            &queue_context->Lock_context.Lock_context);
97        _ISR_Local_enable(isr_level);
98}
99
100static inline void
101rtems_bsd_mutex_set_isr_level(Thread_queue_Context *queue_context,
102    ISR_Level isr_level)
103{
104
105        _ISR_lock_Context_set_level(&queue_context->Lock_context.Lock_context,
106            isr_level);
107}
108
109static inline void
110rtems_bsd_mutex_lock(struct lock_object *lock, rtems_bsd_mutex *m)
111{
112        ISR_Level isr_level;
113        Thread_queue_Context queue_context;
114        Thread_Control *executing;
115        Thread_Control *owner;
116
117        _Thread_queue_Context_initialize(&queue_context);
118        rtems_bsd_mutex_isr_disable(isr_level, &queue_context);
119        executing = _Thread_Executing;
120        rtems_bsd_mutex_acquire_critical(m, &queue_context);
121
122        owner = m->queue.Queue.owner;
123
124        if (__predict_true(owner == NULL)) {
125                m->queue.Queue.owner = executing;
126                _Thread_Resource_count_increment(executing);
127                rtems_bsd_mutex_release(m, isr_level, &queue_context);
128        } else {
129                rtems_bsd_mutex_set_isr_level(&queue_context, isr_level);
130                rtems_bsd_mutex_lock_more(lock, m, owner, executing,
131                    &queue_context);
132        }
133}
134
135static inline int
136rtems_bsd_mutex_trylock(struct lock_object *lock, rtems_bsd_mutex *m)
137{
138        int success;
139        ISR_Level isr_level;
140        Thread_queue_Context queue_context;
141        Thread_Control *executing;
142        Thread_Control *owner;
143
144        _Thread_queue_Context_initialize(&queue_context);
145        rtems_bsd_mutex_isr_disable(isr_level, &queue_context);
146        executing = _Thread_Executing;
147        rtems_bsd_mutex_acquire_critical(m, &queue_context);
148
149        owner = m->queue.Queue.owner;
150
151        if (owner == NULL) {
152                m->queue.Queue.owner = executing;
153                _Thread_Resource_count_increment(executing);
154                success = 1;
155        } else if (owner == executing) {
156                BSD_ASSERT(lock->lo_flags & LO_RECURSABLE);
157                ++m->nest_level;
158                success = 1;
159        } else {
160                success = 0;
161        }
162
163        rtems_bsd_mutex_release(m, isr_level, &queue_context);
164
165        return (success);
166}
167
168static inline void
169rtems_bsd_mutex_unlock(rtems_bsd_mutex *m)
170{
171        ISR_Level isr_level;
172        Thread_queue_Context queue_context;
173        Thread_Control *owner;
174        int nest_level;
175
176        _Thread_queue_Context_initialize(&queue_context);
177        rtems_bsd_mutex_isr_disable(isr_level, &queue_context);
178        rtems_bsd_mutex_acquire_critical(m, &queue_context);
179
180        nest_level = m->nest_level;
181        owner = m->queue.Queue.owner;
182
183        BSD_ASSERT(owner == _Thread_Executing);
184
185        if (__predict_true(nest_level == 0)) {
186                Thread_queue_Heads *heads;
187
188                heads = m->queue.Queue.heads;
189                m->queue.Queue.owner = NULL;
190                _Thread_Resource_count_decrement(owner);
191
192                if (__predict_true(heads == NULL)) {
193                        rtems_bsd_mutex_release(m, isr_level, &queue_context);
194                } else {
195                        rtems_bsd_mutex_set_isr_level(&queue_context, isr_level);
196                        _Thread_queue_Surrender(&m->queue.Queue, heads, owner,
197                            &queue_context, RTEMS_BSD_MUTEX_TQ_OPERATIONS);
198                }
199        } else {
200                m->nest_level = nest_level - 1;
201                rtems_bsd_mutex_release(m, isr_level, &queue_context);
202        }
203}
204
205static inline int
206rtems_bsd_mutex_owned(rtems_bsd_mutex *m)
207{
208
209        return (m->queue.Queue.owner == _Thread_Get_executing());
210}
211
212static inline int
213rtems_bsd_mutex_recursed(rtems_bsd_mutex *m)
214{
215
216        return (m->nest_level);
217}
218
219static inline void
220rtems_bsd_mutex_destroy(struct lock_object *lock, rtems_bsd_mutex *m)
221{
222        BSD_ASSERT(m->queue.Queue.heads == NULL);
223
224        if (rtems_bsd_mutex_owned(m)) {
225                m->nest_level = 0;
226                rtems_bsd_mutex_unlock(m);
227        }
228
229        _Thread_queue_Destroy(&m->queue);
230        lock_destroy(lock);
231}
232
233#ifdef __cplusplus
234}
235#endif /* __cplusplus */
236
237#endif /* _RTEMS_BSD_MACHINE_RTEMS_BSD_MUTEXIMPL_H_ */
Note: See TracBrowser for help on using the repository browser.