PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
thvpool.c
1#include "intrman.h"
2#include "kerr.h"
3#include "thcommon.h"
4#include "thpool.h"
5#include "heaplib.h"
6
7static void vpl_get_info(struct vpool *vpl, iop_vpl_info_t *info);
8
9int CreateVpl(iop_vpl_param *param)
10{
11 struct vpool *vpl;
12 int state;
13
14 if (QueryIntrContext()) {
15 return KE_ILLEGAL_CONTEXT;
16 }
17
18 if (param->attr & ~(VA_THFIFO | VA_THPRI | VA_MEMBTM)) {
19 return KE_ILLEGAL_ATTR;
20 }
21
22 if (param->size == 0) {
23 return KE_ILLEGAL_MEMSIZE;
24 }
25
26 CpuSuspendIntr(&state);
27
28 vpl = heap_alloc(TAG_VPL, sizeof(*vpl));
29 if (!vpl) {
30 CpuResumeIntr(state);
31 return KE_NO_MEMORY;
32 }
33
34 vpl->heap = CreateHeap(param->size, (param->attr & VA_MEMBTM) << 1);
35 vpl->free_size = HeapTotalFreeSize(vpl->heap);
36 vpl->event.attr = param->attr;
37 vpl->event.option = param->option;
38
39 list_init(&vpl->event.waiters);
40 list_insert(&thctx.vpool, &vpl->vpl_list);
41
42 CpuResumeIntr(state);
43
44 return MAKE_HANDLE(vpl);
45}
46
47int DeleteVpl(int vplId)
48{
49 struct thread *waiter;
50 struct vpool *vpl;
51 u32 waiter_count;
52 int state;
53
54 if (QueryIntrContext()) {
55 return KE_ILLEGAL_CONTEXT;
56 }
57
58 CpuSuspendIntr(&state);
59 vpl = HANDLE_PTR(vplId);
60 if (!HANDLE_VERIFY(vplId, TAG_VPL)) {
61 CpuResumeIntr(state);
62 return KE_UNKNOWN_VPLID;
63 }
64
65 list_for_each_safe (waiter, &vpl->event.waiters, queue) {
66 waiter->saved_regs->v0 = KE_WAIT_DELETE;
67 waiter->status = THS_READY;
68 list_remove(&waiter->queue);
69 readyq_insert_back(waiter);
70 }
71
72 waiter_count = vpl->event.waiter_count;
73 DeleteHeap(vpl->heap);
74 list_remove(&vpl->vpl_list);
75 heap_free(&vpl->tag);
76
77 if (waiter_count) {
78 thctx.run_next = NULL;
79 return thread_leave(KE_OK, 0, state, 0);
80 }
81
82 CpuResumeIntr(state);
83
84 return KE_OK;
85}
86
87void *AllocateVpl(int vplId, int size)
88{
89 struct thread *thread;
90 struct vpool *vpl;
91 void *mem;
92 int state;
93
94 if (QueryIntrContext()) {
95 return (void *)KE_ILLEGAL_CONTEXT;
96 }
97
98 if (CpuSuspendIntr(&state) == KE_CPUDI && (thctx.debug_flags & 8)) {
99 Kprintf("WARNING: AllocateVpl KE_CAN_NOT_WAIT\n");
100 }
101
102 vpl = HANDLE_PTR(vplId);
103 if (!HANDLE_VERIFY(vplId, TAG_VPL)) {
104 CpuResumeIntr(state);
105 return (void *)KE_UNKNOWN_VPLID;
106 }
107
108 if (!size || vpl->free_size < size) {
109 CpuResumeIntr(state);
110 return (void *)KE_ILLEGAL_MEMSIZE;
111 }
112
113 mem = AllocHeapMemory(vpl->heap, size);
114 if (mem) {
115 CpuResumeIntr(state);
116 return mem;
117 }
118
119 thread = thctx.current_thread;
120 thread->status = THS_WAIT;
121 thread->wait_type = TSW_FPL;
122 thread->wait_event = &vpl->event;
123
124 thctx.run_next = NULL;
125 vpl->event.waiter_count++;
126
127 if (vpl->event.attr & VA_THPRI) {
128 waitlist_insert(thread, &vpl->event, thread->priority);
129 } else {
130 list_insert(&vpl->event.waiters, &thread->queue);
131 }
132
133 return (void *)thread_leave(size, 0, state, 1);
134}
135
136void *pAllocateVpl(int vplId, int size)
137{
138 struct vpool *vpl;
139 void *mem;
140 int state;
141
142 if (QueryIntrContext()) {
143 return (void *)KE_ILLEGAL_CONTEXT;
144 }
145
146 CpuSuspendIntr(&state);
147 vpl = HANDLE_PTR(vplId);
148 if (!HANDLE_VERIFY(vplId, TAG_VPL)) {
149 CpuResumeIntr(state);
150 return (void *)KE_UNKNOWN_VPLID;
151 }
152
153 if (!size || vpl->free_size < size) {
154 CpuResumeIntr(state);
155 return (void *)KE_ILLEGAL_MEMSIZE;
156 }
157
158 mem = AllocHeapMemory(vpl->heap, size);
159 CpuResumeIntr(state);
160
161 if (!mem) {
162 return (void *)KE_NO_MEMORY;
163 }
164
165 return mem;
166}
167
168void *ipAllocateVpl(int vplId, int size)
169{
170 struct vpool *vpl;
171 void *mem;
172
173 if (!QueryIntrContext()) {
174 return (void *)KE_ILLEGAL_CONTEXT;
175 }
176
177 vpl = HANDLE_PTR(vplId);
178 if (!HANDLE_VERIFY(vplId, TAG_VPL)) {
179 return (void *)KE_UNKNOWN_VPLID;
180 }
181
182 mem = AllocHeapMemory(vpl->heap, size);
183 if (!mem) {
184 return (void *)KE_NO_MEMORY;
185 }
186
187 return mem;
188}
189
190int FreeVpl(int vplId, void *memory)
191{
192 struct thread *thread;
193 struct vpool *vpl;
194 void *new_mem;
195 int state;
196
197 if (QueryIntrContext()) {
198 return KE_ILLEGAL_CONTEXT;
199 }
200
201 CpuSuspendIntr(&state);
202 vpl = HANDLE_PTR(vplId);
203 if (!HANDLE_VERIFY(vplId, TAG_VPL)) {
204 CpuResumeIntr(state);
205 // BUG: originally wrong value
206 // return KE_UNKNOWN_FPLID;
207 return KE_UNKNOWN_VPLID;
208 }
209
210 if (FreeHeapMemory(vpl->heap, memory) < 0) {
211 CpuResumeIntr(state);
212 return KE_ERROR;
213 }
214
215 if (vpl->event.waiter_count) {
216 thread = list_first_entry(&vpl->event.waiters, struct thread, queue);
217 new_mem = AllocHeapMemory(vpl->heap, thread->saved_regs->v0);
218 if (new_mem) {
219 vpl->event.waiter_count--;
220 list_remove(&thread->queue);
221 thread->status = THS_READY;
222 thread->saved_regs->v0 = (u32)new_mem;
223
224 return thread_start(thread, state);
225 }
226 }
227
228 CpuResumeIntr(state);
229
230 return KE_OK;
231}
232
233int ReferVplStatus(int vplId, iop_vpl_info_t *info)
234{
235 struct vpool *vpl;
236 int state;
237
238 if (QueryIntrContext()) {
239 return KE_ILLEGAL_CONTEXT;
240 }
241
242 CpuSuspendIntr(&state);
243 vpl = HANDLE_PTR(vplId);
244 if (!HANDLE_VERIFY(vplId, TAG_VPL)) {
245 CpuResumeIntr(state);
246 return KE_UNKNOWN_VPLID;
247 }
248
249 vpl_get_info(vpl, info);
250
251 CpuResumeIntr(state);
252
253 return KE_OK;
254}
255
256int iReferVplStatus(int vplId, iop_vpl_info_t *info)
257{
258 struct vpool *vpl;
259
260 if (!QueryIntrContext()) {
261 return KE_ILLEGAL_CONTEXT;
262 }
263
264 vpl = HANDLE_PTR(vplId);
265 if (!HANDLE_VERIFY(vplId, TAG_VPL)) {
266 return KE_UNKNOWN_VPLID;
267 }
268
269 vpl_get_info(vpl, info);
270
271 return KE_OK;
272}
273
274static void vpl_get_info(struct vpool *vpl, iop_vpl_info_t *info)
275{
276 info->attr = vpl->event.attr;
277 info->option = vpl->event.option;
278 info->size = vpl->free_size;
279 info->freeSize = HeapTotalFreeSize(vpl->heap);
280 info->numWaitThreads = vpl->event.waiter_count;
281}
int CpuResumeIntr(int state)
Definition intrman.c:227
int QueryIntrContext(void)
int CpuSuspendIntr(int *state)
Definition intrman.c:205