/* heap.c (rsxnt) -- Copyright (c) 1996-1997 Rainer Schnitker */

#include "rsxnt.h"

int _rsxnt_init_heap (EMXPROCESS *pptr)
{
    extern int _sys_heap_size;
    SYSTEM_INFO sysi;
    DWORD size;

    size = (pptr->rsxnt_opt.heapsize) ?
            pptr->rsxnt_opt.heapsize : _sys_heap_size;

    pptr->heapmem = VirtualAlloc(0, size, MEM_RESERVE, PAGE_NOACCESS);
    if (!pptr->heapmem)
        return FALSE;

    pptr->heap_start =
    pptr->heap_brk =
    pptr->heap_pagebrk = pptr->heapmem;
    pptr->heap_end = (char *) pptr->heapmem + size;

    GetSystemInfo(&sysi);
    pptr->pagesize = sysi.dwPageSize;

    InitializeCriticalSection(&(pptr->CritSectHeap));
    return TRUE;
}

void * _rsxnt_grow_heap (EMXPROCESS *p, int bytes)
{
    DWORD pagealign;
    void *oldbrk = p->heap_brk;
    void *newbrk = (void *) ((DWORD) p->heap_brk + bytes);

    /* overflow check */
    if (newbrk > p->heap_end || newbrk < p->heap_brk)
        return NULL;

    pagealign = ((DWORD) newbrk + (p->pagesize -1)) & ~(p->pagesize-1);

    if ((void *) pagealign > p->heap_pagebrk) {
        void *base;
        base = VirtualAlloc(p->heap_pagebrk,
                            pagealign - (DWORD)p->heap_pagebrk,
                            MEM_COMMIT, PAGE_READWRITE);
        if (base != p->heap_pagebrk)
            return NULL;
    }

    p->heap_brk = newbrk;
    p->heap_pagebrk = (void *) pagealign;
    return oldbrk;
}

void * _rsxnt_shrink_heap (EMXPROCESS *p, int bytes)
{
    DWORD pagealign;
    void *oldbrk = p->heap_brk;
    void *newbrk = (void *) ((DWORD) p->heap_brk - bytes);

    if (newbrk < p->heap_start || newbrk > p->heap_brk)   /* overflow */
        return NULL;

    pagealign = ((DWORD)newbrk + (p->pagesize -1)) & ~(p->pagesize-1);

    if ((void *)pagealign < p->heap_pagebrk) {
        if (VirtualFree((LPVOID)pagealign,
                            (DWORD)p->heap_pagebrk - pagealign,
                            MEM_DECOMMIT) == FALSE)
            return NULL;
    }

    p->heap_brk = newbrk;
    p->heap_pagebrk = (void *) pagealign;
    return oldbrk;
}
