mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 19:36:47 +00:00
new: kthread机制
This commit is contained in:
parent
edef02286e
commit
02a6b3a303
134
kernel/arch/x86_64/asm.h
Normal file
134
kernel/arch/x86_64/asm.h
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define sti() __asm__ __volatile__("sti\n\t" :: \
|
||||||
|
: "memory") //开启外部中断
|
||||||
|
#define cli() __asm__ __volatile__("cli\n\t" :: \
|
||||||
|
: "memory") //关闭外部中断
|
||||||
|
#define nop() __asm__ __volatile__("nop\n\t")
|
||||||
|
#define hlt() __asm__ __volatile__("hlt\n\t")
|
||||||
|
#define pause() asm volatile("pause\n\t"); // 处理器等待一段时间
|
||||||
|
|
||||||
|
//内存屏障
|
||||||
|
#define io_mfence() __asm__ __volatile__("mfence\n\t" :: \
|
||||||
|
: "memory") // 在mfence指令前的读写操作必须在mfence指令后的读写操作前完成。
|
||||||
|
#define io_sfence() __asm__ __volatile__("sfence\n\t" :: \
|
||||||
|
: "memory") // 在sfence指令前的写操作必须在sfence指令后的写操作前完成
|
||||||
|
#define io_lfence() __asm__ __volatile__("lfence\n\t" :: \
|
||||||
|
: "memory") // 在lfence指令前的读操作必须在lfence指令后的读操作前完成。
|
||||||
|
|
||||||
|
#define rdtsc() ({ \
|
||||||
|
uint64_t tmp1 = 0, tmp2 = 0; \
|
||||||
|
asm volatile("rdtsc" \
|
||||||
|
: "=d"(tmp1), "=a"(tmp2)::"memory"); \
|
||||||
|
(tmp1 << 32 | tmp2); \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 读取rsp寄存器的值(存储了页目录的基地址)
|
||||||
|
*
|
||||||
|
* @return unsigned* rsp的值的指针
|
||||||
|
*/
|
||||||
|
unsigned long *get_rsp()
|
||||||
|
{
|
||||||
|
uint64_t *tmp;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"movq %%rsp, %0\n\t"
|
||||||
|
: "=r"(tmp)::"memory");
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 读取rbp寄存器的值(存储了页目录的基地址)
|
||||||
|
*
|
||||||
|
* @return unsigned* rbp的值的指针
|
||||||
|
*/
|
||||||
|
unsigned long *get_rbp()
|
||||||
|
{
|
||||||
|
uint64_t *tmp;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"movq %%rbp, %0\n\t"
|
||||||
|
: "=r"(tmp)::"memory");
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 读取ds寄存器的值(存储了页目录的基地址)
|
||||||
|
*
|
||||||
|
* @return unsigned* ds的值的指针
|
||||||
|
*/
|
||||||
|
unsigned long *get_ds()
|
||||||
|
{
|
||||||
|
uint64_t *tmp;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"movq %%ds, %0\n\t"
|
||||||
|
: "=r"(tmp)::"memory");
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 读取rax寄存器的值(存储了页目录的基地址)
|
||||||
|
*
|
||||||
|
* @return unsigned* rax的值的指针
|
||||||
|
*/
|
||||||
|
unsigned long *get_rax()
|
||||||
|
{
|
||||||
|
uint64_t *tmp;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"movq %%rax, %0\n\t"
|
||||||
|
: "=r"(tmp)::"memory");
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief 读取rbx寄存器的值(存储了页目录的基地址)
|
||||||
|
*
|
||||||
|
* @return unsigned* rbx的值的指针
|
||||||
|
*/
|
||||||
|
unsigned long *get_rbx()
|
||||||
|
{
|
||||||
|
uint64_t *tmp;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"movq %%rbx, %0\n\t"
|
||||||
|
: "=r"(tmp)::"memory");
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========= MSR寄存器组操作 =============
|
||||||
|
/**
|
||||||
|
* @brief 向msr寄存器组的address处的寄存器写入值value
|
||||||
|
*
|
||||||
|
* @param address 地址
|
||||||
|
* @param value 要写入的值
|
||||||
|
*/
|
||||||
|
void wrmsr(uint64_t address, uint64_t value)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__("wrmsr \n\t" ::"d"(value >> 32), "a"(value & 0xffffffff), "c"(address)
|
||||||
|
: "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从msr寄存器组的address地址处读取值
|
||||||
|
* rdmsr返回高32bits在edx,低32bits在eax
|
||||||
|
* @param address 地址
|
||||||
|
* @return uint64_t address处的寄存器的值
|
||||||
|
*/
|
||||||
|
uint64_t rdmsr(uint64_t address)
|
||||||
|
{
|
||||||
|
unsigned int tmp0, tmp1;
|
||||||
|
__asm__ __volatile__("rdmsr \n\t"
|
||||||
|
: "=d"(tmp0), "=a"(tmp1)
|
||||||
|
: "c"(address)
|
||||||
|
: "memory");
|
||||||
|
return ((uint64_t)tmp0 << 32) | tmp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t get_rflags()
|
||||||
|
{
|
||||||
|
unsigned long tmp = 0;
|
||||||
|
__asm__ __volatile__("pushfq \n\t"
|
||||||
|
"movq (%%rsp), %0 \n\t"
|
||||||
|
"popfq \n\t"
|
||||||
|
: "=r"(tmp)::"memory");
|
||||||
|
return tmp;
|
||||||
|
}
|
@ -28,3 +28,19 @@ static inline long __must_check IS_ERR_OR_NULL(const void* ptr)
|
|||||||
{
|
{
|
||||||
return !ptr || IS_ERR_VALUE((uint64_t)ptr);
|
return !ptr || IS_ERR_VALUE((uint64_t)ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将错误码转换为指针
|
||||||
|
*
|
||||||
|
* @param error 错误码
|
||||||
|
* @return void* 转换后的指针
|
||||||
|
*/
|
||||||
|
static inline void* __must_check ERR_PTR(long error)
|
||||||
|
{
|
||||||
|
return (void*)(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline long __must_check PTR_ERR(void * ptr)
|
||||||
|
{
|
||||||
|
return (long)ptr;
|
||||||
|
}
|
@ -11,29 +11,13 @@
|
|||||||
#include <common/stddef.h>
|
#include <common/stddef.h>
|
||||||
#include <arch/arch.h>
|
#include <arch/arch.h>
|
||||||
#include <common/compiler.h>
|
#include <common/compiler.h>
|
||||||
|
#include <common/list.h>
|
||||||
|
|
||||||
#define sti() __asm__ __volatile__("sti\n\t" :: \
|
#if ARCH(I386) || ARCH(X86_64)
|
||||||
: "memory") //开启外部中断
|
#include <arch/x86_64/asm.h>
|
||||||
#define cli() __asm__ __volatile__("cli\n\t" :: \
|
#else
|
||||||
: "memory") //关闭外部中断
|
#error Arch not supported.
|
||||||
#define nop() __asm__ __volatile__("nop\n\t")
|
#endif
|
||||||
#define hlt() __asm__ __volatile__("hlt\n\t")
|
|
||||||
#define pause() asm volatile("pause\n\t"); // 处理器等待一段时间
|
|
||||||
|
|
||||||
//内存屏障
|
|
||||||
#define io_mfence() __asm__ __volatile__("mfence\n\t" :: \
|
|
||||||
: "memory") // 在mfence指令前的读写操作必须在mfence指令后的读写操作前完成。
|
|
||||||
#define io_sfence() __asm__ __volatile__("sfence\n\t" :: \
|
|
||||||
: "memory") // 在sfence指令前的写操作必须在sfence指令后的写操作前完成
|
|
||||||
#define io_lfence() __asm__ __volatile__("lfence\n\t" :: \
|
|
||||||
: "memory") // 在lfence指令前的读操作必须在lfence指令后的读操作前完成。
|
|
||||||
|
|
||||||
#define rdtsc() ({ \
|
|
||||||
uint64_t tmp1 = 0, tmp2 = 0; \
|
|
||||||
asm volatile("rdtsc" \
|
|
||||||
: "=d"(tmp1), "=a"(tmp2)::"memory"); \
|
|
||||||
(tmp1 << 32 | tmp2); \
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 根据结构体变量内某个成员变量member的基地址,计算出该结构体变量的基地址
|
* @brief 根据结构体变量内某个成员变量member的基地址,计算出该结构体变量的基地址
|
||||||
@ -83,121 +67,7 @@ static __always_inline ul ALIGN(const ul addr, const ul _align)
|
|||||||
return (ul)((addr + _align - 1) & (~(_align - 1)));
|
return (ul)((addr + _align - 1) & (~(_align - 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
//链表数据结构
|
|
||||||
struct List
|
|
||||||
{
|
|
||||||
struct List *prev, *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
//初始化循环链表
|
|
||||||
static inline void list_init(struct List *list)
|
|
||||||
{
|
|
||||||
list->next = list;
|
|
||||||
io_mfence();
|
|
||||||
list->prev = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
|
|
||||||
* @param entry 给定的节点
|
|
||||||
* @param node 待插入的节点
|
|
||||||
**/
|
|
||||||
static inline void list_add(struct List *entry, struct List *node)
|
|
||||||
{
|
|
||||||
|
|
||||||
node->next = entry->next;
|
|
||||||
barrier();
|
|
||||||
node->prev = entry;
|
|
||||||
barrier();
|
|
||||||
node->next->prev = node;
|
|
||||||
barrier();
|
|
||||||
entry->next = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 将node添加到给定的list的结尾(也就是当前节点的前面)
|
|
||||||
* @param entry 列表的入口
|
|
||||||
* @param node 待添加的节点
|
|
||||||
*/
|
|
||||||
static inline void list_append(struct List *entry, struct List *node)
|
|
||||||
{
|
|
||||||
|
|
||||||
struct List *tail = entry->prev;
|
|
||||||
list_add(tail, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 从列表中删除节点
|
|
||||||
* @param entry 待删除的节点
|
|
||||||
*/
|
|
||||||
static inline void list_del(struct List *entry)
|
|
||||||
{
|
|
||||||
|
|
||||||
entry->next->prev = entry->prev;
|
|
||||||
entry->prev->next = entry->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 将新的链表结点替换掉旧的链表结点,并使得旧的结点的前后指针均为NULL
|
|
||||||
*
|
|
||||||
* @param old 要被替换的结点
|
|
||||||
* @param new 新的要换上去的结点
|
|
||||||
*/
|
|
||||||
static inline void list_replace(struct List* old, struct List * new)
|
|
||||||
{
|
|
||||||
if(old->prev!=NULL)
|
|
||||||
old->prev->next=new;
|
|
||||||
new->prev = old->prev;
|
|
||||||
if(old->next!=NULL)
|
|
||||||
old->next->prev = new;
|
|
||||||
new->next = old->next;
|
|
||||||
|
|
||||||
old->prev = NULL;
|
|
||||||
old->next = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline bool list_empty(struct List *entry)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief 判断循环链表是否为空
|
|
||||||
* @param entry 入口
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (entry == entry->next && entry->prev == entry)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取链表的上一个元素
|
|
||||||
*
|
|
||||||
* @param entry
|
|
||||||
* @return 链表的上一个元素
|
|
||||||
*/
|
|
||||||
static inline struct List *list_prev(struct List *entry)
|
|
||||||
{
|
|
||||||
if (entry->prev != NULL)
|
|
||||||
return entry->prev;
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取链表的下一个元素
|
|
||||||
*
|
|
||||||
* @param entry
|
|
||||||
* @return 链表的下一个元素
|
|
||||||
*/
|
|
||||||
static inline struct List *list_next(struct List *entry)
|
|
||||||
{
|
|
||||||
if (entry->next != NULL)
|
|
||||||
return entry->next;
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *memset(void *dst, unsigned char C, ul size)
|
void *memset(void *dst, unsigned char C, ul size)
|
||||||
{
|
{
|
||||||
@ -323,113 +193,6 @@ void io_out32(unsigned short port, unsigned int value)
|
|||||||
__asm__ __volatile__("cld;rep;outsw;mfence;" ::"d"(port), "S"(buffer), "c"(nr) \
|
__asm__ __volatile__("cld;rep;outsw;mfence;" ::"d"(port), "S"(buffer), "c"(nr) \
|
||||||
: "memory")
|
: "memory")
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 读取rsp寄存器的值(存储了页目录的基地址)
|
|
||||||
*
|
|
||||||
* @return unsigned* rsp的值的指针
|
|
||||||
*/
|
|
||||||
unsigned long *get_rsp()
|
|
||||||
{
|
|
||||||
ul *tmp;
|
|
||||||
__asm__ __volatile__(
|
|
||||||
"movq %%rsp, %0\n\t"
|
|
||||||
: "=r"(tmp)::"memory");
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 读取rbp寄存器的值(存储了页目录的基地址)
|
|
||||||
*
|
|
||||||
* @return unsigned* rbp的值的指针
|
|
||||||
*/
|
|
||||||
unsigned long *get_rbp()
|
|
||||||
{
|
|
||||||
ul *tmp;
|
|
||||||
__asm__ __volatile__(
|
|
||||||
"movq %%rbp, %0\n\t"
|
|
||||||
: "=r"(tmp)::"memory");
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 读取ds寄存器的值(存储了页目录的基地址)
|
|
||||||
*
|
|
||||||
* @return unsigned* ds的值的指针
|
|
||||||
*/
|
|
||||||
unsigned long *get_ds()
|
|
||||||
{
|
|
||||||
ul *tmp;
|
|
||||||
__asm__ __volatile__(
|
|
||||||
"movq %%ds, %0\n\t"
|
|
||||||
: "=r"(tmp)::"memory");
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 读取rax寄存器的值(存储了页目录的基地址)
|
|
||||||
*
|
|
||||||
* @return unsigned* rax的值的指针
|
|
||||||
*/
|
|
||||||
unsigned long *get_rax()
|
|
||||||
{
|
|
||||||
ul *tmp;
|
|
||||||
__asm__ __volatile__(
|
|
||||||
"movq %%rax, %0\n\t"
|
|
||||||
: "=r"(tmp)::"memory");
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @brief 读取rbx寄存器的值(存储了页目录的基地址)
|
|
||||||
*
|
|
||||||
* @return unsigned* rbx的值的指针
|
|
||||||
*/
|
|
||||||
unsigned long *get_rbx()
|
|
||||||
{
|
|
||||||
ul *tmp;
|
|
||||||
__asm__ __volatile__(
|
|
||||||
"movq %%rbx, %0\n\t"
|
|
||||||
: "=r"(tmp)::"memory");
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========= MSR寄存器组操作 =============
|
|
||||||
/**
|
|
||||||
* @brief 向msr寄存器组的address处的寄存器写入值value
|
|
||||||
*
|
|
||||||
* @param address 地址
|
|
||||||
* @param value 要写入的值
|
|
||||||
*/
|
|
||||||
void wrmsr(ul address, ul value)
|
|
||||||
{
|
|
||||||
__asm__ __volatile__("wrmsr \n\t" ::"d"(value >> 32), "a"(value & 0xffffffff), "c"(address)
|
|
||||||
: "memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 从msr寄存器组的address地址处读取值
|
|
||||||
* rdmsr返回高32bits在edx,低32bits在eax
|
|
||||||
* @param address 地址
|
|
||||||
* @return ul address处的寄存器的值
|
|
||||||
*/
|
|
||||||
ul rdmsr(ul address)
|
|
||||||
{
|
|
||||||
unsigned int tmp0, tmp1;
|
|
||||||
__asm__ __volatile__("rdmsr \n\t"
|
|
||||||
: "=d"(tmp0), "=a"(tmp1)
|
|
||||||
: "c"(address)
|
|
||||||
: "memory");
|
|
||||||
return ((ul)tmp0 << 32) | tmp1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t get_rflags()
|
|
||||||
{
|
|
||||||
unsigned long tmp = 0;
|
|
||||||
__asm__ __volatile__("pushfq \n\t"
|
|
||||||
"movq (%%rsp), %0 \n\t"
|
|
||||||
"popfq \n\t"
|
|
||||||
: "=r"(tmp)::"memory");
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 验证地址空间是否为用户地址空间
|
* @brief 验证地址空间是否为用户地址空间
|
||||||
|
77
kernel/common/kthread.h
Normal file
77
kernel/common/kthread.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <common/numa.h>
|
||||||
|
#include <process/proc-types.h>
|
||||||
|
#include <common/err.h>
|
||||||
|
#include <process/process.h>
|
||||||
|
|
||||||
|
struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data),
|
||||||
|
void *data,
|
||||||
|
int node,
|
||||||
|
const char name_fmt[], ...);
|
||||||
|
/**
|
||||||
|
* @brief 在当前结点上创建一个内核线程
|
||||||
|
*
|
||||||
|
* @param thread_fn 该内核线程要执行的函数
|
||||||
|
* @param data 传递给 thread_fn 的参数数据
|
||||||
|
* @param name_fmt printf-style format string for the thread name
|
||||||
|
* @param arg name_fmt的参数
|
||||||
|
*
|
||||||
|
* 请注意,该宏会创建一个内核线程,并将其设置为停止状态
|
||||||
|
*/
|
||||||
|
#define kthread_create(thread_fn, data, name_fmt, arg...) \
|
||||||
|
kthread_create_on_node(thread_fn, data, NUMA_NO_NODE, name_fmt, ##arg)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建内核线程,并将其唤醒
|
||||||
|
*
|
||||||
|
* @param thread_fn 该内核线程要执行的函数
|
||||||
|
* @param data 传递给 thread_fn 的参数数据
|
||||||
|
* @param name_fmt printf-style format string for the thread name
|
||||||
|
* @param arg name_fmt的参数
|
||||||
|
*/
|
||||||
|
#define kthread_run(thread_fn, data, name_fmt, ...) \
|
||||||
|
({ \
|
||||||
|
struct process_control_block *__kt = kthread_create(thread_fn, data, name_fmt, ##__VA_ARGS__); \
|
||||||
|
if (!IS_ERR(__kt)) \
|
||||||
|
process_wakeup(__kt); \
|
||||||
|
__kt; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 向kthread发送停止信号,请求其结束
|
||||||
|
*
|
||||||
|
* @param pcb 内核线程的pcb
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int kthread_stop(struct process_control_block * pcb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 内核线程调用该函数,检查自身的标志位,判断自己是否应该执行完任务后退出
|
||||||
|
*
|
||||||
|
* @return true 内核线程应该退出
|
||||||
|
* @return false 无需退出
|
||||||
|
*/
|
||||||
|
bool kthread_should_stop(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 让当前内核线程退出,并返回result参数给kthread_stop()函数
|
||||||
|
*
|
||||||
|
* @param result 返回值
|
||||||
|
*/
|
||||||
|
void kthread_exit(long result);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化kthread机制(只应被process_init调用)
|
||||||
|
*
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int kthread_mechanism_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置pcb中的worker_private字段(只应被设置一次)
|
||||||
|
*
|
||||||
|
* @param pcb pcb
|
||||||
|
* @return bool 成功或失败
|
||||||
|
*/
|
||||||
|
bool kthread_set_worker_private(struct process_control_block *pcb);
|
131
kernel/common/list.h
Normal file
131
kernel/common/list.h
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <common/stddef.h>
|
||||||
|
|
||||||
|
#if ARCH(I386) || ARCH(X86_64)
|
||||||
|
#include <arch/x86_64/asm.h>
|
||||||
|
#else
|
||||||
|
#error Arch not supported.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//链表数据结构
|
||||||
|
struct List
|
||||||
|
{
|
||||||
|
struct List *prev, *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
//初始化循环链表
|
||||||
|
static inline void list_init(struct List *list)
|
||||||
|
{
|
||||||
|
list->next = list;
|
||||||
|
io_mfence();
|
||||||
|
list->prev = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
|
||||||
|
* @param entry 给定的节点
|
||||||
|
* @param node 待插入的节点
|
||||||
|
**/
|
||||||
|
static inline void list_add(struct List *entry, struct List *node)
|
||||||
|
{
|
||||||
|
|
||||||
|
node->next = entry->next;
|
||||||
|
barrier();
|
||||||
|
node->prev = entry;
|
||||||
|
barrier();
|
||||||
|
node->next->prev = node;
|
||||||
|
barrier();
|
||||||
|
entry->next = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将node添加到给定的list的结尾(也就是当前节点的前面)
|
||||||
|
* @param entry 列表的入口
|
||||||
|
* @param node 待添加的节点
|
||||||
|
*/
|
||||||
|
static inline void list_append(struct List *entry, struct List *node)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct List *tail = entry->prev;
|
||||||
|
list_add(tail, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从列表中删除节点
|
||||||
|
* @param entry 待删除的节点
|
||||||
|
*/
|
||||||
|
static inline void list_del(struct List *entry)
|
||||||
|
{
|
||||||
|
|
||||||
|
entry->next->prev = entry->prev;
|
||||||
|
entry->prev->next = entry->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define list_del_init(entry) \
|
||||||
|
list_del(entry); \
|
||||||
|
list_init(entry);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将新的链表结点替换掉旧的链表结点,并使得旧的结点的前后指针均为NULL
|
||||||
|
*
|
||||||
|
* @param old 要被替换的结点
|
||||||
|
* @param new 新的要换上去的结点
|
||||||
|
*/
|
||||||
|
static inline void list_replace(struct List *old, struct List *new)
|
||||||
|
{
|
||||||
|
if (old->prev != NULL)
|
||||||
|
old->prev->next = new;
|
||||||
|
new->prev = old->prev;
|
||||||
|
if (old->next != NULL)
|
||||||
|
old->next->prev = new;
|
||||||
|
new->next = old->next;
|
||||||
|
|
||||||
|
old->prev = NULL;
|
||||||
|
old->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool list_empty(struct List *entry)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief 判断循环链表是否为空
|
||||||
|
* @param entry 入口
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (entry == entry->next && entry->prev == entry)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取链表的上一个元素
|
||||||
|
*
|
||||||
|
* @param entry
|
||||||
|
* @return 链表的上一个元素
|
||||||
|
*/
|
||||||
|
static inline struct List *list_prev(struct List *entry)
|
||||||
|
{
|
||||||
|
if (entry->prev != NULL)
|
||||||
|
return entry->prev;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取链表的下一个元素
|
||||||
|
*
|
||||||
|
* @param entry
|
||||||
|
* @return 链表的下一个元素
|
||||||
|
*/
|
||||||
|
static inline struct List *list_next(struct List *entry)
|
||||||
|
{
|
||||||
|
if (entry->next != NULL)
|
||||||
|
return entry->next;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
3
kernel/common/numa.h
Normal file
3
kernel/common/numa.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define NUMA_NO_NODE (-1)
|
@ -27,6 +27,22 @@
|
|||||||
unlikely(__ret_warn_on); \
|
unlikely(__ret_warn_on); \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 当condition不为0时输出警告信息,且只会输出一次警告信息
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define WARN_ON_ONCE(condition) ({ \
|
||||||
|
static int __warned; \
|
||||||
|
int __ret_warn_once = !!(condition); \
|
||||||
|
\
|
||||||
|
if (unlikely(__ret_warn_once && !__warned)) \
|
||||||
|
{ \
|
||||||
|
__warned = true; \
|
||||||
|
WARN_ON(1); \
|
||||||
|
} \
|
||||||
|
unlikely(__ret_warn_once); \
|
||||||
|
})
|
||||||
|
|
||||||
#define FAIL_ON_TO(condition, to) ({ \
|
#define FAIL_ON_TO(condition, to) ({ \
|
||||||
int __ret_warn_on = !!(condition); \
|
int __ret_warn_on = !!(condition); \
|
||||||
if (unlikely(__ret_warn_on)) \
|
if (unlikely(__ret_warn_on)) \
|
||||||
|
@ -18,7 +18,7 @@ static int usb_pdevs_count = 0;
|
|||||||
* @brief 初始化usb驱动程序
|
* @brief 初始化usb驱动程序
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int usb_init()
|
int usb_init(void* unused)
|
||||||
{
|
{
|
||||||
kinfo("Initializing usb driver...");
|
kinfo("Initializing usb driver...");
|
||||||
spin_init(&xhci_controller_init_lock);
|
spin_init(&xhci_controller_init_lock);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* @param arg 传递给测试函数的参数
|
* @param arg 传递给测试函数的参数
|
||||||
* @return pid_t 测试内核线程的pid
|
* @return pid_t 测试内核线程的pid
|
||||||
*/
|
*/
|
||||||
pid_t ktest_start(uint64_t (*func)(uint64_t arg), uint64_t arg)
|
pid_t ktest_start(int (*func)(void* arg), void* arg)
|
||||||
{
|
{
|
||||||
return kernel_thread(func, arg, 0);
|
return kernel_thread(func, arg, 0);
|
||||||
}
|
}
|
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <common/sys/types.h>
|
#include <common/sys/types.h>
|
||||||
|
|
||||||
uint64_t ktest_test_bitree(uint64_t arg);
|
int ktest_test_bitree(void* arg);
|
||||||
uint64_t ktest_test_kfifo(uint64_t arg);
|
int ktest_test_kfifo(void* arg);
|
||||||
uint64_t ktest_test_mutex(uint64_t arg);
|
int ktest_test_mutex(void* arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 开启一个新的内核线程以进行测试
|
* @brief 开启一个新的内核线程以进行测试
|
||||||
@ -12,4 +12,4 @@ uint64_t ktest_test_mutex(uint64_t arg);
|
|||||||
* @param arg 传递给测试函数的参数
|
* @param arg 传递给测试函数的参数
|
||||||
* @return pid_t 测试内核线程的pid
|
* @return pid_t 测试内核线程的pid
|
||||||
*/
|
*/
|
||||||
pid_t ktest_start(uint64_t (*func)(uint64_t arg), uint64_t arg);
|
pid_t ktest_start(int (*func)(void* arg), void* arg);
|
@ -119,7 +119,7 @@ static ktest_case_table kt_bitree_func_table[] = {
|
|||||||
ktest_bitree_case1,
|
ktest_bitree_case1,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint64_t ktest_test_bitree(uint64_t arg)
|
int ktest_test_bitree(void* arg)
|
||||||
{
|
{
|
||||||
kTEST("Testing bitree...");
|
kTEST("Testing bitree...");
|
||||||
for (int i = 0; i < sizeof(kt_bitree_func_table) / sizeof(ktest_case_table); ++i)
|
for (int i = 0; i < sizeof(kt_bitree_func_table) / sizeof(ktest_case_table); ++i)
|
||||||
|
@ -152,7 +152,7 @@ static ktest_case_table kt_kfifo_func_table[] = {
|
|||||||
ktest_kfifo_case0_1,
|
ktest_kfifo_case0_1,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint64_t ktest_test_kfifo(uint64_t arg)
|
int ktest_test_kfifo(void* arg)
|
||||||
{
|
{
|
||||||
kTEST("Testing kfifo...");
|
kTEST("Testing kfifo...");
|
||||||
for (int i = 0; i < sizeof(kt_kfifo_func_table) / sizeof(ktest_case_table); ++i)
|
for (int i = 0; i < sizeof(kt_kfifo_func_table) / sizeof(ktest_case_table); ++i)
|
||||||
|
@ -31,7 +31,7 @@ static long ktest_mutex_case0(uint64_t arg0, uint64_t arg1)
|
|||||||
* @param arg
|
* @param arg
|
||||||
* @return long
|
* @return long
|
||||||
*/
|
*/
|
||||||
static unsigned long ktest_mutex_case1_pid1(uint64_t arg)
|
static int ktest_mutex_case1_pid1(void* arg)
|
||||||
{
|
{
|
||||||
kTEST("ktest_mutex_case1_subproc start.");
|
kTEST("ktest_mutex_case1_subproc start.");
|
||||||
assert(mutex_is_locked(&mtx) == 1);
|
assert(mutex_is_locked(&mtx) == 1);
|
||||||
@ -78,7 +78,7 @@ static ktest_case_table kt_mutex_func_table[] = {
|
|||||||
ktest_mutex_case0,
|
ktest_mutex_case0,
|
||||||
ktest_mutex_case1,
|
ktest_mutex_case1,
|
||||||
};
|
};
|
||||||
uint64_t ktest_test_mutex(uint64_t arg)
|
int ktest_test_mutex(void* arg)
|
||||||
{
|
{
|
||||||
kTEST("Testing mutex...");
|
kTEST("Testing mutex...");
|
||||||
mutex_init(&mtx);
|
mutex_init(&mtx);
|
||||||
|
@ -6,12 +6,9 @@ kernel_lib_sys_objs:= $(shell find ./*.c)
|
|||||||
ECHO:
|
ECHO:
|
||||||
@echo "$@"
|
@echo "$@"
|
||||||
|
|
||||||
$(kernel_lib_sys_objs): ECHO
|
|
||||||
$(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" PIC="$(PIC)"
|
|
||||||
|
|
||||||
$(kernel_lib_sys_objs): ECHO
|
$(kernel_lib_sys_objs): ECHO
|
||||||
gcc $(CFLAGS) -c $@ -o $@.o
|
gcc $(CFLAGS) -c $@ -o $@.o
|
||||||
|
|
||||||
all: $(kernel_lib_sys_objs) $(kernel_lib_sys_objs)
|
all: $(kernel_lib_sys_objs)
|
||||||
@echo $(kernel_lib_sys_objs)
|
@echo $(kernel_lib_sys_objs)
|
||||||
|
|
||||||
|
@ -249,6 +249,8 @@ void mm_init()
|
|||||||
initial_mm.stack_start = _stack_start;
|
initial_mm.stack_start = _stack_start;
|
||||||
initial_mm.vmas = NULL;
|
initial_mm.vmas = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mmio_init();
|
mmio_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,8 +491,30 @@ void page_table_init()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_tlb();
|
|
||||||
|
|
||||||
|
barrier();
|
||||||
|
// ========= 在IDLE进程的顶层页表中添加对内核地址空间的映射 =====================
|
||||||
|
|
||||||
|
// 由于IDLE进程的顶层页表的高地址部分会被后续进程所复制,为了使所有进程能够共享相同的内核空间,
|
||||||
|
// 因此需要先在IDLE进程的顶层页表内映射二级页表
|
||||||
|
|
||||||
|
uint64_t *idle_pml4t_vaddr = (uint64_t *)phys_2_virt((uint64_t)get_CR3() & (~0xfffUL));
|
||||||
|
|
||||||
|
for (int i = 256; i < 512; ++i)
|
||||||
|
{
|
||||||
|
uint64_t *tmp = idle_pml4t_vaddr + i;
|
||||||
|
barrier();
|
||||||
|
if (*tmp == 0)
|
||||||
|
{
|
||||||
|
void *pdpt = kmalloc(PAGE_4K_SIZE, 0);
|
||||||
|
barrier();
|
||||||
|
memset(pdpt, 0, PAGE_4K_SIZE);
|
||||||
|
barrier();
|
||||||
|
set_pml4t(tmp, mk_pml4t(virt_2_phys(pdpt), PAGE_KERNEL_PGT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
barrier();
|
||||||
|
flush_tlb();
|
||||||
kinfo("Page table Initialized. Affects:%d", js);
|
kinfo("Page table Initialized. Affects:%d", js);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
|
|
||||||
all: procs.o process.o
|
|
||||||
|
|
||||||
CFLAGS += -I .
|
CFLAGS += -I .
|
||||||
|
|
||||||
|
|
||||||
|
kernel_process_objs:= $(shell find ./*.c)
|
||||||
|
|
||||||
|
ECHO:
|
||||||
|
@echo "$@"
|
||||||
|
|
||||||
|
|
||||||
|
$(kernel_process_objs): ECHO
|
||||||
|
gcc $(CFLAGS) -c $@ -o $@.o
|
||||||
|
|
||||||
procs.o: proc.S
|
procs.o: proc.S
|
||||||
gcc -E proc.S > _proc.s
|
gcc -E proc.S > _proc.s
|
||||||
as $(ASFLAGS) -o procs.o _proc.s
|
as $(ASFLAGS) -o procs.o _proc.s
|
||||||
|
|
||||||
process.o: process.c
|
all: procs.o $(kernel_process_objs)
|
||||||
gcc $(CFLAGS) -c process.c -o process.o
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
305
kernel/process/kthread.c
Normal file
305
kernel/process/kthread.c
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
#include <common/kthread.h>
|
||||||
|
#include <common/glib.h>
|
||||||
|
#include <common/spinlock.h>
|
||||||
|
#include <sched/sched.h>
|
||||||
|
#include <debug/bug.h>
|
||||||
|
|
||||||
|
static spinlock_t __kthread_create_lock; // kthread创建过程的锁
|
||||||
|
static struct List kthread_create_list; // kthread创建任务的链表
|
||||||
|
struct process_control_block *kthreadd_pcb = NULL; // kthreadd守护线程的pcb
|
||||||
|
|
||||||
|
// 枚举各个标志位是在第几位
|
||||||
|
enum KTHREAD_BITS
|
||||||
|
{
|
||||||
|
KTHREAD_IS_PER_CPU = 0,
|
||||||
|
KTHREAD_SHOULD_STOP,
|
||||||
|
KTHREAD_SHOULD_PARK,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief kthread的创建信息(仅在创建过程中存在)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct kthread_create_info_t
|
||||||
|
{
|
||||||
|
// 传递给kthread的信息
|
||||||
|
int (*thread_fn)(void *data);
|
||||||
|
void *data;
|
||||||
|
int node;
|
||||||
|
|
||||||
|
// kthreadd守护进程传递给kthread_create的结果
|
||||||
|
struct process_control_block *result;
|
||||||
|
|
||||||
|
struct List list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief kthread信息
|
||||||
|
* 该结构体将会绑定到pcb的worker_private中
|
||||||
|
*/
|
||||||
|
struct kthread_info_t
|
||||||
|
{
|
||||||
|
uint64_t flags;
|
||||||
|
uint32_t cpu;
|
||||||
|
int result;
|
||||||
|
int (*thread_fn)(void *);
|
||||||
|
void *data;
|
||||||
|
// todo: 将这里改为completion机制
|
||||||
|
bool exited; // 是否已退出
|
||||||
|
char *full_name; // 内核线程的名称
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取pcb中的kthread结构体
|
||||||
|
*
|
||||||
|
* @param pcb pcb
|
||||||
|
* @return struct kthread* kthread信息结构体
|
||||||
|
*/
|
||||||
|
static inline struct kthread_info_t *to_kthread(struct process_control_block *pcb)
|
||||||
|
{
|
||||||
|
WARN_ON(!(pcb->flags & PF_KTHREAD));
|
||||||
|
return pcb->worker_private;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct process_control_block *__kthread_create_on_node(int (*thread_fn)(void *data), void *data,
|
||||||
|
int node,
|
||||||
|
const char name_fmt[], va_list args)
|
||||||
|
{
|
||||||
|
struct process_control_block *pcb = NULL;
|
||||||
|
struct kthread_create_info_t *create = kzalloc(sizeof(struct kthread_create_info_t), 0);
|
||||||
|
|
||||||
|
if (create == NULL)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
create->thread_fn = thread_fn;
|
||||||
|
create->data = data;
|
||||||
|
create->node = node;
|
||||||
|
create->result = NULL;
|
||||||
|
list_init(&create->list);
|
||||||
|
|
||||||
|
spin_lock(&__kthread_create_lock);
|
||||||
|
list_append(&kthread_create_list, &create->list);
|
||||||
|
spin_unlock(&__kthread_create_lock);
|
||||||
|
kdebug("to wakeup kthread daemon..., current preempt=%d, rflags=%#018lx", current_pcb->preempt_count, get_rflags());
|
||||||
|
while (kthreadd_pcb == NULL) // 若kthreadd未初始化,则等待kthreadd启动
|
||||||
|
;
|
||||||
|
// 唤醒kthreadd守护进程
|
||||||
|
process_wakeup_immediately(kthreadd_pcb);
|
||||||
|
|
||||||
|
// 等待创建完成
|
||||||
|
// todo: 使用completion机制以降低忙等时间
|
||||||
|
while (create->result == NULL)
|
||||||
|
pause();
|
||||||
|
// 获取结果
|
||||||
|
pcb = create->result;
|
||||||
|
if (!IS_ERR(create->result))
|
||||||
|
{
|
||||||
|
// todo: 为内核线程设置名字
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(create);
|
||||||
|
return pcb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 让当前内核线程退出,并返回result参数给kthread_stop()函数
|
||||||
|
*
|
||||||
|
* @param result 返回值
|
||||||
|
*/
|
||||||
|
void kthread_exit(long result)
|
||||||
|
{
|
||||||
|
struct kthread_info_t *kt = to_kthread(current_pcb);
|
||||||
|
kt->result = result;
|
||||||
|
kt->exited = true;
|
||||||
|
process_do_exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 在当前结点上创建一个内核线程
|
||||||
|
*
|
||||||
|
* @param thread_fn 该内核线程要执行的函数
|
||||||
|
* @param data 传递给 thread_fn 的参数数据
|
||||||
|
* @param node 线程的任务和线程结构都分配在这个节点上
|
||||||
|
* @param name_fmt printf-style format string for the thread name
|
||||||
|
* @param arg name_fmt的参数
|
||||||
|
* @return 返回一个pcb或者是ERR_PTR(-ENOMEM)
|
||||||
|
*
|
||||||
|
* 请注意,该宏会创建一个内核线程,并将其设置为停止状态。您可以使用wake_up_process来启动这个线程。
|
||||||
|
* 新的线程的调度策略为SCHED_NORMAL,并且能在所有的cpu上运行
|
||||||
|
*
|
||||||
|
* 当内核线程被唤醒时,会运行thread_fn函数,并将data作为参数传入。
|
||||||
|
* 内核线程可以直接返回,也可以在kthread_should_stop为真时返回。
|
||||||
|
*/
|
||||||
|
struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data), void *data,
|
||||||
|
int node,
|
||||||
|
const char name_fmt[], ...)
|
||||||
|
{
|
||||||
|
struct process_control_block *pcb;
|
||||||
|
va_list args;
|
||||||
|
va_start(args, name_fmt);
|
||||||
|
pcb = __kthread_create_on_node(thread_fn, data, node, name_fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
return pcb;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief 内核线程的包裹程序
|
||||||
|
* 当内核线程被运行后,从kernel_thread_func跳转到这里。
|
||||||
|
* @param _create 内核线程的创建信息
|
||||||
|
* @return int 内核线程的退出返回值
|
||||||
|
*/
|
||||||
|
static int kthread(void *_create)
|
||||||
|
{
|
||||||
|
struct kthread_create_info_t *create = _create;
|
||||||
|
// 将这几个信息从kthread_create_info中拷贝过来。以免在kthread_create_info被free后,数据丢失从而导致错误。
|
||||||
|
int (*thread_fn)(void *data) = create->thread_fn;
|
||||||
|
void *data = create->data;
|
||||||
|
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
struct kthread_info_t *self = to_kthread(current_pcb);
|
||||||
|
|
||||||
|
self->thread_fn = thread_fn;
|
||||||
|
self->data = data;
|
||||||
|
|
||||||
|
// todo: 增加调度参数设定
|
||||||
|
// todo: 当前内核线程继承了kthreadd的优先级以及调度策略,需要在这里进行更新
|
||||||
|
|
||||||
|
// 设置当前进程为不可被打断
|
||||||
|
current_pcb->state = PROC_UNINTERRUPTIBLE;
|
||||||
|
|
||||||
|
// 将当前pcb返回给创建者
|
||||||
|
create->result = current_pcb;
|
||||||
|
|
||||||
|
// 发起调度,使得当前内核线程休眠。直到创建者通过process_wakeup将当前内核线程唤醒
|
||||||
|
sched();
|
||||||
|
|
||||||
|
retval = -EINTR;
|
||||||
|
// 如果发起者没有调用kthread_stop(),则该kthread的功能函数开始执行
|
||||||
|
if (!(self->flags & (1 << KTHREAD_SHOULD_STOP)))
|
||||||
|
{
|
||||||
|
retval = thread_fn(data);
|
||||||
|
}
|
||||||
|
kthread_exit(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __create_kthread(struct kthread_create_info_t *create)
|
||||||
|
{
|
||||||
|
pid_t pid = kernel_thread(kthread, create, CLONE_FS | CLONE_SIGNAL);
|
||||||
|
if (IS_ERR((void *)pid))
|
||||||
|
{
|
||||||
|
// todo: 使用complete机制完善这里
|
||||||
|
|
||||||
|
create->result = (struct process_control_block *)pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief kthread守护线程
|
||||||
|
*
|
||||||
|
* @param unused
|
||||||
|
* @return int 不应当退出
|
||||||
|
*/
|
||||||
|
int kthreadd(void *unused)
|
||||||
|
{
|
||||||
|
kinfo("kthread daemon started!");
|
||||||
|
struct process_control_block *pcb = current_pcb;
|
||||||
|
kthreadd_pcb = current_pcb;
|
||||||
|
current_pcb->flags |= PF_NOFREEZE;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
current_pcb->state = PROC_INTERRUPTIBLE;
|
||||||
|
// 所有的创建任务都被处理完了
|
||||||
|
if (list_empty(&kthread_create_list))
|
||||||
|
sched();
|
||||||
|
|
||||||
|
spin_lock(&__kthread_create_lock);
|
||||||
|
// 循环取出链表中的任务
|
||||||
|
while (!list_empty(&kthread_create_list))
|
||||||
|
{
|
||||||
|
|
||||||
|
// 从链表中取出第一个要创建的内核线程任务
|
||||||
|
struct kthread_create_info_t *create = container_of(kthread_create_list.next, struct kthread_create_info_t, list);
|
||||||
|
list_del_init(&create->list);
|
||||||
|
spin_unlock(&__kthread_create_lock);
|
||||||
|
|
||||||
|
__create_kthread(create);
|
||||||
|
|
||||||
|
spin_lock(&__kthread_create_lock);
|
||||||
|
}
|
||||||
|
spin_unlock(&__kthread_create_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 内核线程调用该函数,检查自身的标志位,判断自己是否应该执行完任务后退出
|
||||||
|
*
|
||||||
|
* @return true 内核线程应该退出
|
||||||
|
* @return false 无需退出
|
||||||
|
*/
|
||||||
|
bool kthread_should_stop(void)
|
||||||
|
{
|
||||||
|
struct kthread_info_t *self = to_kthread(current_pcb);
|
||||||
|
if (self->flags & (1 << KTHREAD_SHOULD_STOP))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 向kthread发送停止信号,请求其结束
|
||||||
|
*
|
||||||
|
* @param pcb 内核线程的pcb
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int kthread_stop(struct process_control_block *pcb)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
struct kthread_info_t *target = to_kthread(pcb);
|
||||||
|
target->flags |= (1 << KTHREAD_SHOULD_STOP);
|
||||||
|
process_wakeup(pcb);
|
||||||
|
// 等待指定的内核线程退出
|
||||||
|
// todo: 使用completion机制改进这里
|
||||||
|
while (target->exited == false)
|
||||||
|
usleep(5000);
|
||||||
|
retval = target->result;
|
||||||
|
|
||||||
|
// 释放内核线程的页表
|
||||||
|
process_exit_mm(pcb);
|
||||||
|
process_release_pcb(pcb);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置pcb中的worker_private字段(只应被设置一次)
|
||||||
|
*
|
||||||
|
* @param pcb pcb
|
||||||
|
* @return bool 成功或失败
|
||||||
|
*/
|
||||||
|
bool kthread_set_worker_private(struct process_control_block *pcb)
|
||||||
|
{
|
||||||
|
if (WARN_ON_ONCE(to_kthread(pcb)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
struct kthread_info_t *kt = kzalloc(sizeof(struct kthread_info_t), 0);
|
||||||
|
if (kt == NULL)
|
||||||
|
return false;
|
||||||
|
pcb->worker_private = kt;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化kthread机制(只应被process_init调用)
|
||||||
|
*
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int kthread_mechanism_init()
|
||||||
|
{
|
||||||
|
kinfo("Initializing kthread mechanism...");
|
||||||
|
spin_init(&__kthread_create_lock);
|
||||||
|
list_init(&kthread_create_list);
|
||||||
|
// 创建kthreadd守护进程
|
||||||
|
kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_SIGNAL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -58,6 +58,7 @@ struct thread_struct
|
|||||||
#define PF_NEED_SCHED (1UL << 1) // 进程需要被调度
|
#define PF_NEED_SCHED (1UL << 1) // 进程需要被调度
|
||||||
#define PF_VFORK (1UL << 2) // 标志进程是否由于vfork而存在资源共享
|
#define PF_VFORK (1UL << 2) // 标志进程是否由于vfork而存在资源共享
|
||||||
#define PF_KFORK (1UL << 3) // 标志在内核态下调用fork(临时标记,do_fork()结束后会将其复位)
|
#define PF_KFORK (1UL << 3) // 标志在内核态下调用fork(临时标记,do_fork()结束后会将其复位)
|
||||||
|
#define PF_NOFREEZE (1UL << 4) // 当前进程不能被冻结
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 进程控制块
|
* @brief 进程控制块
|
||||||
@ -101,6 +102,9 @@ struct process_control_block
|
|||||||
|
|
||||||
int32_t exit_code; // 进程退出时的返回码
|
int32_t exit_code; // 进程退出时的返回码
|
||||||
wait_queue_node_t wait_child_proc_exit; // 子进程退出等待队列
|
wait_queue_node_t wait_child_proc_exit; // 子进程退出等待队列
|
||||||
|
|
||||||
|
/* PF_kTHREAD | PF_IO_WORKER 的进程,worker_private不为NULL*/
|
||||||
|
void *worker_private;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 将进程的pcb和内核栈融合到一起,8字节对齐
|
// 将进程的pcb和内核栈融合到一起,8字节对齐
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <common/string.h>
|
#include <common/string.h>
|
||||||
#include <common/compiler.h>
|
#include <common/compiler.h>
|
||||||
#include <common/elf.h>
|
#include <common/elf.h>
|
||||||
|
#include <common/kthread.h>
|
||||||
#include <common/time.h>
|
#include <common/time.h>
|
||||||
#include <common/sys/wait.h>
|
#include <common/sys/wait.h>
|
||||||
#include <driver/video/video.h>
|
#include <driver/video/video.h>
|
||||||
@ -21,6 +22,7 @@
|
|||||||
#include <sched/sched.h>
|
#include <sched/sched.h>
|
||||||
#include <common/unistd.h>
|
#include <common/unistd.h>
|
||||||
#include <debug/traceback/traceback.h>
|
#include <debug/traceback/traceback.h>
|
||||||
|
#include <debug/bug.h>
|
||||||
#include <driver/disk/ahci/ahci.h>
|
#include <driver/disk/ahci/ahci.h>
|
||||||
|
|
||||||
#include <ktest/ktest.h>
|
#include <ktest/ktest.h>
|
||||||
@ -578,7 +580,7 @@ ul process_do_exit(ul code)
|
|||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigned long flags)
|
pid_t kernel_thread(int (*fn)(void*), void* arg, unsigned long flags)
|
||||||
{
|
{
|
||||||
struct pt_regs regs;
|
struct pt_regs regs;
|
||||||
barrier();
|
barrier();
|
||||||
@ -617,50 +619,9 @@ int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigne
|
|||||||
void process_init()
|
void process_init()
|
||||||
{
|
{
|
||||||
kinfo("Initializing process...");
|
kinfo("Initializing process...");
|
||||||
initial_mm.pgd = (pml4t_t *)get_CR3();
|
|
||||||
|
|
||||||
initial_mm.code_addr_start = memory_management_struct.kernel_code_start;
|
|
||||||
initial_mm.code_addr_end = memory_management_struct.kernel_code_end;
|
|
||||||
|
|
||||||
initial_mm.data_addr_start = (ul)&_data;
|
|
||||||
initial_mm.data_addr_end = memory_management_struct.kernel_data_end;
|
|
||||||
|
|
||||||
initial_mm.rodata_addr_start = (ul)&_rodata;
|
|
||||||
initial_mm.rodata_addr_end = (ul)&_erodata;
|
|
||||||
initial_mm.bss_start = (uint64_t)&_bss;
|
|
||||||
initial_mm.bss_end = (uint64_t)&_ebss;
|
|
||||||
|
|
||||||
initial_mm.brk_start = memory_management_struct.start_brk;
|
|
||||||
initial_mm.brk_end = current_pcb->addr_limit;
|
|
||||||
|
|
||||||
initial_mm.stack_start = _stack_start;
|
|
||||||
initial_mm.vmas = NULL;
|
|
||||||
|
|
||||||
initial_tss[proc_current_cpu_id].rsp0 = initial_thread.rbp;
|
initial_tss[proc_current_cpu_id].rsp0 = initial_thread.rbp;
|
||||||
|
|
||||||
// ========= 在IDLE进程的顶层页表中添加对内核地址空间的映射 =====================
|
|
||||||
|
|
||||||
// 由于IDLE进程的顶层页表的高地址部分会被后续进程所复制,为了使所有进程能够共享相同的内核空间,
|
|
||||||
// 因此需要先在IDLE进程的顶层页表内映射二级页表
|
|
||||||
|
|
||||||
uint64_t *idle_pml4t_vaddr = (uint64_t *)phys_2_virt((uint64_t)get_CR3() & (~0xfffUL));
|
|
||||||
|
|
||||||
for (int i = 256; i < 512; ++i)
|
|
||||||
{
|
|
||||||
uint64_t *tmp = idle_pml4t_vaddr + i;
|
|
||||||
barrier();
|
|
||||||
if (*tmp == 0)
|
|
||||||
{
|
|
||||||
void *pdpt = kmalloc(PAGE_4K_SIZE, 0);
|
|
||||||
barrier();
|
|
||||||
memset(pdpt, 0, PAGE_4K_SIZE);
|
|
||||||
barrier();
|
|
||||||
set_pml4t(tmp, mk_pml4t(virt_2_phys(pdpt), PAGE_KERNEL_PGT));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
barrier();
|
|
||||||
|
|
||||||
flush_tlb();
|
|
||||||
/*
|
/*
|
||||||
kdebug("initial_thread.rbp=%#018lx", initial_thread.rbp);
|
kdebug("initial_thread.rbp=%#018lx", initial_thread.rbp);
|
||||||
kdebug("initial_tss[0].rsp1=%#018lx", initial_tss[0].rsp1);
|
kdebug("initial_tss[0].rsp1=%#018lx", initial_tss[0].rsp1);
|
||||||
@ -672,14 +633,19 @@ void process_init()
|
|||||||
|
|
||||||
// 初始化进程的循环链表
|
// 初始化进程的循环链表
|
||||||
list_init(&initial_proc_union.pcb.list);
|
list_init(&initial_proc_union.pcb.list);
|
||||||
|
|
||||||
|
// 临时设置IDLE进程的的虚拟运行时间为0,防止下面的这些内核线程的虚拟运行时间出错
|
||||||
|
current_pcb->virtual_runtime = 0;
|
||||||
barrier();
|
barrier();
|
||||||
kernel_thread(initial_kernel_thread, 10, CLONE_FS | CLONE_SIGNAL); // 初始化内核线程
|
kernel_thread(initial_kernel_thread, 10, CLONE_FS | CLONE_SIGNAL); // 初始化内核线程
|
||||||
barrier();
|
barrier();
|
||||||
|
kthread_mechanism_init(); // 初始化kthread机制
|
||||||
|
|
||||||
initial_proc_union.pcb.state = PROC_RUNNING;
|
initial_proc_union.pcb.state = PROC_RUNNING;
|
||||||
initial_proc_union.pcb.preempt_count = 0;
|
initial_proc_union.pcb.preempt_count = 0;
|
||||||
initial_proc_union.pcb.cpu_id = 0;
|
initial_proc_union.pcb.cpu_id = 0;
|
||||||
initial_proc_union.pcb.virtual_runtime = (1UL << 60);
|
initial_proc_union.pcb.virtual_runtime = (1UL << 60);
|
||||||
|
// 将IDLE进程的虚拟运行时间设置为一个很大的数值
|
||||||
current_pcb->virtual_runtime = (1UL << 60);
|
current_pcb->virtual_runtime = (1UL << 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,6 +678,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
|
|||||||
io_mfence();
|
io_mfence();
|
||||||
// 将当前进程的pcb复制到新的pcb内
|
// 将当前进程的pcb复制到新的pcb内
|
||||||
memcpy(tsk, current_pcb, sizeof(struct process_control_block));
|
memcpy(tsk, current_pcb, sizeof(struct process_control_block));
|
||||||
|
tsk->worker_private = NULL;
|
||||||
io_mfence();
|
io_mfence();
|
||||||
|
|
||||||
// 初始化进程的循环链表结点
|
// 初始化进程的循环链表结点
|
||||||
@ -719,9 +686,17 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
|
|||||||
|
|
||||||
io_mfence();
|
io_mfence();
|
||||||
// 判断是否为内核态调用fork
|
// 判断是否为内核态调用fork
|
||||||
if (current_pcb->flags & PF_KTHREAD && stack_start != 0)
|
if ((current_pcb->flags & PF_KTHREAD) && stack_start != 0)
|
||||||
tsk->flags |= PF_KFORK;
|
tsk->flags |= PF_KFORK;
|
||||||
|
|
||||||
|
if (tsk->flags & PF_KTHREAD)
|
||||||
|
{
|
||||||
|
// 对于内核线程,设置其worker私有信息
|
||||||
|
retval = kthread_set_worker_private(tsk);
|
||||||
|
if (IS_ERR_VALUE(retval))
|
||||||
|
goto copy_flags_failed;
|
||||||
|
tsk->virtual_runtime = 0;
|
||||||
|
}
|
||||||
tsk->priority = 2;
|
tsk->priority = 2;
|
||||||
tsk->preempt_count = 0;
|
tsk->preempt_count = 0;
|
||||||
|
|
||||||
@ -815,10 +790,17 @@ struct process_control_block *process_get_pcb(long pid)
|
|||||||
*
|
*
|
||||||
* @param pcb 进程的pcb
|
* @param pcb 进程的pcb
|
||||||
*/
|
*/
|
||||||
void process_wakeup(struct process_control_block *pcb)
|
int process_wakeup(struct process_control_block *pcb)
|
||||||
{
|
{
|
||||||
|
BUG_ON(pcb == NULL);
|
||||||
|
if (pcb == current_pcb || pcb == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
// 如果pcb正在调度队列中,则不重复加入调度队列
|
||||||
|
if (pcb->state == PROC_RUNNING)
|
||||||
|
return 0;
|
||||||
pcb->state = PROC_RUNNING;
|
pcb->state = PROC_RUNNING;
|
||||||
sched_enqueue(pcb);
|
sched_enqueue(pcb);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -826,10 +808,13 @@ void process_wakeup(struct process_control_block *pcb)
|
|||||||
*
|
*
|
||||||
* @param pcb 进程的pcb
|
* @param pcb 进程的pcb
|
||||||
*/
|
*/
|
||||||
void process_wakeup_immediately(struct process_control_block *pcb)
|
int process_wakeup_immediately(struct process_control_block *pcb)
|
||||||
{
|
{
|
||||||
pcb->state = PROC_RUNNING;
|
if (pcb->state == PROC_RUNNING)
|
||||||
sched_enqueue(pcb);
|
return 0;
|
||||||
|
int retval = process_wakeup(pcb);
|
||||||
|
if (retval != 0)
|
||||||
|
return retval;
|
||||||
// 将当前进程标志为需要调度,缩短新进程被wakeup的时间
|
// 将当前进程标志为需要调度,缩短新进程被wakeup的时间
|
||||||
current_pcb->flags |= PF_NEED_SCHED;
|
current_pcb->flags |= PF_NEED_SCHED;
|
||||||
}
|
}
|
||||||
@ -1159,6 +1144,17 @@ void process_exit_thread(struct process_control_block *pcb)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 释放pcb
|
||||||
|
*
|
||||||
|
* @param pcb
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int process_release_pcb(struct process_control_block *pcb)
|
||||||
|
{
|
||||||
|
kfree(pcb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @brief 申请可用的文件句柄
|
* @brief 申请可用的文件句柄
|
||||||
*
|
*
|
||||||
|
@ -52,7 +52,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// 设置初始进程的tss
|
// 设置初始进程的tss
|
||||||
#define INITIAL_TSS \
|
#define INITIAL_TSS \
|
||||||
{ \
|
{ \
|
||||||
@ -73,13 +72,11 @@
|
|||||||
.io_map_base_addr = 0 \
|
.io_map_base_addr = 0 \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define GET_CURRENT_PCB \
|
#define GET_CURRENT_PCB \
|
||||||
"movq %rsp, %rbx \n\t" \
|
"movq %rsp, %rbx \n\t" \
|
||||||
"andq $-32768, %rbx\n\t"
|
"andq $-32768, %rbx\n\t"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 切换进程上下文
|
* @brief 切换进程上下文
|
||||||
* 先把rbp和rax保存到栈中,然后将rsp和rip保存到prev的thread结构体中
|
* 先把rbp和rax保存到栈中,然后将rsp和rip保存到prev的thread结构体中
|
||||||
* 然后调用__switch_to切换栈,配置其他信息,最后恢复下一个进程的rax rbp。
|
* 然后调用__switch_to切换栈,配置其他信息,最后恢复下一个进程的rax rbp。
|
||||||
@ -134,14 +131,14 @@ struct process_control_block *process_get_pcb(long pid);
|
|||||||
*
|
*
|
||||||
* @param pcb 进程的pcb
|
* @param pcb 进程的pcb
|
||||||
*/
|
*/
|
||||||
void process_wakeup(struct process_control_block *pcb);
|
int process_wakeup(struct process_control_block *pcb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 将进程加入到调度器的就绪队列中,并标志当前进程需要被调度
|
* @brief 将进程加入到调度器的就绪队列中,并标志当前进程需要被调度
|
||||||
*
|
*
|
||||||
* @param pcb 进程的pcb
|
* @param pcb 进程的pcb
|
||||||
*/
|
*/
|
||||||
void process_wakeup_immediately(struct process_control_block *pcb);
|
int process_wakeup_immediately(struct process_control_block *pcb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 使当前进程去执行新的代码
|
* @brief 使当前进程去执行新的代码
|
||||||
@ -185,7 +182,17 @@ void process_exit_notify();
|
|||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigned long flags);
|
pid_t kernel_thread(int (*fn)(void*), void* arg, unsigned long flags);
|
||||||
|
|
||||||
|
int process_fd_alloc(struct vfs_file_t *file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 释放pcb
|
||||||
|
*
|
||||||
|
* @param pcb
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int process_release_pcb(struct process_control_block *pcb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 切换页表
|
* @brief 切换页表
|
||||||
@ -213,4 +220,3 @@ extern struct mm_struct initial_mm;
|
|||||||
extern struct thread_struct initial_thread;
|
extern struct thread_struct initial_thread;
|
||||||
extern union proc_union initial_proc_union;
|
extern union proc_union initial_proc_union;
|
||||||
extern struct process_control_block *initial_proc[MAX_CPU_NUM];
|
extern struct process_control_block *initial_proc[MAX_CPU_NUM];
|
||||||
int process_fd_alloc(struct vfs_file_t *file);
|
|
||||||
|
@ -170,7 +170,7 @@ uint64_t sys_read(struct pt_regs *regs)
|
|||||||
int64_t count = (int64_t)regs->r10;
|
int64_t count = (int64_t)regs->r10;
|
||||||
|
|
||||||
// 校验buf的空间范围
|
// 校验buf的空间范围
|
||||||
if(SYSCALL_FROM_USER(regs) && (!verify_area(buf, count)))
|
if(SYSCALL_FROM_USER(regs) && (!verify_area((uint64_t)buf, count)))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
// kdebug("sys read: fd=%d", fd_num);
|
// kdebug("sys read: fd=%d", fd_num);
|
||||||
@ -210,7 +210,7 @@ uint64_t sys_write(struct pt_regs *regs)
|
|||||||
int64_t count = (int64_t)regs->r10;
|
int64_t count = (int64_t)regs->r10;
|
||||||
|
|
||||||
// 校验buf的空间范围
|
// 校验buf的空间范围
|
||||||
if(SYSCALL_FROM_USER(regs) && (!verify_area(buf, count)))
|
if(SYSCALL_FROM_USER(regs) && (!verify_area((uint64_t)buf, count)))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
kdebug("sys write: fd=%d", fd_num);
|
kdebug("sys write: fd=%d", fd_num);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user