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