Logo Search packages:      
Sourcecode: ksh version File versions  Download package

vmpool.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*          Copyright (c) 1985-2010 AT&T Intellectual Property          *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                    by AT&T Intellectual Property                     *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                 Glenn Fowler <gsf@research.att.com>                  *
*                  David Korn <dgk@research.att.com>                   *
*                   Phong Vo <kpv@research.att.com>                    *
*                                                                      *
***********************************************************************/
#if defined(_UWIN) && defined(_BLD_ast)

void _STUB_vmpool(){}

#else

#include    "vmhdr.h"

#define POOLFREE  0x55555555L /* block free indicator  */

/*    Method for pool allocation.
**    All elements in a pool have the same size.
**    The following fields of Vmdata_t are used as:
**          pool: size of a block.
**          free: list of free blocks.
**
**    Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
*/

#if __STD_C
static Void_t* poolalloc(Vmalloc_t* vm, reg size_t size)
#else
static Void_t* poolalloc(vm, size )
Vmalloc_t*  vm;
reg size_t  size;
#endif
{
      reg Vmdata_t*     vd = vm->data;
      reg Block_t *tp, *next;
      reg size_t  s;
      reg Seg_t*  seg;
      reg int           local, inuse;

      if(size <= 0)
            return NIL(Void_t*);
      if(size != vd->pool)
      {     if(vd->pool <= 0)
                  vd->pool = size;
            else  return NIL(Void_t*);
      }

      SETINUSE(vd, inuse);
      if(!(local = vd->mode&VM_TRUST) )
      {     GETLOCAL(vd,local);
            if(ISLOCK(vd, local))
            {     CLRINUSE(vd, inuse);
                  return NIL(Void_t*);
            }
            SETLOCK(vd, local);
      }

      if((tp = vd->free) ) /* there is a ready free block */
      {     vd->free = SEGLINK(tp);
            goto done;
      }

      size = ROUND(size,ALIGN);

      /* look thru all segments for a suitable free block */
      for(tp = NIL(Block_t*), seg = vd->seg; seg; seg = seg->next)
      {     if((tp = seg->free) &&
               (s = (SIZE(tp) & ~BITS) + sizeof(Head_t)) >= size )
                  goto has_blk;
      }

      for(;;) /* must extend region */
      {     if((tp = (*_Vmextend)(vm,ROUND(size,vd->incr),NIL(Vmsearch_f))) )
            {     s = (SIZE(tp) & ~BITS) + sizeof(Head_t);
                  seg = SEG(tp);
                  goto has_blk;
            }
            else if(vd->mode&VM_AGAIN)
                  vd->mode &= ~VM_AGAIN;
            else  goto done;
      }

has_blk: /* if get here, (tp, s, seg) must be well-defined */
      next = (Block_t*)((Vmuchar_t*)tp+size);
      if((s -= size) <= (size + sizeof(Head_t)) )
      {     for(; s >= size; s -= size)
            {     SIZE(next) = POOLFREE;
                  SEGLINK(next) = vd->free;
                  vd->free = next;
                  next = (Block_t*)((Vmuchar_t*)next + size);
            }
            seg->free = NIL(Block_t*);
      }
      else
      {     SIZE(next) = s - sizeof(Head_t);
            SEG(next) = seg;
            seg->free = next;
      }

done:
      if(!local && (vd->mode&VM_TRACE) && _Vmtrace && tp)
            (*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)tp,vd->pool,0);

      CLRLOCK(vd, local);
      ANNOUNCE(local, vm, VM_ALLOC, (Void_t*)tp, vm->disc);
      CLRINUSE(vd, inuse);
      return (Void_t*)tp;
}

#if __STD_C
static long pooladdr(Vmalloc_t* vm, reg Void_t* addr)
#else
static long pooladdr(vm, addr)
Vmalloc_t*  vm;
reg Void_t* addr;
#endif
{
      reg Block_t *bp, *tp;
      reg Vmuchar_t     *laddr, *baddr;
      reg size_t  size;
      reg Seg_t*  seg;
      reg long    offset;
      reg Vmdata_t*     vd = vm->data;
      reg int           local, inuse;

      SETINUSE(vd, inuse);
      if(!(local = vd->mode&VM_TRUST))
      {     GETLOCAL(vd,local);
            if(ISLOCK(vd,local))
            {     CLRINUSE(vd, inuse);
                  return -1L;
            }
            SETLOCK(vd,local);
      }

      offset = -1L;
      for(seg = vd->seg; seg; seg = seg->next)
      {     laddr = (Vmuchar_t*)SEGBLOCK(seg);
            baddr = seg->baddr-sizeof(Head_t);
            if((Vmuchar_t*)addr < laddr || (Vmuchar_t*)addr >= baddr)
                  continue;

            /* the block that has this address */
            size = ROUND(vd->pool,ALIGN);
            tp = (Block_t*)(laddr + (((Vmuchar_t*)addr-laddr)/size)*size );

            /* see if this block has been freed */
            if(SIZE(tp) == POOLFREE) /* may be a coincidence - make sure */
                  for(bp = vd->free; bp; bp = SEGLINK(bp))
                        if(bp == tp)
                              goto done;

            offset = (Vmuchar_t*)addr - (Vmuchar_t*)tp;
            goto done;
      }

done :
      CLRLOCK(vd,local);
      CLRINUSE(vd, inuse);
      return offset;
}

#if __STD_C
static int poolfree(reg Vmalloc_t* vm, reg Void_t* data )
#else
static int poolfree(vm, data)
reg Vmalloc_t*    vm;
reg Void_t* data;
#endif
{
      reg Block_t*      bp;
      reg Vmdata_t*     vd = vm->data;
      reg int           local, inuse;

      if(!data)
            return 0;

      SETINUSE(vd, inuse);
      if(!(local = vd->mode&VM_TRUST))
      {     GETLOCAL(vd, local);

            if(ISLOCK(vd, local) || vd->pool <= 0)
            {     CLRINUSE(vd, inuse);
                  return -1;
            }

            if(KPVADDR(vm,data,pooladdr) != 0)
            {     if(vm->disc->exceptf)
                        (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
                  CLRINUSE(vd, inuse);
                  return -1;
            }

            SETLOCK(vd, local);
      }

      bp = (Block_t*)data;
      SIZE(bp) = POOLFREE;
      SEGLINK(bp) = vd->free;
      vd->free = bp;

      if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
            (*_Vmtrace)(vm, (Vmuchar_t*)data, NIL(Vmuchar_t*), vd->pool, 0);

      CLRLOCK(vd,local);
      ANNOUNCE(local, vm, VM_FREE, data, vm->disc);
      CLRINUSE(vd, inuse);
      return 0;
}

#if __STD_C
static Void_t* poolresize(Vmalloc_t* vm, Void_t* data, size_t size, int type )
#else
static Void_t* poolresize(vm, data, size, type )
Vmalloc_t*  vm;
Void_t*           data;
size_t            size;
int         type;
#endif
{
      int         local, inuse;
      reg Vmdata_t*     vd = vm->data;

      NOTUSED(type);

      SETINUSE(vd, inuse);
      if(!data)
      {     if((data = poolalloc(vm,size)) && (type&VM_RSZERO) )
            {     reg int     *d = (int*)data, *ed = (int*)((char*)data+size);
                  do { *d++ = 0;} while(d < ed);
            }
            CLRINUSE(vd, inuse);
            return data;
      }
      if(size == 0)
      {     (void)poolfree(vm,data);
            CLRINUSE(vd, inuse);
            return NIL(Void_t*);
      }

      if(!(local = vd->mode&VM_TRUST) )
      {     GETLOCAL(vd, local);

            if(ISLOCK(vd, local) )
            {     CLRINUSE(vd, inuse);
                  return NIL(Void_t*);
            }

            if(size != vd->pool || KPVADDR(vm,data,pooladdr) != 0)
            {     if(vm->disc->exceptf)
                        (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
                  CLRINUSE(vd, inuse);
                  return NIL(Void_t*);
            }

            if((vd->mode&VM_TRACE) && _Vmtrace)
                  (*_Vmtrace)(vm, (Vmuchar_t*)data, (Vmuchar_t*)data, size, 0);
      }

      ANNOUNCE(local, vm, VM_RESIZE, data, vm->disc);
      CLRINUSE(vd, inuse);
      return data;
}

#if __STD_C
static long poolsize(Vmalloc_t* vm, Void_t* addr)
#else
static long poolsize(vm, addr)
Vmalloc_t*  vm;
Void_t*           addr;
#endif
{
      return pooladdr(vm,addr) == 0 ? (long)vm->data->pool : -1L;
}

#if __STD_C
static int poolcompact(Vmalloc_t* vm)
#else
static int poolcompact(vm)
Vmalloc_t*  vm;
#endif
{
      reg Block_t*      fp;
      reg Seg_t   *seg, *next;
      reg size_t  s;
      reg Vmdata_t*     vd = vm->data;
      reg int           inuse;

      SETINUSE(vd, inuse);
      if(!(vd->mode&VM_TRUST))
      {     if(ISLOCK(vd,0))
            {     CLRINUSE(vd, inuse);
                  return -1;
            }
            SETLOCK(vd,0);
      }

      for(seg = vd->seg; seg; seg = next)
      {     next = seg->next;

            if(!(fp = seg->free))
                  continue;

            seg->free = NIL(Block_t*);
            if(seg->size == (s = SIZE(fp)&~BITS))
                  s = seg->extent;
            else  s += sizeof(Head_t);

            if((*_Vmtruncate)(vm,seg,s,1) == s)
                  seg->free = fp;
      }

      if((vd->mode&VM_TRACE) && _Vmtrace)
            (*_Vmtrace)(vm, (Vmuchar_t*)0, (Vmuchar_t*)0, 0, 0);

      CLRLOCK(vd,0);
      CLRINUSE(vd, inuse);
      return 0;
}

#if __STD_C
static Void_t* poolalign(Vmalloc_t* vm, size_t size, size_t align)
#else
static Void_t* poolalign(vm, size, align)
Vmalloc_t*  vm;
size_t            size;
size_t            align;
#endif
{
      NOTUSED(vm);
      NOTUSED(size);
      NOTUSED(align);
      return NIL(Void_t*);
}

/* Public interface */
static Vmethod_t _Vmpool =
{
      poolalloc,
      poolresize,
      poolfree,
      pooladdr,
      poolsize,
      poolcompact,
      poolalign,
      VM_MTPOOL
};

__DEFINE__(Vmethod_t*,Vmpool,&_Vmpool);

#ifdef NoF
NoF(vmpool)
#endif

#endif

Generated by  Doxygen 1.6.0   Back to index