PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
thevent.c
1#include "thevent.h"
2#include "intrman.h"
3#include "kerr.h"
4#include "thcommon.h"
5#include "list.h"
6
7static void event_get_status(struct event_flag *event, iop_event_info_t *info);
8
9int CreateEventFlag(iop_event_t *event_params)
10{
11 struct event_flag *event;
12 int state;
13
14 if (QueryIntrContext()) {
15 return KE_ILLEGAL_CONTEXT;
16 }
17
18 if ((event_params->attr & ~EA_MULTI) != 0) {
19 return KE_ILLEGAL_ATTR;
20 }
21
22 CpuSuspendIntr(&state);
23
24 event = heap_alloc(TAG_EVF, sizeof(*event));
25 if (!event) {
26 CpuResumeIntr(state);
27 return KE_NO_MEMORY;
28 }
29
30 event->tag.id = ++thctx.evflag_id;
31 event->event.attr = event_params->attr;
32 event->event.option = event_params->option;
33 event->init_bits = event_params->bits;
34 event->bits = event_params->bits;
35
36 list_init(&event->event.waiters);
37
38 list_insert(&thctx.event_flag, &event->evf_list);
39
40 CpuResumeIntr(state);
41
42 return MAKE_HANDLE(event);
43}
44
45int DeleteEventFlag(int ef)
46{
47 struct event_flag *event;
48 struct thread *waiter;
49 u32 waiter_count;
50 int state;
51
52 if (QueryIntrContext()) {
53 return KE_ILLEGAL_CONTEXT;
54 }
55
56 CpuSuspendIntr(&state);
57
58 event = HANDLE_PTR(ef);
59 if (!HANDLE_VERIFY(ef, TAG_EVF)) {
60 CpuResumeIntr(state);
61 return KE_UNKNOWN_EVFID;
62 }
63
64 list_for_each_safe (waiter, &event->event.waiters, queue) {
65 waiter->saved_regs->v0 = KE_WAIT_DELETE;
66 list_remove(&waiter->queue);
67 waiter->status = THS_READY;
68 readyq_insert_back(waiter);
69 }
70
71 waiter_count = event->event.waiter_count;
72 list_remove(&event->evf_list);
73 heap_free(&event->tag);
74
75 if (waiter_count) {
76 thctx.run_next = NULL;
77 return thread_leave(KE_OK, 0, state, 0);
78 }
79
80 CpuResumeIntr(state);
81
82 return KE_OK;
83}
84
85int SetEventFlag(int ef, u32 bits)
86{
87 struct event_flag *evt;
88 struct thread *thread = NULL;
89 int state, num_wakeups;
90 u32 shared_bits, *resbits;
91
92 if (QueryIntrContext()) {
93 return KE_ILLEGAL_CONTEXT;
94 }
95
96 CpuSuspendIntr(&state);
97 evt = HANDLE_PTR(ef);
98 if (!HANDLE_VERIFY(ef, TAG_EVF)) {
99 CpuResumeIntr(state);
100 return KE_UNKNOWN_EVFID;
101 }
102
103 if (bits == 0) {
104 CpuResumeIntr(state);
105 return KE_OK;
106 }
107
108 evt->bits |= bits;
109 num_wakeups = 0;
110
111 list_for_each_safe (thread, &evt->event.waiters, queue) {
112 if (!evt->bits) {
113 break;
114 }
115
116 shared_bits = thread->event_bits & evt->bits;
117 if ((thread->event_mode & WEF_OR) == 0) {
118 shared_bits = shared_bits == thread->event_bits;
119 }
120
121 if (shared_bits) {
122 // We stored the WaitEventFlag resbits arg
123 // here when waiting.
124 resbits = (u32 *)thread->saved_regs->v0;
125
126 if (resbits) {
127 *resbits = evt->bits;
128 }
129
130 if (thread->event_mode & WEF_CLEAR) {
131 evt->bits = 0;
132 }
133
134 num_wakeups++;
135
136 evt->event.waiter_count--;
137 list_remove(&thread->queue);
138 thread->status = THS_READY;
139 readyq_insert_back(thread);
140 }
141 }
142
143 if (num_wakeups == 1) {
144 readyq_remove(thread, thread->priority);
145 return thread_start(thread, state);
146 }
147
148 if (num_wakeups > 0) {
149 thctx.run_next = 0;
150 return thread_leave(KE_OK, 0, state, 0);
151 }
152
153 CpuResumeIntr(state);
154
155 return KE_OK;
156}
157
158int iSetEventFlag(int ef, u32 bits)
159{
160 struct event_flag *evt;
161 struct thread *thread;
162 u32 shared_bits, *resbits;
163
164 if (!QueryIntrContext()) {
165 return KE_ILLEGAL_CONTEXT;
166 }
167
168 evt = HANDLE_PTR(ef);
169 if (!HANDLE_VERIFY(ef, TAG_EVF)) {
170 return KE_UNKNOWN_EVFID;
171 }
172
173 if (bits == 0) {
174 return KE_OK;
175 }
176
177 evt->bits |= bits;
178
179 list_for_each_safe (thread, &evt->event.waiters, queue) {
180 if (!evt->bits) {
181 break;
182 }
183
184 shared_bits = thread->event_bits & evt->bits;
185 if ((thread->event_mode & WEF_OR) == 0) {
186 shared_bits = shared_bits == thread->event_bits;
187 }
188
189 if (shared_bits) {
190 // We stored the WaitEventFlag resbits arg
191 // here when waiting.
192 resbits = (u32 *)thread->saved_regs->v0;
193
194 if (resbits) {
195 *resbits = evt->bits;
196 }
197
198 if (thread->event_mode & WEF_CLEAR) {
199 evt->bits = 0;
200 }
201
202 evt->event.waiter_count--;
203 list_remove(&thread->queue);
204 thread->status = THS_READY;
205 readyq_insert_back(thread);
206 thctx.run_next = NULL;
207 }
208 }
209
210
211 return KE_OK;
212}
213
214int ClearEventFlag(int ef, u32 bits)
215{
216 struct event_flag *evt;
217 int state;
218
219 if (QueryIntrContext()) {
220 return KE_ILLEGAL_CONTEXT;
221 }
222
223 CpuSuspendIntr(&state);
224
225 evt = HANDLE_PTR(ef);
226 if (!HANDLE_VERIFY(ef, TAG_EVF)) {
227 CpuResumeIntr(state);
228 return KE_UNKNOWN_EVFID;
229 }
230
231 evt->bits &= bits;
232
233 CpuResumeIntr(state);
234
235 return KE_OK;
236}
237
238int iClearEventFlag(int ef, u32 bits)
239{
240 struct event_flag *evt;
241
242 if (!QueryIntrContext()) {
243 return KE_ILLEGAL_CONTEXT;
244 }
245
246 evt = HANDLE_PTR(ef);
247 if (!HANDLE_VERIFY(ef, TAG_EVF)) {
248 return KE_UNKNOWN_EVFID;
249 }
250
251 evt->bits &= bits;
252
253 return KE_OK;
254}
255
256int WaitEventFlag(int ef, u32 bits, int mode, u32 *resbits)
257{
258 struct event_flag *evt;
259 struct thread *thread;
260 u32 shared_bits;
261 int state;
262
263 if (QueryIntrContext()) {
264 return KE_ILLEGAL_CONTEXT;
265 }
266
267 if (mode & ~(WEF_AND | WEF_OR | WEF_CLEAR)) {
268 return KE_ILLEGAL_MODE;
269 }
270
271 if (bits == 0) {
272 return KE_EVF_ILPAT;
273 }
274
275 if (CpuSuspendIntr(&state) == KE_CPUDI && (thctx.debug_flags & 8)) {
276 Kprintf("WARNING: DelayThread KE_CAN_NOT_WAIT\n");
277 }
278
279 check_thread_stack();
280
281 evt = HANDLE_PTR(ef);
282 if (!HANDLE_VERIFY(ef, TAG_EVF)) {
283 CpuResumeIntr(state);
284 return KE_UNKNOWN_EVFID;
285 }
286
287 if ((evt->event.attr & EA_MULTI) == 0 && evt->event.waiter_count >= 0) {
288 CpuResumeIntr(state);
289 return KE_EVF_MULTI;
290 }
291
292 if (mode & WEF_OR) {
293 shared_bits = evt->bits & bits;
294 } else {
295 shared_bits = (evt->bits & bits) == bits;
296 }
297
298 if (shared_bits) {
299 if (resbits) {
300 *resbits = evt->bits;
301 }
302
303 if (mode & WEF_CLEAR) {
304 evt->bits = 0;
305 }
306
307 CpuResumeIntr(state);
308 return KE_OK;
309 }
310
311 thread = thctx.current_thread;
312 thread->status = THS_WAIT;
313 thread->wait_type = TSW_EVENTFLAG;
314 thread->wait_event = &evt->event;
315 thread->event_bits = bits;
316 thread->event_mode = bits;
317 thctx.run_next = NULL;
318 evt->event.waiter_count++;
319 list_insert(&evt->event.waiters, &thread->queue);
320
321 // put resbits in the return value
322 // so we can grab it in SetEventFlag
323 return thread_leave((int)resbits, 0, state, 1);
324}
325
326int PollEventFlag(int ef, u32 bits, int mode, u32 *resbits)
327{
328 struct event_flag *evt;
329 u32 shared_bits;
330 int state;
331
332 if (QueryIntrContext()) {
333 return KE_ILLEGAL_CONTEXT;
334 }
335
336 if (mode & ~(WEF_AND | WEF_OR | WEF_CLEAR)) {
337 return KE_ILLEGAL_MODE;
338 }
339
340 if (bits == 0) {
341 return KE_EVF_ILPAT;
342 }
343
344 CpuSuspendIntr(&state);
345
346 evt = HANDLE_PTR(ef);
347 if (!HANDLE_VERIFY(ef, TAG_EVF)) {
348 CpuResumeIntr(state);
349 return KE_UNKNOWN_EVFID;
350 }
351
352 if ((evt->event.attr & EA_MULTI) == 0 && evt->event.waiter_count >= 0) {
353 CpuResumeIntr(state);
354 return KE_EVF_MULTI;
355 }
356
357 if (mode & WEF_OR) {
358 shared_bits = evt->bits & bits;
359 } else {
360 shared_bits = (evt->bits & bits) == bits;
361 }
362
363 if (shared_bits == 0) {
364 CpuResumeIntr(state);
365 return KE_EVF_COND;
366 }
367
368 if (resbits) {
369 *resbits = evt->bits;
370 }
371
372 if (mode & WEF_CLEAR) {
373 evt->bits = 0;
374 }
375
376 CpuResumeIntr(state);
377
378 return KE_OK;
379}
380
381int ReferEventFlagStatus(int ef, iop_event_info_t *info)
382{
383 struct event_flag *event;
384 int state;
385
386 if (QueryIntrContext()) {
387 return KE_ILLEGAL_CONTEXT;
388 }
389
390 CpuSuspendIntr(&state);
391
392 event = HANDLE_PTR(ef);
393 if (!HANDLE_VERIFY(ef, TAG_EVF)) {
394 CpuResumeIntr(state);
395 return KE_UNKNOWN_EVFID;
396 }
397
398 event_get_status(event, info);
399
400 CpuResumeIntr(state);
401
402 return KE_OK;
403}
404
405int iReferEventFlagStatus(int ef, iop_event_info_t *info)
406{
407 struct event_flag *event;
408
409 if (!QueryIntrContext()) {
410 return KE_ILLEGAL_CONTEXT;
411 }
412
413 event = HANDLE_PTR(ef);
414 if (!HANDLE_VERIFY(ef, TAG_EVF)) {
415 return KE_UNKNOWN_EVFID;
416 }
417
418 event_get_status(event, info);
419
420 return KE_OK;
421}
422
423static void event_get_status(struct event_flag *event, iop_event_info_t *info)
424{
425 info->attr = event->event.attr;
426 info->currBits = event->bits;
427 info->initBits = event->init_bits;
428 info->numThreads = event->event.waiter_count;
429 info->option = event->event.option;
430}
int CpuResumeIntr(int state)
Definition intrman.c:227
int QueryIntrContext(void)
int CpuSuspendIntr(int *state)
Definition intrman.c:205
#define EA_MULTI
Definition thevent.h:35