FreeCalypso > hg > fc-tourmaline
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gpf/osl/os_mem_fl.c Fri Oct 16 06:23:26 2020 +0000 @@ -0,0 +1,453 @@ +/* + * This C module is a reconstruction based on the disassembly of + * os_mem.obj in frame_na7_db_fl.lib from the Leonardo package. + */ + +/* set of included headers from COFF symtab: */ +#include <stdio.h> +#include <string.h> +#include "nucleus.h" +#include "typedefs.h" +#include "os.h" +#include "gdi.h" +#include "os_types.h" +#include "os_glob.h" + +extern T_OS_PART_GRP_TABLE_ENTRY PartGrpTable[]; +extern T_OS_MEM_POOL_TABLE_ENTRY MemPoolTable[]; +extern T_OS_POOL_BORDER PoolBorder[]; + +OS_HANDLE os_ext_pool_handle; +OS_HANDLE os_int_pool_handle; + +static USHORT NumOfMemoryPools; +static NU_SEMAPHORE MemSemCB; +static NU_MEMORY_POOL mem_pool_head; + +GLOBAL LONG +os_SetPoolHandles(OS_HANDLE ext_pool_handle, OS_HANDLE int_pool_handle) +{ + os_ext_pool_handle = ext_pool_handle; + os_int_pool_handle = int_pool_handle; + return(OS_OK); +} + +static int +os_GetPartitionPoolEntry(USHORT Index, T_OS_PART_POOL **pool) +{ + static T_OS_PART_POOL *part_pool; + static int grp_hndl; + + switch (Index) { + case FIRST_ENTRY: + grp_hndl = 0; + *pool = part_pool = PartGrpTable[0].grp_head; + return(OS_OK); + case NEXT_ENTRY: + if (part_pool->next) { + *pool = part_pool = part_pool->next; + return(OS_OK); + } + grp_hndl++; + if (PartGrpTable[grp_hndl].grp_head) { + *pool = part_pool = PartGrpTable[grp_hndl].grp_head; + return(OS_OK); + } else + return(OS_ERROR); + default: + return(OS_ERROR); + } +} + +GLOBAL LONG +os_PartitionInformation(USHORT Handle, char *Buffer) +{ + T_OS_PART_POOL *pool; + OPTION SuspendType; + UNSIGNED PoolSize; + UNSIGNED PartitionSize; + UNSIGNED Available; + UNSIGNED Waiting; + UNSIGNED Allocated; + VOID *pStartAddress; + NU_TASK *First; + CHAR Name[NU_MAX_NAME]; + + if (os_GetPartitionPoolEntry(Handle, &pool) == OS_ERROR) + return(OS_ERROR); + if (NU_Partition_Pool_Information(&pool->pcb, Name, &pStartAddress, + &PoolSize, &PartitionSize, &Available, + &Allocated, &SuspendType, &Waiting, + &First) + != NU_SUCCESS) + return(OS_ERROR); + sprintf(Buffer, + "Name:%s Addr:%lx PoolSize:%ld PartSize:%ld Free:%ld Used:%ld", + Name, (UNSIGNED) pStartAddress, PoolSize, PartitionSize, + Available, Allocated); + return(OS_OK); +} + +static int +os_GetMemoryPoolEntry(USHORT Index, OS_HANDLE *Handle) +{ + static USHORT Idx; + + switch (Index) { + case FIRST_ENTRY: + Idx = 0; + break; + case NEXT_ENTRY: + Idx++; + break; + default: + Idx = Index; + } + if (Idx == NumOfMemoryPools) + return(OS_ERROR); + *Handle = Idx; + return(OS_OK); +} + +GLOBAL LONG +os_MemoryInformation(USHORT Index, char *Buffer) +{ + OS_HANDLE Handle; + OPTION SuspendType; + UNSIGNED Size, Min, Available, Waiting; + VOID *pStartAddress; + NU_TASK *First; + CHAR Name[NU_MAX_NAME]; + + if (os_GetMemoryPoolEntry(Index, &Handle) == OS_ERROR) + return(OS_ERROR); + if (NU_Memory_Pool_Information(MemPoolTable[Handle].pcb, Name, + &pStartAddress, &Size, &Min, + &Available, &SuspendType, &Waiting, + &First) + != NU_SUCCESS) + return(OS_ERROR); + sprintf(Buffer, + "Heapname:%s Addr:%lx Size:%ld Min:%ld Free:%ld Suspend:%d", + Name, (UNSIGNED) pStartAddress, Size, Min, Available, + SuspendType); + return(OS_OK); +} + +GLOBAL LONG +os_MemInit(void) +{ + USHORT i; + + if (NU_Create_Semaphore(&MemSemCB, "MEMSEM", 1, NU_PRIORITY) + != NU_SUCCESS) + return(OS_ERROR); + for (i = 0; i <= MaxPoolGroups; i++) { + PoolBorder[i].Start = (char *)0xFFFFFFFF; + PoolBorder[i].End = (char *)0; + PartGrpTable[i].grp_head = 0; + PartGrpTable[i].name[0] = 0; + } + MemPoolTable[0].pcb = &mem_pool_head; + return(OS_OK); +} + +void +os_InitPartitionCheck(T_OS_PART_POOL *pool) +{ + unsigned **Buffer, offset; + USHORT i, k; + + NU_Allocate_Memory(MemPoolTable[0].pcb, (VOID **) &Buffer, + pool->pcb.pm_available * sizeof(unsigned *), + NU_NO_SUSPEND); + offset = pool->pcb.pm_partition_size / sizeof(unsigned) - 1; + for (i = 0; ; i++) { + if (NU_Allocate_Partition(&pool->pcb, (VOID **)(Buffer + i), + NU_NO_SUSPEND) + != NU_SUCCESS) + break; + Buffer[i][offset] = GUARD_PATTERN; + } + for (k = 0; k < i; k++) + if (NU_Deallocate_Partition(Buffer[k]) != NU_SUCCESS) + break; + NU_Deallocate_Memory(Buffer); +} + +GLOBAL const ULONG * +os_GetPrimpoolCB(int grp, int id) +{ + T_OS_PART_POOL *pool; + int i; + + pool = PartGrpTable[grp].grp_head; + if (!pool) + return(0); + if (id < 0) + return(0); + for (i = 0; i < id; i++) { + pool = pool->next; + if (!pool) + return(0); + } + return (const ULONG *) &pool->pcb; +} + +GLOBAL LONG +os_GetPartitionPoolStatus(ULONG size, OS_HANDLE gr_hndl, + USHORT *m_free, USHORT *m_alloc) +{ + T_OS_PART_POOL *pool; + UNSIGNED dummy, allocated, available; + CHAR Name[NU_MAX_NAME]; + + for (pool = PartGrpTable[gr_hndl].grp_head; pool; pool = pool->next) { + if (!size) + break; + if (size > pool->size) + continue; + if (NU_Partition_Pool_Information(&pool->pcb, Name, + (VOID **)&dummy, &dummy, + &dummy, &available, + &allocated, (OPTION *)&dummy, + &dummy, (NU_TASK **)&dummy) + != NU_SUCCESS) + break; + *m_alloc = allocated; + *m_free = available; + return(OS_OK); + } + *m_alloc = 0; + *m_free = 0; + return(OS_ERROR); +} + +GLOBAL LONG +os_GetPartitionGroupHandle(OS_HANDLE Caller, char *Name, OS_HANDLE *GroupHandle) +{ + int i; + + for (i = 0; i <= MaxPoolGroups; i++) { + if (!PartGrpTable[i].grp_head) + continue; + if (strncmp(Name, PartGrpTable[i].name, RESOURCE_NAMELEN-1)) + continue; + *GroupHandle = i; + return(OS_OK); + } + return(OS_ERROR); +} + +GLOBAL LONG +os_DeallocateMemory(OS_HANDLE TaskHandle, T_VOID_STRUCT *Buffer) +{ + if (NU_Deallocate_Memory(Buffer) == NU_SUCCESS) + return(OS_OK); + else + return(OS_ERROR); +} + +GLOBAL LONG +os_AllocateMemory(OS_HANDLE TaskHandle, T_VOID_STRUCT **Buffer, ULONG Size, + ULONG Suspend, OS_HANDLE PoolHandle) +{ + int ret, sts; + + if (Suspend == 0xFFFFFFFF) + Suspend = 1; + ret = OS_OK; + for (;;) { + sts = NU_Allocate_Memory(MemPoolTable[PoolHandle].pcb, + (VOID **) Buffer, Size, Suspend); + switch (sts) { + case NU_SUCCESS: + return(ret); + case NU_INVALID_SUSPEND: + Suspend = 0; + continue; + case NU_NO_MEMORY: + case NU_TIMEOUT: + if (Suspend == 1) { + Suspend = 0xFFFFFFFF; + ret = OS_WAITED; + continue; + } else { + *Buffer = 0; + return(OS_TIMEOUT); + } + default: + /* + * Disassembly reveals that the original code + * has an endless loop here, the equivalent + * of continue. My guess is that they simply + * forgot the default case, and so control + * falls onto the closing brace of the switch + * and then onto the closing brace of the for + * loop. But I prefer better error handling, + * hence the present addition. - Space Falcon + */ + *Buffer = 0; + return(OS_ERROR); + } + } +} + +GLOBAL LONG +os_CreatePartitionPool(OS_HANDLE TaskHandle, char *GroupName, void *Addr, + USHORT Num, ULONG Size, OS_HANDLE *GroupHandle) +{ + STATUS sts; + T_OS_PART_POOL *part_group_head, *opool, *npool; + USHORT part_group; + USHORT i, j; + char PoolName[8], *cp; + + sts = NU_Obtain_Semaphore(&MemSemCB, NU_SUSPEND); + j = 0; + part_group_head = 0; + for (i = 0; i <= MaxPoolGroups; i++) { + if (!PartGrpTable[i].grp_head || !PartGrpTable[i].name[0]) + break; + if (!strncmp(GroupName, PartGrpTable[i].name, + RESOURCE_NAMELEN - 1)) { + part_group_head = PartGrpTable[i].grp_head; + opool = part_group_head; + j++; + while (opool->next) { + opool = opool->next; + j++; + } + break; + } + } + /* + * This error check logic has been modified from the original + * faithful reconstruction by Space Falcon. In the original code + * if MaxPoolGroups had been reached and the for loop above + * never broke, the code would proceed to overwrite pool #0 + * instead of catching the error. + */ + if (i > MaxPoolGroups) { +release_sem_return_err: + if (sts == NU_SUCCESS) + NU_Release_Semaphore(&MemSemCB); + return(OS_ERROR); + } + part_group = i; + if (!part_group_head) { + strncpy(PartGrpTable[part_group].name, GroupName, + RESOURCE_NAMELEN); + PartGrpTable[part_group].name[RESOURCE_NAMELEN-1] = 0; + } + if (os_AllocateMemory(OS_NOTASK, (T_VOID_STRUCT **) &npool, + sizeof(T_OS_PART_POOL), OS_NO_SUSPEND, + os_ext_pool_handle) != OS_OK) + goto release_sem_return_err; + sprintf(PoolName, "POOL%1d%1d", part_group + 1, j); + Size &= ~3; + npool->pool_mem = Addr; +#if 0 + /* + * FreeCalypso: in our first-attempt gcc-built firmwares we needed to + * bzero the PM_PCB before calling NU_Create_Partition_Pool() to + * prevent the possibility of Nucleus error checker failing the call + * because the signature word happens to be there already. The issue + * arose because we were using "raw" memory sections that weren't + * zeroed out on boot like standard .bss, but in TI's original + * architecture everything is zeroed out on boot, so we don't need + * this additional zeroing here. + */ + bzero(&npool->pcb, sizeof(NU_PARTITION_POOL)); +#endif + if (NU_Create_Partition_Pool(&npool->pcb, PoolName, npool->pool_mem, + POOL_SIZE(Num, Size), + Size + PT_CHKOVERHEAD + PPM_OVERHEAD, + NU_FIFO) != NU_SUCCESS) + goto release_sem_return_err; + if (!part_group_head) + PartGrpTable[part_group].grp_head = npool; + else + opool->next = npool; + npool->size = Size; + npool->next = 0; + *GroupHandle = part_group; + cp = (char *) npool->pool_mem; + if (PoolBorder[part_group].Start >= cp) + PoolBorder[part_group].Start = cp; + cp += POOL_SIZE(Num, Size); + if (PoolBorder[part_group].End < cp) + PoolBorder[part_group].End = cp; + os_InitPartitionCheck(npool); + if (sts == NU_SUCCESS) + NU_Release_Semaphore(&MemSemCB); + return(OS_OK); +} + +GLOBAL LONG +os_CreatePartitionPool_fixed_pool_size(OS_HANDLE TaskHandle, char *GroupName, + void *Addr, USHORT PoolSize, + ULONG PartSize, OS_HANDLE *GroupHandle, + ULONG *NumCreated) +{ + USHORT num; + + num = PoolSize / (PartSize + PT_CHKOVERHEAD + PT_OVERHEAD); + *NumCreated = num; + return os_CreatePartitionPool(TaskHandle, GroupName, Addr, num, + PartSize, GroupHandle); +} + +GLOBAL LONG +os_CreateMemoryPool(OS_HANDLE TaskHandle, char *Name, void *Addr, + ULONG PoolSize, OS_HANDLE *PoolHandle) +{ + STATUS sts; + USHORT i; + + sts = NU_Obtain_Semaphore(&MemSemCB, NU_SUSPEND); + for (i = 0; i < NumOfMemoryPools; i++) + if (!strncmp(Name, MemPoolTable[i].name, RESOURCE_NAMELEN-1)) { + *PoolHandle = i; + if (sts == NU_SUCCESS) + NU_Release_Semaphore(&MemSemCB); + return(OS_OK); + } + if (i >= MaxMemoryPools) { +release_sem_return_err: + if (sts == NU_SUCCESS) + NU_Release_Semaphore(&MemSemCB); + return(OS_ERROR); + } + if (i) { + if (os_AllocateMemory(OS_NOTASK, + (T_VOID_STRUCT **) &MemPoolTable[i].pcb, + sizeof(NU_MEMORY_POOL), OS_NO_SUSPEND, + os_ext_pool_handle) != OS_OK) + goto release_sem_return_err; +#if 0 + /* + * FreeCalypso: in our first-attempt gcc-built firmwares we + * needed to bzero the DM_PCB before calling + * NU_Create_Memory_Pool() to prevent the possibility of + * Nucleus error checker failing the call because the signature + * word happens to be there already. The issue arose because + * we were using "raw" memory sections that weren't zeroed out + * on boot like standard .bss, but in TI's original architecture + * everything is zeroed out on boot, so we don't need this + * additional zeroing here. + */ + bzero(MemPoolTable[i].pcb, sizeof(NU_MEMORY_POOL)); +#endif + } + if (NU_Create_Memory_Pool(MemPoolTable[i].pcb, Name, Addr, PoolSize, + 4, NU_FIFO) != NU_SUCCESS) + goto release_sem_return_err; + strncpy(MemPoolTable[i].name, Name, RESOURCE_NAMELEN); + MemPoolTable[i].name[RESOURCE_NAMELEN-1] = 0; + *PoolHandle = i; + NumOfMemoryPools++; + if (sts == NU_SUCCESS) + NU_Release_Semaphore(&MemSemCB); + return(OS_OK); +}