1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright © 2022 Keith Packard
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * 3. Neither the name of the copyright holder nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #define _DEFAULT_SOURCE
37 #include <stdint.h>
38 #include <assert.h>
39 #include <stdlib.h>
40 #include <sys/lock.h>
41
42 #ifdef RETARGETABLE_LOCKING
43
44 /*
45 * Validate lock usage in libc by creating fake locks
46 * to be used during testing
47 */
48
49 #define _LOCK_T struct __lock*
50
51 struct __lock {
52 intptr_t val;
53 };
54
55 struct __lock __lock___libc_recursive_mutex;
56
57 #define MAX_LOCKS 32
58
59 static struct __lock locks[MAX_LOCKS];
60 static uint8_t in_use[MAX_LOCKS];
61
62 /* Create a new dynamic non-recursive lock */
__retarget_lock_init(_LOCK_T * lock)63 void __retarget_lock_init(_LOCK_T *lock)
64 {
65 int lock_id = 0;
66
67 for (lock_id = 0; lock_id < MAX_LOCKS; lock_id++)
68 if (!in_use[lock_id]) {
69 in_use[lock_id] = 1;
70 *lock = &locks[lock_id];
71 (*lock)->val = 0;
72 return;
73 }
74 assert(0);
75 }
76
77 /* Create a new dynamic recursive lock */
__retarget_lock_init_recursive(_LOCK_T * lock)78 void __retarget_lock_init_recursive(_LOCK_T *lock)
79 {
80 __retarget_lock_init(lock);
81 }
82
83 /* Close dynamic non-recursive lock */
__retarget_lock_close(_LOCK_T lock)84 void __retarget_lock_close(_LOCK_T lock)
85 {
86 assert(lock->val == 0);
87 int lock_id = lock - locks;
88 assert(0 <= lock_id && lock_id < MAX_LOCKS);
89 in_use[lock_id] = 0;
90 }
91
92 /* Close dynamic recursive lock */
__retarget_lock_close_recursive(_LOCK_T lock)93 void __retarget_lock_close_recursive(_LOCK_T lock)
94 {
95 __retarget_lock_close(lock);
96 }
97
98 /* Acquiure non-recursive lock */
__retarget_lock_acquire(_LOCK_T lock)99 void __retarget_lock_acquire(_LOCK_T lock)
100 {
101 assert(lock->val == 0);
102 lock->val = 1;
103 }
104
105 /* Acquiure recursive lock */
__retarget_lock_acquire_recursive(_LOCK_T lock)106 void __retarget_lock_acquire_recursive(_LOCK_T lock)
107 {
108 assert(lock->val >= 0);
109 ++(lock->val);
110 }
111
112 /* Release non-recursive lock */
__retarget_lock_release(_LOCK_T lock)113 void __retarget_lock_release(_LOCK_T lock)
114 {
115 assert(lock->val == 1);
116 lock->val = 0;
117 }
118
119 /* Release recursive lock */
__retarget_lock_release_recursive(_LOCK_T lock)120 void __retarget_lock_release_recursive(_LOCK_T lock)
121 {
122 assert(lock->val > 0);
123 --(lock->val);
124 }
125
126 __attribute__((destructor))
lock_validate(void)127 static void lock_validate(void)
128 {
129 int i;
130 for (i = 0; i < MAX_LOCKS; i++) {
131 assert(locks[i].val == 0);
132 }
133
134 assert(__lock___libc_recursive_mutex.val == 0);
135 }
136
137 #endif
138