PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
lock.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
16#include <stdint.h>
17#include <stdio.h>
18#include <stdbool.h>
19#include <stdlib.h>
20#include <reent.h>
21#include <sys/lock.h>
22#include <kernel.h>
23
24// Structure representing the lock
25struct __lock {
26 int32_t sem_id;
27 int32_t thread_id;
28 int32_t count;
29};
30
31#ifdef F___lock___sfp_recursive_mutex
32struct __lock __lock___sfp_recursive_mutex;
33#endif
34
35#ifdef F___lock___atexit_recursive_mutex
36struct __lock __lock___atexit_recursive_mutex;
37#endif
38
39#ifdef F___lock___at_quick_exit_mutex
40struct __lock __lock___at_quick_exit_mutex;
41#endif
42
43#ifdef F___lock___malloc_recursive_mutex
44struct __lock __lock___malloc_recursive_mutex;
45#endif
46
47#ifdef F___lock___env_recursive_mutex
48struct __lock __lock___env_recursive_mutex;
49#endif
50
51#ifdef F___lock___tz_mutex
52struct __lock __lock___tz_mutex;
53#endif
54
55#ifdef F___lock___dd_hash_mutex
56struct __lock __lock___dd_hash_mutex;
57#endif
58
59#ifdef F___lock___arc4random_mutex
60struct __lock __lock___arc4random_mutex;
61#endif
62
63static inline void __common_lock_init(_LOCK_T lock)
64{
65 ee_sema_t sema;
66 sema.init_count = 1;
67 sema.max_count = 1;
68 sema.option = 0;
69 sema.attr = 0;
70 sema.wait_threads = 0;
71 lock->sem_id = CreateSema(&sema);
72 lock->count = -1;
73 lock->thread_id = -1;
74}
75
76static inline void __common_lock_init_recursive(_LOCK_T lock)
77{
78 ee_sema_t sema;
79 sema.init_count = 1;
80 sema.max_count = 1;
81 sema.option = 0;
82 sema.attr = 0;
83 sema.wait_threads = 0;
84 lock->sem_id = CreateSema(&sema);
85 lock->count = 0;
86 lock->thread_id = -1;
87}
88
89static inline void __common_lock_close(_LOCK_T lock)
90{
91 DeleteSema(lock->sem_id);
92}
93
94static inline void __common_lock_close_recursive(_LOCK_T lock)
95{
96 DeleteSema(lock->sem_id);
97}
98
99#ifdef F___retarget_lock_init
100void __retarget_lock_init(_LOCK_T *lock)
101{
102 _LOCK_T new_lock = (_LOCK_T)malloc(sizeof(struct __lock));
103 __common_lock_init(new_lock);
104 *lock = new_lock;
105}
106#endif
107
108#ifdef F___retarget_lock_init_recursive
109void __retarget_lock_init_recursive(_LOCK_T *lock)
110{
111 _LOCK_T new_lock = (_LOCK_T)malloc(sizeof(struct __lock));
112 __common_lock_init_recursive(new_lock);
113 *lock = new_lock;
114}
115#endif
116
117#ifdef F___retarget_lock_close
118void __retarget_lock_close(_LOCK_T lock)
119{
120 __common_lock_close(lock);
121 free(lock);
122}
123#endif
124
125#ifdef F___retarget_lock_close_recursive
126void __retarget_lock_close_recursive(_LOCK_T lock)
127{
128 __common_lock_close_recursive(lock);
129 free(lock);
130}
131#endif
132
133#ifdef F___retarget_lock_acquire
134void __retarget_lock_acquire(_LOCK_T lock)
135{
136 WaitSema(lock->sem_id);
137}
138#endif
139
140#ifdef F___retarget_lock_acquire_recursive
141void __retarget_lock_acquire_recursive(_LOCK_T lock)
142{
143 bool starting = false;
144 int32_t thread_id = GetThreadId();
145 starting = lock->count == 0;
146 if (starting) {
147 lock->thread_id = thread_id;
148 }
149 if (lock->thread_id == thread_id) {
150 lock->count++;
151 if (starting) {
152 WaitSema(lock->sem_id);
153 }
154 } else {
155 WaitSema(lock->sem_id);
156 // Reached here means that the lock was acquired by another thread
157 // so now we need to make it ours
158 // We can't put the lock->count++ before the WaitSema because it will
159 // cause a deadlock
160 lock->thread_id = thread_id;
161 lock->count++;
162 }
163}
164#endif
165
166#ifdef F___retarget_lock_try_acquire
167int __retarget_lock_try_acquire(_LOCK_T lock)
168{
169 return PollSema(lock->sem_id) > 0 ? 0 : 1;
170}
171#endif
172
173#ifdef F___retarget_lock_try_acquire_recursive
174int __retarget_lock_try_acquire_recursive(_LOCK_T lock)
175{
176 int res = 0;
177 bool starting = false;
178 int32_t thread_id = GetThreadId();
179 starting = lock->count == 0;
180 if (starting) {
181 lock->thread_id = thread_id;
182 }
183 if (lock->thread_id == thread_id) {
184 lock->count++;
185 if (starting) {
186 res = PollSema(lock->sem_id) > 0 ? 0 : 1;
187 }
188 } else {
189 res = PollSema(lock->sem_id) > 0 ? 0 : 1;
190 // Reached here means that the lock was acquired by another thread
191 // so now we need to make it ours
192 // We can't put the lock->count++ before the WaitSema because it will
193 // cause a deadlock
194 lock->thread_id = thread_id;
195 lock->count++;
196 }
197 return res;
198}
199#endif
200
201#ifdef F___retarget_lock_release
202void __retarget_lock_release(_LOCK_T lock)
203{
204 SignalSema(lock->sem_id);
205}
206#endif
207
208#ifdef F___retarget_lock_release_recursive
209void __retarget_lock_release_recursive(_LOCK_T lock)
210{
211 bool tobeRelease = false;
212 int32_t thread_id = GetThreadId();
213 if (lock->thread_id != thread_id) {
214 // error this shouldn't never happen
215 perror("Error: Trying to release a lock that was not acquired by the current thread");
216 exit(1);
217 }
218
219 tobeRelease = lock->count == 1;
220 lock->count--;
221 if (lock->count == 0) {
222 lock->thread_id = -1;
223 }
224 if (tobeRelease) {
225 SignalSema(lock->sem_id);
226 }
227}
228#endif
229
230#ifdef F___locks_init
231extern struct __lock __lock___malloc_recursive_mutex;
232extern struct __lock __lock___atexit_recursive_mutex;
233extern struct __lock __lock___at_quick_exit_mutex;
234extern struct __lock __lock___sfp_recursive_mutex;
235extern struct __lock __lock___env_recursive_mutex;
236extern struct __lock __lock___tz_mutex;
237extern struct __lock __lock___dd_hash_mutex;
238extern struct __lock __lock___arc4random_mutex;
239
240void __locks_init()
241{
242 /* Reset stdio initialization state so __sinit will reinitialize
243 * FILE structs and their locks on next use.
244 * _impure_data lives in .data (survives BSS clear on restart via
245 * ExecPS2), while FILE structs and locks live in .bss (zeroed).
246 * Without this, __sinit skips reinitialization and uses NULL locks. */
247 _REENT_CLEANUP(_REENT) = NULL;
248
249 _LOCK_T lock_malloc = &__lock___malloc_recursive_mutex;
250 _LOCK_T lock_atexit = &__lock___atexit_recursive_mutex;
251 _LOCK_T lock_quick_exit = &__lock___at_quick_exit_mutex;
252 _LOCK_T lock_sfp = &__lock___sfp_recursive_mutex;
253 _LOCK_T lock_env = &__lock___env_recursive_mutex;
254 _LOCK_T lock_tz = &__lock___tz_mutex;
255 _LOCK_T lock_dd_hash = &__lock___dd_hash_mutex;
256 _LOCK_T lock_arc4random = &__lock___arc4random_mutex;
257
258 __common_lock_init_recursive(lock_malloc);
259 __common_lock_init_recursive(lock_atexit);
260 __common_lock_init(lock_quick_exit);
261 __common_lock_init_recursive(lock_sfp);
262 __common_lock_init_recursive(lock_env);
263 __common_lock_init(lock_tz);
264 __common_lock_init(lock_dd_hash);
265 __common_lock_init(lock_arc4random);
266}
267#endif
268
269#ifdef F___locks_deinit
270extern struct __lock __lock___malloc_recursive_mutex;
271extern struct __lock __lock___atexit_recursive_mutex;
272extern struct __lock __lock___at_quick_exit_mutex;
273extern struct __lock __lock___sfp_recursive_mutex;
274extern struct __lock __lock___env_recursive_mutex;
275extern struct __lock __lock___tz_mutex;
276extern struct __lock __lock___dd_hash_mutex;
277extern struct __lock __lock___arc4random_mutex;
278
279void __locks_deinit()
280{
281 _LOCK_T lock_malloc = &__lock___malloc_recursive_mutex;
282 _LOCK_T lock_atexit = &__lock___atexit_recursive_mutex;
283 _LOCK_T lock_quick_exit = &__lock___at_quick_exit_mutex;
284 _LOCK_T lock_sfp = &__lock___sfp_recursive_mutex;
285 _LOCK_T lock_env = &__lock___env_recursive_mutex;
286 _LOCK_T lock_tz = &__lock___tz_mutex;
287 _LOCK_T lock_dd_hash = &__lock___dd_hash_mutex;
288 _LOCK_T lock_arc4random = &__lock___arc4random_mutex;
289
290
291 __common_lock_close_recursive(lock_malloc);
292 __common_lock_close_recursive(lock_atexit);
293 __common_lock_close(lock_quick_exit);
294 __common_lock_close_recursive(lock_sfp);
295 __common_lock_close_recursive(lock_env);
296 __common_lock_close(lock_tz);
297 __common_lock_close(lock_dd_hash);
298 __common_lock_close(lock_arc4random);
299}
300#endif
Definition lock.c:25