source: rtems-libbsd/rtemsbsd/include/machine/rtems-bsd-muteximpl.h @ 70555d5

55-freebsd-126-freebsd-12
Last change on this file since 70555d5 was 70555d5, checked in by Sebastian Huber <sebastian.huber@…>, on 11/15/18 at 08:18:18

mutex: Avoid NULL pointer access in panic()

  • Property mode set to 100644
File size: 7.4 KB
RevLine 
[be43b79]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/*
[eae664e]11 * Copyright (c) 2014, 2018 embedded brains GmbH.  All rights reserved.
[be43b79]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
[3d1e767]47#include <sys/types.h>
[3c967ca]48#include <sys/lock.h>
[eae664e]49#include <sys/systm.h>
50
51#include <inttypes.h>
[be43b79]52
53#include <rtems/score/threadimpl.h>
[691ed15]54#include <rtems/score/threadqimpl.h>
[be43b79]55
56#ifdef __cplusplus
57extern "C" {
58#endif /* __cplusplus */
59
[691ed15]60#define RTEMS_BSD_MUTEX_TQ_OPERATIONS \
61    &_Thread_queue_Operations_priority_inherit
62
[be43b79]63static inline void
64rtems_bsd_mutex_init(struct lock_object *lock, rtems_bsd_mutex *m,
65    struct lock_class *class, const char *name, const char *type, int flags)
66{
[ee94f8a]67        _Thread_queue_Initialize(&m->queue, name);
[be43b79]68        m->nest_level = 0;
69
70        lock_init(lock, class, name, type, flags);
71}
72
[8176af1]73void rtems_bsd_mutex_lock_more(struct lock_object *lock, rtems_bsd_mutex *m,
[c0b0b3e]74    Thread_Control *owner, Thread_Control *executing,
[9546d90]75    Thread_queue_Context *queue_context);
[8176af1]76
[8b0bcb8]77#define rtems_bsd_mutex_isr_disable(isr_level, queue_context)   \
78do {                                                            \
79        _ISR_Local_disable(isr_level);                          \
80        _ISR_lock_ISR_disable_profile(                          \
81              &(queue_context)->Lock_context.Lock_context)      \
82} while (0)
83
84static inline void
85rtems_bsd_mutex_acquire_critical(rtems_bsd_mutex *m,
86    Thread_queue_Context *queue_context)
87{
88
89        _Thread_queue_Queue_acquire_critical(&m->queue.Queue,
90            &m->queue.Lock_stats, &queue_context->Lock_context.Lock_context);
[f11bfc2]91#if defined(RTEMS_SMP) && defined(RTEMS_DEBUG)
92        m->queue.owner = _SMP_lock_Who_am_I();
93#endif
[8b0bcb8]94}
95
96static inline void
97rtems_bsd_mutex_release(rtems_bsd_mutex *m, ISR_Level isr_level,
98    Thread_queue_Context *queue_context)
99{
100
[f11bfc2]101#if defined(RTEMS_SMP) && defined(RTEMS_DEBUG)
102        _Assert( _Thread_queue_Is_lock_owner( &m->queue ) );
103        m->queue.owner = SMP_LOCK_NO_OWNER;
104#endif
[8b0bcb8]105        _Thread_queue_Queue_release_critical(&m->queue.Queue,
106            &queue_context->Lock_context.Lock_context);
107        _ISR_Local_enable(isr_level);
108}
109
110static inline void
111rtems_bsd_mutex_set_isr_level(Thread_queue_Context *queue_context,
112    ISR_Level isr_level)
113{
114
115        _ISR_lock_Context_set_level(&queue_context->Lock_context.Lock_context,
116            isr_level);
117}
118
[be43b79]119static inline void
120rtems_bsd_mutex_lock(struct lock_object *lock, rtems_bsd_mutex *m)
121{
[8b0bcb8]122        ISR_Level isr_level;
[9546d90]123        Thread_queue_Context queue_context;
[be43b79]124        Thread_Control *executing;
125        Thread_Control *owner;
126
[70d52b8]127        _Thread_queue_Context_initialize(&queue_context);
[8b0bcb8]128        rtems_bsd_mutex_isr_disable(isr_level, &queue_context);
129        executing = _Thread_Executing;
130        rtems_bsd_mutex_acquire_critical(m, &queue_context);
[be43b79]131
[bf7faad]132        owner = m->queue.Queue.owner;
[be43b79]133
[8176af1]134        if (__predict_true(owner == NULL)) {
[bf7faad]135                m->queue.Queue.owner = executing;
[0b08247]136                _Thread_Resource_count_increment(executing);
[8b0bcb8]137                rtems_bsd_mutex_release(m, isr_level, &queue_context);
[be43b79]138        } else {
[8b0bcb8]139                rtems_bsd_mutex_set_isr_level(&queue_context, isr_level);
[c0b0b3e]140                rtems_bsd_mutex_lock_more(lock, m, owner, executing,
[9546d90]141                    &queue_context);
[be43b79]142        }
143}
144
145static inline int
146rtems_bsd_mutex_trylock(struct lock_object *lock, rtems_bsd_mutex *m)
147{
148        int success;
[8b0bcb8]149        ISR_Level isr_level;
[9546d90]150        Thread_queue_Context queue_context;
[be43b79]151        Thread_Control *executing;
152        Thread_Control *owner;
153
[70d52b8]154        _Thread_queue_Context_initialize(&queue_context);
[8b0bcb8]155        rtems_bsd_mutex_isr_disable(isr_level, &queue_context);
156        executing = _Thread_Executing;
157        rtems_bsd_mutex_acquire_critical(m, &queue_context);
[be43b79]158
[bf7faad]159        owner = m->queue.Queue.owner;
[be43b79]160
161        if (owner == NULL) {
[bf7faad]162                m->queue.Queue.owner = executing;
[0b08247]163                _Thread_Resource_count_increment(executing);
[be43b79]164                success = 1;
165        } else if (owner == executing) {
[eae664e]166                if ((lock->lo_flags & LO_RECURSABLE) == 0) {
167                        rtems_bsd_mutex_release(m, isr_level, &queue_context);
168                        panic("mutex trylock: %s: not LO_RECURSABLE\n",
169                            m->queue.Queue.name);
170                }
171
[be43b79]172                ++m->nest_level;
173                success = 1;
174        } else {
175                success = 0;
176        }
177
[8b0bcb8]178        rtems_bsd_mutex_release(m, isr_level, &queue_context);
[be43b79]179
180        return (success);
181}
182
183static inline void
184rtems_bsd_mutex_unlock(rtems_bsd_mutex *m)
185{
[8b0bcb8]186        ISR_Level isr_level;
[9546d90]187        Thread_queue_Context queue_context;
[9bfcb86]188        Thread_Control *owner;
[eae664e]189        Thread_Control *executing;
[be43b79]190        int nest_level;
191
[70d52b8]192        _Thread_queue_Context_initialize(&queue_context);
[8b0bcb8]193        rtems_bsd_mutex_isr_disable(isr_level, &queue_context);
194        rtems_bsd_mutex_acquire_critical(m, &queue_context);
[be43b79]195
196        nest_level = m->nest_level;
[bf7faad]197        owner = m->queue.Queue.owner;
[eae664e]198        executing = _Thread_Executing;
[9bfcb86]199
[eae664e]200        if (__predict_false(owner != executing)) {
201                rtems_bsd_mutex_release(m, isr_level, &queue_context);
202                panic("mutex unlock: %s: owner 0x%08" PRIx32
203                    " != executing 0x%08" PRIx32 "\n", m->queue.Queue.name,
[70555d5]204                    owner != NULL ? owner->Object.id : 0,
205                    executing->Object.id);
[eae664e]206        }
[9bfcb86]207
[8176af1]208        if (__predict_true(nest_level == 0)) {
[07ff2c1]209                Thread_queue_Heads *heads;
[b3ff71e]210
[bf7faad]211                heads = m->queue.Queue.heads;
212                m->queue.Queue.owner = NULL;
[0b08247]213                _Thread_Resource_count_decrement(owner);
[be43b79]214
[02d344f4]215                if (__predict_true(heads == NULL)) {
[8b0bcb8]216                        rtems_bsd_mutex_release(m, isr_level, &queue_context);
[be43b79]217                } else {
[8b0bcb8]218                        rtems_bsd_mutex_set_isr_level(&queue_context, isr_level);
[02d344f4]219                        _Thread_queue_Surrender(&m->queue.Queue, heads, owner,
220                            &queue_context, RTEMS_BSD_MUTEX_TQ_OPERATIONS);
[be43b79]221                }
[8176af1]222        } else {
223                m->nest_level = nest_level - 1;
[8b0bcb8]224                rtems_bsd_mutex_release(m, isr_level, &queue_context);
[be43b79]225        }
226}
227
[62c8ca0]228static inline Thread_Control *
229rtems_bsd_mutex_owner(const rtems_bsd_mutex *m)
230{
231
232        return (m->queue.Queue.owner);
233}
234
[be43b79]235static inline int
[62c8ca0]236rtems_bsd_mutex_owned(const rtems_bsd_mutex *m)
[be43b79]237{
238
[62c8ca0]239        return (rtems_bsd_mutex_owner(m) == _Thread_Get_executing());
[be43b79]240}
241
242static inline int
[62c8ca0]243rtems_bsd_mutex_recursed(const rtems_bsd_mutex *m)
244{
245
246        return (m->nest_level != 0);
247}
248
249static inline const char *
250rtems_bsd_mutex_name(const rtems_bsd_mutex *m)
[be43b79]251{
252
[62c8ca0]253        return (m->queue.Queue.name);
[be43b79]254}
255
256static inline void
257rtems_bsd_mutex_destroy(struct lock_object *lock, rtems_bsd_mutex *m)
258{
[bf7faad]259        BSD_ASSERT(m->queue.Queue.heads == NULL);
[be43b79]260
261        if (rtems_bsd_mutex_owned(m)) {
262                m->nest_level = 0;
263                rtems_bsd_mutex_unlock(m);
264        }
265
[c5abeb5]266        _Thread_queue_Destroy(&m->queue);
[be43b79]267        lock_destroy(lock);
268}
269
270#ifdef __cplusplus
271}
272#endif /* __cplusplus */
273
274#endif /* _RTEMS_BSD_MACHINE_RTEMS_BSD_MUTEXIMPL_H_ */
Note: See TracBrowser for help on using the repository browser.