new: kthread机制

This commit is contained in:
fslongjin 2022-09-30 15:30:50 +08:00
parent edef02286e
commit 02a6b3a303
21 changed files with 802 additions and 326 deletions

134
kernel/arch/x86_64/asm.h Normal file
View 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在edx32bits在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;
}

View File

@ -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;
}

View File

@ -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在edx32bits在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
View 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
View 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
View File

@ -0,0 +1,3 @@
#pragma once
#define NUMA_NO_NODE (-1)

View File

@ -7,7 +7,7 @@
/** /**
* @brief condition为true时bug * @brief condition为true时bug
* *
*/ */
#define BUG_ON(condition) ({ \ #define BUG_ON(condition) ({ \
int __ret_bug_on = !!(condition); \ int __ret_bug_on = !!(condition); \
@ -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)) \

View File

@ -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);

View File

@ -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);
} }

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -248,6 +248,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);
} }

View File

@ -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
View 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_NORMALcpu上运行
*
* 线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;
}

View File

@ -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字节对齐

View File

@ -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>
@ -278,7 +280,7 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys; uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
struct vm_area_struct *vma = NULL; struct vm_area_struct *vma = NULL;
int ret = mm_create_vma(current_pcb->mm, virt_base, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma); int ret = mm_create_vma(current_pcb->mm, virt_base, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma);
// 防止内存泄露 // 防止内存泄露
if (ret == -EEXIST) if (ret == -EEXIST)
free_pages(Phy_to_2M_Page(pa), 1); free_pages(Phy_to_2M_Page(pa), 1);
@ -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
* *

View File

@ -52,7 +52,6 @@
* *
*/ */
// 设置初始进程的tss // 设置初始进程的tss
#define INITIAL_TSS \ #define INITIAL_TSS \
{ \ { \
@ -73,17 +72,15 @@
.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
*/ */
#define switch_proc(prev, next) \ #define switch_proc(prev, next) \
do \ do \
@ -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);

View 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);