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 <types.h>
12#include <stdio.h>
13#include <sysmem.h>
14#include <thsemap.h>
15#include <thbase.h>
16#include <thmsgbx.h>
17#include <sysclib.h>
18#include <intrman.h>
19
20#include "lwip/sys.h"
21#include "lwip/opt.h"
22#include "lwip/stats.h"
23#include "lwip/debug.h"
24#include "lwip/timeouts.h"
25#include "lwip/pbuf.h"
26#include "arch/sys_arch.h"
27
28#include "ps2ip_internal.h"
29
30static arch_message msg_pool[SYS_MAX_MESSAGES];
31static arch_message *free_head;
32
33/* Function prototypes */
34static arch_message *alloc_msg(void);
35static void free_msg(arch_message *msg);
36
37static int MsgCountSema;
38
39static arch_message *try_alloc_msg(void)
40{
41 arch_message *message;
42 int OldState;
43
44 if(PollSema(MsgCountSema)==0)
45 {
46 CpuSuspendIntr(&OldState);
47
48 message = free_head;
49 free_head = free_head->next;
50
51 CpuResumeIntr(OldState);
52 }else message=NULL;
53
54 return message;
55}
56
57static arch_message *alloc_msg(void)
58{
59 arch_message *message;
60 int OldState;
61
62 WaitSema(MsgCountSema);
63
64 CpuSuspendIntr(&OldState);
65
66 message = free_head;
67 free_head = free_head->next;
68
69 CpuResumeIntr(OldState);
70
71 return message;
72}
73
74static void free_msg(arch_message *msg)
75{
76 int oldIntr;
77
78 CpuSuspendIntr(&oldIntr);
79
80 msg->next = free_head;
81 free_head = msg;
82
83 CpuResumeIntr(oldIntr);
84 SignalSema(MsgCountSema);
85}
86
87static unsigned int
88TimeoutHandler(void* pvArg)
89{
90 iReleaseWaitThread((int)pvArg);
91 return 0;
92}
93
94static u32_t
95ComputeTimeDiff(iop_sys_clock_t* pStart,iop_sys_clock_t* pEnd)
96{
97 iop_sys_clock_t Diff;
98 u32 iSec, iUSec, iDiff;
99
100 Diff.lo=pEnd->lo-pStart->lo;
101 Diff.hi=pEnd->hi-pStart->hi - (pStart->lo>pEnd->lo);
102
103 SysClock2USec(&Diff, &iSec, &iUSec);
104 iDiff=(iSec*1000)+(iUSec/1000);
105
106 return((iDiff!=0)?iDiff:1);
107}
108
109//Create a new thread.
110sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
111{
112 iop_thread_t thp;
113 int tid, rv;
114
115 (void)name;
116
117 thp.attr = TH_C;
118 thp.option = (u32)"PS2IP";
119 thp.thread = thread;
120 thp.stacksize = stacksize;
121 thp.priority = prio;
122
123 if((tid = CreateThread(&thp)) < 0)
124 {
125 dbgprintf("sys_thread_new: CreateThread failed, EC: %d\n", tid);
126 return ERR_MEM;
127 }
128
129 if((rv = StartThread(tid, arg)) < 0)
130 {
131 dbgprintf("sys_thread_new: StartThread failed, EC: %d\n", rv);
132 DeleteThread(tid);
133 return ERR_MEM;
134 }
135
136 dbgprintf("sys_thread_new: thread %d\n", tid);
137
138 return((sys_thread_t) tid);
139}
140
141err_t sys_mbox_new(sys_mbox_t *mbox, int size)
142{
143 iop_mbx_t mbp;
144
145 (void)size;
146
147 mbp.attr = MBA_THFIFO;
148 mbp.option = (u32)"PS2IP";
149
150 if((*mbox = CreateMbx(&mbp)) < 0)
151 {
152 printf("sys_mbox_new: CreateMbx failed, EC: %d\n", *mbox);
153 return ERR_MEM;
154 }
155
156 dbgprintf("sys_mbox_new: mbox %d\n", *mbox);
157
158 return ERR_OK;
159}
160
161//Delete the messagebox, pMBox.
162void sys_mbox_free(sys_mbox_t *mbox)
163{
164 DeleteMbx(*mbox);
165}
166
167int sys_mbox_valid(sys_mbox_t *mbox){
168 return(*mbox>=0);
169}
170
171err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg){
172 arch_message *MsgPkt;
173 err_t result;
174
175 if((MsgPkt = try_alloc_msg()) != NULL){
176 MsgPkt->sys_msg = msg;
177 SendMbx(*mbox, (iop_message_t *)MsgPkt);
178 result=ERR_OK;
179 }
180 else result=ERR_MEM;
181
182 return result;
183}
184
185void sys_mbox_post(sys_mbox_t *mbox, void *msg)
186{
187 arch_message *MsgPkt;
188 MsgPkt=alloc_msg();
189 MsgPkt->sys_msg = msg;
190 SendMbx(*mbox, (iop_message_t *)MsgPkt);
191}
192
193void sys_mbox_set_invalid(sys_mbox_t *mbox)
194{
195 *mbox=SYS_MBOX_NULL;
196}
197
198static u32_t sys_arch_mbox_fetch_internal(sys_mbox_t pMBox, void** ppvMSG, u32_t TimeElaspedout, char block)
199{
200 void *pmsg;
201 u32_t TimeElasped = 0;
202 iop_sys_clock_t ClockTicks;
203 iop_sys_clock_t Start;
204 iop_sys_clock_t End;
205 int result;
206
207 pmsg = 0;
208 result = -1;
209 if(block){
210 int iPID;
211
212 iPID=GetThreadId();
213
214 if(TimeElaspedout > 0)
215 {
216 GetSystemTime(&Start);
217 USec2SysClock(TimeElaspedout * 1000, &ClockTicks);
218 SetAlarm(&ClockTicks, &TimeoutHandler, (void*)iPID);
219 }
220
221 if((result=ReceiveMbx(&pmsg, pMBox))!= 0) { return(SYS_ARCH_TIMEOUT); }
222
223 if(TimeElaspedout > 0)
224 {
225 CancelAlarm(TimeoutHandler,(void*)iPID);
226 GetSystemTime(&End);
227
228 TimeElasped = ComputeTimeDiff(&Start, &End);
229 }
230 }
231 else{
232 TimeElasped=((result=PollMbx(&pmsg, pMBox))!=0)?SYS_MBOX_EMPTY:0;
233 }
234
235 if(result==0){
236 if (pmsg != NULL)
237 {
238 *ppvMSG = ((arch_message *)pmsg)->sys_msg;
239 free_msg((arch_message *) pmsg);
240 }
241 }
242
243 //Return the number of msec waited.
244 return TimeElasped;
245}
246
247u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
248{
249 return(sys_arch_mbox_fetch_internal(*mbox, msg, timeout, 1));
250}
251
252u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg){
253 return(sys_arch_mbox_fetch_internal(*mbox, msg, 0, 0));
254}
255
256err_t sys_sem_new(sys_sem_t *sem, u8_t count)
257{
258 //Create a new semaphore. Use SA_THPRI to prevent lower-priority threads from hogging the resource.
259 iop_sema_t Sema={SA_THPRI, (u32)"PS2IP", count, 1};
260 err_t result;
261
262 if((*sem=CreateSema(&Sema))<0)
263 {
264 printf("sys_sem_new: CreateSema failed, EC: %d\n", *sem);
265 result=ERR_MEM;
266 }
267 else result=ERR_OK;
268
269 dbgprintf("sys_sem_new: CreateSema cnt %d sema %d\n", count, *sem);
270
271 return result;
272}
273
274int sys_sem_valid(sys_sem_t *sem){
275 return(*sem>=0);
276}
277
278void sys_sem_set_invalid(sys_sem_t *sem){
279 *sem=SYS_SEM_NULL;
280}
281
282u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
283{
284 u32_t result;
285
286 //Wait TimeElaspedout msec for the Sema to receive a signal.
287 if(timeout==0)
288 {
289 //Wait with no timeouts.
290 result=(WaitSema(*sem)==0)?0:SYS_ARCH_TIMEOUT;
291 }
292 else if(timeout==1)
293 {
294 //Poll.
295 result=(PollSema(*sem)==0)?0:SYS_ARCH_TIMEOUT;
296 }
297 else
298 {
299 //Use alarm to timeout.
300 iop_sys_clock_t ClockTicks;
301 iop_sys_clock_t Start;
302 iop_sys_clock_t End;
303 int iPID=GetThreadId();
304 u32_t u32WaitTime;
305
306 GetSystemTime(&Start);
307 USec2SysClock(timeout*1000,&ClockTicks);
308 SetAlarm(&ClockTicks, &TimeoutHandler, (void*)iPID);
309
310 if(WaitSema(*sem)==0){
311 CancelAlarm(TimeoutHandler,(void*)iPID);
312 GetSystemTime(&End);
313
314 u32WaitTime=ComputeTimeDiff(&Start, &End);
315 result=(u32WaitTime<=timeout)?u32WaitTime:timeout;
316 }else result=SYS_ARCH_TIMEOUT;
317 }
318
319 return result;
320}
321
322void sys_sem_signal(sys_sem_t *sem)
323{
324 SignalSema(*sem);
325}
326
327void sys_sem_free(sys_sem_t *sem)
328{
329 DeleteSema(*sem);
330}
331
332void sys_init(void)
333{
334 arch_message *prev;
335 unsigned int i;
336 iop_sema_t sema;
337
338 sema.initial=sema.max=SYS_MAX_MESSAGES;
339 sema.attr=sema.option=0;
340 MsgCountSema=CreateSema(&sema);
341
342 free_head = &msg_pool[0];
343 prev = &msg_pool[0];
344
345 for(i = 1; i < SYS_MAX_MESSAGES; i++)
346 {
347 prev->next = &msg_pool[i];
348 prev = &msg_pool[i];
349 }
350
351 //NULL-terminate free message list
352 prev->next = NULL;
353}
354
355sys_prot_t sys_arch_protect(void)
356{
357 sys_prot_t Flags;
358
359 CpuSuspendIntr(&Flags);
360 return Flags;
361}
362
363void sys_arch_unprotect(sys_prot_t Flags)
364{
365 CpuResumeIntr(Flags);
366}
367
368void *malloc(size_t size)
369{
370 int flags;
371 void *ptr;
372
373 CpuSuspendIntr(&flags);
374 ptr=AllocSysMemory(ALLOC_LAST, size, NULL);
375 CpuResumeIntr(flags);
376
377 return ptr;
378}
379
380void free(void *ptr)
381{
382 int flags;
383
384 CpuSuspendIntr(&flags);
385 FreeSysMemory(ptr);
386 CpuResumeIntr(flags);
387}
388
389void *calloc(size_t n, size_t size)
390{
391 int flags;
392 void *ptr;
393
394 CpuSuspendIntr(&flags);
395 ptr=AllocSysMemory(ALLOC_LAST, n * size, NULL);
396 CpuResumeIntr(flags);
397
398 if(ptr != NULL)
399 memset(ptr, 0, n * size);
400
401 return ptr;
402}
403
404u32_t sys_now(void)
405{
406 iop_sys_clock_t timenow;
407 u32 seconds, usecs;
408
409 GetSystemTime(&timenow);
410 SysClock2USec(&timenow, &seconds, &usecs);
411
412 return(seconds*1000 + usecs / 1000);
413}
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
u32 count
start sector of fragmented bd/file