Skip to content

Commit bacd691

Browse files
fslongjinhoumkh
andauthored
软中断&定时器重构 (#223)
* 软中断&定时器重构 Co-authored-by: houmkh<[email protected]> * 修改timer的clock() * 删除debug信息 --------- Co-authored-by: houmkh <[email protected]>
1 parent 6d345b7 commit bacd691

File tree

33 files changed

+879
-655
lines changed

33 files changed

+879
-655
lines changed

kernel/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ crate-type = ["staticlib"]
1010

1111
# 运行时依赖项
1212
[dependencies]
13+
x86 = "0.52.0"
1314
x86_64 = "0.14.10"
1415
bitflags = "1.3.2"
1516
virtio-drivers = "0.3.0"

kernel/src/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export ASFLAGS := --64
1717
LD_LIST := head.o
1818

1919

20-
kernel_subdirs := common driver process debug time arch exception mm smp sched syscall ktest libs ipc io
20+
kernel_subdirs := common driver process debug arch exception mm smp sched syscall ktest libs ipc io
2121

2222

2323

kernel/src/arch/x86_64/cpu.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
use core::arch::asm;
22

3+
use super::asm::current::current_pcb;
4+
35
/// @brief 获取当前cpu的apic id
46
#[inline]
5-
pub fn current_cpu_id() -> u8 {
6-
let cpuid_res: u32;
7-
unsafe {
8-
asm!(
9-
"mov eax, 1",
10-
"cpuid",
11-
"mov r15, rbx",
12-
lateout("r15") cpuid_res
13-
);
14-
}
15-
return ((cpuid_res >> 24) & 0xff) as u8;
7+
pub fn current_cpu_id() -> u32 {
8+
// TODO: apic重构后,使用apic id来设置这里
9+
current_pcb().cpu_id as u32
1610
}
1711

1812
/// @brief 通过pause指令,让cpu休息一会儿。降低空转功耗

kernel/src/common/time.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,18 @@ struct tm
2121
const char *__tm_zone; /* Timezone abbreviation. */
2222
};
2323

24-
2524
struct timespec
2625
{
27-
int64_t tv_sec; // 秒
28-
int64_t tv_nsec; // 纳秒
26+
int64_t tv_sec; // 秒
27+
int64_t tv_nsec; // 纳秒
2928
};
3029

3130
/**
3231
* @brief 休眠指定时间
33-
*
32+
*
3433
* @param rqtp 指定休眠的时间
3534
* @param rmtp 返回的剩余休眠时间
36-
* @return int
35+
* @return int
3736
*/
3837
extern int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
3938

@@ -47,7 +46,7 @@ extern int usleep(useconds_t usec);
4746

4847
/**
4948
* @brief 获取当前的CPU时间
50-
*
49+
*
5150
* @return uint64_t timer_jiffies
5251
*/
53-
extern uint64_t clock();
52+
extern uint64_t rs_clock();

kernel/src/driver/interrupt/apic/apic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ void do_IRQ(struct pt_regs *rsp, ul number)
456456

457457
// kdebug("before softirq");
458458
// 进入软中断处理程序
459-
do_softirq();
459+
rs_do_softirq();
460460

461461
// kdebug("after softirq");
462462
// 检测当前进程是否持有自旋锁,若持有自旋锁,则不进行抢占式的进程调度

kernel/src/driver/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ pub mod pci;
44
pub mod timers;
55
pub mod tty;
66
pub mod uart;
7+
pub mod video;
78
pub mod virtio;

kernel/src/driver/timers/HPET/HPET.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
6767
switch (param)
6868
{
6969
case 0: // 定时器0中断
70-
timer_jiffies += HPET0_INTERVAL;
70+
rs_update_timer_jiffies(HPET0_INTERVAL);
7171

7272
/*
7373
// 将HEPT中断消息转发到ap:1处理器
@@ -76,18 +76,18 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
7676
*/
7777

7878
// 若当前时间比定时任务的时间间隔大,则进入中断下半部
79-
if (container_of(list_next(&timer_func_head.list), struct timer_func_list_t, list)->expire_jiffies <= timer_jiffies)
80-
raise_softirq(TIMER_SIRQ);
79+
if (rs_timer_get_first_expire() <= rs_clock())
80+
rs_raise_softirq(TIMER_SIRQ);
8181

8282
// 当时间到了,或进程发生切换时,刷新帧缓冲区
83-
if (timer_jiffies >= video_refresh_expire_jiffies || (video_last_refresh_pid != current_pcb->pid))
83+
if (rs_clock() >= video_refresh_expire_jiffies || (video_last_refresh_pid != current_pcb->pid))
8484
{
85-
raise_softirq(VIDEO_REFRESH_SIRQ);
85+
rs_raise_softirq(VIDEO_REFRESH_SIRQ);
8686
// 超过130ms仍未刷新完成,则重新发起刷新(防止由于进程异常退出导致的屏幕无法刷新)
87-
if (unlikely(timer_jiffies >= (video_refresh_expire_jiffies + (1 << 17))))
87+
if (unlikely(rs_clock() >= (video_refresh_expire_jiffies + (1 << 17))))
8888
{
89-
video_refresh_expire_jiffies = timer_jiffies + (1 << 20);
90-
clear_softirq_pending(VIDEO_REFRESH_SIRQ);
89+
video_refresh_expire_jiffies = rs_clock() + (1 << 20);
90+
rs_clear_softirq_pending(VIDEO_REFRESH_SIRQ);
9191
}
9292
}
9393
break;

kernel/src/driver/usb/xhci/xhci.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ static int xhci_hc_stop(int id)
245245
while ((xhci_read_op_reg32(id, XHCI_OPS_USBSTS) & (1 << 0)) == 0)
246246
{
247247
io_mfence();
248-
usleep(1000);
248+
rs_usleep(1000);
249249
if (--timeout == 0)
250250
return -ETIMEDOUT;
251251
}
@@ -285,7 +285,7 @@ static int xhci_hc_reset(int id)
285285
while (xhci_read_op_reg32(id, XHCI_OPS_USBCMD) & (1 << 1))
286286
{
287287
io_mfence();
288-
usleep(1000);
288+
rs_usleep(1000);
289289
if (--timeout == 0)
290290
return -ETIMEDOUT;
291291
}
@@ -319,7 +319,7 @@ static int xhci_hc_stop_legacy(int id)
319319
XHCI_XECP_LEGACY_OS_OWNED)
320320
{
321321
io_mfence();
322-
usleep(1000);
322+
rs_usleep(1000);
323323
if (--timeout == 0)
324324
{
325325
kerror("The BIOS doesn't stop legacy support.");
@@ -352,7 +352,7 @@ static int xhci_hc_start_sched(int id)
352352
io_mfence();
353353
xhci_write_op_reg32(id, XHCI_OPS_USBCMD, (1 << 0) | (1 << 2) | (1 << 3));
354354
io_mfence();
355-
usleep(100 * 1000);
355+
rs_usleep(100 * 1000);
356356
}
357357

358358
/**
@@ -793,7 +793,7 @@ static int xhci_reset_port(const int id, const int port)
793793
io_mfence();
794794
xhci_write_cap_reg32(id, port_status_offset + XHCI_PORT_PORTSC, (1 << 9));
795795
io_mfence();
796-
usleep(2000);
796+
rs_usleep(2000);
797797
// 检测端口是否被启用, 若未启用,则报错
798798
if ((xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC) & (1 << 9)) == 0)
799799
{
@@ -833,14 +833,14 @@ static int xhci_reset_port(const int id, const int port)
833833
break;
834834
#endif
835835
--timeout;
836-
usleep(500);
836+
rs_usleep(500);
837837
}
838838
// kdebug("timeout= %d", timeout);
839839

840840
if (timeout > 0)
841841
{
842842
// 等待恢复
843-
usleep(USB_TIME_RST_REC * 100);
843+
rs_usleep(USB_TIME_RST_REC * 100);
844844
uint32_t val = xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC);
845845
io_mfence();
846846

@@ -1219,7 +1219,7 @@ static int xhci_wait_for_interrupt(const int id, uint64_t status_vaddr)
12191219
}
12201220
}
12211221
--timer;
1222-
usleep(1000);
1222+
rs_usleep(1000);
12231223
}
12241224

12251225
kerror(" USB xHCI Interrupt wait timed out.");
@@ -2001,7 +2001,7 @@ static int xhci_send_command(int id, struct xhci_TRB_t *trb, const bool do_ring)
20012001
// We use bit 31 of the command dword since it is reserved
20022002
while (timer && ((__read4b(origin_trb_vaddr + 8) & XHCI_IRQ_DONE) == 0))
20032003
{
2004-
usleep(1000);
2004+
rs_usleep(1000);
20052005
--timer;
20062006
}
20072007
uint32_t x = xhci_read_cap_reg32(id, xhci_hc[id].rts_offset + 0x20);

kernel/src/driver/video/mod.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use core::{ptr::null_mut, sync::atomic::{AtomicBool, Ordering}};
2+
3+
use alloc::sync::Arc;
4+
5+
use crate::{
6+
exception::softirq::{SoftirqNumber, SoftirqVec, softirq_vectors},
7+
include::bindings::bindings::video_refresh_framebuffer,
8+
};
9+
10+
#[derive(Debug)]
11+
pub struct VideoRefreshFramebuffer{
12+
running: AtomicBool
13+
}
14+
15+
impl SoftirqVec for VideoRefreshFramebuffer {
16+
fn run(&self) {
17+
if self.set_run() == false{
18+
return;
19+
}
20+
21+
unsafe {
22+
video_refresh_framebuffer(null_mut());
23+
}
24+
25+
self.clear_run();
26+
}
27+
}
28+
impl VideoRefreshFramebuffer {
29+
pub fn new() -> VideoRefreshFramebuffer {
30+
VideoRefreshFramebuffer {
31+
running: AtomicBool::new(false)
32+
}
33+
}
34+
35+
fn set_run(&self) -> bool {
36+
let x = self
37+
.running
38+
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed);
39+
if x.is_ok() {
40+
return true;
41+
} else {
42+
return false;
43+
}
44+
}
45+
46+
fn clear_run(&self) {
47+
self.running.store(false, Ordering::Release);
48+
}
49+
}
50+
51+
pub fn register_softirq_video() {
52+
// kdebug!("register_softirq_video");
53+
let handler = Arc::new(VideoRefreshFramebuffer::new());
54+
softirq_vectors()
55+
.register_softirq(SoftirqNumber::VideoRefresh, handler)
56+
.expect("register_softirq_video run failed");
57+
}
58+
// ======= 以下为给C提供的接口,video重构完后请删除 =======
59+
#[no_mangle]
60+
pub extern "C" fn rs_register_softirq_video() {
61+
register_softirq_video();
62+
}

kernel/src/driver/video/video.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <sched/sched.h>
1414
#include <time/timer.h>
1515

16+
extern void rs_register_softirq_video();
17+
1618
uint64_t video_refresh_expire_jiffies = 0;
1719
uint64_t video_last_refresh_pid = -1;
1820

@@ -57,7 +59,7 @@ int video_refresh_daemon(void *unused)
5759

5860
for (;;)
5961
{
60-
if (clock() >= video_refresh_expire_jiffies)
62+
if (rs_clock() >= video_refresh_expire_jiffies)
6163
{
6264

6365
if (likely(video_refresh_target != NULL))
@@ -68,7 +70,7 @@ int video_refresh_daemon(void *unused)
6870
spin_unlock(&daemon_refresh_lock);
6971
video_daemon_pcb->virtual_runtime = 0xfffff0000000; // 临时解决由于显示刷新进程的虚拟运行时间过大/过小,导致其不运行,或者一直运行的问题。将来应使用实时调度解决它
7072
}
71-
video_refresh_expire_jiffies = cal_next_n_ms_jiffies(REFRESH_INTERVAL << 1);
73+
video_refresh_expire_jiffies = rs_timer_next_n_ms_jiffies(REFRESH_INTERVAL << 1);
7274
}
7375
video_daemon_pcb->state &= ~PROC_RUNNING;
7476
video_daemon_pcb->flags |= PF_NEED_SCHED;
@@ -85,7 +87,7 @@ void video_refresh_framebuffer(void *data)
8587
{
8688
if (unlikely(video_daemon_pcb == NULL))
8789
return;
88-
if (clock() >= video_refresh_expire_jiffies)
90+
if (rs_clock() >= video_refresh_expire_jiffies)
8991
{
9092
video_daemon_pcb->virtual_runtime = 0;
9193
process_wakeup(video_daemon_pcb);
@@ -105,18 +107,18 @@ int video_reinitialize(bool level) // 这个函数会在main.c调用, 保证 vid
105107
init_frame_buffer();
106108
else
107109
{
108-
unregister_softirq(VIDEO_REFRESH_SIRQ);
110+
rs_unregister_softirq(VIDEO_REFRESH_SIRQ);
109111
// 计算开始时间
110-
video_refresh_expire_jiffies = cal_next_n_ms_jiffies(10 * REFRESH_INTERVAL);
112+
video_refresh_expire_jiffies = rs_timer_next_n_ms_jiffies(10 * REFRESH_INTERVAL);
111113

112114
// 创建video守护进程
113115
video_daemon_pcb = kthread_run(&video_refresh_daemon, NULL, "Video refresh daemon");
114116
video_daemon_pcb->virtual_runtime = 0; // 特殊情况, 最高优先级, 以后再改
115117

116118
// 启用屏幕刷新软中断
117-
register_softirq(VIDEO_REFRESH_SIRQ, &video_refresh_framebuffer, NULL);
119+
rs_register_softirq_video();
118120

119-
raise_softirq(VIDEO_REFRESH_SIRQ);
121+
rs_raise_softirq(VIDEO_REFRESH_SIRQ);
120122
}
121123
return 0;
122124
}
@@ -130,20 +132,21 @@ int video_reinitialize(bool level) // 这个函数会在main.c调用, 保证 vid
130132
int video_set_refresh_target(struct scm_buffer_info_t *buf)
131133
{
132134

133-
unregister_softirq(VIDEO_REFRESH_SIRQ);
135+
rs_unregister_softirq(VIDEO_REFRESH_SIRQ);
134136
// todo: 在completion实现后,在这里等待其他刷新任务完成,再进行下一步。
135137

136138
// int counter = 100;
137139

138140
// while ((get_softirq_pending() & (1 << VIDEO_REFRESH_SIRQ)) && counter > 0)
139141
// {
140142
// --counter;
141-
// usleep(1000);
143+
// rs_usleep(1000);
142144
// }
143145
// kdebug("buf = %#018lx", buf);
144146
video_refresh_target = buf;
145-
register_softirq(VIDEO_REFRESH_SIRQ, &video_refresh_framebuffer, NULL);
146-
raise_softirq(VIDEO_REFRESH_SIRQ);
147+
rs_register_softirq_video();
148+
kdebug("register softirq video done");
149+
// rs_raise_softirq(VIDEO_REFRESH_SIRQ);
147150
}
148151

149152
/**

0 commit comments

Comments
 (0)