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
41 /*
42 * Validate lock usage in libc by creating fake locks
43 * to be used during testing
44 */
45
46 #define _LOCK_T intptr_t*
47
48 intptr_t __lock___libc_recursive_mutex;
49
50 #define MAX_LOCKS 32
51
52 static intptr_t locks[MAX_LOCKS];
53 static uint8_t in_use[MAX_LOCKS];
54
55 /* Create a new dynamic non-recursive lock */
__retarget_lock_init(_LOCK_T * lock)56 void __retarget_lock_init(_LOCK_T *lock)
57 {
58 int lock_id = 0;
59
60 for (lock_id = 0; lock_id < MAX_LOCKS; lock_id++)
61 if (!in_use[lock_id]) {
62 in_use[lock_id] = 1;
63 *lock = &locks[lock_id];
64 **lock = 0;
65 return;
66 }
67 assert(0);
68 }
69
70 /* Create a new dynamic recursive lock */
__retarget_lock_init_recursive(_LOCK_T * lock)71 void __retarget_lock_init_recursive(_LOCK_T *lock)
72 {
73 __retarget_lock_init(lock);
74 }
75
76 /* Close dynamic non-recursive lock */
__retarget_lock_close(_LOCK_T lock)77 void __retarget_lock_close(_LOCK_T lock)
78 {
79 assert(*lock == 0);
80 int lock_id = lock - locks;
81 assert(0 <= lock_id && lock_id < MAX_LOCKS);
82 in_use[lock_id] = 0;
83 }
84
85 /* Close dynamic recursive lock */
__retarget_lock_close_recursive(_LOCK_T lock)86 void __retarget_lock_close_recursive(_LOCK_T lock)
87 {
88 __retarget_lock_close(lock);
89 }
90
91 /* Acquiure non-recursive lock */
__retarget_lock_acquire(_LOCK_T lock)92 void __retarget_lock_acquire(_LOCK_T lock)
93 {
94 assert(*lock == 0);
95 *lock = 1;
96 }
97
98 /* Acquiure recursive lock */
__retarget_lock_acquire_recursive(_LOCK_T lock)99 void __retarget_lock_acquire_recursive(_LOCK_T lock)
100 {
101 assert(*lock >= 0);
102 ++(*lock);
103 }
104
105 /* Release non-recursive lock */
__retarget_lock_release(_LOCK_T lock)106 void __retarget_lock_release(_LOCK_T lock)
107 {
108 assert(*lock == 1);
109 *lock = 0;
110 }
111
112 /* Release recursive lock */
__retarget_lock_release_recursive(_LOCK_T lock)113 void __retarget_lock_release_recursive(_LOCK_T lock)
114 {
115 assert(*lock > 0);
116 --(*lock);
117 }
118
119 __attribute__((destructor))
lock_validate(void)120 static void lock_validate(void)
121 {
122 int i;
123 for (i = 0; i < MAX_LOCKS; i++) {
124 assert(locks[i] == 0);
125 }
126
127 assert(__lock___libc_recursive_mutex == 0);
128 }
129