🆕 usleep()、nanosleep()

This commit is contained in:
fslongjin
2022-07-12 12:01:51 +08:00
parent 4208c56074
commit 676260c537
21 changed files with 277 additions and 15 deletions

View File

@ -1,6 +1,6 @@
#pragma once
#include <common/miniLibc/sys/types.h>
#include <common/sys/types.h>
struct dirent
{
ino_t d_ino; // 文件序列号

View File

@ -8,7 +8,7 @@
//引入对bool类型的支持
#include <stdbool.h>
#include <stdint.h>
#include <common/miniLibc/stddef.h>
#include <common/stddef.h>
#include <arch/arch.h>
#define sti() __asm__ __volatile__("sti\n\t" :: \

38
kernel/common/time.h Normal file
View File

@ -0,0 +1,38 @@
#pragma once
#include "stddef.h"
// 操作系统定义时间以ns为单位
#define CLOCKS_PER_SEC 1000000
struct tm
{
int tm_sec; /* Seconds. [0-60] (1 leap second) */
int tm_min; /* Minutes. [0-59] */
int tm_hour; /* Hours. [0-23] */
int tm_mday; /* Day. [1-31] */
int tm_mon; /* Month. [0-11] */
int tm_year; /* Year - 1900. */
int tm_wday; /* Day of week. [0-6] */
int tm_yday; /* Days in year.[0-365] */
int tm_isdst; /* DST. [-1/0/1]*/
long int __tm_gmtoff; /* Seconds east of UTC. */
const char *__tm_zone; /* Timezone abbreviation. */
};
struct timespec
{
long int tv_sec; // 秒
long int tv_nsec; // 纳秒
};
/**
* @brief 休眠指定时间
*
* @param rqtp 指定休眠的时间
* @param rmtp 返回的剩余休眠时间
* @return int
*/
extern int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);

View File

@ -58,7 +58,7 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
switch (param)
{
case 0: // 定时器0中断
++timer_jiffies;
timer_jiffies += HPET0_INTERVAL;
/*
// 将HEPT中断消息转发到ap:1处理器
@ -68,7 +68,7 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
// 若当前时间比定时任务的时间间隔大,则进入中断下半部
if (container_of(list_next(&timer_func_head.list), struct timer_func_list_t, list)->expire_jiffies <= timer_jiffies)
raise_softirq((1 << TIMER_SIRQ));
raise_softirq(TIMER_SIRQ);
// 当时间到了,或进程发生切换时,刷新帧缓冲区
if (timer_jiffies >= video_refresh_expire_jiffies || (video_last_refresh_pid != current_pcb->pid))

View File

@ -702,13 +702,23 @@ struct process_control_block *process_get_pcb(long pid)
* @param pcb 进程的pcb
*/
void process_wakeup(struct process_control_block *pcb)
{
pcb->state = PROC_RUNNING;
sched_cfs_enqueue(pcb);
}
/**
* @brief 将进程加入到调度器的就绪队列中,并标志当前进程需要被调度
*
* @param pcb 进程的pcb
*/
void process_wakeup_immediately(struct process_control_block *pcb)
{
pcb->state = PROC_RUNNING;
sched_cfs_enqueue(pcb);
// 将当前进程标志为需要调度缩短新进程被wakeup的时间
current_pcb->flags |= PF_NEED_SCHED;
}
/**
* @brief 拷贝当前进程的标志位
*

View File

@ -286,6 +286,13 @@ struct process_control_block *process_get_pcb(long pid);
*/
void process_wakeup(struct process_control_block *pcb);
/**
* @brief 将进程加入到调度器的就绪队列中,并标志当前进程需要被调度
*
* @param pcb 进程的pcb
*/
void process_wakeup_immediately(struct process_control_block *pcb);
/**
* @brief 使当前进程去执行新的代码
*

View File

@ -10,11 +10,14 @@
#include <filesystem/VFS/VFS.h>
#include <driver/keyboard/ps2_keyboard.h>
#include <process/process.h>
#include <time/sleep.h>
// 导出系统调用入口函数定义在entry.S中
extern void system_call(void);
extern void syscall_int(void);
/**
* @brief 导出系统调用处理函数的符号
*
@ -723,6 +726,15 @@ uint64_t sys_exit(struct pt_regs *regs)
return process_do_exit(regs->r8);
}
uint64_t sys_nanosleep(struct pt_regs * regs)
{
const struct timespec * rqtp = (const struct timespec*)regs->r8;
struct timespec * rmtp = (struct timespec*)regs->r9;
return nanosleep(rqtp, rmtp);
}
ul sys_ahci_end_req(struct pt_regs *regs)
{
ahci_end_request();
@ -757,5 +769,6 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] =
[15] = sys_wait4,
[16] = sys_exit,
[17] = sys_mkdir,
[18 ... 254] = system_call_not_exists,
[18] = sys_nanosleep,
[19 ... 254] = system_call_not_exists,
[255] = sys_ahci_end_req};

View File

@ -28,5 +28,6 @@
#define SYS_WAIT4 15 // 等待进程退出
#define SYS_EXIT 16 // 进程退出
#define SYS_MKDIR 17 // 创建文件夹
#define SYS_NANOSLEEP 18 // 纳秒级休眠
#define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用

View File

@ -1,10 +1,13 @@
all: timer.o
all: timer.o sleep.o
CFLAGS += -I .
timer.o: timer.c
gcc $(CFLAGS) -c timer.c -o timer.o
sleep.o: sleep.c
gcc $(CFLAGS) -c sleep.c -o sleep.o
clean:
echo "Done."

62
kernel/time/sleep.c Normal file
View File

@ -0,0 +1,62 @@
#include "sleep.h"
#include <common/errno.h>
#include <time/timer.h>
#include <process/process.h>
#include <sched/sched.h>
#include <mm/slab.h>
/**
* @brief nanosleep定时事件到期后唤醒指定的进程
*
* @param pcb 待唤醒的进程的pcb
*/
void nanosleep_handler(void *pcb)
{
process_wakeup((struct process_control_block *)pcb);
}
/**
* @brief 休眠指定时间
*
* @param rqtp 指定休眠的时间
* @param rmtp 返回的剩余休眠时间
* @return int
*/
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
{
int64_t total_ns = rqtp->tv_nsec;
// kdebug("totalns = %ld", total_ns);
if (total_ns < 0 || total_ns >= 1000000000)
return -EINVAL;
// todo: 对于小于500us的时间使用spin/rdtsc来进行定时
if (total_ns < 50000)
return 0;
if (total_ns < 500000)
total_ns = 500000;
// 增加定时任务
struct timer_func_list_t *sleep_task = (struct timer_func_list_t *)kmalloc(sizeof(struct timer_func_list_t), 0);
memset(sleep_task, 0, sizeof(struct timer_func_list_t));
timer_func_init_us(sleep_task, &nanosleep_handler, (void *)current_pcb, total_ns / 1000);
timer_func_add(sleep_task);
current_pcb->state = PROC_INTERRUPTIBLE;
current_pcb->flags |= PF_NEED_SCHED;
sched_cfs();
// todo: 增加信号唤醒的功能后设置rmtp
if (rmtp != NULL)
{
rmtp->tv_nsec = 0;
rmtp->tv_sec = 0;
}
return 0;
}

16
kernel/time/sleep.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <common/glib.h>
#include <process/ptrace.h>
#include <common/time.h>
/**
* @brief 休眠指定时间
*
* @param rqtp 指定休眠的时间
* @param rmtp 返回的剩余休眠时间
* @return int
*/
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);

View File

@ -30,7 +30,7 @@ void timer_init()
void do_timer_softirq(void *data)
{
// todo: 修改这里以及softirq的部分使得timer具有并行性
struct timer_func_list_t *tmp = container_of(list_next(&timer_func_head.list), struct timer_func_list_t, list);
int cycle_count = 0;
while ((!list_empty(&timer_func_head.list)) && (tmp->expire_jiffies <= timer_jiffies))
@ -60,11 +60,27 @@ void timer_func_init(struct timer_func_list_t *timer_func, void (*func)(void *da
{
list_init(&timer_func->list);
timer_func->func = func;
timer_func->data = data,
// timer_func->expire_jiffies = timer_jiffies + expire_ms / 5 + expire_ms % HPET0_INTERVAL ? 1 : 0; // 设置过期的时间片
timer_func->data = data;
timer_func->expire_jiffies = cal_next_n_ms_jiffies(expire_ms); // 设置过期的时间片
}
/**
* @brief 初始化定时功能
*
* @param timer_func 队列结构体
* @param func 定时功能处理函数
* @param data 传输的数据
* @param expire_us 定时时长(单位us)
*/
void timer_func_init_us(struct timer_func_list_t *timer_func, void (*func)(void *data), void *data, uint64_t expire_us)
{
list_init(&timer_func->list);
timer_func->func = func;
timer_func->data = data;
timer_func->expire_jiffies = cal_next_n_us_jiffies(expire_us); // 设置过期的时间片
// kdebug("timer_func->expire_jiffies=%ld",cal_next_n_us_jiffies(expire_us));
}
/**
* @brief 将定时功能添加到列表中
*

View File

@ -7,9 +7,9 @@
uint64_t volatile timer_jiffies = 0; // 系统时钟计数
// 计算接下来n毫秒对应的系统时间片
#define cal_next_n_ms_jiffies(expire_ms) (timer_jiffies + 1000*expire_ms / HPET0_INTERVAL + ((1000*expire_ms % HPET0_INTERVAL) ? 1 : 0))
#define cal_next_n_ms_jiffies(expire_ms) (timer_jiffies + 1000*expire_ms)
// 计算接下来n微秒对应的系统时间片
#define cal_next_n_us_jiffies(expire_us) (timer_jiffies + expire_us / HPET0_INTERVAL + ((expire_us % HPET0_INTERVAL) ? 1 : 0))
#define cal_next_n_us_jiffies(expire_us) (timer_jiffies + expire_us)
void timer_init();
@ -38,6 +38,16 @@ extern struct timer_func_list_t timer_func_head;
*/
void timer_func_init(struct timer_func_list_t *timer_func, void (*func)(void *data), void *data, uint64_t expire_ms);
/**
* @brief 初始化定时功能
*
* @param timer_func 队列结构体
* @param func 定时功能处理函数
* @param data 传输的数据
* @param expire_us 定时时长(单位us)
*/
void timer_func_init_us(struct timer_func_list_t *timer_func, void (*func)(void *data), void *data, uint64_t expire_us);
/**
* @brief 将定时功能添加到列表中
*