PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
thread.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Licenced under Academic Free License version 2.0
7# Review ps2sdk README & LICENSE files for further details.
8*/
9
15#include "kernel.h"
16
17struct request
18{
19 u8 mode;
20 u8 data;
21};
22
23enum TOP_REQ {
24 TOP_REQ_WAKEUP,
25 TOP_REQ_ROTATE,
26 TOP_REQ_SUSPEND
27};
28
29struct topArg
30{
31 int requestOut;
32 int requestIn;
33 struct request request[512];
34};
35
36extern int topId;
37extern int topSema;
38extern struct topArg topArg;
39
40#ifdef F__thread_internals
41
42extern void *_gp;
43
44u8 stack[0x400] __attribute__((aligned(16)));
45
46int topId = 0;
47int topSema = 0;
48struct topArg topArg = {0};
49
50static void topThread(void *arg)
51{
52 (void)arg;
53
54 while (1) {
55 int index;
56
57 WaitSema(topSema);
58 index = topArg.requestOut & 0x1FF;
59 topArg.requestOut = index + 1;
60
61 switch (topArg.request[index].mode) {
62 case TOP_REQ_WAKEUP:
63 WakeupThread(topArg.request[index].data);
64 break;
65 case TOP_REQ_ROTATE:
66 RotateThreadReadyQueue(topArg.request[index].data);
67 break;
68 case TOP_REQ_SUSPEND:
69 SuspendThread(topArg.request[index].data);
70 break;
71 /* default:
72 Kprintf("## internal error in libkernel!\n"); */
73 }
74 }
75}
76
77__attribute__((weak))
78int InitThread(void)
79{
80 ee_sema_t sema;
82
83 sema.max_count = 255;
84 sema.init_count = 0;
85 sema.option = (u32) "KernelTopThread";
86 if ((topSema = CreateSema(&sema)) < 0)
87 return -1;
88
89 thread.func = &topThread;
90 thread.stack = stack;
91 thread.stack_size = sizeof(stack);
92 thread.gp_reg = &_gp;
93 thread.option = (u32) "KernelTopThread";
94 thread.initial_priority = 0;
95 if ((topId = CreateThread(&thread)) < 0) {
96 DeleteSema(topSema);
97 return -1;
98 }
99
100 topArg.requestOut = 0;
101 topArg.requestIn = 0;
102 StartThread(topId, &topArg);
103
104 ChangeThreadPriority(GetThreadId(), 1);
105
106 return topId;
107}
108#endif
109
110#ifdef F_iWakeupThread
111// The original iWakeupThread cannot wake up threads in THS_RUN state.
112__attribute__((weak))
113s32 iWakeupThread(s32 thread_id)
114{
115 if (_iGetThreadId() == thread_id) {
116 if (thread_id < 256 && topId != 0) {
117 int index;
118
119 index = topArg.requestIn & 0x1FF;
120 topArg.requestIn = index + 1;
121 topArg.request[index].mode = TOP_REQ_WAKEUP;
122 topArg.request[index].data = thread_id;
123
124 iSignalSema(topSema);
125 return 0;
126 } else
127 return -1;
128 } else {
129 return _iWakeupThread(thread_id);
130 }
131}
132#endif
133
134#ifdef F_iRotateThreadReadyQueue
135// The original iRotateThreadReadyQueue will not change the current thread ID.
136__attribute__((weak))
137s32 iRotateThreadReadyQueue(s32 priority)
138{
139 if (priority < 128 && topId != 0) {
140 int index;
141
142 index = topArg.requestIn & 0x1FF;
143 topArg.requestIn = index + 1;
144 topArg.request[index].mode = TOP_REQ_ROTATE;
145 topArg.request[index].data = priority;
146
147 iSignalSema(topSema);
148 return 0;
149 } else
150 return -1;
151}
152#endif
153
154#ifdef F_iSuspendThread
155// The original iSuspendThread allows a thread to suspend itself, but won't change the current thread ID.
156__attribute__((weak))
157s32 iSuspendThread(s32 thread_id)
158{
159 if (_iGetThreadId() == thread_id) {
160 if (thread_id < 256 && topId != 0) {
161 int index;
162
163 index = topArg.requestIn & 0x1FF;
164 topArg.requestIn = index + 1;
165 topArg.request[index].mode = TOP_REQ_SUSPEND;
166 topArg.request[index].data = thread_id;
167
168 iSignalSema(topSema);
169 return 0;
170 } else
171 return -1;
172 } else {
173 return _iSuspendThread(thread_id);
174 }
175}
176#endif