sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
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
185/* lwIP 2.2.x distinguishes ISR-context posts from task-context posts. The
186 IOP has cooperative scheduling and no preemptive ISRs that interact with
187 the lwIP message queue, so the two are equivalent here. */
188err_t sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg){
189 return sys_mbox_trypost(mbox, msg);
190}
191
192void sys_mbox_post(sys_mbox_t *mbox, void *msg)
193{
194 arch_message *MsgPkt;
195 MsgPkt=alloc_msg();
196 MsgPkt->sys_msg = msg;
197 SendMbx(*mbox, (iop_message_t *)MsgPkt);
198}
199
200void sys_mbox_set_invalid(sys_mbox_t *mbox)
201{
202 *mbox=SYS_MBOX_NULL;
203}
204
205static u32_t sys_arch_mbox_fetch_internal(sys_mbox_t pMBox, void** ppvMSG, u32_t TimeElaspedout, char block)
206{
207 void *pmsg;
208 u32_t TimeElasped = 0;
209 iop_sys_clock_t ClockTicks;
210 iop_sys_clock_t Start;
211 iop_sys_clock_t End;
212 int result;
213
214 pmsg = 0;
215 result = -1;
216 if(block){
217 int iPID;
218
219 iPID=GetThreadId();
220
221 if(TimeElaspedout > 0)
222 {
223 GetSystemTime(&Start);
224 USec2SysClock(TimeElaspedout * 1000, &ClockTicks);
225 SetAlarm(&ClockTicks, &TimeoutHandler, (void*)iPID);
226 }
227
228 if((result=ReceiveMbx(&pmsg, pMBox))!= 0) { return(SYS_ARCH_TIMEOUT); }
229
230 if(TimeElaspedout > 0)
231 {
232 CancelAlarm(TimeoutHandler,(void*)iPID);
233 GetSystemTime(&End);
234
235 TimeElasped = ComputeTimeDiff(&Start, &End);
236 }
237 }
238 else{
239 TimeElasped=((result=PollMbx(&pmsg, pMBox))!=0)?SYS_MBOX_EMPTY:0;
240 }
241
242 if(result==0){
243 if (pmsg != NULL)
244 {
245 *ppvMSG = ((arch_message *)pmsg)->sys_msg;
246 free_msg((arch_message *) pmsg);
247 }
248 }
249
250 //Return the number of msec waited.
251 return TimeElasped;
252}
253
254u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
255{
256 return(sys_arch_mbox_fetch_internal(*mbox, msg, timeout, 1));
257}
258
259u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg){
260 return(sys_arch_mbox_fetch_internal(*mbox, msg, 0, 0));
261}
262
263err_t sys_sem_new(sys_sem_t *sem, u8_t count)
264{
265 //Create a new semaphore. Use SA_THPRI to prevent lower-priority threads from hogging the resource.
266 iop_sema_t Sema={SA_THPRI, (u32)"PS2IP", count, 1};
267 err_t result;
268
269 if((*sem=CreateSema(&Sema))<0)
270 {
271 printf("sys_sem_new: CreateSema failed, EC: %d\n", *sem);
272 result=ERR_MEM;
273 }
274 else result=ERR_OK;
275
276 dbgprintf("sys_sem_new: CreateSema cnt %d sema %d\n", count, *sem);
277
278 return result;
279}
280
281int sys_sem_valid(sys_sem_t *sem){
282 return(*sem>=0);
283}
284
285void sys_sem_set_invalid(sys_sem_t *sem){
286 *sem=SYS_SEM_NULL;
287}
288
289u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
290{
291 u32_t result;
292
293 //Wait TimeElaspedout msec for the Sema to receive a signal.
294 if(timeout==0)
295 {
296 //Wait with no timeouts.
297 result=(WaitSema(*sem)==0)?0:SYS_ARCH_TIMEOUT;
298 }
299 else if(timeout==1)
300 {
301 //Poll.
302 result=(PollSema(*sem)==0)?0:SYS_ARCH_TIMEOUT;
303 }
304 else
305 {
306 //Use alarm to timeout.
307 iop_sys_clock_t ClockTicks;
308 iop_sys_clock_t Start;
309 iop_sys_clock_t End;
310 int iPID=GetThreadId();
311 u32_t u32WaitTime;
312
313 GetSystemTime(&Start);
314 USec2SysClock(timeout*1000,&ClockTicks);
315 SetAlarm(&ClockTicks, &TimeoutHandler, (void*)iPID);
316
317 if(WaitSema(*sem)==0){
318 CancelAlarm(TimeoutHandler,(void*)iPID);
319 GetSystemTime(&End);
320
321 u32WaitTime=ComputeTimeDiff(&Start, &End);
322 result=(u32WaitTime<=timeout)?u32WaitTime:timeout;
323 }else result=SYS_ARCH_TIMEOUT;
324 }
325
326 return result;
327}
328
329void sys_sem_signal(sys_sem_t *sem)
330{
331 SignalSema(*sem);
332}
333
334void sys_sem_free(sys_sem_t *sem)
335{
336 DeleteSema(*sem);
337}
338
339void sys_init(void)
340{
341 arch_message *prev;
342 unsigned int i;
343 iop_sema_t sema;
344
345 sema.initial=sema.max=SYS_MAX_MESSAGES;
346 sema.attr=sema.option=0;
347 MsgCountSema=CreateSema(&sema);
348
349 free_head = &msg_pool[0];
350 prev = &msg_pool[0];
351
352 for(i = 1; i < SYS_MAX_MESSAGES; i++)
353 {
354 prev->next = &msg_pool[i];
355 prev = &msg_pool[i];
356 }
357
358 //NULL-terminate free message list
359 prev->next = NULL;
360}
361
362sys_prot_t sys_arch_protect(void)
363{
364 sys_prot_t Flags;
365
366 CpuSuspendIntr(&Flags);
367 return Flags;
368}
369
370void sys_arch_unprotect(sys_prot_t Flags)
371{
372 CpuResumeIntr(Flags);
373}
374
375void *malloc(size_t size)
376{
377 int flags;
378 void *ptr;
379
380 CpuSuspendIntr(&flags);
381 ptr=AllocSysMemory(ALLOC_LAST, size, NULL);
382 CpuResumeIntr(flags);
383
384 return ptr;
385}
386
387void free(void *ptr)
388{
389 int flags;
390
391 CpuSuspendIntr(&flags);
392 FreeSysMemory(ptr);
393 CpuResumeIntr(flags);
394}
395
396void *calloc(size_t n, size_t size)
397{
398 int flags;
399 void *ptr;
400
401 CpuSuspendIntr(&flags);
402 ptr=AllocSysMemory(ALLOC_LAST, n * size, NULL);
403 CpuResumeIntr(flags);
404
405 if(ptr != NULL)
406 memset(ptr, 0, n * size);
407
408 return ptr;
409}
410
411u32_t sys_now(void)
412{
413 iop_sys_clock_t timenow;
414 u32 seconds, usecs;
415
416 GetSystemTime(&timenow);
417 SysClock2USec(&timenow, &seconds, &usecs);
418
419 return(seconds*1000 + usecs / 1000);
420}
@ ERR_OK
Definition err.h:55
@ ERR_MEM
Definition err.h:57
void sys_mbox_set_invalid(sys_mbox_t *mbox)
Definition sys_arch.c:200
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
Definition sys_arch.c:254
int sys_mbox_valid(sys_mbox_t *mbox)
Definition sys_arch.c:167
void sys_mbox_post(sys_mbox_t *mbox, void *msg)
Definition sys_arch.c:192
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
Definition sys_arch.c:171
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
Definition sys_arch.c:141
void sys_mbox_free(sys_mbox_t *mbox)
Definition sys_arch.c:162
err_t sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg)
Definition sys_arch.c:188
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
Definition sys_arch.c:259
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
Definition sys_arch.c:110
void sys_init(void)
Definition sys_arch.c:339
int sys_sem_valid(sys_sem_t *sem)
Definition sys_arch.c:281
void sys_sem_set_invalid(sys_sem_t *sem)
Definition sys_arch.c:285
void sys_sem_free(sys_sem_t *sem)
Definition sys_arch.c:334
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
Definition sys_arch.c:289
void sys_sem_signal(sys_sem_t *sem)
Definition sys_arch.c:329
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
Definition sys_arch.c:263
u32_t sys_now(void)
Definition sys_arch.c:411
int CpuResumeIntr(int state)
Definition intrman.c:217
int CpuSuspendIntr(int *state)
Definition intrman.c:195
#define SYS_MBOX_EMPTY
Definition sys.h:92
#define SYS_ARCH_TIMEOUT
Definition sys.h:87
void(*) lwip_thread_fn(void *arg)
Definition sys.h:98
u32 count
start sector of fragmented bd/file