Subversion Repositories Kolibri OS

Rev

Rev 859 | Rev 862 | 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.      idx0 = _bsf(mask);
  95.  
  96.      ASSERT( !list_empty(&lheap.list[idx0]))
  97.  
  98.      md = (md_t*)lheap.list[idx0].next;
  99.    }
  100.    else
  101.      return NULL;
  102.  
  103.    list_remove((link_t*)md);
  104.    if(list_empty(&lheap.list[idx0]))
  105.      _reset_lmask(idx0);
  106.  
  107.    if(md->size > size)
  108.    {
  109.      count_t idx1;
  110.      md_t *new_md = (md_t*)slab_alloc(md_slab,0);
  111.  
  112.      link_initialize(&new_md->link);
  113.      list_insert(&new_md->adj, &md->adj);
  114.  
  115.      new_md->base = md->base;
  116.      new_md->size = size;
  117.  
  118.      md->base+= size;
  119.      md->size-= size;
  120.  
  121.      idx1 = (md->size>>22) - 1 < 32 ? (md->size>>22) - 1 : 31;
  122.  
  123.      list_prepend(&md->link, &lheap.list[idx1]);
  124.      _set_lmask(idx1);
  125.  
  126.      return new_md;
  127.    }
  128.    return md;
  129. }
  130.  
  131. md_t* __fastcall find_small_md(size_t size)
  132. {
  133.    eflags_t efl;
  134.  
  135.    md_t *md = NULL;
  136.  
  137.    count_t idx0;
  138.    u32_t mask;
  139.  
  140.    ASSERT(size & 0xFFF == 0);
  141.  
  142.    efl = safe_cli();
  143.  
  144.    idx0 = (size>>12) - 1 < 32 ? (size>>12) - 1 : 31;
  145.    mask = sheap.availmask & ( -1<<idx0 );
  146.  
  147.    //printf("smask %x size %x idx0 %x mask %x\n",sheap.availmask, size, idx0, mask);
  148.  
  149.    if(mask)
  150.    {
  151.      md_t *tmp;
  152.  
  153.      idx0 = _bsf(mask);
  154.  
  155.      ASSERT( !list_empty(&sheap.list[idx0]))
  156.  
  157.      tmp = (md_t*)sheap.list[idx0].next;
  158.  
  159.      while((link_t*)tmp != &sheap.list[idx0])
  160.      {
  161.        if(tmp->size >= size)
  162.        {
  163.          //printf("remove tmp %x\n", tmp);
  164.          list_remove((link_t*)tmp);
  165.          if(list_empty(&sheap.list[idx0]))
  166.            _reset_smask(idx0);
  167.          md = tmp;
  168.          break;
  169.        };
  170.        tmp = (md_t*)tmp->link.next;
  171.      };
  172.    };
  173.  
  174.    if( !md)
  175.    {
  176.      md_t *lmd;
  177.      lmd = find_large_md((size+0x3FFFFF)&~0x3FFFFF);
  178.      if( !lmd)
  179.      {
  180.        safe_sti(efl);
  181.        return NULL;
  182.      };
  183.  
  184.      md = (md_t*)slab_alloc(md_slab,0);
  185.      link_initialize(&md->link);
  186.      list_initialize(&md->adj);
  187.      md->base = lmd->base;
  188.      md->size = lmd->size;
  189.      md->parent  = lmd;
  190.      md->reserved = 0;
  191.    };
  192.  
  193.    if(md->size > size)
  194.    {
  195.      count_t idx1;
  196.      md_t *new_md = (md_t*)slab_alloc(md_slab,0);
  197.  
  198.      link_initialize(&new_md->link);
  199.      list_insert(&new_md->adj, &md->adj);
  200.  
  201.      new_md->base = md->base;
  202.      new_md->size = size;
  203.      new_md->parent = md->parent;
  204.      new_md->reserved = 0;
  205.  
  206.      md->base+= size;
  207.      md->size-= size;
  208.  
  209.      idx1 = (md->size>>12) - 1 < 32 ? (md->size>>12) - 1 : 31;
  210.  
  211.      //printf("insert md %x, base %x size %x idx %x\n", md,md->base, md->size,idx1);
  212.  
  213.      if( idx1 < 31)
  214.        list_prepend(&md->link, &sheap.list[idx1]);
  215.      else
  216.      {
  217.        if( list_empty(&sheap.list[31]))
  218.          list_prepend(&md->link, &sheap.list[31]);
  219.        else
  220.        {
  221.          md_t *tmp = (md_t*)sheap.list[31].next;
  222.  
  223.          while((link_t*)tmp != &sheap.list[31])
  224.          {
  225.            if(md->base < tmp->base)
  226.              break;
  227.            tmp = (md_t*)tmp->link.next;
  228.          }
  229.          list_insert(&md->link, &tmp->link);
  230.        };
  231.      };
  232.  
  233.      _set_smask(idx1);
  234.  
  235.      safe_sti(efl);
  236.  
  237.      return new_md;
  238.    }
  239.    safe_sti(efl);
  240.    return md;
  241. }
  242.  
  243. phismem_t* __fastcall phis_alloc(count_t count)
  244. {
  245.    phismem_t *phm;
  246.    count_t tmp;
  247.    phm = (phismem_t*)slab_alloc(phm_slab, 0);
  248.  
  249.    phm->count = count;
  250.    tmp = count;
  251.    while(tmp)
  252.    {
  253.       u32_t order;
  254.  
  255.       asm volatile ("bsr %0, %1":"=&r"(order):"r"(tmp):"cc");
  256.       asm volatile ("btr %0, %1" :"=r"(tmp):"r"(order):"cc");
  257.  
  258.       phm->frames[order] = core_alloc(order);
  259.  
  260.    };
  261.  
  262.    return phm;
  263. }
  264.  
  265. #define page_tabs 0xDF800000
  266.  
  267. void map_phm(addr_t base, phismem_t *phm, u32_t mapflags)
  268. {
  269.    count_t count;
  270.    addr_t  *pte;
  271.  
  272.    count = phm->count;
  273.    pte = &((addr_t*)page_tabs)[base>>12];
  274.  
  275.    while(count)
  276.    {
  277.      u32_t order;
  278.      addr_t frame;
  279.      count_t size;
  280.  
  281.      asm volatile ("bsr %0, %1":"=&r"(order):"r"(count):"cc");
  282.      asm volatile ("btr %0, %1" :"=r"(count):"r"(order):"cc");
  283.  
  284.      frame = phm->frames[order] | mapflags;
  285.      size = (1 << order);
  286.      while(size--)
  287.      {
  288.        *pte++ = frame;
  289.        frame+= 4096;
  290.      }
  291.    }
  292. };
  293.  
  294. void* __fastcall mem_alloc(size_t size, u32_t flags)
  295. {
  296.    md_t *md;
  297.    phismem_t *phm;
  298.  
  299.    size = (size+4095)&~4095;
  300.  
  301.    md = find_small_md(size);
  302.    if( md )
  303.    {
  304.      phm = phis_alloc(size>>12);
  305.      map_phm(md->base, phm, flags);
  306.      return (void*)md->base;
  307.    }
  308.    return NULL;
  309. };
  310.  
  311. void* __stdcall alloc_kernel_space(size_t size); //__asm__("alloc_kernel_space");
  312.  
  313.  
  314. void* __stdcall alloc_kernel_space(size_t size)
  315. {
  316.    md_t *md;
  317.  
  318.    size = (size+4095)&~4095;
  319.  
  320.    md = find_small_md(size);
  321.  
  322.   // printf("alloc_kernel_space: %x size %x\n\n",md->base, size);
  323.    if( md )
  324.      return (void*)md->base;
  325.    return NULL;
  326. }
  327.  
  328. //void* __stdcall kernel_alloc(size_t size)
  329. //{
  330. //
  331. //   return NULL;
  332. //}
  333. //*/
  334.