PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
thfpool.c
1#include "intrman.h"
2#include "kerr.h"
3#include "thcommon.h"
4#include "thpool.h"
5
6static void fpl_block_free(struct fpool *fpl, struct fpl_block *block);
7static struct fpl_block *fpl_block_alloc(struct fpool *fpl);
8static void fpl_get_info(struct fpool *fpl, iop_fpl_info_t *info);
9
10int CreateFpl(iop_fpl_param *param)
11{
12 struct fpool *fpl;
13 u32 block_size, mem_size;
14 int state;
15 void *mem;
16
17 if (QueryIntrContext()) {
18 return KE_ILLEGAL_CONTEXT;
19 }
20
21 if (param->attr & ~(FA_THFIFO | FA_THPRI | FA_MEMBTM)) {
22 return KE_ILLEGAL_ATTR;
23 }
24
25 if (param->block_size == 0 || param->blocks == 0) {
26 return KE_ILLEGAL_MEMSIZE;
27 }
28
29 CpuSuspendIntr(&state);
30
31 block_size = ALIGN(param->block_size);
32 mem_size = block_size * param->blocks;
33
34 mem = AllocSysMemory((param->attr & FA_MEMBTM) >> 9, mem_size, NULL);
35 if (!mem) {
36 CpuResumeIntr(state);
37 return KE_NO_MEMORY;
38 }
39
40 fpl = heap_alloc(TAG_FPL, sizeof(*fpl));
41 if (!fpl) {
42 FreeSysMemory(mem);
43 CpuResumeIntr(state);
44 return KE_NO_MEMORY;
45 }
46
47 fpl->memory = mem;
48 fpl->block_size = param->block_size;
49 fpl->blocks = param->blocks;
50 fpl->mem_size = mem_size;
51 fpl->event.attr = param->attr;
52 fpl->event.option = param->option;
53
54 list_init(&fpl->event.waiters);
55 list_insert(&thctx.fpool, &fpl->fpl_list);
56
57 fpl->free = NULL;
58 for (int i = 0; i < param->blocks; i++, mem += block_size) {
59 fpl_block_free(fpl, mem);
60 }
61
62 CpuResumeIntr(state);
63
64 return MAKE_HANDLE(fpl);
65}
66
67int DeleteFpl(int fplId)
68{
69 struct thread *waiter;
70 struct fpool *fpl;
71 u32 waiter_count;
72 int state;
73
74 if (QueryIntrContext()) {
75 return KE_ILLEGAL_CONTEXT;
76 }
77
78 CpuSuspendIntr(&state);
79 fpl = HANDLE_PTR(fplId);
80 if (!HANDLE_VERIFY(fplId, TAG_FPL)) {
81 CpuResumeIntr(state);
82 return KE_UNKNOWN_FPLID;
83 }
84
85 list_for_each_safe (waiter, &fpl->event.waiters, queue) {
86 waiter->saved_regs->v0 = KE_WAIT_DELETE;
87 waiter->status = THS_READY;
88 list_remove(&waiter->queue);
89 readyq_insert_back(waiter);
90 }
91
92 waiter_count = fpl->event.waiter_count;
93 FreeSysMemory(fpl->memory);
94 list_remove(&fpl->fpl_list);
95 heap_free(&fpl->tag);
96
97 if (waiter_count) {
98 thctx.run_next = NULL;
99 return thread_leave(KE_OK, 0, state, 0);
100 }
101
102 CpuResumeIntr(state);
103
104 return KE_OK;
105}
106
107void *AllocateFpl(int fplId)
108{
109 struct thread *thread;
110 struct fpool *fpl;
111 void *block;
112 int state;
113
114 if (QueryIntrContext()) {
115 return (void *)KE_ILLEGAL_CONTEXT;
116 }
117
118 if (CpuSuspendIntr(&state) == KE_CPUDI && (thctx.debug_flags & 8)) {
119 Kprintf("WARNING: AllocateFpl KE_CAN_NOT_WAIT\n");
120 }
121
122 fpl = HANDLE_PTR(fplId);
123 if (!HANDLE_VERIFY(fplId, TAG_FPL)) {
124 CpuResumeIntr(state);
125 return (void *)KE_UNKNOWN_FPLID;
126 }
127
128 if (fpl->free) {
129 block = fpl_block_alloc(fpl);
130 CpuResumeIntr(state);
131 return block;
132 }
133
134 thread = thctx.current_thread;
135
136 thread->status = THS_WAIT;
137 thread->wait_type = TSW_FPL;
138 thread->wait_event = &fpl->event;
139 thctx.run_next = NULL;
140
141 fpl->event.waiter_count++;
142
143 if (fpl->event.attr & FA_THPRI) {
144 waitlist_insert(thread, &fpl->event, thread->priority);
145 } else {
146 list_insert(&fpl->event.waiters, &thread->queue);
147 }
148
149 return (void *)thread_leave(KE_OK, 0, state, 1);
150}
151
152void *pAllocateFpl(int fplId)
153{
154 struct fpool *fpl;
155 void *block;
156 int state;
157
158 if (QueryIntrContext()) {
159 return (void *)KE_ILLEGAL_CONTEXT;
160 }
161
162 CpuSuspendIntr(&state);
163
164 fpl = HANDLE_PTR(fplId);
165 if (!HANDLE_VERIFY(fplId, TAG_FPL)) {
166 CpuResumeIntr(state);
167 return (void *)KE_UNKNOWN_FPLID;
168 }
169
170 if (!fpl->free) {
171 CpuResumeIntr(state);
172 return (void *)KE_NO_MEMORY;
173 }
174
175 block = fpl_block_alloc(fpl);
176 CpuResumeIntr(state);
177
178 return block;
179}
180
181void *ipAllocateFpl(int fplId)
182{
183 struct fpool *fpl;
184
185 if (!QueryIntrContext()) {
186 return (void *)KE_ILLEGAL_CONTEXT;
187 }
188
189 fpl = HANDLE_PTR(fplId);
190 if (!HANDLE_VERIFY(fplId, TAG_FPL)) {
191 return (void *)KE_UNKNOWN_FPLID;
192 }
193
194 if (!fpl->free) {
195 return (void *)KE_NO_MEMORY;
196 }
197
198 return fpl_block_alloc(fpl);
199}
200
201int FreeFpl(int fplId, void *memory)
202{
203 struct thread *waiter;
204 struct fpool *fpl;
205 int state;
206
207 if (QueryIntrContext()) {
208 return KE_ILLEGAL_CONTEXT;
209 }
210
211 CpuSuspendIntr(&state);
212 fpl = HANDLE_PTR(fplId);
213 if (!HANDLE_VERIFY(fplId, TAG_FPL)) {
214 CpuResumeIntr(state);
215 return KE_UNKNOWN_FPLID;
216 }
217
218 if (memory < fpl->memory || memory >= (fpl->memory + fpl->mem_size)) {
219 return KE_ILLEGAL_MEMBLOCK;
220 }
221
222 if (fpl->event.waiter_count) {
223 waiter = list_first_entry(&fpl->event.waiters, struct thread, queue);
224 fpl->event.waiter_count--;
225 list_remove(&waiter->queue);
226 waiter->status = THS_READY;
227 waiter->saved_regs->v0 = (u32)memory;
228
229 return thread_start(waiter, state);
230 }
231
232 fpl_block_free(fpl, memory);
233
234 return KE_OK;
235}
236
237int ReferFplStatus(int fplId, iop_fpl_info_t *info)
238{
239 struct fpool *fpl;
240 int state;
241
242 if (QueryIntrContext()) {
243 return KE_ILLEGAL_CONTEXT;
244 }
245
246 CpuSuspendIntr(&state);
247 fpl = HANDLE_PTR(fplId);
248 if (!HANDLE_VERIFY(fplId, TAG_FPL)) {
249 CpuResumeIntr(state);
250 return KE_UNKNOWN_FPLID;
251 }
252
253 fpl_get_info(fpl, info);
254
255 CpuResumeIntr(state);
256
257 return KE_OK;
258}
259
260int iReferFplStatus(int fplId, iop_fpl_info_t *info)
261{
262 struct fpool *fpl;
263
264 if (!QueryIntrContext()) {
265 return KE_ILLEGAL_CONTEXT;
266 }
267
268 fpl = HANDLE_PTR(fplId);
269 if (!HANDLE_VERIFY(fplId, TAG_FPL)) {
270 return KE_UNKNOWN_FPLID;
271 }
272
273 fpl_get_info(fpl, info);
274
275 return KE_OK;
276}
277
278static struct fpl_block *fpl_block_alloc(struct fpool *fpl)
279{
280 struct fpl_block *tail, *head;
281
282 if (!fpl->free) {
283 return NULL;
284 }
285
286 fpl->free_blocks--;
287
288 tail = fpl->free;
289 head = tail->next;
290
291 if (tail == head) {
292 fpl->free = NULL;
293 } else {
294 tail->next = head->next;
295 }
296
297 return head;
298}
299
300static void fpl_block_free(struct fpool *fpl, struct fpl_block *block)
301{
302 struct fpl_block *tail;
303 tail = fpl->free;
304
305 fpl->free_blocks++;
306 if (tail) {
307 block->next = tail->next;
308 tail->next = block;
309 fpl->free = block;
310 } else {
311 fpl->free = block;
312 block->next = block;
313 }
314}
315
316static void fpl_get_info(struct fpool *fpl, iop_fpl_info_t *info)
317{
318 info->attr = fpl->event.attr;
319 info->option = fpl->event.option;
320 info->blockSize = fpl->block_size;
321 info->numBlocks = fpl->blocks;
322 info->freeBlocks = fpl->free_blocks;
323 info->numWaitThreads = fpl->event.waiter_count;
324}
int CpuResumeIntr(int state)
Definition intrman.c:227
int QueryIntrContext(void)
int CpuSuspendIntr(int *state)
Definition intrman.c:205