geniusgogo hace 1 año
padre
commit
7aa130c83c
Se han modificado 2 ficheros con 59 adiciones y 20 borrados
  1. 55 0
      components/mm/mm_aspace.c
  2. 4 20
      components/mm/mm_aspace.h

+ 55 - 0
components/mm/mm_aspace.c

@@ -1068,6 +1068,61 @@ int rt_aspace_unmap_range(rt_aspace_t aspace, void *addr, size_t length)
     return error;
 }
 
+void *rt_aspace_mremap_range(rt_aspace_t aspace, void *old_address, size_t old_size,
+                                size_t new_size, int flags, void *new_address)
+{
+    void *ret = RT_NULL;
+
+    if (!aspace)
+    {
+        LOG_I("%s: Invalid input", __func__);
+    }
+    else if (_not_in_range(old_address, old_size, aspace->start, aspace->size))
+    {
+        LOG_I("%s: %lx not in range of aspace[%lx:%lx]", __func__, old_address,
+              aspace->start, (char *)aspace->start + aspace->size);
+    }
+    else if (!ALIGNED(old_address))
+    {
+        LOG_I("%s(old_address=%p): Unaligned address", __func__, old_address);
+    }
+    else
+    {
+        /**
+         * Brief: re-arrange the address space to remove existing pages mapping
+         * in [unmap_start, unmap_start + unmap_len)
+         */
+        old_size = RT_ALIGN(old_size, ARCH_PAGE_SIZE);
+
+        WR_LOCK(aspace);
+        {
+            rt_varea_t existed;
+            struct _mm_range unmap_range;
+
+            unmap_range.start = old_address;
+            unmap_range.end = old_address + old_size - 1;
+
+            existed = _aspace_bst_search_overlap(aspace, unmap_range);
+            if (existed && existed->mem_obj && existed->mem_obj->on_varea_mremap)
+            {
+                ret = existed->mem_obj->on_varea_mremap(existed, new_size, flags, new_address);
+            }
+        }
+        WR_UNLOCK(aspace);
+
+        if (ret)
+        {
+            int error = rt_aspace_unmap_range(aspace, old_address, old_size);
+            if (error != RT_EOK)
+            {
+                LOG_I("%s: unmap old failed, addr %p size %p", __func__, old_address, old_size);
+            }
+        }
+    }
+
+    return ret;
+}
+
 static inline void *_lower(void *a, void *b)
 {
     return a < b ? a : b;

+ 4 - 20
components/mm/mm_aspace.h

@@ -121,6 +121,8 @@ typedef struct rt_mem_obj
     void (*page_write)(struct rt_varea *varea, struct rt_aspace_io_msg *msg);
 
     const char *(*get_name)(rt_varea_t varea);
+
+    void *(*on_varea_mremap)(struct rt_varea *varea, rt_size_t new_size, int flags, void *new_address);
 } *rt_mem_obj_t;
 
 extern struct rt_mem_obj rt_mm_dummy_mapper;
@@ -226,26 +228,8 @@ int rt_aspace_unmap(rt_aspace_t aspace, void *addr);
  */
 int rt_aspace_unmap_range(rt_aspace_t aspace, void *addr, size_t length);
 
-/**
- * @brief Remove pages of existed mappings in the range [addr, addr+length)
- * Length is automatically rounded up to the next multiple of the page size.
- *
- * @param aspace target virtual address space
- * @param addr the beginning of the range of pages to be unmapped
- * @param length length of range in bytes
- * @return int rt errno
- */
-int rt_aspace_unmap_range(rt_aspace_t aspace, void *addr, size_t length);
-
-/**
- * @brief Remove pages of existed mappings in the range [addr, addr+length)
- * Length is automatically rounded up to the next multiple of the page size.
- *
- * @param aspace target virtual address space
- * @param addr
- * @return int
- */
-int rt_aspace_unmap_range(rt_aspace_t aspace, void *addr, size_t length);
+void *rt_aspace_mremap_range(rt_aspace_t aspace, void *old_address, size_t old_size,
+                                size_t new_size, int flags, void *new_address);
 
 int rt_aspace_control(rt_aspace_t aspace, void *addr, enum rt_mmu_cntl cmd);