Subversion Repositories Kolibri OS

Rev

Rev 861 | 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(&md->adj, &new_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.    if(mask)
  148.    {
  149.      idx0 = _bsf(mask);
  150.  
  151.      ASSERT( !list_empty(&sheap.list[idx0]))
  152.  
  153.      md = (md_t*)sheap.list[idx0].next;
  154.  
  155.      list_remove((link_t*)md);
  156.      if(list_empty(&sheap.list[idx0]))
  157.        _reset_smask(idx0);
  158.    }
  159.    else
  160.    {
  161.      md_t *lmd;
  162.      lmd = find_large_md((size+0x3FFFFF)&~0x3FFFFF);
  163.      if( !lmd)
  164.      {
  165.        safe_sti(efl);
  166.        return NULL;
  167.      };
  168.  
  169.      md = (md_t*)slab_alloc(md_slab,0);
  170.      link_initialize(&md->link);
  171.      list_initialize(&md->adj);
  172.      md->base = lmd->base;
  173.      md->size = lmd->size;
  174.      md->parent  = lmd;
  175.      md->reserved = 0;
  176.    };
  177.  
  178.    if(md->size > size)
  179.    {
  180.      count_t idx1;
  181.      md_t *new_md = (md_t*)slab_alloc(md_slab,0);
  182.  
  183.      link_initialize(&new_md->link);
  184.      list_insert(&md->adj, &new_md->adj);
  185.  
  186.      new_md->base = md->base;
  187.      new_md->size = size;
  188.      new_md->parent = md->parent;
  189.      new_md->reserved = 0;
  190.  
  191.      md->base+= size;
  192.      md->size-= size;
  193.  
  194.      idx1 = (md->size>>22) - 1 < 32 ? (md->size>>22) - 1 : 31;
  195.  
  196.      list_prepend(&md->link, &sheap.list[idx1]);
  197.      _set_smask(idx1);
  198.  
  199.      safe_sti(efl);
  200.  
  201.      return new_md;
  202.    }
  203.    safe_sti(efl);
  204.    return md;
  205. }
  206.  
  207. phismem_t* __fastcall phis_alloc(count_t count)
  208. {
  209.    phismem_t *phm;
  210.    count_t tmp;
  211.    phm = (phismem_t*)slab_alloc(phm_slab, 0);
  212.  
  213.    phm->count = count;
  214.    tmp = count;
  215.    while(tmp)
  216.    {
  217.       u32_t order;
  218.  
  219.       asm volatile ("bsr %0, %1":"=&r"(order):"r"(tmp):"cc");
  220.       asm volatile ("btr %0, %1" :"=r"(tmp):"r"(order):"cc");
  221.  
  222.       phm->frames[order] = core_alloc(order);
  223.  
  224.    };
  225.  
  226.    return phm;
  227. }
  228.  
  229. #define page_tabs 0xDF800000
  230.  
  231. void map_phm(addr_t base, phismem_t *phm, u32_t mapflags)
  232. {
  233.    count_t count;
  234.    addr_t  *pte;
  235.  
  236.    count = phm->count;
  237.    pte = &((addr_t*)page_tabs)[base>>12];
  238.  
  239.    while(count)
  240.    {
  241.      u32_t order;
  242.      addr_t frame;
  243.      count_t size;
  244.  
  245.      asm volatile ("bsr %0, %1":"=&r"(order):"r"(count):"cc");
  246.      asm volatile ("btr %0, %1" :"=r"(count):"r"(order):"cc");
  247.  
  248.      frame = phm->frames[order] | mapflags;
  249.      size = (1 << order);
  250.      while(size--)
  251.      {
  252.        *pte++ = frame;
  253.        frame+= 4096;
  254.      }
  255.    }
  256. };
  257.  
  258. void* __fastcall mem_alloc(size_t size, u32_t flags)
  259. {
  260.    md_t *md;
  261.    phismem_t *phm;
  262.  
  263.    size = (size+4095)&~4095;
  264.  
  265.    md = find_small_md(size);
  266.    if( md )
  267.    {
  268.      phm = phis_alloc(size>>12);
  269.      map_phm(md->base, phm, flags);
  270.      return (void*)md->base;
  271.    }
  272.    return NULL;
  273. };
  274.  
  275. void* __stdcall alloc_kernel_space(size_t size); //__asm__("alloc_kernel_space");
  276.  
  277.  
  278. void* __stdcall alloc_kernel_space(size_t size)
  279. {
  280.    md_t *md;
  281.  
  282.    size = (size+4095)&~4095;
  283.  
  284.    md = find_small_md(size);
  285.    if( md )
  286.      return (void*)md->base;
  287.    return NULL;
  288. }
  289.  
  290. //void* __stdcall kernel_alloc(size_t size)
  291. //{
  292. //
  293. //   return NULL;
  294. //}
  295. //*/
  296.