fslongjin 2 rokov pred
rodič
commit
f513286f53

+ 1 - 1
docs/kernel/core_api/allocate-memory.md

@@ -4,7 +4,7 @@ DragonOS提供了一些用于内存分配的api。您可以使用*kmalloc*来分
 
 ## 选择合适的内存分配器
 
-在内核中,最直接、最简单的分配内存的方式就是,使用`kmalloc()`函数进行分配。并且,出于安全起见,在得到内存块后,我们强烈建议您使用`memset()`函数将该内存区域清零。
+在内核中,最直接、最简单的分配内存的方式就是,使用`kmalloc()`函数进行分配。并且,出于安全起见,除非内存在分配后一定会被覆盖,且您能确保内存中的脏数据一定不会对程序造成影响,在其余情况下,我们建议使用`kzalloc()`进行内存分配,它将会在`kmalloc()`的基础上,把申请到的内存进行清零。
 
 您可以通过`kmalloc()`函数分配得到32bytes到1MBytes之间的内存对象。并且,这些内存对象具有以下的性质:
 

+ 21 - 4
docs/kernel/core_api/mm-api.md

@@ -4,7 +4,7 @@
 
 SLAB内存池提供小内存对象的分配功能。
 
-### `void *kmalloc(unsigned long size, unsigned long flags)`
+### `void *kmalloc(unsigned long size, gfp_t gfp)`
 
   获取小块的内存。
 
@@ -18,9 +18,26 @@ SLAB内存池提供小内存对象的分配功能。
 
   内存对象的大小
 
-**flags**
+**gfp**
+
+  标志位
+
+### `void *kzalloc(unsigned long size, gfp_t gfp)`
+
+#### 描述
+
+  获取小块的内存,并将其清零。其余功能与kmalloc相同。
+
+
+##### 参数
+
+**size**
+
+  内存对象的大小
+
+**gfp**
 
-  标志位(暂时未实现,默认填0)
+  标志位
 
 ### `unsigned long kfree(void *address)`
 
@@ -30,7 +47,7 @@ SLAB内存池提供小内存对象的分配功能。
 
   该函数用于释放通过kmalloc申请的内存。如果`address`为NULL,则函数被调用后,无事发生。
 
-  请不要通过这个函数释放那些不是从`kmalloc()`申请的内存,否则将会导致系统崩溃。
+  请不要通过这个函数释放那些不是从`kmalloc()`或`kzalloc()`申请的内存,否则将会导致系统崩溃。
 
 ##### 参数
 

+ 2 - 0
kernel/common/compiler.h

@@ -1,5 +1,7 @@
 #pragma once
 
+#define __force __attribute__((force))
+
 #define likely(x) __builtin_expect(!!(x), 1)
 #define unlikely(x) __builtin_expect(!!(x), 0)
 

+ 8 - 0
kernel/common/gfp.h

@@ -0,0 +1,8 @@
+#pragma once
+#include <common/sys/types.h>
+#include <common/compiler.h>
+/**
+ * __GFP_ZERO: 获取内存的同时,将获取到的这块内存清空
+ *
+ */
+#define __GFP_ZERO ((gfp_t)(1UL << 0))

+ 2 - 2
kernel/common/mutex.c

@@ -37,14 +37,14 @@ void mutex_lock(mutex_t *lock)
         spin_lock(&lock->wait_lock);
         if (likely(mutex_is_locked(lock)))
         {
-            struct mutex_waiter_t *waiter = (struct mutex_waiter_t *)kmalloc(sizeof(struct mutex_waiter_t), 0);
+            struct mutex_waiter_t *waiter = (struct mutex_waiter_t *)kzalloc(sizeof(struct mutex_waiter_t), 0);
             if (waiter == NULL)
             {
                 kerror("In mutex_lock: no memory to alloc waiter. Program's behaviour might be indetermined!");
                 spin_unlock(&lock->wait_lock);
                 return;
             }
-            memset(waiter, 0, sizeof(struct mutex_waiter_t));
+            // memset(waiter, 0, sizeof(struct mutex_waiter_t));
             waiter->pcb = current_pcb;
             list_init(&waiter->list);
             list_append(&lock->wait_list, &waiter->list);

+ 3 - 1
kernel/common/sys/types.h

@@ -83,4 +83,6 @@ typedef struct __pthread_spinlock_t
 typedef struct __pthread_condattr_t
 {
     int clockid; // clockid_t
-} pthread_condattr_t;
+} pthread_condattr_t;
+
+typedef uint64_t gfp_t;

+ 1 - 1
kernel/driver/mouse/ps2_mouse.c

@@ -201,7 +201,7 @@ static int ps2_mouse_enable_5keys()
 void ps2_mouse_init()
 {
     // 初始化鼠标读入队列缓冲区
-    ps2_mouse_buf_ptr = (struct ps2_mouse_input_buffer *)kmalloc(sizeof(struct ps2_mouse_input_buffer), 0);
+    ps2_mouse_buf_ptr = (struct ps2_mouse_input_buffer *)kzalloc(sizeof(struct ps2_mouse_input_buffer), 0);
     ps2_mouse_buf_ptr->ptr_head = ps2_mouse_buf_ptr->buffer;
     ps2_mouse_buf_ptr->ptr_tail = ps2_mouse_buf_ptr->buffer;
     ps2_mouse_buf_ptr->count = 0;

+ 1 - 2
kernel/main.c

@@ -105,8 +105,7 @@ void system_initialize()
 
 
     // =========== 重新设置initial_tss[0]的ist
-    uchar *ptr = (uchar *)kmalloc(STACK_SIZE, 0) + STACK_SIZE;
-    memset(ptr, 0, STACK_SIZE); // 将ist清空
+    uchar *ptr = (uchar *)kzalloc(STACK_SIZE, 0) + STACK_SIZE;
     ((struct process_control_block *)(ptr - STACK_SIZE))->cpu_id = 0;
 
     initial_tss[0].ist1 = (ul)ptr;

+ 1 - 0
kernel/mm/mm.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include <common/glib.h>
+#include <common/gfp.h>
 #include <mm/mm-types.h>
 #include <process/process.h>
 

+ 11 - 5
kernel/mm/slab.c

@@ -397,7 +397,6 @@ ul slab_init()
         io_mfence();
         --page->zone->count_pages_free;
         page_init(page, PAGE_KERNEL_INIT | PAGE_KERNEL | PAGE_PGT_MAPPED);
-
     }
     io_mfence();
 
@@ -415,7 +414,7 @@ ul slab_init()
         *(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
 
         ++page->zone->count_pages_using;
-        io_mfence();    // 该位置必须加一个mfence,否则O3优化运行时会报错
+        io_mfence(); // 该位置必须加一个mfence,否则O3优化运行时会报错
         --page->zone->count_pages_free;
         page_init(page, PAGE_PGT_MAPPED | PAGE_KERNEL | PAGE_KERNEL_INIT);
 
@@ -535,11 +534,12 @@ struct slab_obj *kmalloc_create_slab_obj(ul size)
  * @brief 通用内存分配函数
  *
  * @param size 要分配的内存大小
- * @param flags 内存的flag
+ * @param gfp 内存的flag
  * @return void* 内核内存虚拟地址
  */
-void *kmalloc(unsigned long size, unsigned long flags)
+void *kmalloc(unsigned long size, gfp_t gfp)
 {
+    void *result = NULL;
     if (size > 1048576)
     {
         kwarn("kmalloc(): Can't alloc such memory: %ld bytes, because it is too large.", size);
@@ -610,9 +610,15 @@ void *kmalloc(unsigned long size, unsigned long flags)
             // 放锁
             spin_unlock(&kmalloc_cache_group[index].lock);
             // 返回内存对象
-            return (void *)((char *)slab_obj_ptr->vaddr + kmalloc_cache_group[index].size * i);
+            result = (void *)((char *)slab_obj_ptr->vaddr + kmalloc_cache_group[index].size * i);
+            goto done;
         }
     }
+    goto failed;
+done:;
+    if (gfp & __GFP_ZERO)
+        memset(result, 0, size);
+    return result;
 failed:;
     spin_unlock(&kmalloc_cache_group[index].lock);
     kerror("kmalloc(): Cannot alloc more memory: %d bytes", size);

+ 22 - 13
kernel/mm/slab.h

@@ -11,8 +11,8 @@
 
 // SLAB存储池count_using不为空
 #define ESLAB_NOTNULL 101
-#define ENOT_IN_SLAB 102    // 地址不在当前slab内存池中
-#define ECANNOT_FREE_MEM 103    // 无法释放内存
+#define ENOT_IN_SLAB 102     // 地址不在当前slab内存池中
+#define ECANNOT_FREE_MEM 103 // 无法释放内存
 
 struct slab_obj
 {
@@ -43,21 +43,33 @@ struct slab
     // dma内存池对象
     struct slab_obj *cache_dma_pool_entry;
 
-    spinlock_t lock;    // 当前内存池的操作锁
+    spinlock_t lock; // 当前内存池的操作锁
 
     // 内存池的构造函数和析构函数
     void *(*constructor)(void *vaddr, ul arg);
     void *(*destructor)(void *vaddr, ul arg);
 };
-//extern struct slab kmalloc_cache_group[16];
+
 /**
  * @brief 通用内存分配函数
  *
  * @param size 要分配的内存大小
- * @param flags 内存的flag
- * @return void*
+ * @param gfp 内存的flag
+ * @return void* 分配得到的内存的指针
+ */
+void *kmalloc(unsigned long size, gfp_t gfp);
+
+/**
+ * @brief 从kmalloc申请一块内存,并将这块内存清空
+ * 
+ * @param size 要分配的内存大小
+ * @param gfp 内存的flag
+ * @return void* 分配得到的内存的指针
  */
-void *kmalloc(unsigned long size, unsigned long flags);
+static __always_inline void *kzalloc(size_t size, gfp_t gfp)
+{
+    return kmalloc(size, gfp | __GFP_ZERO);
+}
 
 /**
  * @brief 通用内存释放函数
@@ -108,12 +120,11 @@ ul slab_free(struct slab *slab_pool, void *addr, ul arg);
 
 /**
  * @brief 在kmalloc中创建slab_obj的函数(与slab_malloc()类似)
- * 
- * @param size 
+ *
+ * @param size
  * @return struct slab_obj* 创建好的slab_obj
  */
-struct slab_obj * kmalloc_create_slab_obj(ul size);
-
+struct slab_obj *kmalloc_create_slab_obj(ul size);
 
 /**
  * @brief 初始化内存池组
@@ -121,5 +132,3 @@ struct slab_obj * kmalloc_create_slab_obj(ul size);
  * @return ul
  */
 ul slab_init();
-
-