Files
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

265 lines
6.4 KiB
C

static char sccsid[] = "@(#)99 1.9 src/bos/kernel/pfs/genalloc.c, syspfs, bos411, 9428A410j 7/7/94 16:52:54";
/*
* COMPONENT_NAME: (SYSPFS) Physical File System
*
* FUNCTIONS: geninit, genalloc, genfree
*
* ORIGINS: 27
*
* IBM CONFIDENTIAL -- (IBM Confidential Restricted when
* combined with the aggregated modules for this product)
* SOURCE MATERIALS
* (C) COPYRIGHT International Business Machines Corp. 1988, 1994
* All Rights Reserved
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
#include "jfs/genalloc.h"
#include "sys/param.h"
#include "sys/errno.h"
#include "sys/syspest.h"
#include "sys/malloc.h"
/*
* Definitions
*/
genalloc_t *gen_table; /* genalloc_t table */
#define GENT (PAGESIZE/sizeof(genalloc_t))
int gent = GENT; /* # of gen_table elements */
#define IGENT (GENT/2)
int igent = IGENT; /* # of initial gen_table elements */
/* get pointer to the freelist chain field of the object */
#define atofp(a, ap) (*(caddr_t *)((caddr_t)(a) + (ap)->a_froff))
/*
* Declarations
*/
caddr_t genalloc();
/*
* NAME: geninit (ap)
*
* FUNCTION: Commom table manager initialization. Each "user"
* is responsible for calling geninit() to initialize
* its allocation. The first caller of geninit() causes
* the allocation of the genalloc table itself. Therefore
* the 1st entry in the genalloc array will always be for the
* genalloc allocation itself.
*
* PARAMETERS: tblelms - # of total elements in table
* nelms - # of initial allocation
* objsz - object size
* off - offset in struct that is avail to be used as
* a free list pointer(must be on long word boundary).
* id - Allocation id, debug info. This is a char array
* that can be used to identify the allocation when
* doing postmortem analysis.
* app - returned allocation info
*
* RETURNS: 0 - success
* EINVAL - initial arguments invalid
* ENOMEM - failure
*/
geninit (tblelms, nelms, objsz, off, handle, app)
int tblelms; /* # entries in table */
int nelms; /* initial # entries to initialize */
int objsz; /* object size */
off_t off; /* Offset in object to be used as freelist */
caddr_t handle; /* object id, optional */
genalloc_t **app; /* returned allocation info */
{
genalloc_t *ap;
caddr_t a;
int sz, i;
ulong *up;
/*
* First check validity of the arguments
*/
if (objsz < sizeof (caddr_t) || nelms > tblelms ||
off >= objsz || (off & 0x3) != 0)
return EINVAL;
/*
* allocate and initialize the genalloc_t table
*/
if (gen_table == NULL)
{ caddr_t id = "GENTBL";
genalloc_t x, *xp = &x;
off_t xoff;
/* Bootstrap useing x. */
gen_table = xp;
freeobj (xp) = (caddr_t) xp;
xoff = (caddr_t) &xp->a_froff - (caddr_t) xp;
xp->a_froff = xoff;
/* One level recursion */
if (geninit(gent, igent, sizeof (genalloc_t), xoff, id, &xp))
panic ("Geninit: cannot initialize gen_table");
/* Adjust freeobj pointers and finish initialization
*/
(void) genalloc(xp);
gen_table = (genalloc_t *) xp->a_table;
*gen_table = *xp;
/* Fall through to complete original request */
}
/*
* allocate and initialize the object table
*/
/* allocate the allocation structure of the object table
*/
ap = (genalloc_t *) genalloc(gen_table);
if (ap == NULL)
{
BUGPR(("Gen_init: gen_table overflow"));
return ENOMEM;
}
/* allocate the object table
*/
sz = objsz * tblelms;
if ((ap->a_table = (caddr_t) malloc((uint)sz)) == NULL)
return ENOMEM;
/* zero out the initial number of objects to initialize
*/
bzero(ap->a_table, nelms * objsz);
/* initialize the allocation structure of the object table:
* address of end of table, object size and freelist offset in object.
*/
eotbl(ap) = ap->a_table + sz;
objsize(ap) = objsz;
ap->a_froff = off;
/* construct free list of a singly-linked (linked via freelist
* offset in object) NULL-terminated list in the new object table
* with the initial number of objects to initialize
*/
freeobj(ap) = a = ap->a_table;
for (i = 1; i < nelms; i++, a += objsz)
atofp(a, ap) = a + objsz;
atofp(a, ap) = NULL;
/* set high water mark of the object table with the address of
* the next object of the last object of the freelist
*/
ap->a_hiwater = a + objsz;
/* set the object id in the allocation structure of the object table
*/
strncpy (ap->a_handle, handle, sizeof (ap->a_handle));
*app = ap;
return 0;
}
/*
* NAME: genalloc (ap)
*
* FUNCTION: Commom allocator for large tables
*
* PARAMETERS: ap - allocation struct as defined in <sys/genalloc.h>
*
* RETURNS: Pointer to allocated object
* NULL on overflow
*
* SERIALIZATION: ICACHE_LOCK() held on entry/exit (getip()/getdp()).
*/
caddr_t
genalloc (ap)
genalloc_t *ap;
{
caddr_t a;
/* allocate new objects if freelist is empty
*/
if (freeobj(ap) == NULL)
{
caddr_t pb;
int nelms, sz, nalloc, nfree, i;
/* check for the object table overflow
*/
if (ap->a_hiwater >= eotbl(ap))
return NULL;
/* compute allocation size to allocate new object(s):
* remaining area of current page + MAX(PAGESIZE, object size)
*/
sz = MAX(PAGESIZE, objsize(ap));
/* round up the start address to the page boundary */
pb = (caddr_t)(((int) ap->a_hiwater + (sz-1)) & ~(sz-1));
/* truncate allocation size to be within the table */
nalloc = (pb + sz) - ap->a_hiwater;
nfree = eotbl(ap) - ap->a_hiwater;
nalloc = MIN(nalloc, nfree);
if (nalloc < objsize(ap))
return NULL;
/* zero out the allocation area
*/
bzero(ap->a_hiwater, nalloc);
/* insert object of allocation area into freelist
*/
nelms = nalloc / objsize(ap);
freeobj(ap) = a = ap->a_hiwater;
for (i = 1; i < nelms; i++, a += objsize(ap))
atofp(a, ap) = a + objsize(ap);
atofp(a, ap) = NULL;
/* set high water mark of the object table
*/
ap->a_hiwater = a + objsize(ap);
}
/* remove/return object from head of free list
*/
a = (caddr_t) freeobj(ap);
freeobj(ap) = atofp(a, ap);
atofp(a, ap) = NULL;
return a;
}
/*
* NAME: genfree (ap, addr)
*
* FUNCTION: Free objects previously allocated by the commom
* allocator, genalloc().
*
* PARAMETERS: ap - allocation struct as defined in <sys/genalloc.h>
* addr - pointer to the object
*
* RETURNS: None
*
* SERIALIZATION: ICACHE_LOCK() held on entry/exit (iunhash()/dquhash()).
*/
genfree (ap, addr)
genalloc_t *ap;
caddr_t *addr;
{
/* insert at head of free list
*/
atofp(addr, ap) = freeobj(ap);
freeobj(ap) = (caddr_t) addr;
}