🆕 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
*

View File

@ -1,5 +1,7 @@
#include <libc/stdio.h>
#include<libc/stdlib.h>
#include <libc/stdlib.h>
#include <libc/unistd.h>
void print_ascii_logo()
{
printf(" ____ ___ ____ \n");
@ -24,6 +26,8 @@ int main()
{
// printf("Hello World!\n");
print_ascii_logo();
usleep(500000);
usleep(500000);
print_copyright();
// exit(0);
// while (1)

View File

@ -9,7 +9,7 @@ libc_sub_dirs += sysdeps/x86_64
endif
libc: unistd.o fcntl.o malloc.o errno.o printf.o stdlib.o ctype.o string.o dirent.o
libc: unistd.o fcntl.o malloc.o errno.o printf.o stdlib.o ctype.o string.o dirent.o time.o
@list='$(libc_sub_dirs)'; for subdir in $$list; do \
echo "make all in $$subdir";\
cd $$subdir;\
@ -42,4 +42,7 @@ string.o: string.c
gcc $(CFLAGS) -c string.c -o string.o
dirent.o: dirent.c
gcc $(CFLAGS) -c dirent.c -o dirent.o
gcc $(CFLAGS) -c dirent.c -o dirent.o
time.o: time.c
gcc $(CFLAGS) -c time.c -o time.o

32
user/libs/libc/time.c Normal file
View File

@ -0,0 +1,32 @@
#include "time.h"
#include "errno.h"
#include "unistd.h"
#include <libsystem/syscall.h>
/**
* @brief
*
* @param rqtp
* @param rmtp
* @return int
*/
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
{
return syscall_invoke(SYS_NANOSLEEP, (uint64_t)rqtp, (uint64_t)rmtp, 0, 0, 0, 0, 0, 0);
}
/**
* @brief
*
* @param usec
* @return int
*/
int usleep(useconds_t usec)
{
struct timespec ts = {
tv_sec : (long int)(usec / 1000000),
tv_nsec : (long int)(usec % 1000000) * 1000UL
};
return nanosleep(&ts, NULL);
}

38
user/libs/libc/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
*/
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);

View File

@ -89,3 +89,11 @@ int64_t chdir(char *dest_path);
* @return int
*/
int execv(const char* path, char * const argv[]);
/**
* @brief
*
* @param usec
* @return int
*/
extern int usleep(useconds_t usec);

View File

@ -22,6 +22,7 @@
#define SYS_WAIT4 15 // 等待进程退出
#define SYS_EXIT 16 // 进程退出
#define SYS_MKDIR 17 // 创建文件夹
#define SYS_NANOSLEEP 18 // 纳秒级休眠
/**
* @brief