PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
sys_arch.c
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
11#include <stdlib.h>
12#include <stdio.h>
13#include <string.h>
14#include <kernel.h>
15#include <kernel_util.h>
16#include <time.h>
17#include <limits.h>
18
19#include "lwip/sys.h"
20#include "lwip/opt.h"
21#include "lwip/stats.h"
22#include "lwip/debug.h"
23#include "lwip/pbuf.h"
24#include "arch/sys_arch.h"
25
26#include "ps2ip_internal.h"
27
28static arch_message msg_pool[SYS_MAX_MESSAGES];
29static arch_message *free_head;
30
31/* Function prototypes */
32static inline arch_message *alloc_msg(void);
33static void free_msg(arch_message *msg);
34static int WaitSemaTimeout(int sema, unsigned int msec);
35
36static int MsgCountSema;
37
38extern void *_gp;
39
40static inline arch_message *try_alloc_msg(void)
41{
42 arch_message *message;
43
44 if(PollSema(MsgCountSema)==MsgCountSema)
45 {
46 DI();
47
48 message = free_head;
49 free_head = free_head->next;
50
51 EI();
52 }else message=NULL;
53
54 return message;
55}
56
57static inline arch_message *alloc_msg(void)
58{
59 arch_message *message;
60
61 WaitSema(MsgCountSema);
62 DI();
63
64 message = free_head;
65 free_head = free_head->next;
66
67 EI();
68
69 return message;
70}
71
72static void free_msg(arch_message *msg)
73{
74 DI();
75
76 msg->next = free_head;
77 free_head = msg;
78
79 EI();
80 SignalSema(MsgCountSema);
81}
82
83//Create a new thread.
84sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
85{
86 ee_thread_t thp;
87 int tid, rv;
88
89 (void)name;
90
91 thp.attr = 0;
92 thp.option = 0;
93 thp.func = thread;
94 thp.stack_size = stacksize;
95 thp.stack = malloc(stacksize);
96 thp.initial_priority = prio;
97 thp.gp_reg = &_gp;
98
99 if((tid = CreateThread(&thp)) < 0)
100 {
101 dbgprintf("sys_thread_new: CreateThread failed, EC: %d\n", tid);
102 return ERR_MEM;
103 }
104
105 if((rv = StartThread(tid, arg)) < 0)
106 {
107 dbgprintf("sys_thread_new: StartThread failed, EC: %d\n", rv);
108 DeleteThread(tid);
109 return ERR_MEM;
110 }
111
112 dbgprintf("sys_thread_new(): %d\n", tid);
113
114 return((sys_thread_t)tid);
115}
116
117err_t sys_mbox_new(sys_mbox_t *mbox, int size)
118{
119 struct MboxData *MBox;
120 ee_sema_t sema;
121
122 (void)size;
123
124 *mbox=SYS_MBOX_NULL;
125
126 if((MBox=malloc(sizeof(struct MboxData)))!=NULL)
127 {
128 //Last = first, empty mbox.
129 MBox->LastMessage=MBox->FirstMessage=NULL;
130
131 sema.attr = 0;
132 sema.option = (u32)"PS2IP-msgcount";
133 sema.init_count=0;
134 sema.max_count=SYS_MAX_MESSAGES;
135 if((MBox->MessageCountSema=CreateSema(&sema))<0)
136 {
137 printf("sys_mbox_new: CreateMbx failed. Code: %d\n", MBox->MessageCountSema);
138 free(MBox);
139 return ERR_MEM;
140 }
141 }
142 else{
143 printf("sys_mbox_new: Out of memory.\n");
144 return ERR_MEM;
145 }
146
147 dbgprintf("sys_mbox_new(): sema %d\n", MBox->MessageCountSema);
148
149 *mbox=MBox;
150
151 return ERR_OK;
152}
153
154//Delete the messagebox, (*pMBox).
155void sys_mbox_free(sys_mbox_t *pMBox)
156{
157 arch_message *Message, *NextMessage;
158
159 /* Free all messages that were not freed yet. */
160 Message=(*pMBox)->FirstMessage;
161 while(Message!=NULL)
162 {
163 NextMessage=Message->next;
164 free_msg(Message);
165 Message=NextMessage;
166 }
167
168 /* Delete all allocated resources for this message box and mark the message box as invalid. */
169 DeleteSema((*pMBox)->MessageCountSema);
170 free((*pMBox));
171 (*pMBox)=SYS_MBOX_NULL;
172}
173
174int sys_mbox_valid(sys_mbox_t *mbox)
175{
176 return((*mbox)!=SYS_MBOX_NULL);
177}
178
179void sys_mbox_set_invalid(sys_mbox_t *mbox)
180{
181 *mbox=SYS_MBOX_NULL;
182}
183
184static void RetrieveMbxInternal(sys_mbox_t mBox, arch_message **message)
185{
186 arch_message *NextMessage;
187
188 DI();
189
190 *message=mBox->FirstMessage; //Take first message in mbox
191
192 //The next message is next. If there is no next message, NULL is assigned,
193 NextMessage=((*message != NULL) && ((unsigned int)(*message)->next!=0xFFFFFFFF))?(*message)->next:NULL;
194
195 //if the mbox only had one message, then update LastMessage as well.
196 if(mBox->FirstMessage == mBox->LastMessage)
197 mBox->LastMessage = NULL;
198
199 mBox->FirstMessage = NextMessage; //The next message becomes the first message. Or NULL, if there are no next messages.
200
201 EI();
202}
203
204static int WaitSemaTimeout(int sema, unsigned int msec)
205{
206 int ret;
207 u64 timeoutUsec;
208 u64 *timeoutPtr;
209
210 if (msec == 0) {
211 if (PollSema(sema) < 0) {
212 return -1;
213 }
214 return sema;
215 }
216
217 timeoutPtr = NULL;
218
219 if (msec > 0 && msec != UINT32_MAX) {
220 timeoutUsec = msec * 1000;
221 timeoutPtr = &timeoutUsec;
222 }
223
224 ret = WaitSemaEx(sema, 1, timeoutPtr);
225
226 if (ret < 0)
227 return -1; //Timed out.
228 return sema; //Wait condition satisfied.
229}
230
231static int ReceiveMbx(arch_message **message, sys_mbox_t mBox, u32_t timeout)
232{
233 int result;
234
235 if(timeout > 0) {
236 result = WaitSemaTimeout(mBox->MessageCountSema, timeout);
237 } else {
238 result = WaitSema(mBox->MessageCountSema);
239 }
240
241 if(result == mBox->MessageCountSema)
242 {
243 RetrieveMbxInternal(mBox, message);
244 result=0;
245 }
246 else result=-1;
247
248 return result;
249}
250
251static int PollMbx(arch_message **message, sys_mbox_t mBox)
252{
253 int result;
254
255 if(PollSema(mBox->MessageCountSema)==mBox->MessageCountSema)
256 {
257 RetrieveMbxInternal(mBox, message);
258 result=0;
259 }
260 else result=-1;
261
262 return result;
263}
264
265static u32_t sys_arch_mbox_fetch_internal(sys_mbox_t pMBox, void** ppvMSG, u32_t u32Timeout, char block)
266{
267 arch_message *pmsg;
268 unsigned int TimeElasped;
269 int result;
270
271 pmsg = NULL;
272 result = -1;
273 TimeElasped=0;
274 if(block){
275 int start;
276 start=clock();
277
278 if((result=ReceiveMbx(&pmsg, pMBox, u32Timeout))==0){
279 TimeElasped = (clock() - start) / (1000);
280 }
281 else{
282 return SYS_ARCH_TIMEOUT;
283 }
284 }
285 else{
286 TimeElasped=((result=PollMbx(&pmsg, pMBox))!=0)?SYS_MBOX_EMPTY:0;
287 }
288
289 if(result==0){
290 if (pmsg != NULL)
291 {
292 if(ppvMSG!=NULL) *ppvMSG = pmsg->sys_msg;
293 free_msg(pmsg);
294 }
295 }
296
297 //Return the number of msec waited.
298 return TimeElasped;
299}
300
301u32_t sys_arch_mbox_fetch(sys_mbox_t *pMBox, void** ppvMSG, u32_t u32Timeout)
302{
303 return sys_arch_mbox_fetch_internal(*pMBox, ppvMSG, u32Timeout, 1);
304}
305
306u32_t sys_arch_mbox_tryfetch(sys_mbox_t *pMBox, void** ppvMSG)
307{
308 return sys_arch_mbox_fetch_internal(*pMBox, ppvMSG, 0, 0);
309}
310
311static void SendMbx(sys_mbox_t *mbox, arch_message *msg, void *sys_msg){
312 DI();
313
314 /* Store the message and update the message chain for this message box. */
315 msg->sys_msg = sys_msg;
316 msg->next = NULL;
317 if((*mbox)->FirstMessage==NULL) (*mbox)->FirstMessage=msg; //If this is the first message, it goes at the front.
318 if((*mbox)->LastMessage!=NULL) (*mbox)->LastMessage->next=msg; //Otherwise, it becomes the next message of the last message.
319 (*mbox)->LastMessage=msg; //The message becomes the new message at the end of the queue.
320
321 EI();
322 SignalSema((*mbox)->MessageCountSema);
323}
324
325err_t sys_mbox_trypost(sys_mbox_t *mbox, void *sys_msg)
326{
327 arch_message *msg;
328 err_t result;
329
330 /* Attempt to allocate one more message. */
331 if((msg=try_alloc_msg())!=NULL){
332 SendMbx(mbox, msg, sys_msg);
333
334 result=ERR_OK;
335 }
336 else result=ERR_MEM;
337
338 return result;
339}
340
341void sys_mbox_post(sys_mbox_t *mbox, void *sys_msg)
342{
343 SendMbx(mbox, alloc_msg(), sys_msg);
344}
345
346err_t sys_sem_new(sys_sem_t *sem, u8_t count)
347{
348 //Create a new semaphore.
349 ee_sema_t sema;
350
351 sema.init_count = count;
352 sema.max_count = 1;
353 sema.attr = 0;
354 sema.option = (u32)"PS2IP";
355
356 if((*sem=CreateSema(&sema))<0)
357 {
358 printf("sys_sem_new: CreateSema failed, EC: %d\n", *sem);
359 return ERR_MEM;
360 }
361
362 dbgprintf("sys_sem_new: CreateSema (CNT: %d) %d\n", count, *sem);
363
364 return ERR_OK;
365}
366
367u32_t sys_arch_sem_wait(sys_sem_t *sema, u32_t timeout)
368{
369 u32_t result;
370
371 //Wait timeout msec for the Sema to receive a signal.
372 if(timeout==0)
373 {
374 //Wait with no timeouts.
375 result=(WaitSema(*sema)==*sema?0:SYS_ARCH_TIMEOUT);
376 }
377 else if(timeout==1)
378 {
379 //Poll.
380 result=(PollSema(*sema)==*sema?0:SYS_ARCH_TIMEOUT);
381 }
382 else
383 {
384 //Use alarm to timeout.
385 unsigned int start;
386 u32_t WaitTime;
387
388 start=clock();
389 if(WaitSemaTimeout(*sema, timeout) == *sema)
390 {
391 WaitTime=(clock()-start)/(1000);
392 result=(WaitTime <= timeout ? WaitTime : timeout);
393 }
394 else result=SYS_ARCH_TIMEOUT;
395 }
396
397 return result;
398}
399
400void sys_sem_signal(sys_sem_t *Sema)
401{
402 SignalSema(*Sema);
403}
404
405void sys_sem_free(sys_sem_t *Sema)
406{
407 DeleteSema(*Sema);
408}
409
410int sys_sem_valid(sys_sem_t *sem){
411 return(*sem>=0);
412}
413
414void sys_sem_set_invalid(sys_sem_t *sem){
415 *sem=SYS_SEM_NULL;
416}
417
418void sys_init(void)
419{
420 arch_message *prev;
421 unsigned int i;
422 ee_sema_t sema;
423
424 dbgprintf("sys_init: Initializing...\n");
425
426 sema.attr = 0;
427 sema.option = (u32)"PS2IP";
428 sema.init_count = sema.max_count = SYS_MAX_MESSAGES;
429 MsgCountSema=CreateSema(&sema);
430
431 free_head = &msg_pool[0];
432 prev = &msg_pool[0];
433
434 for(i = 1; i < SYS_MAX_MESSAGES; i++)
435 {
436 prev->next = &msg_pool[i];
437 prev = &msg_pool[i];
438 }
439
440 //NULL-terminate free message list
441 prev->next = NULL;
442}
443
444u32_t sys_now(void)
445{
446 return(clock()/1000);
447}
448
449sys_prot_t sys_arch_protect(void)
450{
451 return DIntr();
452}
453
454void sys_arch_unprotect(sys_prot_t level)
455{
456 if(level)
457 EIntr();
458}
459
460void *ps2ip_calloc64(size_t n, size_t size)
461{
462 void *ptr = NULL;
463 size_t sz = n * size;
464
465 if ((ptr = memalign(64, sz)) == NULL)
466 return ptr;
467
468 memset(ptr, 0, sz);
469 return ptr;
470}
u32 count
start sector of fragmented bd/file