home *** CD-ROM | disk | FTP | other *** search
- /* $Id: lxmalloc.cpp,v 1.2 2002/04/26 23:09:23 smilcke Exp $ */
-
- /*
- * malloc.cpp
- * Autor: Stefan Milcke
- * Erstellt am: 26.10.2001
- * Letzte Aenderung am: 28.04.2002
- *
- */
- extern "C" {
- #define INCL_NOPMAPI
- #define INCL_DOSERRORS // for ERROR_INVALID_FUNCTION
- #include <os2.h>
- }
- #include <devhelp.h>
- #include <ldefos2.h>
- #include <string.h>
- #ifdef KEE
- #include <kee.h>
- #endif
- extern "C" {
- #include <linux/types.h>
- #include <linux/spinlock.h>
- #include <asm/page.h>
- }
-
- #define DEFAULT_HEAP_SIZE 4096
-
- #define MEMFLAG_USED 1
- #define MEMFLAG_FREE 2
-
- #pragma pack(1)
-
- unsigned long default_heap_size=DEFAULT_HEAP_SIZE;
-
- #ifdef DEBUG
- #define USE_SIGNATURE
- #define SIGNATURE 0x2817EAFD
- #define DEBUG_INLINE
- #else
- #define DEBUG_INLINE inline
- #endif
-
- extern "C"
- {
-
- typedef struct _MEMBLOCK
- {
- #ifdef USE_SIGNATURE
- unsigned long signature;
- #endif
- unsigned long size;
- unsigned long flags;
- struct _MEMBLOCK *pNext;
- } MEMBLOCK, near *PMEMBLOCK;
-
- typedef struct _HEAP
- {
- #ifdef USE_SIGNATURE
- unsigned long signature;
- #endif
- unsigned long size;
- struct _HEAP *pNext;
- struct _MEMBLOCK *pMem;
- } HEAP, near *PHEAP;
-
- #pragma pack()
-
- PHEAP root_heap=NULL;
-
- static spinlock_t memlock=SPIN_LOCK_UNLOCKED;
-
- #define MEMFLAGS (VMDHA_FIXED | VMDHA_CONTIG)
-
- //--------------------------------- allocHeap ----------------------------------
- static DEBUG_INLINE PHEAP allocHeap(unsigned long heapSize)
- {
- char near *heap;
- #ifdef KEE
- SHORT sel;
- if(KernVMAlloc(heapSize,MEMFLAGS,(PVOID*)&heap,(PVOID*)-1,&sel))
- {
- #else
- if(DevVMAlloc(MEMFLAGS,heapSize,(LINEAR)-1,__StackToFlat((ULONG)&heap)))
- {
- #endif
- return (PHEAP)0;
- }
- *(ULONG *)heap=0;
- {
- PHEAP pHeap=(PHEAP)heap;
- PMEMBLOCK pMem=NULL;
- #ifdef USE_SIGNATURE
- pHeap->signature=SIGNATURE;
- #endif
- pHeap->size=heapSize-sizeof(HEAP);
- pHeap->pNext=NULL;
- pHeap->pMem=(PMEMBLOCK)((unsigned long)heap+sizeof(HEAP));
-
- pMem=(PMEMBLOCK)pHeap->pMem;
- #ifdef USE_SIGNATURE
- pMem->signature=SIGNATURE;
- #endif
- pMem->size=pHeap->size-sizeof(MEMBLOCK);
- pMem->flags=MEMFLAG_FREE;
- pMem->pNext=NULL;
- }
- return (PHEAP)heap;
- }
-
- //---------------------------------- freeHeap ----------------------------------
- // returns 1, if the heap was removed
- static DEBUG_INLINE int freeHeap(PHEAP pHeap)
- {
- char near *heap=0;
- // Special for zero pointer
- if(!pHeap)
- return 0;
- // Special for root heap
- if(pHeap==root_heap)
- {
- if((!pHeap->pNext))
- return 0;
- root_heap=(PHEAP)pHeap->pNext;
- heap=(char near *)pHeap;
- }
- else
- { // Walk through the heap chain until we found our heap
- PHEAP p=root_heap;
- while(p)
- {
- if(p->pNext==pHeap)
- { // Fond it, so move this heap out of the chain
- if(p->pNext)
- p->pNext=p->pNext->pNext;
- heap=(char near *)pHeap;
- break;
- }
- else
- p=(PHEAP)p->pNext;
- }
- }
- if(heap)
- {
- #ifdef KEE
- KernVMFree(heap);
- #else
- DevVMFree((LINEAR)heap);
- #endif
- return 1;
- }
- return 0;
- }
-
- //-------------------------------- compressHeap --------------------------------
- // returns 1, if the heap was empty and so removed
- static DEBUG_INLINE int compressHeap(PHEAP pHeap)
- {
- PMEMBLOCK pm;
- PMEMBLOCK previous;
- PMEMBLOCK next=(PMEMBLOCK)NULL;
- if(!pHeap)
- return 0;
- pm=(PMEMBLOCK)pHeap->pMem;
- previous=(PMEMBLOCK)pHeap->pMem;
- while(pm)
- {
- if(pm->flags & MEMFLAG_FREE)
- { // Check, if next block is also free.
- next=(PMEMBLOCK)pm->pNext;
- if(next)
- {
- if(next->flags & MEMFLAG_FREE)
- {
- PMEMBLOCK tmp=(PMEMBLOCK)next->pNext;
- pm->pNext=(_MEMBLOCK *)tmp;
- pm->size=pm->size+next->size;
- pm=previous;
- }
- }
- }
- previous=pm;
- pm=(PMEMBLOCK)pm->pNext;
- }
- pm=(PMEMBLOCK)pHeap->pMem;
- if(!pm->pNext)
- {
- freeHeap(pHeap);
- return 1;
- }
- return 0;
- }
-
- //------------------------------------ free ------------------------------------
- void free(void *ptr)
- {
- PHEAP p=root_heap;
- PMEMBLOCK pm=NULL;
- if(!ptr)
- return;
- spin_lock_irq(&memlock);
- while(p)
- {
- pm=(PMEMBLOCK)p->pMem;
- while(pm)
- {
- if((pm->flags & MEMFLAG_USED)
- && (void *)((unsigned long)pm+sizeof(MEMBLOCK))==ptr)
- {
- p->size+=pm->size;
- pm->flags=MEMFLAG_FREE;
- compressHeap(p);
- spin_unlock_irq(&memlock);
- return;
- }
- pm=(PMEMBLOCK)pm->pNext;
- }
- p=(PHEAP)p->pNext;
- }
- spin_unlock_irq(&memlock);
- }
-
- //----------------------------------- malloc -----------------------------------
- void *malloc(unsigned long size)
- {
- PHEAP p;
- PMEMBLOCK pm=NULL;
- spin_lock_irq(&memlock);
- p=root_heap;
- while(p)
- {
- // Is there enough room in this heap ?
- if(p->size>=size)
- {
- pm=(PMEMBLOCK)p->pMem;
- while(pm)
- {
- if((pm->flags & MEMFLAG_FREE) && (pm->size >= size))
- { // Found a free block
- long remaining_size=pm->size-size-sizeof(MEMBLOCK);
- pm->flags=MEMFLAG_USED;
- pm->size=size;
- if(remaining_size>0)
- {
- PMEMBLOCK npm=(PMEMBLOCK)(((unsigned long)pm)+pm->size+sizeof(MEMBLOCK));
- pm->pNext=npm;
- #ifdef USE_SIGNATURE
- npm->signature=SIGNATURE;
- #endif
- npm->size=remaining_size;
- npm->pNext=NULL;
- npm->flags=MEMFLAG_FREE;
- }
- p->size-=pm->size;
- spin_unlock_irq(&memlock);
- return (void *)((unsigned long)pm+sizeof(MEMBLOCK));
- }
- #ifdef USE_SIGNATURE
- if(pm->pNext && pm->pNext->signature==SIGNATURE)
- #else
- if(pm->pNext)
- #endif
- pm=(PMEMBLOCK)pm->pNext;
- else
- break;
- }
- }
- #ifdef USE_SIGNATURE
- if(p->pNext && p->pNext->signature==SIGNATURE)
- #else
- if(p->pNext)
- #endif
- p=(PHEAP)p->pNext;
- else
- { // No heaps left, so allocate a new one
- unsigned long requested_size=size+sizeof(HEAP)+sizeof(MEMBLOCK);
- if(requested_size>default_heap_size)
- {
- requested_size=((unsigned long)((requested_size/default_heap_size)+1))*default_heap_size;
- p->pNext=allocHeap(requested_size);
- }
- else
- p->pNext=allocHeap(default_heap_size);
- p=(PHEAP)p->pNext;
- }
- }
- spin_unlock_irq(&memlock);
- return NULL;
- }
-
- //---------------------------------- realloc -----------------------------------
- void *realloc(void *oldPtr,unsigned long newSize)
- {
- void *p=malloc(newSize);
- void *pf=NULL;
- unsigned long oldSize=0;
- spin_lock_irq(&memlock);
- if(p)
- {
- if(oldPtr)
- {
- PHEAP p=root_heap;
- PMEMBLOCK pm=NULL;
- while(p)
- {
- pm=(PMEMBLOCK)p->pMem;
- while(pm)
- {
- if((pm->flags & MEMFLAG_USED)
- && (void *)((unsigned long)pm+sizeof(MEMBLOCK))==oldPtr)
- {
- pf=oldPtr;
- oldSize=pm->size;
- memcpy(p,pf,oldSize);
- p->size+=pm->size;
- pm->flags=MEMFLAG_FREE;
- compressHeap(p);
- spin_unlock_irq(&memlock);
- return p;
- }
- pm=(PMEMBLOCK)pm->pNext;
- }
- p=(PHEAP)p->pNext;
- }
- }
- }
- spin_unlock_irq(&memlock);
- return p;
- }
-
- //-------------------------------- __mallocInit --------------------------------
- int __mallocInit(void)
- {
- if(!root_heap)
- if(0==(root_heap=allocHeap(default_heap_size)))
- return 1;
- return 0;
- }
-
- #define VMMEMFLAGS (VMDHA_PROCESS)
-
- typedef struct _VMMEMADDR
- {
- struct _VMMEMADDR *next;
- unsigned long size;
- unsigned long pid;
- void *ptr;
- #ifdef KEE
- KEEVMLock lock;
- #else
- char lock[12];
- #endif
- } VMMEMADDR,*PVMMEMADDR;
-
- PVMMEMADDR vm_root_addr=NULL;
- extern "C" unsigned long OS2_get_current_pid(void);
- //--------------------------------- __vmalloc ----------------------------------
- void *__vmalloc(unsigned long size,int gfp_mask,pgprot_t prot)
- {
- PVMMEMADDR p=NULL;
- unsigned long sz=PAGE_ALIGN(size);
- #ifdef KEE
- void *ptr=NULL;
- #else
- char near *ptr=NULL;
- #endif
-
- p=(PVMMEMADDR)malloc(sizeof(VMMEMADDR));
- if(p)
- {
- #ifdef KEE
- SHORT sel;
- if(KernVMAlloc(sz,VMMEMFLAGS,(PVOID*)&ptr,(PVOID*)-1,&sel))
- #else
- if(DevVMAlloc(VMMEMFLAGS,sz,(LINEAR)-1,__StackToFlat((ULONG)&ptr)))
- #endif
- {
- free(p);
- return NULL;
- }
- #ifdef KEE
- if(KernVMLock(KEE_VML_CONTIG | KEE_VML_LONGLOCK | KEE_VML_WRITEABLE
- ,ptr,sz,&(p->lock),(KEEVMPageList*)-1,0))
- {
- KernVMFree(ptr);
- #else
- if(DevVMLock(VMDHL_CONTIG | VMDHL_LONG | VMDHL_WRITE
- ,ptr,sz,(LINEAR)-1,&(p->lock)
- ,(LINEAR)__StackToFlat((ULONG)&PgCount)))
- {
- DevVMFree((LINEAR)ptr);
- #endif
- free(p);
- return NULL;
- }
- p->size=sz;
- p->pid=OS2_get_current_pid();
- p->ptr=ptr;
- spin_lock_irq(&memlock);
- p->next=vm_root_addr;
- vm_root_addr=p;
- spin_unlock_irq(&memlock);
- }
- return (void *)ptr;
- }
-
- //----------------------------------- vfree ------------------------------------
- void vfree(void *ptr)
- {
- void *p=NULL;
- PVMMEMADDR pm;
- PVMMEMADDR previous_pm=NULL;
- unsigned long pid=OS2_get_current_pid();
- spin_lock_irq(&memlock);
- pm=vm_root_addr;
- while(pm)
- {
- if(pm->ptr==ptr && pm->pid==pid)
- {
- p=pm->ptr;
- if(pm==vm_root_addr)
- vm_root_addr=pm->next;
- else if(previous_pm)
- previous_pm->next=pm->next;
- break;
- }
- previous_pm=pm;
- pm=pm->next;
- }
- spin_unlock_irq(&memlock);
- if(p && pm)
- {
- #ifdef KEE
- if(!KernVMUnlock(&pm->lock))
- KernVMFree(pm->ptr);
- #else
- if(!DevVMUnLock(&pm->lock))
- DevVMFree(pm->ptr);
- #endif
- free(pm);
- }
- }
-
- }; // extern "C"
-