FreeCalypso > hg > fc-tourmaline
comparison src/gpf/osl/os_mem_fl.c @ 0:4e78acac3d88
src/{condat,cs,gpf,nucleus}: import from Selenite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:23:26 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4e78acac3d88 |
---|---|
1 /* | |
2 * This C module is a reconstruction based on the disassembly of | |
3 * os_mem.obj in frame_na7_db_fl.lib from the Leonardo package. | |
4 */ | |
5 | |
6 /* set of included headers from COFF symtab: */ | |
7 #include <stdio.h> | |
8 #include <string.h> | |
9 #include "nucleus.h" | |
10 #include "typedefs.h" | |
11 #include "os.h" | |
12 #include "gdi.h" | |
13 #include "os_types.h" | |
14 #include "os_glob.h" | |
15 | |
16 extern T_OS_PART_GRP_TABLE_ENTRY PartGrpTable[]; | |
17 extern T_OS_MEM_POOL_TABLE_ENTRY MemPoolTable[]; | |
18 extern T_OS_POOL_BORDER PoolBorder[]; | |
19 | |
20 OS_HANDLE os_ext_pool_handle; | |
21 OS_HANDLE os_int_pool_handle; | |
22 | |
23 static USHORT NumOfMemoryPools; | |
24 static NU_SEMAPHORE MemSemCB; | |
25 static NU_MEMORY_POOL mem_pool_head; | |
26 | |
27 GLOBAL LONG | |
28 os_SetPoolHandles(OS_HANDLE ext_pool_handle, OS_HANDLE int_pool_handle) | |
29 { | |
30 os_ext_pool_handle = ext_pool_handle; | |
31 os_int_pool_handle = int_pool_handle; | |
32 return(OS_OK); | |
33 } | |
34 | |
35 static int | |
36 os_GetPartitionPoolEntry(USHORT Index, T_OS_PART_POOL **pool) | |
37 { | |
38 static T_OS_PART_POOL *part_pool; | |
39 static int grp_hndl; | |
40 | |
41 switch (Index) { | |
42 case FIRST_ENTRY: | |
43 grp_hndl = 0; | |
44 *pool = part_pool = PartGrpTable[0].grp_head; | |
45 return(OS_OK); | |
46 case NEXT_ENTRY: | |
47 if (part_pool->next) { | |
48 *pool = part_pool = part_pool->next; | |
49 return(OS_OK); | |
50 } | |
51 grp_hndl++; | |
52 if (PartGrpTable[grp_hndl].grp_head) { | |
53 *pool = part_pool = PartGrpTable[grp_hndl].grp_head; | |
54 return(OS_OK); | |
55 } else | |
56 return(OS_ERROR); | |
57 default: | |
58 return(OS_ERROR); | |
59 } | |
60 } | |
61 | |
62 GLOBAL LONG | |
63 os_PartitionInformation(USHORT Handle, char *Buffer) | |
64 { | |
65 T_OS_PART_POOL *pool; | |
66 OPTION SuspendType; | |
67 UNSIGNED PoolSize; | |
68 UNSIGNED PartitionSize; | |
69 UNSIGNED Available; | |
70 UNSIGNED Waiting; | |
71 UNSIGNED Allocated; | |
72 VOID *pStartAddress; | |
73 NU_TASK *First; | |
74 CHAR Name[NU_MAX_NAME]; | |
75 | |
76 if (os_GetPartitionPoolEntry(Handle, &pool) == OS_ERROR) | |
77 return(OS_ERROR); | |
78 if (NU_Partition_Pool_Information(&pool->pcb, Name, &pStartAddress, | |
79 &PoolSize, &PartitionSize, &Available, | |
80 &Allocated, &SuspendType, &Waiting, | |
81 &First) | |
82 != NU_SUCCESS) | |
83 return(OS_ERROR); | |
84 sprintf(Buffer, | |
85 "Name:%s Addr:%lx PoolSize:%ld PartSize:%ld Free:%ld Used:%ld", | |
86 Name, (UNSIGNED) pStartAddress, PoolSize, PartitionSize, | |
87 Available, Allocated); | |
88 return(OS_OK); | |
89 } | |
90 | |
91 static int | |
92 os_GetMemoryPoolEntry(USHORT Index, OS_HANDLE *Handle) | |
93 { | |
94 static USHORT Idx; | |
95 | |
96 switch (Index) { | |
97 case FIRST_ENTRY: | |
98 Idx = 0; | |
99 break; | |
100 case NEXT_ENTRY: | |
101 Idx++; | |
102 break; | |
103 default: | |
104 Idx = Index; | |
105 } | |
106 if (Idx == NumOfMemoryPools) | |
107 return(OS_ERROR); | |
108 *Handle = Idx; | |
109 return(OS_OK); | |
110 } | |
111 | |
112 GLOBAL LONG | |
113 os_MemoryInformation(USHORT Index, char *Buffer) | |
114 { | |
115 OS_HANDLE Handle; | |
116 OPTION SuspendType; | |
117 UNSIGNED Size, Min, Available, Waiting; | |
118 VOID *pStartAddress; | |
119 NU_TASK *First; | |
120 CHAR Name[NU_MAX_NAME]; | |
121 | |
122 if (os_GetMemoryPoolEntry(Index, &Handle) == OS_ERROR) | |
123 return(OS_ERROR); | |
124 if (NU_Memory_Pool_Information(MemPoolTable[Handle].pcb, Name, | |
125 &pStartAddress, &Size, &Min, | |
126 &Available, &SuspendType, &Waiting, | |
127 &First) | |
128 != NU_SUCCESS) | |
129 return(OS_ERROR); | |
130 sprintf(Buffer, | |
131 "Heapname:%s Addr:%lx Size:%ld Min:%ld Free:%ld Suspend:%d", | |
132 Name, (UNSIGNED) pStartAddress, Size, Min, Available, | |
133 SuspendType); | |
134 return(OS_OK); | |
135 } | |
136 | |
137 GLOBAL LONG | |
138 os_MemInit(void) | |
139 { | |
140 USHORT i; | |
141 | |
142 if (NU_Create_Semaphore(&MemSemCB, "MEMSEM", 1, NU_PRIORITY) | |
143 != NU_SUCCESS) | |
144 return(OS_ERROR); | |
145 for (i = 0; i <= MaxPoolGroups; i++) { | |
146 PoolBorder[i].Start = (char *)0xFFFFFFFF; | |
147 PoolBorder[i].End = (char *)0; | |
148 PartGrpTable[i].grp_head = 0; | |
149 PartGrpTable[i].name[0] = 0; | |
150 } | |
151 MemPoolTable[0].pcb = &mem_pool_head; | |
152 return(OS_OK); | |
153 } | |
154 | |
155 void | |
156 os_InitPartitionCheck(T_OS_PART_POOL *pool) | |
157 { | |
158 unsigned **Buffer, offset; | |
159 USHORT i, k; | |
160 | |
161 NU_Allocate_Memory(MemPoolTable[0].pcb, (VOID **) &Buffer, | |
162 pool->pcb.pm_available * sizeof(unsigned *), | |
163 NU_NO_SUSPEND); | |
164 offset = pool->pcb.pm_partition_size / sizeof(unsigned) - 1; | |
165 for (i = 0; ; i++) { | |
166 if (NU_Allocate_Partition(&pool->pcb, (VOID **)(Buffer + i), | |
167 NU_NO_SUSPEND) | |
168 != NU_SUCCESS) | |
169 break; | |
170 Buffer[i][offset] = GUARD_PATTERN; | |
171 } | |
172 for (k = 0; k < i; k++) | |
173 if (NU_Deallocate_Partition(Buffer[k]) != NU_SUCCESS) | |
174 break; | |
175 NU_Deallocate_Memory(Buffer); | |
176 } | |
177 | |
178 GLOBAL const ULONG * | |
179 os_GetPrimpoolCB(int grp, int id) | |
180 { | |
181 T_OS_PART_POOL *pool; | |
182 int i; | |
183 | |
184 pool = PartGrpTable[grp].grp_head; | |
185 if (!pool) | |
186 return(0); | |
187 if (id < 0) | |
188 return(0); | |
189 for (i = 0; i < id; i++) { | |
190 pool = pool->next; | |
191 if (!pool) | |
192 return(0); | |
193 } | |
194 return (const ULONG *) &pool->pcb; | |
195 } | |
196 | |
197 GLOBAL LONG | |
198 os_GetPartitionPoolStatus(ULONG size, OS_HANDLE gr_hndl, | |
199 USHORT *m_free, USHORT *m_alloc) | |
200 { | |
201 T_OS_PART_POOL *pool; | |
202 UNSIGNED dummy, allocated, available; | |
203 CHAR Name[NU_MAX_NAME]; | |
204 | |
205 for (pool = PartGrpTable[gr_hndl].grp_head; pool; pool = pool->next) { | |
206 if (!size) | |
207 break; | |
208 if (size > pool->size) | |
209 continue; | |
210 if (NU_Partition_Pool_Information(&pool->pcb, Name, | |
211 (VOID **)&dummy, &dummy, | |
212 &dummy, &available, | |
213 &allocated, (OPTION *)&dummy, | |
214 &dummy, (NU_TASK **)&dummy) | |
215 != NU_SUCCESS) | |
216 break; | |
217 *m_alloc = allocated; | |
218 *m_free = available; | |
219 return(OS_OK); | |
220 } | |
221 *m_alloc = 0; | |
222 *m_free = 0; | |
223 return(OS_ERROR); | |
224 } | |
225 | |
226 GLOBAL LONG | |
227 os_GetPartitionGroupHandle(OS_HANDLE Caller, char *Name, OS_HANDLE *GroupHandle) | |
228 { | |
229 int i; | |
230 | |
231 for (i = 0; i <= MaxPoolGroups; i++) { | |
232 if (!PartGrpTable[i].grp_head) | |
233 continue; | |
234 if (strncmp(Name, PartGrpTable[i].name, RESOURCE_NAMELEN-1)) | |
235 continue; | |
236 *GroupHandle = i; | |
237 return(OS_OK); | |
238 } | |
239 return(OS_ERROR); | |
240 } | |
241 | |
242 GLOBAL LONG | |
243 os_DeallocateMemory(OS_HANDLE TaskHandle, T_VOID_STRUCT *Buffer) | |
244 { | |
245 if (NU_Deallocate_Memory(Buffer) == NU_SUCCESS) | |
246 return(OS_OK); | |
247 else | |
248 return(OS_ERROR); | |
249 } | |
250 | |
251 GLOBAL LONG | |
252 os_AllocateMemory(OS_HANDLE TaskHandle, T_VOID_STRUCT **Buffer, ULONG Size, | |
253 ULONG Suspend, OS_HANDLE PoolHandle) | |
254 { | |
255 int ret, sts; | |
256 | |
257 if (Suspend == 0xFFFFFFFF) | |
258 Suspend = 1; | |
259 ret = OS_OK; | |
260 for (;;) { | |
261 sts = NU_Allocate_Memory(MemPoolTable[PoolHandle].pcb, | |
262 (VOID **) Buffer, Size, Suspend); | |
263 switch (sts) { | |
264 case NU_SUCCESS: | |
265 return(ret); | |
266 case NU_INVALID_SUSPEND: | |
267 Suspend = 0; | |
268 continue; | |
269 case NU_NO_MEMORY: | |
270 case NU_TIMEOUT: | |
271 if (Suspend == 1) { | |
272 Suspend = 0xFFFFFFFF; | |
273 ret = OS_WAITED; | |
274 continue; | |
275 } else { | |
276 *Buffer = 0; | |
277 return(OS_TIMEOUT); | |
278 } | |
279 default: | |
280 /* | |
281 * Disassembly reveals that the original code | |
282 * has an endless loop here, the equivalent | |
283 * of continue. My guess is that they simply | |
284 * forgot the default case, and so control | |
285 * falls onto the closing brace of the switch | |
286 * and then onto the closing brace of the for | |
287 * loop. But I prefer better error handling, | |
288 * hence the present addition. - Space Falcon | |
289 */ | |
290 *Buffer = 0; | |
291 return(OS_ERROR); | |
292 } | |
293 } | |
294 } | |
295 | |
296 GLOBAL LONG | |
297 os_CreatePartitionPool(OS_HANDLE TaskHandle, char *GroupName, void *Addr, | |
298 USHORT Num, ULONG Size, OS_HANDLE *GroupHandle) | |
299 { | |
300 STATUS sts; | |
301 T_OS_PART_POOL *part_group_head, *opool, *npool; | |
302 USHORT part_group; | |
303 USHORT i, j; | |
304 char PoolName[8], *cp; | |
305 | |
306 sts = NU_Obtain_Semaphore(&MemSemCB, NU_SUSPEND); | |
307 j = 0; | |
308 part_group_head = 0; | |
309 for (i = 0; i <= MaxPoolGroups; i++) { | |
310 if (!PartGrpTable[i].grp_head || !PartGrpTable[i].name[0]) | |
311 break; | |
312 if (!strncmp(GroupName, PartGrpTable[i].name, | |
313 RESOURCE_NAMELEN - 1)) { | |
314 part_group_head = PartGrpTable[i].grp_head; | |
315 opool = part_group_head; | |
316 j++; | |
317 while (opool->next) { | |
318 opool = opool->next; | |
319 j++; | |
320 } | |
321 break; | |
322 } | |
323 } | |
324 /* | |
325 * This error check logic has been modified from the original | |
326 * faithful reconstruction by Space Falcon. In the original code | |
327 * if MaxPoolGroups had been reached and the for loop above | |
328 * never broke, the code would proceed to overwrite pool #0 | |
329 * instead of catching the error. | |
330 */ | |
331 if (i > MaxPoolGroups) { | |
332 release_sem_return_err: | |
333 if (sts == NU_SUCCESS) | |
334 NU_Release_Semaphore(&MemSemCB); | |
335 return(OS_ERROR); | |
336 } | |
337 part_group = i; | |
338 if (!part_group_head) { | |
339 strncpy(PartGrpTable[part_group].name, GroupName, | |
340 RESOURCE_NAMELEN); | |
341 PartGrpTable[part_group].name[RESOURCE_NAMELEN-1] = 0; | |
342 } | |
343 if (os_AllocateMemory(OS_NOTASK, (T_VOID_STRUCT **) &npool, | |
344 sizeof(T_OS_PART_POOL), OS_NO_SUSPEND, | |
345 os_ext_pool_handle) != OS_OK) | |
346 goto release_sem_return_err; | |
347 sprintf(PoolName, "POOL%1d%1d", part_group + 1, j); | |
348 Size &= ~3; | |
349 npool->pool_mem = Addr; | |
350 #if 0 | |
351 /* | |
352 * FreeCalypso: in our first-attempt gcc-built firmwares we needed to | |
353 * bzero the PM_PCB before calling NU_Create_Partition_Pool() to | |
354 * prevent the possibility of Nucleus error checker failing the call | |
355 * because the signature word happens to be there already. The issue | |
356 * arose because we were using "raw" memory sections that weren't | |
357 * zeroed out on boot like standard .bss, but in TI's original | |
358 * architecture everything is zeroed out on boot, so we don't need | |
359 * this additional zeroing here. | |
360 */ | |
361 bzero(&npool->pcb, sizeof(NU_PARTITION_POOL)); | |
362 #endif | |
363 if (NU_Create_Partition_Pool(&npool->pcb, PoolName, npool->pool_mem, | |
364 POOL_SIZE(Num, Size), | |
365 Size + PT_CHKOVERHEAD + PPM_OVERHEAD, | |
366 NU_FIFO) != NU_SUCCESS) | |
367 goto release_sem_return_err; | |
368 if (!part_group_head) | |
369 PartGrpTable[part_group].grp_head = npool; | |
370 else | |
371 opool->next = npool; | |
372 npool->size = Size; | |
373 npool->next = 0; | |
374 *GroupHandle = part_group; | |
375 cp = (char *) npool->pool_mem; | |
376 if (PoolBorder[part_group].Start >= cp) | |
377 PoolBorder[part_group].Start = cp; | |
378 cp += POOL_SIZE(Num, Size); | |
379 if (PoolBorder[part_group].End < cp) | |
380 PoolBorder[part_group].End = cp; | |
381 os_InitPartitionCheck(npool); | |
382 if (sts == NU_SUCCESS) | |
383 NU_Release_Semaphore(&MemSemCB); | |
384 return(OS_OK); | |
385 } | |
386 | |
387 GLOBAL LONG | |
388 os_CreatePartitionPool_fixed_pool_size(OS_HANDLE TaskHandle, char *GroupName, | |
389 void *Addr, USHORT PoolSize, | |
390 ULONG PartSize, OS_HANDLE *GroupHandle, | |
391 ULONG *NumCreated) | |
392 { | |
393 USHORT num; | |
394 | |
395 num = PoolSize / (PartSize + PT_CHKOVERHEAD + PT_OVERHEAD); | |
396 *NumCreated = num; | |
397 return os_CreatePartitionPool(TaskHandle, GroupName, Addr, num, | |
398 PartSize, GroupHandle); | |
399 } | |
400 | |
401 GLOBAL LONG | |
402 os_CreateMemoryPool(OS_HANDLE TaskHandle, char *Name, void *Addr, | |
403 ULONG PoolSize, OS_HANDLE *PoolHandle) | |
404 { | |
405 STATUS sts; | |
406 USHORT i; | |
407 | |
408 sts = NU_Obtain_Semaphore(&MemSemCB, NU_SUSPEND); | |
409 for (i = 0; i < NumOfMemoryPools; i++) | |
410 if (!strncmp(Name, MemPoolTable[i].name, RESOURCE_NAMELEN-1)) { | |
411 *PoolHandle = i; | |
412 if (sts == NU_SUCCESS) | |
413 NU_Release_Semaphore(&MemSemCB); | |
414 return(OS_OK); | |
415 } | |
416 if (i >= MaxMemoryPools) { | |
417 release_sem_return_err: | |
418 if (sts == NU_SUCCESS) | |
419 NU_Release_Semaphore(&MemSemCB); | |
420 return(OS_ERROR); | |
421 } | |
422 if (i) { | |
423 if (os_AllocateMemory(OS_NOTASK, | |
424 (T_VOID_STRUCT **) &MemPoolTable[i].pcb, | |
425 sizeof(NU_MEMORY_POOL), OS_NO_SUSPEND, | |
426 os_ext_pool_handle) != OS_OK) | |
427 goto release_sem_return_err; | |
428 #if 0 | |
429 /* | |
430 * FreeCalypso: in our first-attempt gcc-built firmwares we | |
431 * needed to bzero the DM_PCB before calling | |
432 * NU_Create_Memory_Pool() to prevent the possibility of | |
433 * Nucleus error checker failing the call because the signature | |
434 * word happens to be there already. The issue arose because | |
435 * we were using "raw" memory sections that weren't zeroed out | |
436 * on boot like standard .bss, but in TI's original architecture | |
437 * everything is zeroed out on boot, so we don't need this | |
438 * additional zeroing here. | |
439 */ | |
440 bzero(MemPoolTable[i].pcb, sizeof(NU_MEMORY_POOL)); | |
441 #endif | |
442 } | |
443 if (NU_Create_Memory_Pool(MemPoolTable[i].pcb, Name, Addr, PoolSize, | |
444 4, NU_FIFO) != NU_SUCCESS) | |
445 goto release_sem_return_err; | |
446 strncpy(MemPoolTable[i].name, Name, RESOURCE_NAMELEN); | |
447 MemPoolTable[i].name[RESOURCE_NAMELEN-1] = 0; | |
448 *PoolHandle = i; | |
449 NumOfMemoryPools++; | |
450 if (sts == NU_SUCCESS) | |
451 NU_Release_Semaphore(&MemSemCB); | |
452 return(OS_OK); | |
453 } |