Subversion Repositories Kolibri OS

Rev

Rev 862 | Rev 886 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1.  
  2. #include <types.h>
  3. #include <core.h>
  4. #include <spinlock.h>
  5. #include <link.h>
  6. #include <mm.h>
  7. #include <slab.h>
  8.  
  9. typedef struct
  10. {
  11.    link_t link;
  12.    link_t adj;
  13.    addr_t base;
  14.    size_t size;
  15.    void*  parent;
  16.    u32_t  reserved;
  17. }md_t;
  18.  
  19. typedef struct {
  20.    SPINLOCK_DECLARE(lock);   /**< this lock protects everything below */
  21.  
  22.    u32_t  availmask;
  23.    link_t list[32];
  24. }heap_t;
  25.  
  26. slab_cache_t *md_slab;
  27. slab_cache_t *phm_slab;
  28.  
  29. heap_t lheap;
  30. heap_t sheap;
  31.  
  32. static inline void _set_lmask(count_t idx)
  33. { asm volatile ("bts DWORD PTR [_lheap], %0"::"r"(idx):"cc"); }
  34.  
  35. static inline void _reset_lmask(count_t idx)
  36. { asm volatile ("btr DWORD PTR [_lheap], %0"::"r"(idx):"cc"); }
  37.  
  38. static inline void _set_smask(count_t idx)
  39. { asm volatile ("bts DWORD PTR [_sheap], %0"::"r"(idx):"cc"); }
  40.  
  41. static inline void _reset_smask(count_t idx)
  42. { asm volatile ("btr DWORD PTR [_sheap], %0"::"r"(idx):"cc"); }
  43.  
  44.  
  45. int __fastcall init_heap(addr_t base, size_t size)
  46. {
  47.    md_t *md;
  48.    u32_t i;
  49.  
  50.    ASSERT(base != 0);
  51.    ASSERT(size != 0)
  52.    ASSERT((base & 0x3FFFFF) == 0);
  53.    ASSERT((size & 0x3FFFFF) == 0);
  54.  
  55.    for (i = 0; i < 32; i++)
  56.    {
  57.      list_initialize(&lheap.list[i]);
  58.      list_initialize(&sheap.list[i]);
  59.    };
  60.  
  61.    md_slab = slab_cache_create(sizeof(md_t), 32,NULL,NULL,SLAB_CACHE_MAGDEFERRED);
  62.  
  63.    md = (md_t*)slab_alloc(md_slab,0);
  64.  
  65.    list_initialize(&md->adj);
  66.    md->base = base;
  67.    md->size = size;
  68.    md->parent = NULL;
  69.    md->reserved = 0;
  70.  
  71.    list_prepend(&md->link, &lheap.list[31]);
  72.    lheap.availmask = 0x80000000;
  73.    sheap.availmask = 0x00000000;
  74.  
  75.   // phm_slab = slab_cache_create(sizeof(phismem_t), 32,NULL,NULL,SLAB_CACHE_MAGDEFERRED);
  76.  
  77.    return 1;
  78. };
  79.  
  80. md_t* __fastcall find_large_md(size_t size)
  81. {
  82.    md_t *md = NULL;
  83.  
  84.    count_t idx0;
  85.    u32_t mask;
  86.  
  87.    ASSERT((size & 0x3FFFFF) == 0);
  88.  
  89.    idx0 = (size>>22) - 1 < 32 ? (size>>22) - 1 : 31;
  90.    mask = lheap.availmask & ( -1<<idx0 );
  91.  
  92.    if(mask)
  93.    {
  94.      if(idx0 == 31)
  95.      {
  96.         md_t *tmp = (md_t*)lheap.list[31].next;
  97.         while((link_t*)tmp != &lheap.list[31])
  98.         {
  99.           if(tmp->size >= size)
  100.           {
  101.             DBG("remove large tmp %x\n", tmp);
  102.  
  103.             md = tmp;
  104.             break;
  105.           };
  106.         };
  107.         tmp = (md_t*)tmp->link.next;
  108.      }
  109.      else
  110.      {
  111.        idx0 = _bsf(mask);
  112.  
  113.        ASSERT( !list_empty(&lheap.list[idx0]))
  114.  
  115.        md = (md_t*)lheap.list[idx0].next;
  116.      };
  117.    }
  118.    else
  119.      return NULL;
  120.  
  121.    list_remove((link_t*)md);
  122.    if(list_empty(&lheap.list[idx0]))
  123.      _reset_lmask(idx0);
  124.  
  125.    if(md->size > size)
  126.    {
  127.      count_t idx1;
  128.      md_t *new_md = (md_t*)slab_alloc(md_slab,0);
  129.  
  130.      link_initialize(&new_md->link);
  131.      list_insert(&new_md->adj, &md->adj);
  132.  
  133.      new_md->base = md->base;
  134.      new_md->size = size;
  135.  
  136.      md->base+= size;
  137.      md->size-= size;
  138.  
  139.      idx1 = (md->size>>22) - 1 < 32 ? (md->size>>22) - 1 : 31;
  140.  
  141.      list_prepend(&md->link, &lheap.list[idx1]);
  142.      _set_lmask(idx1);
  143.  
  144.      return new_md;
  145.    }
  146.    return md;
  147. }
  148.  
  149. md_t* __fastcall find_small_md(size_t size)
  150. {
  151.    eflags_t efl;
  152.  
  153.    md_t *md = NULL;
  154.  
  155.    count_t idx0;
  156.    u32_t mask;
  157.  
  158.    ASSERT((size & 0xFFF) == 0);
  159.  
  160.    efl = safe_cli();
  161.  
  162.    idx0 = (size>>12) - 1 < 32 ? (size>>12) - 1 : 31;
  163.    mask = sheap.availmask & ( -1<<idx0 );
  164.  
  165.    DBG("smask %x size %x idx0 %x mask %x\n",sheap.availmask, size, idx0, mask);
  166.  
  167.    if(mask)
  168.    {
  169.      if(idx0 == 31)
  170.      {
  171.         md_t *tmp = (md_t*)sheap.list[31].next;
  172.         while((link_t*)tmp != &sheap.list[31])
  173.         {
  174.           if(tmp->size >= size)
  175.           {
  176.              md = tmp;
  177.              break;
  178.           };
  179.           tmp = (md_t*)tmp->link.next;
  180.         };
  181.      }
  182.      else
  183.      {
  184.        idx0 = _bsf(mask);
  185.        ASSERT( !list_empty(&sheap.list[idx0]))
  186.        md = (md_t*)sheap.list[idx0].next;
  187.      }
  188.    };
  189.  
  190.    if(md)
  191.    {
  192.      DBG("remove md %x\n", md);
  193.  
  194.      list_remove((link_t*)md);
  195.      if(list_empty(&sheap.list[idx0]))
  196.        _reset_smask(idx0);
  197.    }
  198.    else
  199.    {
  200.      md_t *lmd;
  201.      lmd = find_large_md((size+0x3FFFFF)&~0x3FFFFF);
  202.  
  203.      DBG("get large md %x\n", lmd);
  204.  
  205.      if( !lmd)
  206.      {
  207.        safe_sti(efl);
  208.        return NULL;
  209.      };
  210.  
  211.      md = (md_t*)slab_alloc(md_slab,0);
  212.      link_initialize(&md->link);
  213.      list_initialize(&md->adj);
  214.      md->base = lmd->base;
  215.      md->size = lmd->size;
  216.      md->parent  = lmd;
  217.      md->reserved = 0;
  218.    };
  219.  
  220.    if(md->size > size)
  221.    {
  222.      count_t idx1;
  223.      md_t *new_md = (md_t*)slab_alloc(md_slab,0);
  224.  
  225.      link_initialize(&new_md->link);
  226.      list_insert(&new_md->adj, &md->adj);
  227.  
  228.      new_md->base = md->base;
  229.      new_md->size = size;
  230.      new_md->parent = md->parent;
  231.      new_md->reserved = 0;
  232.  
  233.      md->base+= size;
  234.      md->size-= size;
  235.  
  236.      idx1 = (md->size>>12) - 1 < 32 ? (md->size>>12) - 1 : 31;
  237.  
  238.      DBG("insert md %x, base %x size %x idx %x\n", md,md->base, md->size,idx1);
  239.  
  240.      if( idx1 < 31)
  241.        list_prepend(&md->link, &sheap.list[idx1]);
  242.      else
  243.      {
  244.        if( list_empty(&sheap.list[31]))
  245.          list_prepend(&md->link, &sheap.list[31]);
  246.        else
  247.        {
  248.          md_t *tmp = (md_t*)sheap.list[31].next;
  249.  
  250.          while((link_t*)tmp != &sheap.list[31])
  251.          {
  252.            if(md->base < tmp->base)
  253.              break;
  254.            tmp = (md_t*)tmp->link.next;
  255.          }
  256.          list_insert(&md->link, &tmp->link);
  257.        };
  258.      };
  259.  
  260.      _set_smask(idx1);
  261.  
  262.      safe_sti(efl);
  263.  
  264.      return new_md;
  265.    }
  266.    safe_sti(efl);
  267.    return md;
  268. }
  269.  
  270. phismem_t* __fastcall phis_alloc(count_t count)
  271. {
  272.    phismem_t *phm;
  273.    count_t tmp;
  274.    phm = (phismem_t*)slab_alloc(phm_slab, 0);
  275.  
  276.    phm->count = count;
  277.    tmp = count;
  278.    while(tmp)
  279.    {
  280.       u32_t order;
  281.  
  282.       asm volatile ("bsr %0, %1":"=&r"(order):"r"(tmp):"cc");
  283.       asm volatile ("btr %0, %1" :"=r"(tmp):"r"(order):"cc");
  284.  
  285.       phm->frames[order] = core_alloc(order);
  286.  
  287.    };
  288.  
  289.    return phm;
  290. }
  291.  
  292. #define page_tabs 0xDF800000
  293.  
  294. void map_phm(addr_t base, phismem_t *phm, u32_t mapflags)
  295. {
  296.    count_t count;
  297.    addr_t  *pte;
  298.  
  299.    count = phm->count;
  300.    pte = &((addr_t*)page_tabs)[base>>12];
  301.  
  302.    while(count)
  303.    {
  304.      u32_t order;
  305.      addr_t frame;
  306.      count_t size;
  307.  
  308.      asm volatile ("bsr %0, %1":"=&r"(order):"r"(count):"cc");
  309.      asm volatile ("btr %0, %1" :"=r"(count):"r"(order):"cc");
  310.  
  311.      frame = phm->frames[order] | mapflags;
  312.      size = (1 << order);
  313.      while(size--)
  314.      {
  315.        *pte++ = frame;
  316.        frame+= 4096;
  317.      }
  318.    }
  319. };
  320.  
  321. void* __fastcall mem_alloc(size_t size, u32_t flags)
  322. {
  323.    md_t *md;
  324.    phismem_t *phm;
  325.  
  326.    size = (size+4095)&~4095;
  327.  
  328.    md = find_small_md(size);
  329.    if( md )
  330.    {
  331.      phm = phis_alloc(size>>12);
  332.      map_phm(md->base , phm, flags);
  333.      return (void*)md->base;
  334.    }
  335.    return NULL;
  336. };
  337.  
  338. void * __fastcall heap_alloc(size_t size, u32_t flags)
  339. {
  340.    md_t *md;
  341.  
  342.    size = (size+4095)&~4095;
  343.  
  344.    md = find_small_md(size);
  345.  
  346.    if( md )
  347.    {
  348.      if( flags & PG_MAP )
  349.      {
  350.        count_t tmp = size >> 12;
  351.        addr_t  *pte = &((addr_t*)page_tabs)[md->base>>12];
  352.  
  353.        while(tmp)
  354.        {
  355.          u32_t  order;
  356.          addr_t frame;
  357.          size_t size;
  358.  
  359.          asm volatile ("bsr %0, %1":"=&r"(order):"r"(tmp):"cc");
  360.          asm volatile ("btr %0, %1" :"=r"(tmp):"r"(order):"cc");
  361.  
  362.          frame = core_alloc(order) | flags;
  363.  
  364.          size = (1 << order);
  365.          while(size--)
  366.          {
  367.            *pte++ = frame;
  368.            frame+= 4096;
  369.          };
  370.        };
  371.      };
  372.      DBG("alloc_heap: %x size %x\n\n",md->base, size);
  373.      return (void*)md->base;
  374.    };
  375.    return NULL;
  376. };
  377.  
  378.  
  379.