#include "vmhdr.h"
typedef struct _vminit_
{
Vmdata_t vd;
Seg_t seg;
Block_t block;
Head_t head;
char a[3*ALIGN];
} Vminit_t;
#if __STD_C
Vmalloc_t* vmopen(Vmdisc_t* disc, Vmethod_t* meth, int mode)
#else
Vmalloc_t* vmopen(disc, meth, mode)
Vmdisc_t* disc;
Vmethod_t* meth;
int mode;
#endif
{
reg Vmalloc_t* vm;
reg Vmdata_t* vd;
reg size_t s, a, incr;
reg Block_t* b;
reg Seg_t* seg;
Vmuchar_t* addr;
reg Vmemory_f memoryf;
reg int e;
if(!meth || !disc || !(memoryf = disc->memoryf) )
return NIL(Vmalloc_t*);
GETPAGESIZE(_Vmpagesize);
if(!(vm = (Vmalloc_t*)vmalloc(Vmheap,sizeof(Vmalloc_t))) )
return NIL(Vmalloc_t*);
vm->meth = *meth;
vm->disc = disc;
vm->file = NIL(char*);
vm->line = 0;
if(disc->exceptf)
{ addr = NIL(Vmuchar_t*);
if((e = (*disc->exceptf)(vm,VM_OPEN,(Void_t*)(&addr),disc)) != 0)
{ if(e < 0 || !addr)
goto open_error;
if((a = (size_t)(VLONG(addr)%ALIGN)) != 0)
addr += ALIGN-a;
vd = (Vmdata_t*)addr;
if((vd->mode&meth->meth) != 0)
{ vm->data = vd;
return vm;
}
else
{ open_error:
vmfree(Vmheap,vm);
return NIL(Vmalloc_t*);
}
}
}
incr = disc->round <= 0 ? _Vmpagesize : disc->round;
incr = MULTIPLE(incr,ALIGN);
s = ROUND(sizeof(Vminit_t),incr);
if(!(addr = (Vmuchar_t*)(*memoryf)(vm,NIL(Void_t*),0,s,disc)) )
{ vmfree(Vmheap,vm);
return NIL(Vmalloc_t*);
}
if((a = (size_t)(VLONG(addr)%ALIGN)) != 0)
addr += ALIGN-a;
vd = (Vmdata_t*)addr;
vd->mode = (mode&VM_FLAGS) | meth->meth;
vd->incr = incr;
vd->pool = 0;
vd->free = vd->wild = NIL(Block_t*);
if(vd->mode&(VM_TRACE|VM_MTDEBUG))
vd->mode &= ~VM_TRUST;
if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE))
{ vd->root = NIL(Block_t*);
for(e = S_TINY-1; e >= 0; --e)
TINY(vd)[e] = NIL(Block_t*);
for(e = S_CACHE; e >= 0; --e)
CACHE(vd)[e] = NIL(Block_t*);
incr = sizeof(Vmdata_t);
}
else incr = OFFSET(Vmdata_t,root);
vd->seg = (Seg_t*)(addr + ROUND(incr,ALIGN));
ASSERT(VLONG(vd->seg)%ALIGN == 0);
seg = vd->seg;
seg->next = NIL(Seg_t*);
seg->vm = vm;
seg->addr = (Void_t*)(addr - (a ? ALIGN-a : 0));
seg->extent = s;
seg->baddr = addr + s - (a ? ALIGN : 0);
seg->size = s;
seg->free = NIL(Block_t*);
b = SEGBLOCK(seg);
SEG(b) = seg;
SIZE(b) = seg->baddr - (Vmuchar_t*)b - 2*sizeof(Head_t);
*SELF(b) = b;
ASSERT(SIZE(b)%ALIGN == 0);
ASSERT(VLONG(b)%ALIGN == 0);
SEG(NEXT(b)) = seg;
SIZE(NEXT(b)) = BUSY|PFREE;
if(vd->mode&(VM_MTLAST|VM_MTPOOL))
seg->free = b;
else vd->wild = b;
vm->data = vd;
vm->next = Vmheap->next;
Vmheap->next = vm;
return vm;
}