Subversion Repositories Kolibri OS

Rev

Rev 886 | Rev 889 | 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. #define page_tabs 0xDF800000
  10.  
  11. typedef struct
  12. {
  13.    link_t link;
  14.    link_t adj;
  15.    addr_t base;
  16.    size_t size;
  17.     void   *parent;
  18.    u32_t  state;
  19. }md_t;
  20.  
  21. #define   MD_FREE    1
  22. #define   MD_USED    2
  23.  
  24. typedef struct {
  25.     u32_t  av_mapped;
  26.     u32_t  av_unmapped;
  27.  
  28.     link_t mapped[32];
  29.     link_t unmapped[32];
  30.  
  31.     link_t used;
  32.  
  33.     SPINLOCK_DECLARE(lock);   /**< this lock protects everything below */
  34. }heap_t;
  35.  
  36.  
  37. slab_cache_t *md_slab;
  38. slab_cache_t *phm_slab;
  39.  
  40.  
  41. heap_t        lheap;
  42. heap_t        sheap;
  43.  
  44.  
  45. static inline void _set_lavu(count_t idx)
  46. { asm volatile ("bts %0, _lheap+4"::"r"(idx):"cc"); }
  47.  
  48. static inline void _reset_lavu(count_t idx)
  49. { asm volatile ("btr %0, _lheap+4"::"r"(idx):"cc"); }
  50.  
  51. static inline void _set_savm(count_t idx)
  52. { asm volatile ("bts %0, _sheap"::"r"(idx):"cc"); }
  53.  
  54. static inline void _reset_savm(count_t idx)
  55. { asm volatile ("btr %0, _sheap"::"r"(idx):"cc"); }
  56.  
  57. static inline void _set_savu(count_t idx)
  58. { asm volatile ("bts %0, _sheap+4"::"r"(idx):"cc"); }
  59.  
  60. static inline void _reset_savu(count_t idx)
  61. { asm volatile ("btr %0, _sheap+4"::"r"(idx):"cc"); }
  62.  
  63.  
  64. int __fastcall init_heap(addr_t base, size_t size)
  65. {
  66.    md_t *md;
  67.    u32_t i;
  68.  
  69.    ASSERT(base != 0);
  70.    ASSERT(size != 0)
  71.    ASSERT((base & 0x3FFFFF) == 0);
  72.    ASSERT((size & 0x3FFFFF) == 0);
  73.  
  74.    for (i = 0; i < 32; i++)
  75.    {
  76.         list_initialize(&lheap.mapped[i]);
  77.         list_initialize(&lheap.unmapped[i]);
  78.  
  79.         list_initialize(&sheap.mapped[i]);
  80.         list_initialize(&sheap.unmapped[i]);
  81.    };
  82.  
  83.    list_initialize(&lheap.used);
  84.    list_initialize(&sheap.used);
  85.  
  86.  
  87.    md_slab = slab_cache_create(sizeof(md_t), 32,NULL,NULL,SLAB_CACHE_MAGDEFERRED);
  88.  
  89.    md = (md_t*)slab_alloc(md_slab,0);
  90.  
  91.    list_initialize(&md->adj);
  92.    md->base = base;
  93.    md->size = size;
  94.    md->parent = NULL;
  95.    md->state = MD_FREE;
  96.  
  97.     list_prepend(&md->link, &lheap.unmapped[31]);
  98.     lheap.av_mapped    = 0x00000000;
  99.     lheap.av_unmapped  = 0x80000000;
  100.     sheap.av_mapped    = 0x00000000;
  101.     sheap.av_unmapped  = 0x00000000;
  102.  
  103.    return 1;
  104. };
  105.  
  106. md_t* __fastcall find_large_md(size_t size)
  107. {
  108.    md_t *md = NULL;
  109.  
  110.    count_t idx0;
  111.    u32_t mask;
  112.  
  113.    ASSERT((size & 0x3FFFFF) == 0);
  114.  
  115.    idx0 = (size>>22) - 1 < 32 ? (size>>22) - 1 : 31;
  116.     mask = lheap.av_unmapped & ( -1<<idx0 );
  117.  
  118.    if(mask)
  119.    {
  120.      if(idx0 == 31)
  121.      {
  122.             md_t *tmp = (md_t*)lheap.unmapped[31].next;
  123.             while((link_t*)tmp != &lheap.unmapped[31])
  124.         {
  125.           if(tmp->size >= size)
  126.           {
  127.             DBG("remove large tmp %x\n", tmp);
  128.  
  129.             md = tmp;
  130.             break;
  131.           };
  132.         };
  133.         tmp = (md_t*)tmp->link.next;
  134.      }
  135.      else
  136.      {
  137.        idx0 = _bsf(mask);
  138.  
  139.             ASSERT( !list_empty(&lheap.unmapped[idx0]))
  140.  
  141.             md = (md_t*)lheap.unmapped[idx0].next;
  142.      };
  143.    }
  144.    else
  145.      return NULL;
  146.  
  147.    ASSERT(md->state == MD_FREE);
  148.  
  149.    list_remove((link_t*)md);
  150.     if(list_empty(&lheap.unmapped[idx0]))
  151.         _reset_lavu(idx0);
  152.  
  153.    if(md->size > size)
  154.    {
  155.      count_t idx1;
  156.      md_t *new_md = (md_t*)slab_alloc(md_slab,0);         /* FIXME check */
  157.  
  158.      link_initialize(&new_md->link);
  159.      list_insert(&new_md->adj, &md->adj);
  160.  
  161.      new_md->base = md->base;
  162.      new_md->size = size;
  163.         new_md->parent = NULL;
  164.      new_md->state = MD_USED;
  165.  
  166.      md->base+= size;
  167.      md->size-= size;
  168.  
  169.      idx1 = (md->size>>22) - 1 < 32 ? (md->size>>22) - 1 : 31;
  170.  
  171.         list_prepend(&md->link, &lheap.unmapped[idx1]);
  172.         _set_lavu(idx1);
  173.  
  174.      return new_md;
  175.    };
  176.    md->state = MD_USED;
  177.  
  178.    return md;
  179. }
  180.  
  181. md_t* __fastcall find_unmapped_md(size_t size)
  182. {
  183.     eflags_t efl;
  184.  
  185.     md_t *md = NULL;
  186.  
  187.     count_t idx0;
  188.     u32_t mask;
  189.  
  190.     ASSERT((size & 0xFFF) == 0);
  191.  
  192.     efl = safe_cli();
  193.  
  194.     idx0 = (size>>12) - 1 < 32 ? (size>>12) - 1 : 31;
  195.     mask = sheap.av_unmapped & ( -1<<idx0 );
  196.  
  197.     DBG("smask %x size %x idx0 %x mask %x\n",sheap.av_unmapped, size, idx0, mask);
  198.  
  199.     if(mask)
  200.     {
  201.         if(idx0 == 31)
  202.         {
  203.             ASSERT( !list_empty(&sheap.unmapped[31]));
  204.  
  205.             md_t *tmp = (md_t*)sheap.unmapped[31].next;
  206.             while((link_t*)tmp != &sheap.unmapped[31])
  207.             {
  208.                 if(tmp->size >= size)
  209.                 {
  210.                     md = tmp;
  211.                     break;
  212.                 };
  213.                 tmp = (md_t*)tmp->link.next;
  214.             };
  215.         }
  216.         else
  217.         {
  218.             idx0 = _bsf(mask);
  219.  
  220.             ASSERT( !list_empty(&sheap.unmapped[idx0]));
  221.  
  222.             md = (md_t*)sheap.unmapped[idx0].next;
  223.         }
  224.     };
  225.  
  226.     if(md)
  227.     {
  228.         DBG("remove md %x\n", md);
  229.  
  230.         ASSERT(md->state==MD_FREE);
  231.         ASSERT(md->parent != NULL);
  232.  
  233.         list_remove((link_t*)md);
  234.         if(list_empty(&sheap.unmapped[idx0]))
  235.             _reset_savu(idx0);
  236.     }
  237.     else
  238.     {
  239.         md_t *lmd;
  240.         lmd = find_large_md((size+0x3FFFFF)&~0x3FFFFF);
  241.  
  242.         DBG("get large md %x\n", lmd);
  243.  
  244.         if( !lmd)
  245.         {
  246.             safe_sti(efl);
  247.             return NULL;
  248.         };
  249.  
  250.         ASSERT(lmd->size != 0);
  251.         ASSERT(lmd->base != 0);
  252.         ASSERT((lmd->base & 0x3FFFFF) == 0);
  253.         ASSERT(lmd->parent == NULL);
  254.  
  255.         md = (md_t*)slab_alloc(md_slab,0);    /* FIXME check */
  256.  
  257.         link_initialize(&md->link);
  258.         list_initialize(&md->adj);
  259.         md->base = lmd->base;
  260.         md->size = lmd->size;
  261.         md->parent  = lmd;
  262.         md->state = MD_USED;
  263.     };
  264.  
  265.     if(md->size > size)
  266.     {
  267.         count_t idx1;
  268.         md_t *new_md = (md_t*)slab_alloc(md_slab,0);    /* FIXME check */
  269.  
  270.         link_initialize(&new_md->link);
  271.         list_insert(&new_md->adj, &md->adj);
  272.  
  273.         new_md->base = md->base;
  274.         new_md->size = size;
  275.         new_md->parent = md->parent;
  276.         new_md->state = MD_USED;
  277.  
  278.         md->base+= size;
  279.         md->size-= size;
  280.         md->state = MD_FREE;
  281.  
  282.         idx1 = (md->size>>12) - 1 < 32 ? (md->size>>12) - 1 : 31;
  283.  
  284.         DBG("insert md %x, base %x size %x idx %x\n", md,md->base, md->size,idx1);
  285.  
  286.         if( idx1 < 31)
  287.           list_prepend(&md->link, &sheap.unmapped[idx1]);
  288.         else
  289.         {
  290.             if( list_empty(&sheap.unmapped[31]))
  291.                 list_prepend(&md->link, &sheap.unmapped[31]);
  292.             else
  293.             {
  294.                 md_t *tmp = (md_t*)sheap.unmapped[31].next;
  295.  
  296.                 while((link_t*)tmp != &sheap.unmapped[31])
  297.                 {
  298.                     if(md->base < tmp->base)
  299.                         break;
  300.                     tmp = (md_t*)tmp->link.next;
  301.                 }
  302.                 list_insert(&md->link, &tmp->link);
  303.             };
  304.         };
  305.  
  306.         _set_savu(idx1);
  307.  
  308.         safe_sti(efl);
  309.  
  310.         return new_md;
  311.     };
  312.  
  313.     md->state = MD_USED;
  314.  
  315.     safe_sti(efl);
  316.  
  317.     return md;
  318. }
  319.  
  320. md_t* __fastcall find_mapped_md(size_t size)
  321. {
  322.     eflags_t efl;
  323.  
  324.     md_t *md = NULL;
  325.  
  326.     count_t idx0;
  327.     u32_t mask;
  328.  
  329.     ASSERT((size & 0xFFF) == 0);
  330.  
  331.     efl = safe_cli();
  332.  
  333.     idx0 = (size>>12) - 1 < 32 ? (size>>12) - 1 : 31;
  334.     mask = sheap.av_mapped & ( -1<<idx0 );
  335.  
  336.     DBG("small av_mapped %x size %x idx0 %x mask %x\n",sheap.av_mapped, size,
  337.          idx0, mask);
  338.  
  339.     if(mask)
  340.     {
  341.         if(idx0 == 31)
  342.         {
  343.             ASSERT( !list_empty(&sheap.mapped[31]));
  344.  
  345.             md_t *tmp = (md_t*)sheap.mapped[31].next;
  346.             while((link_t*)tmp != &sheap.mapped[31])
  347.             {
  348.                 if(tmp->size >= size)
  349.                 {
  350.                     md = tmp;
  351.                     break;
  352.                 };
  353.                 tmp = (md_t*)tmp->link.next;
  354.             };
  355.         }
  356.         else
  357.         {
  358.             idx0 = _bsf(mask);
  359.  
  360.             ASSERT( !list_empty(&sheap.mapped[idx0]));
  361.  
  362.             md = (md_t*)sheap.mapped[idx0].next;
  363.         }
  364.     };
  365.  
  366.     if(md)
  367.     {
  368.         DBG("remove md %x\n", md);
  369.  
  370.         ASSERT(md->state==MD_FREE);
  371.  
  372.         list_remove((link_t*)md);
  373.         if(list_empty(&sheap.mapped[idx0]))
  374.             _reset_savm(idx0);
  375.     }
  376.     else
  377.     {
  378.         md_t    *lmd;
  379.         addr_t  frame;
  380.         addr_t  *pte;
  381.         int i;
  382.  
  383.         lmd = find_large_md((size+0x3FFFFF)&~0x3FFFFF);
  384.  
  385.         DBG("get large md %x\n", lmd);
  386.  
  387.         if( !lmd)
  388.         {
  389.             safe_sti(efl);
  390.             return NULL;
  391.         };
  392.  
  393.         ASSERT(lmd->size != 0);
  394.         ASSERT(lmd->base != 0);
  395.         ASSERT((lmd->base & 0x3FFFFF) == 0);
  396.         ASSERT(lmd->parent == NULL);
  397.  
  398.         frame = core_alloc(10);                        /* FIXME check */
  399.  
  400.         lmd->parent = (void*)frame;
  401.  
  402.         pte = &((addr_t*)page_tabs)[lmd->base>>12];    /* FIXME remove */
  403.  
  404.         for(i = 0; i<1024; i++)
  405.         {
  406.            *pte++ = frame;
  407.            frame+= 4096;
  408.         }
  409.  
  410.         md = (md_t*)slab_alloc(md_slab,0);             /* FIXME check */
  411.  
  412.         link_initialize(&md->link);
  413.         list_initialize(&md->adj);
  414.         md->base = lmd->base;
  415.         md->size = lmd->size;
  416.         md->parent  = lmd;
  417.         md->state = MD_USED;
  418.     };
  419.  
  420.     if(md->size > size)
  421.     {
  422.         count_t idx1;
  423.         md_t *new_md = (md_t*)slab_alloc(md_slab,0);    /* FIXME check */
  424.  
  425.         link_initialize(&new_md->link);
  426.         list_insert(&new_md->adj, &md->adj);
  427.  
  428.         new_md->base = md->base;
  429.         new_md->size = size;
  430.         new_md->parent = md->parent;
  431.  
  432.         md->base+= size;
  433.         md->size-= size;
  434.         md->state = MD_FREE;
  435.  
  436.         idx1 = (md->size>>12) - 1 < 32 ? (md->size>>12) - 1 : 31;
  437.  
  438.         DBG("insert md %x, base %x size %x idx %x\n", md,md->base, md->size,idx1);
  439.  
  440.         if( idx1 < 31)
  441.           list_prepend(&md->link, &sheap.mapped[idx1]);
  442.         else
  443.         {
  444.             if( list_empty(&sheap.mapped[31]))
  445.                 list_prepend(&md->link, &sheap.mapped[31]);
  446.             else
  447.             {
  448.                 md_t *tmp = (md_t*)sheap.mapped[31].next;
  449.  
  450.                 while((link_t*)tmp != &sheap.mapped[31])
  451.                 {
  452.                     if(md->base < tmp->base)
  453.                         break;
  454.                     tmp = (md_t*)tmp->link.next;
  455.                 }
  456.                 list_insert(&md->link, &tmp->link);
  457.             };
  458.         };
  459.  
  460.         _set_savm(idx1);
  461.  
  462.         md = new_md;
  463.     };
  464.  
  465.     md->state = MD_USED;
  466.  
  467.     safe_sti(efl);
  468.  
  469.     return md;
  470. }
  471.  
  472. void __fastcall free_unmapped_md(md_t *md)
  473. {
  474.     eflags_t  efl ;
  475.     md_t     *fd;
  476.     md_t     *bk;
  477.     count_t   idx;
  478.  
  479.     ASSERT(md->parent != NULL);
  480.  
  481.     efl = safe_cli();
  482.     spinlock_lock(&sheap.lock);
  483.  
  484.     if( !list_empty(&md->adj))
  485.     {
  486.         bk = (md_t*)md->adj.prev;
  487.         fd = (md_t*)md->adj.next;
  488.  
  489.         if(fd->state == MD_FREE)
  490.         {
  491.             idx = (fd->size>>12) - 1 < 32 ? (fd->size>>12) - 1 : 31;
  492.  
  493.             list_remove((link_t*)fd);
  494.             if(list_empty(&sheap.unmapped[idx]))
  495.                 _reset_savu(idx);
  496.  
  497.             md->size+= fd->size;
  498.             md->adj.next = fd->adj.next;
  499.             md->adj.next->prev = (link_t*)md;
  500.             slab_free(md_slab, fd);
  501.         };
  502.         if(bk->state == MD_FREE)
  503.         {
  504.             idx = (bk->size>>12) - 1 < 32 ? (bk->size>>12) - 1 : 31;
  505.  
  506.             list_remove((link_t*)bk);
  507.             if(list_empty(&sheap.unmapped[idx]))
  508.                 _reset_savu(idx);
  509.  
  510.             bk->size+= md->size;
  511.             bk->adj.next = md->adj.next;
  512.             bk->adj.next->prev = (link_t*)bk;
  513.             slab_free(md_slab, md);
  514.             md = fd;
  515.         };
  516.     };
  517.  
  518.     md->state = MD_FREE;
  519.  
  520.     idx = (md->size>>12) - 1 < 32 ? (md->size>>12) - 1 : 31;
  521.  
  522.     _set_savu(idx);
  523.  
  524.     if( idx < 31)
  525.         list_prepend(&md->link, &sheap.unmapped[idx]);
  526.     else
  527.     {
  528.         if( list_empty(&sheap.unmapped[31]))
  529.             list_prepend(&md->link, &sheap.unmapped[31]);
  530.         else
  531.         {
  532.             md_t *tmp = (md_t*)sheap.unmapped[31].next;
  533.  
  534.             while((link_t*)tmp != &sheap.unmapped[31])
  535.             {
  536.                 if(md->base < tmp->base)
  537.                     break;
  538.                 tmp = (md_t*)tmp->link.next;
  539.             }
  540.             list_insert(&md->link, &tmp->link);
  541.         };
  542.     };
  543.     spinlock_unlock(&sheap.lock);
  544.     safe_sti(efl);
  545.  
  546. };
  547.  
  548. void __fastcall free_mapped_md(md_t *md)
  549. {
  550.     eflags_t  efl ;
  551.     md_t     *fd;
  552.     md_t     *bk;
  553.     count_t   idx;
  554.  
  555.     ASSERT(md->parent != NULL);
  556.     ASSERT( ((md_t*)(md->parent))->parent != NULL);
  557.  
  558.     efl = safe_cli();
  559.     spinlock_lock(&sheap.lock);
  560.  
  561.     if( !list_empty(&md->adj))
  562.     {
  563.         bk = (md_t*)md->adj.prev;
  564.         fd = (md_t*)md->adj.next;
  565.  
  566.         if(fd->state == MD_FREE)
  567.    {
  568.             idx = (fd->size>>12) - 1 < 32 ? (fd->size>>12) - 1 : 31;
  569.  
  570.             list_remove((link_t*)fd);
  571.             if(list_empty(&sheap.mapped[idx]))
  572.                 _reset_savm(idx);
  573.  
  574.             md->size+= fd->size;
  575.             md->adj.next = fd->adj.next;
  576.             md->adj.next->prev = (link_t*)md;
  577.             slab_free(md_slab, fd);
  578.         };
  579.         if(bk->state == MD_FREE)
  580.         {
  581.             idx = (bk->size>>12) - 1 < 32 ? (bk->size>>12) - 1 : 31;
  582.  
  583.             list_remove((link_t*)bk);
  584.             if(list_empty(&sheap.mapped[idx]))
  585.                 _reset_savm(idx);
  586.  
  587.             bk->size+= md->size;
  588.             bk->adj.next = md->adj.next;
  589.             bk->adj.next->prev = (link_t*)bk;
  590.             slab_free(md_slab, md);
  591.             md = fd;
  592.         };
  593.    };
  594.  
  595.     md->state = MD_FREE;
  596.  
  597.     idx = (md->size>>12) - 1 < 32 ? (md->size>>12) - 1 : 31;
  598.  
  599.     _set_savm(idx);
  600.  
  601.     if( idx < 31)
  602.         list_prepend(&md->link, &sheap.mapped[idx]);
  603.     else
  604.     {
  605.         if( list_empty(&sheap.mapped[31]))
  606.             list_prepend(&md->link, &sheap.mapped[31]);
  607.         else
  608.    {
  609.             md_t *tmp = (md_t*)sheap.mapped[31].next;
  610.  
  611.             while((link_t*)tmp != &sheap.mapped[31])
  612.      {
  613.                 if(md->base < tmp->base)
  614.                     break;
  615.                 tmp = (md_t*)tmp->link.next;
  616.    }
  617.             list_insert(&md->link, &tmp->link);
  618.         };
  619.     };
  620.     spinlock_unlock(&sheap.lock);
  621.     safe_sti(efl);
  622. };
  623.  
  624.  
  625. void * __fastcall mem_alloc(size_t size, u32_t flags)
  626. {
  627.     eflags_t efl;
  628.  
  629.     md_t *md;
  630.  
  631.     DBG("\nmem_alloc: %x bytes\n", size);
  632.  
  633.     ASSERT(size != 0);
  634.  
  635.     size = (size+4095)&~4095;
  636.  
  637.     if( flags & PG_MAP )
  638.     {
  639.         md = find_mapped_md(size);
  640.  
  641.         if( !md )
  642.             return NULL;
  643.  
  644.         md_t *lmd = (md_t*)md->parent;
  645.  
  646.         ASSERT( lmd != NULL);
  647.         ASSERT( lmd->parent != NULL);
  648.  
  649.         addr_t  frame  = (md->base - lmd->base + (addr_t)lmd->parent)|
  650.                          (flags & 0xFFF);
  651.         DBG("frame %x\n", frame);
  652.         ASSERT(frame != 0);
  653.  
  654.         count_t  tmp = size >> 12;
  655.         addr_t  *pte = &((addr_t*)page_tabs)[md->base>>12];
  656.  
  657.         while(tmp--)
  658.                 {
  659.                     *pte++ = frame;
  660.                     frame+= 4096;
  661.                 };
  662.     }
  663.     else
  664.         md = find_unmapped_md(size);
  665.  
  666.     if( !md )
  667.         return NULL;
  668.  
  669.     ASSERT(md->parent != NULL);
  670.     ASSERT(md->state == MD_USED);
  671.  
  672.  
  673.         efl = safe_cli();
  674.         spinlock_lock(&sheap.lock);
  675.  
  676.         if( list_empty(&sheap.used) )
  677.             list_prepend(&md->link, &sheap.used);
  678.         else
  679.         {
  680.             md_t *tmp = (md_t*)sheap.used.next;
  681.  
  682.             while((link_t*)tmp != &sheap.used)
  683.             {
  684.                 if(md->base < tmp->base)
  685.                     break;
  686.                 tmp = (md_t*)tmp->link.next;
  687.             }
  688.             list_insert(&md->link, &tmp->link);
  689.         };
  690.  
  691.         spinlock_unlock(&sheap.lock);
  692.         safe_sti(efl);
  693.  
  694.         DBG("allocate: %x size %x\n\n",md->base, size);
  695.         return (void*)md->base;
  696. };
  697.  
  698. void __fastcall mem_free(void *mem)
  699. {
  700.     eflags_t efl;
  701.  
  702.     md_t *tmp;
  703.     md_t *md = NULL;
  704.  
  705.     DBG("mem_free: %x\n",mem);
  706.  
  707.     ASSERT( mem != 0 );
  708.     ASSERT( ((addr_t)mem & 0xFFF) == 0 );
  709.     ASSERT( ! list_empty(&sheap.used));
  710.  
  711.     efl = safe_cli();
  712.  
  713.     tmp = (md_t*)sheap.used.next;
  714.  
  715.     while((link_t*)tmp != &sheap.used)
  716.     {
  717.         if( tmp->base == (addr_t)mem )
  718.         {
  719.             md = tmp;
  720.             break;
  721.         };
  722.         tmp = (md_t*)tmp->link.next;
  723.     }
  724.  
  725.     if( md )
  726.     {
  727.         md_t *lmd;
  728.  
  729.         DBG("\tmd: %x base: %x size: %x\n",md, md->base, md->size);
  730.  
  731.         ASSERT(md->state == MD_USED);
  732.  
  733.         list_remove((link_t*)md);
  734.  
  735.         lmd = (md_t*)md->parent;
  736.  
  737.         ASSERT(lmd != 0);
  738.  
  739.         if(lmd->parent != 0)
  740.         {
  741.         count_t tmp  = md->size >> 12;
  742.         addr_t  *pte = &((addr_t*)page_tabs)[md->base>>12];
  743.  
  744.         while(tmp--)
  745.         {
  746.             *pte++ = 0;
  747.             asm volatile (
  748.                 "invlpg (%0)"
  749.                     ::"r" (mem) );
  750.             mem+= 4096;
  751.         };
  752.  
  753.             free_mapped_md( md );
  754.         }
  755.         else
  756.             free_unmapped_md( md );
  757.     }
  758.     else
  759.         DBG("\tERROR: invalid base address: %x\n", mem);
  760.  
  761.     safe_sti(efl);
  762. };
  763.