📄 pc_memry.c
字号:
/* Contains NUCLEUS Specific Code */
/*
* EBS - RTFS (Real Time File Manager)
*
*
* Copyright Peter Van Oudenaren , 1993
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/******************************************************************************
PC_MEMRY - System specific memory management routines.
Summary
All global memory management occurs in this file including:
. Declaration of globals
. Initialization of systemwide lists and tables.
. Variable sized memory allocator functions for FATs.
. Optional de-allocation of systemwide lists and tables.
******************************************************************************/
#if (PLUS)
#include "nucleus.h"
#else
#include "nu_defs.h"
#include "nu_proto.h"
#endif /* PLUS */
#include "pcdisk.h"
GLOBAL FINODE *inoroot = 0; /* Begining of inode pool */
/* NUCLEUS - The current user is a macro not a constant */
GLOBAL DDRIVE *drv_array[NDRIVES]; /* Array of open drives */
/* List of users. see porting guide and pc_users.c. The only user
structure in single tasking environments */
PFILE_SYSTEM_USER user_heap = 0;
/* Things we need if using fine grained multitasking */
#if (LOCK_METHOD == 2)
/* Semaphore handles used for reentrancy control on fats drives and finodes */
GLOBAL LOCKOBJ drive_locks[NDRIVES];
GLOBAL LOCKOBJ fat_locks[NDRIVES];
GLOBAL LOCKOBJ drive_io_locks[NDRIVES];
GLOBAL WAIT_HANDLE_TYPE finode_lock_handles[NFINODES];
BOOL handles_are_alloced = NO;
#endif
/* NUCLEUS Specific nu_to_rtfs_task_map */
#if (PLUS)
COUNT Task_Map[NUM_USERS];
#endif
COUNT *nu_to_rtfs_task_map;
DDRIVE *mem_drives_structures = 0;
BLKBUFF *mem_block_pool = 0;
PC_FILE *mem_file_pool = 0;
DROBJ *mem_drobj_pool = 0;
DROBJ *mem_drobj_freelist = 0;
FINODE *mem_finode_pool = 0;
FINODE *mem_finode_freelist = 0;
/* Note: There are also a few static declarations in devtable.c
and the device drivers (bios.c, ide_drv.c fl_drver.c, fl_host.c) */
/**************************************************************************
PC_MEMORY_INIT - Initialize and allocate File system structures.
THIS ROUTINE MUST BE CALLED BEFORE ANY FILE SYSTEM ROUTINES !!!!!!
Description
This routine must be called before any file system routines. Its job
is to allocate tables needed by the file system. We chose to implement
memory management this way to provide maximum flexibility for embedded
system developers. In the reference port we use malloc to allocate the
various chunks of memory we need, but we could just have easily comiled
the tables into the BSS section of the program.
Use whatever method makes sense in you system.
Note the total number of bytes allocated by this routine is:
(sizeof(DDRIVE) * NDRIVES) + (sizeof(PC_FILE)*NUSERFILES) +
(sizeof(BLKBUFF)*NBLKBUFFS)+ (sizeof(DROBJ)*NDROBJS) +
(sizeof(FINODE)*NFINODES)
Returns
YES on success or no ON Failure.
*****************************************************************************/
BOOL pc_memory_init() /*__fn__*/
{
COUNT i;
COUNT j;
UCOUNT l;
DROBJ *pobj;
FINODE *pfi;
#if (PLUS)
OPTION preempt_status;
preempt_status = NU_Change_Preemption(NU_NO_PREEMPT);
#else
NU_Disable_Preemption();
#endif /* PLUS */
/* Check if already initialized. If so don't do it again */
if (user_heap)
{
#if (PLUS)
NU_Change_Preemption(preempt_status);
#else
NU_Enable_Preemption();
#endif /* PLUS */
return(YES);
}
/* NUCLEUS. Event handles are simple indeces under nucleus */
mem_drives_structures = NULL;
mem_block_pool = NULL;
mem_file_pool = NULL;
mem_drobj_pool = NULL;
mem_drobj_freelist = NULL;
mem_finode_pool = NULL;
mem_finode_freelist = NULL;
user_heap = NULL;
nu_to_rtfs_task_map = NULL;
/* NUCLEUS - The current user is a macro not a constant */
/* Allocate all event handles */
#if (LOCK_METHOD == 2)
/* Allocate all message handles needed by RTFS. */
/* If they were already alloced we don't allocate them here, we just
check that they are still valid */
for (i = 0; i < NDRIVES; i++)
{
if (!handles_are_alloced)
drive_locks[i].wait_handle = pc_alloc_lock();
drive_locks[i].opencount = 0;
drive_locks[i].exclusive = NO;
if (!handles_are_alloced)
fat_locks[i].wait_handle = pc_alloc_lock();
fat_locks[i].opencount = 0;
fat_locks[i].exclusive = NO;
if (!handles_are_alloced)
drive_io_locks[i].wait_handle = pc_alloc_lock();
drive_io_locks[i].opencount = 0;
drive_io_locks[i].exclusive = NO;
}
for (i = 0; i < NFINODES; i++)
{
if (!handles_are_alloced)
finode_lock_handles[i] = pc_alloc_lock();
}
handles_are_alloced = YES;
#endif
/* Initialize our user list - managed by code in pc_users.c */
l =sizeof(FILE_SYSTEM_USER); l *= NUM_USERS;
#if (PLUS)
if (NU_Allocate_Partition(&NUF_USER_PARTITION, (VOID **)&user_heap,
NU_NO_SUSPEND) != NU_SUCCESS)
#else
if (NU_Alloc_Partition(NUF_USER_PARTITION, (unsigned int **)&user_heap,
NU_NO_TIMEOUT) != NU_SUCCESS)
#endif /* PLUS */
{
user_heap = NULL;
goto meminit_failed;
}
pc_memfill(user_heap, l, (UTINY) 0);
/* Point fs_user at the heap. If NUM_USERS is one it will stay forever */
/* NUCLEUS - The current user is a macro not a constant */
#if (PLUS)
nu_to_rtfs_task_map = Task_Map;
#else
/* NUCLEUS. Allocate one COUNT per Nucleus task. */
if(NU_Alloc_Memory((unsigned long)(SKP_Maximum_Tasks()*2),
(unsigned int **) &nu_to_rtfs_task_map,
NU_NO_TIMEOUT) != NU_SUCCESS)
{
nu_to_rtfs_task_map = NULL;
goto meminit_failed;
}
#endif /* PLUS */
/* Allocate drive structures. */
l =sizeof(DDRIVE); l *= NDRIVES;
#if (PLUS)
if (NU_Allocate_Partition(&NUF_DRIVE_PARTITION,
(VOID **)&mem_drives_structures,
NU_NO_SUSPEND) != NU_SUCCESS)
#else
if (NU_Alloc_Partition(NUF_DRIVE_PARTITION,
(unsigned int **)&mem_drives_structures,
NU_NO_TIMEOUT) != NU_SUCCESS)
#endif /* PLUS */
{
mem_drives_structures = NULL;
goto meminit_failed;
}
pc_memfill(mem_drives_structures, l, (UTINY) 0);
/* Allocate user file structures. Set each structure's is_free
field to YES. The file structure allocator uses this field to
determine if a file is available for use */
l = sizeof(PC_FILE); l *= NUSERFILES;
#if (PLUS)
if (NU_Allocate_Partition(&NUF_FILE_PARTITION,
(VOID **)&mem_file_pool,
NU_NO_SUSPEND) != NU_SUCCESS)
#else
if(NU_Alloc_Partition(NUF_FILE_PARTITION,
(unsigned int **)&mem_file_pool, NU_NO_TIMEOUT)
!= NU_SUCCESS)
#endif /* PLUS */
{
mem_file_pool = NULL;
goto meminit_failed;
}
for (i = 0; i < NUSERFILES; i++)
mem_file_pool[i].is_free = YES;
/* Allocate block buffer pool and make a null terminated list
linked with pnext. The block buffer pool code manages this list
directly */
l = sizeof(BLKBUFF); l *= NBLKBUFFS;
#if (PLUS)
if (NU_Allocate_Partition(&NUF_BLOCK_PARTITION,
(VOID **)&mem_block_pool,
NU_NO_SUSPEND) != NU_SUCCESS)
#else
if(NU_Alloc_Partition(NUF_BLOCK_PARTITION,
(unsigned int **)&mem_block_pool,
NU_NO_TIMEOUT) != NU_SUCCESS)
#endif /* PLUS */
{
mem_block_pool = NULL;
goto meminit_failed;
}
for (i = 0, j = 1; i < (NBLKBUFFS-1); i++, j++)
{
pc_memfill(&mem_block_pool[i], sizeof(BLKBUFF) , (UTINY) 0);
mem_block_pool[i].pnext = mem_block_pool + j;
}
pc_memfill(&mem_block_pool[NBLKBUFFS-1], sizeof(BLKBUFF) , (UTINY) 0);
mem_block_pool[NBLKBUFFS-1].pnext = NULL;
/* Allocate DROBJ structures and make a NULL terminated freelist using
pdrive as the link. This linked freelist structure is used by the
DROBJ memory allocator routine. */
l = sizeof(DROBJ); l *= NDROBJS;
#if (PLUS)
if (NU_Allocate_Partition(&NUF_DROBJ_PARTITION,
(VOID **)&mem_drobj_pool,
NU_NO_SUSPEND) != NU_SUCCESS)
#else
if(NU_Alloc_Partition(NUF_DROBJ_PARTITION,
(unsigned int **)&mem_drobj_pool,
NU_NO_TIMEOUT) != NU_SUCCESS)
#endif /* PLUS */
{
mem_drobj_pool = NULL;
goto meminit_failed;
}
mem_drobj_freelist = mem_drobj_pool;
for (i = 0,j = 1; i < NDROBJS-1; i++, j++)
{
pobj = mem_drobj_freelist + j;
mem_drobj_freelist[i].pdrive = (DDRIVE *) pobj;
}
mem_drobj_freelist[NDROBJS-1].pdrive = (DDRIVE *) NULL;
/* Allocate FINODE structures and make a NULL terminated freelist using
pnext as the link. This linked freelist is used by the FINODE
memory allocator routine */
l = sizeof(FINODE); l *= NFINODES;
#if (PLUS)
if (NU_Allocate_Partition(&NUF_FINODE_PARTITION,
(VOID **)&mem_finode_pool,
NU_NO_SUSPEND) != NU_SUCCESS)
#else
if(NU_Alloc_Partition(NUF_FINODE_PARTITION,
(unsigned int **)&mem_finode_pool,
NU_NO_TIMEOUT) != NU_SUCCESS)
#endif /* PLUS */
{
mem_finode_pool = NULL;
goto meminit_failed;
}
mem_finode_freelist = mem_finode_pool;
#if (LOCK_METHOD == 2)
/* Copy lock handles into our new finode structures */
for (i = 0,pfi = mem_finode_freelist; i < NFINODES; i++, pfi++)
pfi->lock_object.wait_handle = finode_lock_handles[i];
#endif
pfi = mem_finode_freelist = mem_finode_pool;
for (i = 0; i < NFINODES-1; i++)
{
pfi++;
mem_finode_freelist->pnext = pfi;
mem_finode_freelist++;
mem_finode_freelist->pnext = NULL;
}
mem_finode_freelist = mem_finode_pool;
#if (PLUS)
NU_Change_Preemption(preempt_status);
#else
NU_Enable_Preemption();
#endif /* PLUS */
return(YES);
meminit_failed:
#if (PLUS)
if (mem_drives_structures)
NU_Deallocate_Partition( (VOID *)mem_drives_structures);
if (mem_block_pool)
NU_Deallocate_Partition( (VOID *)mem_block_pool);
if (mem_file_pool)
NU_Deallocate_Partition( (VOID *)mem_file_pool);
if (mem_drobj_pool)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -