home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / lxapi32.zip / Lib32 / lxmalloc.cpp < prev    next >
C/C++ Source or Header  |  2002-04-27  |  9KB  |  445 lines

  1. /* $Id: lxmalloc.cpp,v 1.2 2002/04/26 23:09:23 smilcke Exp $ */
  2.  
  3. /*
  4.  * malloc.cpp
  5.  * Autor:               Stefan Milcke
  6.  * Erstellt am:         26.10.2001
  7.  * Letzte Aenderung am: 28.04.2002
  8.  *
  9. */
  10. extern "C" {
  11. #define INCL_NOPMAPI
  12. #define INCL_DOSERRORS           // for ERROR_INVALID_FUNCTION
  13. #include <os2.h>
  14. }
  15. #include <devhelp.h>
  16. #include <ldefos2.h>
  17. #include <string.h>
  18. #ifdef KEE
  19. #include <kee.h>
  20. #endif
  21. extern "C" {
  22. #include <linux/types.h>
  23. #include <linux/spinlock.h>
  24. #include <asm/page.h>
  25. }
  26.  
  27. #define DEFAULT_HEAP_SIZE  4096
  28.  
  29. #define MEMFLAG_USED 1
  30. #define MEMFLAG_FREE 2
  31.  
  32. #pragma pack(1)
  33.  
  34. unsigned long default_heap_size=DEFAULT_HEAP_SIZE;
  35.  
  36. #ifdef DEBUG
  37. #define USE_SIGNATURE
  38. #define SIGNATURE 0x2817EAFD
  39. #define DEBUG_INLINE
  40. #else
  41. #define DEBUG_INLINE inline
  42. #endif
  43.  
  44. extern "C"
  45. {
  46.  
  47. typedef struct _MEMBLOCK
  48. {
  49. #ifdef USE_SIGNATURE
  50.  unsigned long signature;
  51. #endif
  52.  unsigned long size;
  53.  unsigned long flags;
  54.  struct _MEMBLOCK *pNext;
  55. } MEMBLOCK, near *PMEMBLOCK;
  56.  
  57. typedef struct _HEAP
  58. {
  59. #ifdef USE_SIGNATURE
  60.  unsigned long signature;
  61. #endif
  62.  unsigned long size;
  63.  struct _HEAP *pNext;
  64.  struct _MEMBLOCK *pMem;
  65. } HEAP, near *PHEAP;
  66.  
  67. #pragma pack()
  68.  
  69. PHEAP root_heap=NULL;
  70.  
  71. static spinlock_t memlock=SPIN_LOCK_UNLOCKED;
  72.  
  73. #define MEMFLAGS  (VMDHA_FIXED | VMDHA_CONTIG)
  74.  
  75. //--------------------------------- allocHeap ----------------------------------
  76. static DEBUG_INLINE PHEAP allocHeap(unsigned long heapSize)
  77. {
  78.  char near *heap;
  79. #ifdef KEE
  80.  SHORT sel;
  81.  if(KernVMAlloc(heapSize,MEMFLAGS,(PVOID*)&heap,(PVOID*)-1,&sel))
  82.  {
  83. #else
  84.  if(DevVMAlloc(MEMFLAGS,heapSize,(LINEAR)-1,__StackToFlat((ULONG)&heap)))
  85.  {
  86. #endif
  87.   return (PHEAP)0;
  88.  }
  89.  *(ULONG *)heap=0;
  90.  {
  91.   PHEAP pHeap=(PHEAP)heap;
  92.   PMEMBLOCK pMem=NULL;
  93. #ifdef USE_SIGNATURE
  94.   pHeap->signature=SIGNATURE;
  95. #endif
  96.   pHeap->size=heapSize-sizeof(HEAP);
  97.   pHeap->pNext=NULL;
  98.   pHeap->pMem=(PMEMBLOCK)((unsigned long)heap+sizeof(HEAP));
  99.  
  100.   pMem=(PMEMBLOCK)pHeap->pMem;
  101. #ifdef USE_SIGNATURE
  102.   pMem->signature=SIGNATURE;
  103. #endif
  104.   pMem->size=pHeap->size-sizeof(MEMBLOCK);
  105.   pMem->flags=MEMFLAG_FREE;
  106.   pMem->pNext=NULL;
  107.  }
  108.  return (PHEAP)heap;
  109. }
  110.  
  111. //---------------------------------- freeHeap ----------------------------------
  112. // returns 1, if the heap was removed
  113. static DEBUG_INLINE int freeHeap(PHEAP pHeap)
  114. {
  115.  char near *heap=0;
  116.  // Special for zero pointer
  117.  if(!pHeap)
  118.   return 0;
  119.  // Special for root heap
  120.  if(pHeap==root_heap)
  121.  {
  122.   if((!pHeap->pNext))
  123.    return 0;
  124.   root_heap=(PHEAP)pHeap->pNext;
  125.   heap=(char near *)pHeap;
  126.  }
  127.  else
  128.  { // Walk through the heap chain until we found our heap
  129.   PHEAP p=root_heap;
  130.   while(p)
  131.   {
  132.    if(p->pNext==pHeap)
  133.    { // Fond it, so move this heap out of the chain
  134.     if(p->pNext)
  135.      p->pNext=p->pNext->pNext;
  136.     heap=(char near *)pHeap;
  137.     break;
  138.    }
  139.    else
  140.     p=(PHEAP)p->pNext;
  141.   }
  142.  }
  143.  if(heap)
  144.  {
  145. #ifdef KEE
  146.   KernVMFree(heap);
  147. #else
  148.   DevVMFree((LINEAR)heap);
  149. #endif
  150.   return 1;
  151.  }
  152.  return 0;
  153. }
  154.  
  155. //-------------------------------- compressHeap --------------------------------
  156. // returns 1, if the heap was empty and so removed
  157. static DEBUG_INLINE int compressHeap(PHEAP pHeap)
  158. {
  159.  PMEMBLOCK pm;
  160.  PMEMBLOCK previous;
  161.  PMEMBLOCK next=(PMEMBLOCK)NULL;
  162.  if(!pHeap)
  163.   return 0;
  164.  pm=(PMEMBLOCK)pHeap->pMem;
  165.  previous=(PMEMBLOCK)pHeap->pMem;
  166.  while(pm)
  167.  {
  168.   if(pm->flags & MEMFLAG_FREE)
  169.   { // Check, if next block is also free.
  170.    next=(PMEMBLOCK)pm->pNext;
  171.    if(next)
  172.    {
  173.     if(next->flags & MEMFLAG_FREE)
  174.     {
  175.      PMEMBLOCK tmp=(PMEMBLOCK)next->pNext;
  176.      pm->pNext=(_MEMBLOCK *)tmp;
  177.      pm->size=pm->size+next->size;
  178.      pm=previous;
  179.     }
  180.    }
  181.   }
  182.   previous=pm;
  183.   pm=(PMEMBLOCK)pm->pNext;
  184.  }
  185.  pm=(PMEMBLOCK)pHeap->pMem;
  186.  if(!pm->pNext)
  187.  {
  188.   freeHeap(pHeap);
  189.   return 1;
  190.  }
  191.  return 0;
  192. }
  193.  
  194. //------------------------------------ free ------------------------------------
  195. void free(void *ptr)
  196. {
  197.  PHEAP p=root_heap;
  198.  PMEMBLOCK pm=NULL;
  199.  if(!ptr)
  200.   return;
  201.  spin_lock_irq(&memlock);
  202.  while(p)
  203.  {
  204.   pm=(PMEMBLOCK)p->pMem;
  205.   while(pm)
  206.   {
  207.    if((pm->flags & MEMFLAG_USED)
  208.        && (void *)((unsigned long)pm+sizeof(MEMBLOCK))==ptr)
  209.    {
  210.     p->size+=pm->size;
  211.     pm->flags=MEMFLAG_FREE;
  212.     compressHeap(p);
  213.     spin_unlock_irq(&memlock);
  214.     return;
  215.    }
  216.    pm=(PMEMBLOCK)pm->pNext;
  217.   }
  218.   p=(PHEAP)p->pNext;
  219.  }
  220.  spin_unlock_irq(&memlock);
  221. }
  222.  
  223. //----------------------------------- malloc -----------------------------------
  224. void *malloc(unsigned long size)
  225. {
  226.  PHEAP p;
  227.  PMEMBLOCK pm=NULL;
  228.  spin_lock_irq(&memlock);
  229.  p=root_heap;
  230.  while(p)
  231.  {
  232.   // Is there enough room in this heap ?
  233.   if(p->size>=size)
  234.   {
  235.    pm=(PMEMBLOCK)p->pMem;
  236.    while(pm)
  237.    {
  238.     if((pm->flags & MEMFLAG_FREE) && (pm->size >= size))
  239.     { // Found a free block
  240.      long remaining_size=pm->size-size-sizeof(MEMBLOCK);
  241.      pm->flags=MEMFLAG_USED;
  242.      pm->size=size;
  243.      if(remaining_size>0)
  244.      {
  245.       PMEMBLOCK npm=(PMEMBLOCK)(((unsigned long)pm)+pm->size+sizeof(MEMBLOCK));
  246.       pm->pNext=npm;
  247. #ifdef USE_SIGNATURE
  248.       npm->signature=SIGNATURE;
  249. #endif
  250.       npm->size=remaining_size;
  251.       npm->pNext=NULL;
  252.       npm->flags=MEMFLAG_FREE;
  253.      }
  254.      p->size-=pm->size;
  255.      spin_unlock_irq(&memlock);
  256.      return (void *)((unsigned long)pm+sizeof(MEMBLOCK));
  257.     }
  258. #ifdef USE_SIGNATURE
  259.     if(pm->pNext && pm->pNext->signature==SIGNATURE)
  260. #else
  261.     if(pm->pNext)
  262. #endif
  263.      pm=(PMEMBLOCK)pm->pNext;
  264.     else
  265.      break;
  266.    }
  267.   }
  268. #ifdef USE_SIGNATURE
  269.   if(p->pNext && p->pNext->signature==SIGNATURE)
  270. #else
  271.   if(p->pNext)
  272. #endif
  273.    p=(PHEAP)p->pNext;
  274.   else
  275.   { // No heaps left, so allocate a new one
  276.    unsigned long requested_size=size+sizeof(HEAP)+sizeof(MEMBLOCK);
  277.    if(requested_size>default_heap_size)
  278.    {
  279.     requested_size=((unsigned long)((requested_size/default_heap_size)+1))*default_heap_size;
  280.     p->pNext=allocHeap(requested_size);
  281.    }
  282.    else
  283.     p->pNext=allocHeap(default_heap_size);
  284.    p=(PHEAP)p->pNext;
  285.   }
  286.  }
  287.  spin_unlock_irq(&memlock);
  288.  return NULL;
  289. }
  290.  
  291. //---------------------------------- realloc -----------------------------------
  292. void *realloc(void *oldPtr,unsigned long newSize)
  293. {
  294.  void *p=malloc(newSize);
  295.  void *pf=NULL;
  296.  unsigned long oldSize=0;
  297.  spin_lock_irq(&memlock);
  298.  if(p)
  299.  {
  300.   if(oldPtr)
  301.   {
  302.    PHEAP p=root_heap;
  303.    PMEMBLOCK pm=NULL;
  304.    while(p)
  305.    {
  306.     pm=(PMEMBLOCK)p->pMem;
  307.     while(pm)
  308.     {
  309.      if((pm->flags & MEMFLAG_USED)
  310.          && (void *)((unsigned long)pm+sizeof(MEMBLOCK))==oldPtr)
  311.      {
  312.       pf=oldPtr;
  313.       oldSize=pm->size;
  314.       memcpy(p,pf,oldSize);
  315.       p->size+=pm->size;
  316.       pm->flags=MEMFLAG_FREE;
  317.       compressHeap(p);
  318.       spin_unlock_irq(&memlock);
  319.       return p;
  320.      }
  321.      pm=(PMEMBLOCK)pm->pNext;
  322.     }
  323.     p=(PHEAP)p->pNext;
  324.    }
  325.   }
  326.  }
  327.  spin_unlock_irq(&memlock);
  328.  return p;
  329. }
  330.  
  331. //-------------------------------- __mallocInit --------------------------------
  332. int __mallocInit(void)
  333. {
  334.  if(!root_heap)
  335.   if(0==(root_heap=allocHeap(default_heap_size)))
  336.    return 1;
  337.  return 0;
  338. }
  339.  
  340. #define VMMEMFLAGS (VMDHA_PROCESS)
  341.  
  342. typedef struct _VMMEMADDR
  343. {
  344.  struct _VMMEMADDR *next;
  345.  unsigned long size;
  346.  unsigned long pid;
  347.  void *ptr;
  348. #ifdef KEE
  349.  KEEVMLock lock;
  350. #else
  351.  char lock[12];
  352. #endif
  353. } VMMEMADDR,*PVMMEMADDR;
  354.  
  355. PVMMEMADDR vm_root_addr=NULL;
  356. extern "C" unsigned long OS2_get_current_pid(void);
  357. //--------------------------------- __vmalloc ----------------------------------
  358. void *__vmalloc(unsigned long size,int gfp_mask,pgprot_t prot)
  359. {
  360.  PVMMEMADDR p=NULL;
  361.  unsigned long sz=PAGE_ALIGN(size);
  362. #ifdef KEE
  363.  void *ptr=NULL;
  364. #else
  365.  char near *ptr=NULL;
  366. #endif
  367.  
  368.  p=(PVMMEMADDR)malloc(sizeof(VMMEMADDR));
  369.  if(p)
  370.  {
  371. #ifdef KEE
  372.   SHORT sel;
  373.   if(KernVMAlloc(sz,VMMEMFLAGS,(PVOID*)&ptr,(PVOID*)-1,&sel))
  374. #else
  375.   if(DevVMAlloc(VMMEMFLAGS,sz,(LINEAR)-1,__StackToFlat((ULONG)&ptr)))
  376. #endif
  377.   {
  378.    free(p);
  379.    return NULL;
  380.   }
  381. #ifdef KEE
  382.   if(KernVMLock(KEE_VML_CONTIG | KEE_VML_LONGLOCK | KEE_VML_WRITEABLE
  383.                 ,ptr,sz,&(p->lock),(KEEVMPageList*)-1,0))
  384.   {
  385.    KernVMFree(ptr);
  386. #else
  387.   if(DevVMLock(VMDHL_CONTIG | VMDHL_LONG | VMDHL_WRITE
  388.                ,ptr,sz,(LINEAR)-1,&(p->lock)
  389.                ,(LINEAR)__StackToFlat((ULONG)&PgCount)))
  390.   {
  391.    DevVMFree((LINEAR)ptr);
  392. #endif
  393.    free(p);
  394.    return NULL;
  395.   }
  396.   p->size=sz;
  397.   p->pid=OS2_get_current_pid();
  398.   p->ptr=ptr;
  399.   spin_lock_irq(&memlock);
  400.   p->next=vm_root_addr;
  401.   vm_root_addr=p;
  402.   spin_unlock_irq(&memlock);
  403.  }
  404.  return (void *)ptr;
  405. }
  406.  
  407. //----------------------------------- vfree ------------------------------------
  408. void vfree(void *ptr)
  409. {
  410.  void *p=NULL;
  411.  PVMMEMADDR pm;
  412.  PVMMEMADDR previous_pm=NULL;
  413.  unsigned long pid=OS2_get_current_pid();
  414.  spin_lock_irq(&memlock);
  415.  pm=vm_root_addr;
  416.  while(pm)
  417.  {
  418.   if(pm->ptr==ptr && pm->pid==pid)
  419.   {
  420.    p=pm->ptr;
  421.    if(pm==vm_root_addr)
  422.     vm_root_addr=pm->next;
  423.    else if(previous_pm)
  424.     previous_pm->next=pm->next;
  425.    break;
  426.   }
  427.   previous_pm=pm;
  428.   pm=pm->next;
  429.  }
  430.  spin_unlock_irq(&memlock);
  431.  if(p && pm)
  432.  {
  433. #ifdef KEE
  434.   if(!KernVMUnlock(&pm->lock))
  435.    KernVMFree(pm->ptr);
  436. #else
  437.   if(!DevVMUnLock(&pm->lock))
  438.    DevVMFree(pm->ptr);
  439. #endif
  440.   free(pm);
  441.  }
  442. }
  443.  
  444. }; // extern "C"
  445.