Subversion Repositories Kolibri OS

Rev

Rev 1066 | 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.  
  8. extern u32_t pg_balloc;
  9. extern u32_t mem_amount;
  10.  
  11. void __fastcall *balloc(size_t size);
  12.  
  13. static zone_t z_core;
  14.  
  15. #include "buddy.inc"
  16.  
  17. typedef struct
  18. {
  19.     link_t    link;
  20.     SPINLOCK_DECLARE(lock);
  21.     u32_t     state;
  22.     void     *parent;
  23.     count_t   avail;
  24.     addr_t    base;
  25.     index_t   next;
  26.     int       list[512];
  27. }pslab_t;
  28.  
  29. typedef struct
  30. {
  31.     SPINLOCK_DECLARE(lock);
  32.  
  33.     count_t  partial_count;
  34.  
  35.     link_t   full_slabs;           /**< List of full slabs */
  36.     link_t   partial_slabs;        /**< List of partial slabs */
  37. }pcache_t;
  38.  
  39. static pcache_t page_cache;
  40.  
  41. static pslab_t *create_page_slab();
  42.  
  43.  
  44.  
  45. void init_mm()
  46. {
  47.     int i;
  48.  
  49.     u32_t     base;
  50.     u32_t     size;
  51.     count_t   pages;
  52.     size_t    conf_size;
  53.     size_t    core_size;
  54.     pslab_t  *slab;
  55.  
  56.     pages = mem_amount >> PAGE_WIDTH;
  57.     DBG("last page = %x total pages =  %x\n",mem_amount, pages);
  58.  
  59.     conf_size = pages*sizeof(frame_t);
  60.     DBG("conf_size = %x  free mem start =%x\n",conf_size, pg_balloc);
  61.  
  62.     zone_create(&z_core, 0,  pages);
  63.     zone_release(&z_core, 0, pages);
  64.     zone_reserve(&z_core, 0, pg_balloc >> PAGE_WIDTH);
  65.  
  66.     list_initialize(&page_cache.full_slabs);
  67.     list_initialize(&page_cache.partial_slabs);
  68.  
  69.     slab = create_page_slab();
  70.  
  71.     ASSERT(slab);
  72.  
  73.     slab->parent = &page_cache;
  74.     page_cache.partial_count++;
  75.     list_prepend(&slab->link, &page_cache.partial_slabs);
  76. };
  77.  
  78. /** Return wasted space in slab */
  79. static unsigned int badness(index_t order, size_t size)
  80. {
  81.         unsigned int objects;
  82.         unsigned int ssize;
  83.  
  84.     ssize = PAGE_SIZE << order;
  85.     objects = (PAGE_SIZE << order) / size;
  86.         return ssize - objects * size;
  87. }
  88.  
  89. #define SLAB_MAX_BADNESS(order)   (((size_t) PAGE_SIZE << (order)) >> 2)
  90.  
  91.  
  92. static pslab_t *create_page_slab()
  93. {
  94.     pslab_t  *slab;
  95.     link_t   *tmp;
  96.  
  97.     spinlock_lock(&z_core.lock);
  98.  
  99.     tmp = buddy_alloc(9);
  100.  
  101.     if( tmp != 0 )
  102.     {
  103.         frame_t     *frame;
  104.         int          i;
  105.         addr_t       v;
  106.  
  107.         /* Update zone information. */
  108.         z_core.free_count -= 512;
  109.         z_core.busy_count += 512;
  110.  
  111.         spinlock_unlock(&z_core.lock);
  112.  
  113.         /* Frame will be actually a first frame of the block. */
  114.         frame = (frame_t*)tmp;
  115.  
  116.         frame->parent = 0;
  117.  
  118.         v = (z_core.base + (index_t)(frame - z_core.frames)) << PAGE_WIDTH;
  119.  
  120.         slab = (pslab_t*)PA2KA(v);
  121.  
  122.         for(i = 1; i < 512; i++)
  123.                 frame[i].parent = slab;
  124.  
  125.         slab->base = v + PAGE_SIZE;
  126.  
  127.         slab->avail = 511;
  128.         slab->next  = 0;
  129.  
  130.         for(i = 0; i < 511; i++)
  131.             slab->list[i] = i + 1;
  132.  
  133.     }
  134.     else
  135.     {
  136.         spinlock_unlock(&z_core.lock);
  137.         slab = NULL;
  138.     };
  139.  
  140.     DBG("create page slab at %x\n", slab);
  141.  
  142.         return slab;
  143. }
  144.  
  145. static void destroy_page_slab(pslab_t *slab)
  146. {
  147.     u32_t     order;
  148.     count_t   idx;
  149.     frame_t  *frame;
  150.  
  151.  
  152.     idx =  (KA2PA(slab) >> PAGE_WIDTH)-z_core.base;
  153.  
  154.     frame = &z_core.frames[idx];
  155.  
  156.         /* remember frame order */
  157.         order = frame->buddy_order;
  158.  
  159.     ASSERT(frame->refcount);
  160.  
  161.     if (!--frame->refcount)
  162.     {
  163.         spinlock_lock(&z_core.lock);
  164.  
  165.         buddy_system_free(&frame->buddy_link);
  166.  
  167.     /* Update zone information. */
  168.         z_core.free_count += (1 << order);
  169.         z_core.busy_count -= (1 << order);
  170.  
  171.         spinlock_unlock(&z_core.lock);
  172.     }
  173. }
  174.  
  175. #if 0
  176. fslab_t *create_slab(index_t order, size_t size)
  177. {
  178.     fslab_t *slab;
  179.  
  180.     slab = (fslab_t*)PA2KA(frame_alloc(0));
  181.  
  182.     if( slab )
  183.     {
  184.         link_t      *tmp;
  185.  
  186.         spinlock_lock(&z_core.lock);
  187.  
  188.         tmp = buddy_alloc(order);
  189.         ASSERT(tmp);
  190.  
  191.         if( tmp )
  192.         {
  193.             frame_t     *frame;
  194.             count_t      objects;
  195.             count_t      i;
  196.             addr_t       v;
  197.  
  198.         /* Update zone information. */
  199.             z_core.free_count -= (1 << order);
  200.             z_core.busy_count += (1 << order);
  201.  
  202.             spinlock_unlock(&z_heap.lock);
  203.  
  204.         /* Frame will be actually a first frame of the block. */
  205.             frame = (frame_t*)tmp;
  206.  
  207.             for(i = 0; i < (1U<<order); i++)
  208.                 frame[i].parent = slab;
  209.  
  210.         /* get frame address */
  211.             v = z_core.base + (index_t)(frame - z_core.frames);
  212.  
  213.             slab->base = (v << PAGE_WIDTH);
  214.  
  215.             slab->avail = (PAGE_SIZE << order) / size;
  216.             slab->next  = 0;
  217.  
  218.             objects = (PAGE_SIZE << order) / size;
  219.  
  220.             for(i = 0; i < objects; i++)
  221.                 slab->list[i] = i + 1;
  222.         }
  223.         else
  224.         {
  225.             spinlock_unlock(&z_core.lock);
  226.             frame_free(KA2PA(slab));
  227.             slab = NULL;
  228.         };
  229.     };
  230.  
  231.         return slab;
  232. }
  233.  
  234. static void destroy_slab(fslab_t *slab)
  235. {
  236.     u32_t order;
  237.     count_t idx;
  238.     frame_t *frame;
  239.  
  240.     idx =   (slab->base >> PAGE_WIDTH)-z_core.base;
  241.     frame = &z_core.frames[idx];
  242.  
  243.         /* remember frame order */
  244.         order = frame->buddy_order;
  245.  
  246.     ASSERT(frame->refcount);
  247.  
  248.     if (!--frame->refcount)
  249.     {
  250.         spinlock_lock(&z_core.lock);
  251.  
  252.         buddy_system_free(&frame->buddy_link);
  253.  
  254.     /* Update zone information. */
  255.         z_core.free_count += (1 << order);
  256.         z_core.busy_count -= (1 << order);
  257.  
  258.         spinlock_unlock(&z_core.lock);
  259.     }
  260.  
  261. //    slab_free(fslab, slab);
  262.  
  263. };
  264. #endif
  265.  
  266. addr_t alloc_page(void)
  267. {
  268.     eflags_t  efl;
  269.     pslab_t  *slab;
  270.     addr_t    frame;
  271.  
  272.     efl = safe_cli();
  273.  
  274.     spinlock_lock(&page_cache.lock);
  275.  
  276.     if (list_empty(&page_cache.partial_slabs))
  277.     {
  278.         slab = create_page_slab();
  279.         if (!slab)
  280.         {
  281.             spinlock_unlock(&page_cache.lock);
  282.             safe_sti(efl);
  283.             return 0;
  284.         }
  285.         slab->parent = &page_cache;
  286.         slab->state  = 1;
  287.         page_cache.partial_count++;
  288.         list_prepend(&slab->link, &page_cache.partial_slabs);
  289.     }
  290.     else
  291.         slab = (pslab_t*)page_cache.partial_slabs.next;
  292.  
  293.     frame = slab->base + (slab->next << PAGE_WIDTH);
  294.     slab->next = slab->list[slab->next];
  295.  
  296.     slab->avail--;
  297.     if( slab->avail == 0 )
  298.     {
  299.         slab->state  = 0;
  300.         list_remove(&slab->link);
  301.         list_prepend(&slab->link, &page_cache.full_slabs);
  302.         page_cache.partial_count--;
  303.         DBG("%s insert empty page slab\n", __FUNCTION__);
  304.     };
  305.     spinlock_unlock(&page_cache.lock);
  306.  
  307. //    DBG("alloc_page: %x   remain  %d\n", frame, slab->avail);
  308.  
  309.     safe_sti(efl);
  310.  
  311.     return frame;
  312. }
  313.  
  314.  
  315. addr_t __fastcall frame_alloc(count_t count)
  316. {
  317.     addr_t    frame;
  318.  
  319.     if ( count > 1)
  320.     {
  321.         eflags_t  efl;
  322.         index_t   order;
  323.         frame_t  *tmp;
  324.         count_t   i;
  325.  
  326.         order = fnzb(count-1)+1;
  327.  
  328.         efl = safe_cli();
  329.  
  330.         spinlock_lock(&z_core.lock);
  331.  
  332.         tmp = (frame_t*)buddy_alloc( order );
  333.  
  334.         ASSERT(tmp);
  335.  
  336.         z_core.free_count -= (1 << order);
  337.         z_core.busy_count += (1 << order);
  338.  
  339.         for(i = 0; i < (1 << order); i++)
  340.             tmp[i].parent = NULL;
  341.  
  342.         spinlock_unlock(&z_core.lock);
  343.  
  344.         safe_sti(efl);
  345.  
  346.         frame = (z_core.base +
  347.                 (index_t)(tmp - z_core.frames)) << PAGE_WIDTH;
  348.  
  349.  
  350.         DBG("%s %x order %d remain %d\n", __FUNCTION__,
  351.              frame, order, z_core.free_count);
  352.     }
  353.     else
  354.         frame = alloc_page();
  355.  
  356.     return frame;
  357. }
  358.  
  359. size_t __fastcall frame_free(addr_t addr)
  360. {
  361.     eflags_t  efl;
  362.     index_t   idx;
  363.     frame_t  *frame;
  364.     size_t    frame_size;
  365.  
  366.     idx = addr >> PAGE_WIDTH;
  367.  
  368.     if( (idx < z_core.base) ||
  369.         (idx >= z_core.base+z_core.count)) {
  370.         DBG("%s: invalid address %x\n", __FUNCTION__, addr);
  371.         return 0;
  372.     }
  373.  
  374.     efl = safe_cli();
  375.  
  376.     frame = &z_core.frames[idx-z_core.base];
  377.  
  378.     if( frame->parent != NULL )
  379.     {
  380.         pslab_t  *slab;
  381.  
  382.         slab = frame->parent;
  383.  
  384.         spinlock_lock(&page_cache.lock);
  385.  
  386.         idx = (addr - slab->base) >> PAGE_WIDTH;
  387.  
  388.         ASSERT(idx < 512);
  389.  
  390.         slab->list[idx] = slab->next;
  391.         slab->next = idx;
  392.  
  393.         slab->avail++;
  394.  
  395.         if(  (slab->state == 0 ) &&
  396.              (slab->avail >= 4))
  397.         {
  398.             slab->state = 1;
  399.             list_remove(&slab->link);
  400.             list_prepend(&slab->link, &page_cache.partial_slabs);
  401.             page_cache.partial_count++;
  402.  
  403.             DBG("%s: insert partial page slab\n", __FUNCTION__);
  404.         }
  405.         spinlock_unlock(&page_cache.lock);
  406.  
  407.         frame_size = 1;
  408.     }
  409.     else
  410.     {
  411.         count_t   order;
  412.  
  413.         order = frame->buddy_order;
  414.  
  415.         DBG("%s %x order %d\n", __FUNCTION__, addr, order);
  416.  
  417.         ASSERT(frame->refcount);
  418.  
  419.         spinlock_lock(&z_core.lock);
  420.  
  421.         if (!--frame->refcount)
  422.         {
  423.             buddy_system_free(&frame->buddy_link);
  424.  
  425.         /* Update zone information. */
  426.             z_core.free_count += (1 << order);
  427.             z_core.busy_count -= (1 << order);
  428.         }
  429.         spinlock_unlock(&z_core.lock);
  430.  
  431.         frame_size = 1 << order;
  432.     };
  433.     safe_sti(efl);
  434.  
  435.     return frame_size;
  436. }
  437.  
  438. count_t get_free_mem()
  439. {
  440.    return z_core.free_count;
  441. }
  442.  
  443.  
  444.  
  445.  
  446.