mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
🆕 usleep()、nanosleep()
This commit is contained in:
parent
4208c56074
commit
676260c537
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/miniLibc/sys/types.h>
|
||||
#include <common/sys/types.h>
|
||||
struct dirent
|
||||
{
|
||||
ino_t d_ino; // 文件序列号
|
||||
|
@ -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
38
kernel/common/time.h
Normal 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);
|
@ -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))
|
||||
|
@ -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 拷贝当前进程的标志位
|
||||
*
|
||||
|
@ -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 使当前进程去执行新的代码
|
||||
*
|
||||
|
@ -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};
|
||||
|
@ -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的系统调用
|
@ -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
62
kernel/time/sleep.c
Normal 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
16
kernel/time/sleep.h
Normal 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);
|
||||
|
@ -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 将定时功能添加到列表中
|
||||
*
|
||||
|
@ -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 将定时功能添加到列表中
|
||||
*
|
||||
|
@ -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)
|
||||
|
@ -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
32
user/libs/libc/time.c
Normal 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
38
user/libs/libc/time.h
Normal 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);
|
@ -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);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#define SYS_WAIT4 15 // 等待进程退出
|
||||
#define SYS_EXIT 16 // 进程退出
|
||||
#define SYS_MKDIR 17 // 创建文件夹
|
||||
#define SYS_NANOSLEEP 18 // 纳秒级休眠
|
||||
|
||||
/**
|
||||
* @brief 用户态系统调用函数
|
||||
|
Loading…
x
Reference in New Issue
Block a user