#define I_NEED_OS2_H
#define INCL_DOSMEMMGR
#include <os2.h>
#include <sys/types.h>
#include <umalloc.h>
#include "os.h"
#undef ADDRESS
#include "xf86str.h"
#define RESERVED_BLOCKS 4096
void *os2ldAddToHeap(Heap_t, size_t *, int *);
void os2ldRemoveFromHeap(Heap_t, void *, size_t);
PVOID os2ldCommitedTop;
PVOID os2ldBase;
Heap_t os2ldHeap;
int os2ldTotalCommitedBlocks;
static BOOL FirstTime = TRUE;
void *
os2ldcalloc(size_t num_elem, size_t size_elem)
{
APIRET rc;
int ret;
if (FirstTime) {
if ((rc = DosAllocMem(&os2ldBase, RESERVED_BLOCKS * 4096,
PAG_READ | PAG_WRITE | PAG_EXECUTE)) != 0) {
xf86Msg(X_ERROR, "OS2LD: DosAllocMem failed, rc=%d\n", rc);
return NULL;
}
if ((rc = DosSetMem(os2ldBase,
32 * 4096, PAG_DEFAULT | PAG_COMMIT)) != 0) {
xf86Msg(X_ERROR, "OS2LD: DosSetMem failed, rc=%d\n", rc);
DosFreeMem(os2ldBase);
return NULL;
}
os2ldCommitedTop = os2ldBase + 32 * 4096;
os2ldTotalCommitedBlocks = 32;
#ifdef DEBUG
xf86Msg(X_INFO, "OS2LD: Initial heap at addr=%p\n", os2ldBase);
#endif
if ((os2ldHeap = _ucreate(os2ldBase,
32 * 4096, _BLOCK_CLEAN,
_HEAP_REGULAR, os2ldAddToHeap,
os2ldRemoveFromHeap)) == NULL) {
xf86Msg(X_ERROR, "OS2LD: heap creation failed\n");
DosFreeMem(os2ldBase);
return NULL;
}
if ((ret = _uopen(os2ldHeap)) != 0) {
xf86Msg(X_ERROR, "OS2LD: heap open failed\n");
ret = _udestroy(os2ldHeap, _FORCE);
DosFreeMem(os2ldBase);
return (NULL);
}
FirstTime = FALSE;
#ifdef DEBUG
xf86Msg(X_INFO, "OS2LD: Created module heap at addr=%p\n", os2ldHeap);
#endif
}
return _ucalloc(os2ldHeap, num_elem, size_elem);
}
void *
os2ldAddToHeap(Heap_t H, size_t * new_size, int *PCLEAN)
{
PVOID NewBase;
long adjusted_size;
long blocks;
APIRET rc;
if (H != os2ldHeap) {
xf86Msg(X_ERROR, "OS2LD: Heap corruption in GrowHeap, p=%08x\n", H);
return NULL;
}
NewBase = os2ldCommitedTop;
adjusted_size = (*new_size / 65536) * 65536;
if ((*new_size % 65536) > 0)
adjusted_size += 65536;
blocks = adjusted_size / 4096;
if ((os2ldTotalCommitedBlocks + blocks) > RESERVED_BLOCKS) {
xf86Msg(X_ERROR, "OS2LD: Out of memory in GrowHeap\n");
xf86Msg(X_ERROR,
"OS2LD: Max available memory is of %ld bytes\n",
RESERVED_BLOCKS * 4096);
return NULL;
}
if ((rc =
DosSetMem(NewBase, adjusted_size, PAG_DEFAULT | PAG_COMMIT)) != 0) {
xf86Msg(X_ERROR,
"OS2LD: DosSetMem failed in GrowHeap, size req'd=%d, rc=%d\n",
adjusted_size, rc);
return NULL;
}
os2ldCommitedTop += adjusted_size;
os2ldTotalCommitedBlocks += blocks;
*PCLEAN = _BLOCK_CLEAN;
*new_size = adjusted_size;
#ifdef DEBUG
xf86Msg(X_INFO, "OS2LD: Heap extended by %d bytes, addr=%p\n",
adjusted_size, NewBase);
#endif
return NewBase;
}
void
os2ldRemoveFromHeap(Heap_t H, void *memory, size_t size)
{
if (H != os2ldHeap) {
xf86Msg(X_ERROR, "OS2LD: Heap corruption in ShrinkHeap, p=%08x\n", H);
return;
}
if (memory == os2ldBase) {
DosFreeMem(os2ldBase);
#ifdef DEBUG
xf86Msg(X_INFO, "OS2LD: total heap area deallocated\n");
#endif
os2ldBase = 0;
FirstTime = TRUE;
}
}