Browse Source

使用Rust重构CFS调度器 (#131)

* 新建调度器的文件

* 把softirq vector移动到c文件中(原来在.h)

* 将进程切换方式改为“中断返回时切换”

* new:使用rust重构CFS

* 删除已经在smp中废弃的HPET中断转发函数

* 代码格式化

* 删除多余的dunce依赖
login 2 years ago
parent
commit
d4f3de93a2

+ 1 - 0
Makefile

@@ -36,6 +36,7 @@ export CC=$(DragonOS_GCC)/x86_64-elf-gcc
 export LD=ld
 export AS=$(DragonOS_GCC)/x86_64-elf-as
 export NM=$(DragonOS_GCC)/x86_64-elf-nm
+export AR=$(DragonOS_GCC)/x86_64-elf-ar
 export OBJCOPY=$(DragonOS_GCC)/x86_64-elf-objcopy
 
 

+ 1 - 1
kernel/Cargo.toml

@@ -15,5 +15,5 @@ x86_64 = "0.14.10"
 # 构建时依赖项
 [build-dependencies]
 bindgen = "0.61.0"
-cbindgen = "0.24.3"
+
 

+ 1 - 4
kernel/build.rs

@@ -1,7 +1,4 @@
 extern crate bindgen;
-
-extern crate cbindgen;
-
 // use ::std::env;
 
 use std::path::PathBuf;
@@ -21,7 +18,7 @@ fn main() {
         let bindings = bindgen::Builder::default()
             .clang_arg("-I./src")
             .clang_arg("-I./src/include")
-            .clang_arg("-I./src/arch/x86_64/include")   // todo: 当引入多种架构之后,需要修改这里,对于不同的架构编译时,include不同的路径
+            .clang_arg("-I./src/arch/x86_64/include") // todo: 当引入多种架构之后,需要修改这里,对于不同的架构编译时,include不同的路径
             // The input header we would like to generate
             // bindings for.
             .header("src/include/bindings/wrapper.h")

+ 0 - 626
kernel/cbindgen.toml

@@ -1,626 +0,0 @@
-# The language to output bindings in
-#
-# possible values: "C", "C++", "Cython"
-#
-# default: "C++"
-language = "C"
-
-
-
-
-# Options for wrapping the contents of the header:
-
-# 在文件头部添加的注释信息
-# An optional string of text to output at the beginning of the generated file
-# default: doesn't emit anything
-header = "/* DragonOS's C FFI for rust. This file is licensed under GPLv2 */"
-
-# 在文件尾部添加的信息
-# An optional string of text to output at the end of the generated file
-# default: doesn't emit anything
-# trailer = "/* Text to put at the end of the generated file */"
-
-# An optional name to use as an include guard
-# default: doesn't emit an include guard
-# include_guard = "mozilla_wr_bindings_h"
-
-# 是否生成一个 `#pragma once`
-pragma_once = true
-
-# An optional string of text to output between major sections of the generated
-# file as a warning against manual editing
-#
-# default: doesn't emit anything
-autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
-
-# Whether to include a comment with the version of cbindgen used to generate the file
-# default: false
-# include_version = true
-
-# An optional namespace to output around the generated bindings
-# default: doesn't emit a namespace
-namespace = "ffi"
-
-# An optional list of namespaces to output around the generated bindings
-# default: []
-# namespaces = ["mozilla", "wr"]
-
-# An optional list of namespaces to declare as using with "using namespace"
-# default: []
-# using_namespaces = ["mozilla", "wr"]
-
-# A list of sys headers to #include (with angle brackets)
-# default: []
-sys_includes = ["stdint.h"]
-
-# 生成的binding文件要include的头文件
-# A list of headers to #include (with quotes)
-# default: []
-includes = []
-
-# Whether cbindgen's default C/C++ standard imports should be suppressed. These
-# imports are included by default because our generated headers tend to require
-# them (e.g. for uint32_t). Currently, the generated imports are:
-#
-# * for C: <stdarg.h>, <stdbool.h>, <stdint.h>, <stdlib.h>, <uchar.h>
-#
-# * for C++: <cstdarg>, <cstdint>, <cstdlib>, <new>, <cassert> (depending on config)
-#
-# default: false
-no_includes = true
-
-# Whether to make a C header C++ compatible.
-# These will wrap generated functions into a `extern "C"` block, e.g.
-#
-# #ifdef __cplusplus
-# extern "C" {
-# #endif // __cplusplus
-#
-# // Generated functions.
-#
-# #ifdef __cplusplus
-# } // extern "C"
-# #endif // __cplusplus
-#
-# If the language is not C this option won't have any effect.
-#
-# default: false
-cpp_compat = false
-
-# A list of lines to add verbatim after the includes block
-#after_includes = "#define VERSION 1"
-
-
-
-# Code Style Options
-
-# The style to use for curly braces
-#
-# possible values: "SameLine", "NextLine"
-#
-# default: "SameLine"
-braces = "NextLine"
-
-# The desired length of a line to use when formatting lines
-# default: 100
-line_length = 120
-
-# The amount of spaces to indent by
-# default: 2
-tab_width = 4
-
-# Include doc comments from Rust as documentation
-documentation = true
-
-# How the generated documentation should be commented.
-#
-# possible values:
-# * "c": /* like this */
-# * "c99": // like this
-# * "c++": /// like this
-# * "doxy": like C, but with leading *'s on each line
-# * "auto": "c++" if that's the language, "doxy" otherwise
-#
-# default: "auto"
-documentation_style = "doxy"
-
-# How much of the documentation for each item is output.
-#
-# possible values:
-# * "short": Only the first line.
-# * "full": The full documentation.
-#
-# default: "full"
-documentation_length = "short"
-
-
-
-
-# Codegen Options
-
-# When generating a C header, the kind of declaration style to use for structs
-# or enums.
-#
-# possible values:
-# * "type": typedef struct { ... } MyType;
-# * "tag": struct MyType { ... };
-# * "both": typedef struct MyType { ... } MyType;
-#
-# default: "both"
-style = "both"
-
-# If this option is true `usize` and `isize` will be converted into `size_t` and `ptrdiff_t`
-# instead of `uintptr_t` and `intptr_t` respectively.
-usize_is_size_t = true
-
-# A list of substitutions for converting cfg's to ifdefs. cfgs which aren't
-# defined here will just be discarded.
-#
-# e.g.
-# `#[cfg(target = "freebsd")] ...`
-# becomes
-# `#if defined(DEFINE_FREEBSD) ... #endif`
-[defines]
-"target_os = freebsd" = "DEFINE_FREEBSD"
-"feature = serde" = "DEFINE_SERDE"
-
-
-
-
-
-[export]
-# A list of additional items to always include in the generated bindings if they're
-# found but otherwise don't appear to be used by the public API.
-#
-# default: []
-include = ["MyOrphanStruct", "MyGreatTypeRename"]
-
-# A list of items to not include in the generated bindings
-# default: []
-exclude = ["Bad"]
-
-# 生成的内容的前缀
-# A prefix to add before the name of every item
-# default: no prefix is added
-# prefix = "CAPI_"
-
-# Types of items that we'll generate. If empty, then all types of item are emitted.
-#
-# possible items: (TODO: explain these in detail)
-# * "constants":
-# * "globals":
-# * "enums":
-# * "structs":
-# * "unions":
-# * "typedefs":
-# * "opaque":
-# * "functions":
-#
-# default: []
-item_types = ["enums", "structs", "opaque", "functions"]
-
-# Whether applying rules in export.rename prevents export.prefix from applying.
-#
-# e.g. given this toml:
-#
-# [export]
-# prefix = "capi_"
-# [export.rename]
-# "MyType" = "my_cool_type"
-#
-# You get the following results:
-#
-# renaming_overrides_prefixing = true:
-# "MyType" => "my_cool_type"
-#
-# renaming_overrides_prefixing = false:
-# "MyType => capi_my_cool_type"
-#
-# default: false
-renaming_overrides_prefixing = true
-
-# Table of name conversions to apply to item names (lhs becomes rhs)
-[export.rename]
-"MyType" = "my_cool_type"
-"my_function" = "BetterFunctionName"
-
-# Table of things to prepend to the body of any struct, union, or enum that has the
-# given name. This can be used to add things like methods which don't change ABI,
-# mark fields private, etc
-[export.pre_body]
-"MyType" = """
-  MyType() = delete;
-private:
-"""
-
-# Table of things to append to the body of any struct, union, or enum that has the
-# given name. This can be used to add things like methods which don't change ABI.
-[export.body]
-"MyType" = """
-  void cppMethod() const;
-"""
-
-# Configuration for name mangling
-[export.mangle]
-# Whether the types should be renamed during mangling, for example
-# c_char -> CChar, etc.
-rename_types = "PascalCase"
-# Whether the underscores from the mangled name should be omitted.
-remove_underscores = false
-
-[layout]
-# A string that should come before the name of any type which has been marked
-# as `#[repr(packed)]`. For instance, "__attribute__((packed))" would be a
-# reasonable value if targeting gcc/clang. A more portable solution would
-# involve emitting the name of a macro which you define in a platform-specific
-# way. e.g. "PACKED"
-#
-# default: `#[repr(packed)]` types will be treated as opaque, since it would
-# be unsafe for C callers to use a incorrectly laid-out union.
-packed = "PACKED"
-
-# A string that should come before the name of any type which has been marked
-# as `#[repr(align(n))]`. This string must be a function-like macro which takes
-# a single argument (the requested alignment, `n`). For instance, a macro
-# `#define`d as `ALIGNED(n)` in `header` which translates to
-# `__attribute__((aligned(n)))` would be a reasonable value if targeting
-# gcc/clang.
-#
-# default: `#[repr(align(n))]` types will be treated as opaque, since it
-# could be unsafe for C callers to use a incorrectly-aligned union.
-aligned_n = "ALIGNED"
-
-
-[fn]
-# 函数开头要加入的内容
-# An optional prefix to put before every function declaration
-# default: no prefix added
-# prefix = "WR_START_FUNC"
-
-# 函数声明的结尾要加入的内容
-# An optional postfix to put after any function declaration
-# default: no postix added
-# postfix = "WR_END_FUNC"
-
-# How to format function arguments
-#
-# possible values:
-# * "horizontal": place all arguments on the same line
-# * "vertical": place each argument on its own line
-# * "auto": only use vertical if horizontal would exceed line_length
-#
-# default: "auto"
-args = "horizontal"
-
-# An optional string that should prefix function declarations which have been
-# marked as `#[must_use]`. For instance, "__attribute__((warn_unused_result))"
-# would be a reasonable value if targeting gcc/clang. A more portable solution
-# would involve emitting the name of a macro which you define in a
-# platform-specific way. e.g. "MUST_USE_FUNC"
-# default: nothing is emitted for must_use functions
-must_use = "MUST_USE_FUNC"
-
-# An optional string that will be used in the attribute position for functions
-# that don't return (that return `!` in Rust).
-#
-# For instance, `__attribute__((noreturn))` would be a reasonable value if
-# targeting gcc/clang.
-no_return = "NO_RETURN"
-
-# An optional string that, if present, will be used to generate Swift function
-# and method signatures for generated functions, for example "CF_SWIFT_NAME".
-# If no such macro is available in your toolchain, you can define one using the
-# `header` option in cbindgen.toml
-# default: no swift_name function attributes are generated
-# swift_name_macro = "CF_SWIFT_NAME"
-
-# A rule to use to rename function argument names. The renaming assumes the input
-# is the Rust standard snake_case, however it accepts all the different rename_args
-# inputs. This means many options here are no-ops or redundant.
-#
-# possible values (that actually do something):
-# * "CamelCase": my_arg => myArg
-# * "PascalCase": my_arg => MyArg
-# * "GeckoCase": my_arg => aMyArg
-# * "ScreamingSnakeCase": my_arg => MY_ARG
-# * "None": apply no renaming
-#
-# technically possible values (that shouldn't have a purpose here):
-# * "SnakeCase": apply no renaming
-# * "LowerCase": apply no renaming (actually applies to_lowercase, is this bug?)
-# * "UpperCase": same as ScreamingSnakeCase in this context
-# * "QualifiedScreamingSnakeCase" => same as ScreamingSnakeCase in this context
-#
-# default: "None"
-rename_args = "PascalCase"
-
-# This rule specifies the order in which functions will be sorted.
-#
-# "Name": sort by the name of the function
-# "None": keep order in which the functions have been parsed
-#
-# default: "None"
-sort_by = "Name"
-
-[struct]
-# A rule to use to rename struct field names. The renaming assumes the input is
-# the Rust standard snake_case, however it acccepts all the different rename_args
-# inputs. This means many options here are no-ops or redundant.
-#
-# possible values (that actually do something):
-# * "CamelCase": my_arg => myArg
-# * "PascalCase": my_arg => MyArg
-# * "GeckoCase": my_arg => mMyArg
-# * "ScreamingSnakeCase": my_arg => MY_ARG
-# * "None": apply no renaming
-#
-# technically possible values (that shouldn't have a purpose here):
-# * "SnakeCase": apply no renaming
-# * "LowerCase": apply no renaming (actually applies to_lowercase, is this bug?)
-# * "UpperCase": same as ScreamingSnakeCase in this context
-# * "QualifiedScreamingSnakeCase" => same as ScreamingSnakeCase in this context
-#
-# default: "None"
-rename_fields = "PascalCase"
-
-# An optional string that should come before the name of any struct which has been
-# marked as `#[must_use]`. For instance, "__attribute__((warn_unused))"
-# would be a reasonable value if targeting gcc/clang. A more portable solution
-# would involve emitting the name of a macro which you define in a
-# platform-specific way. e.g. "MUST_USE_STRUCT"
-#
-# default: nothing is emitted for must_use structs
-must_use = "MUST_USE_STRUCT"
-
-# Whether a Rust type with associated consts should emit those consts inside the
-# type's body. Otherwise they will be emitted trailing and with the type's name
-# prefixed. This does nothing if the target is C, or if
-# [const]allow_static_const = false
-#
-# default: false
-# associated_constants_in_body: false
-
-# Whether to derive a simple constructor that takes a value for every field.
-# default: false
-derive_constructor = true
-
-# Whether to derive an operator== for all structs
-# default: false
-derive_eq = false
-
-# Whether to derive an operator!= for all structs
-# default: false
-derive_neq = false
-
-# Whether to derive an operator< for all structs
-# default: false
-derive_lt = false
-
-# Whether to derive an operator<= for all structs
-# default: false
-derive_lte = false
-
-# Whether to derive an operator> for all structs
-# default: false
-derive_gt = false
-
-# Whether to derive an operator>= for all structs
-# default: false
-derive_gte = false
-
-
-
-
-
-[enum]
-# A rule to use to rename enum variants, and the names of any fields those
-# variants have. This should probably be split up into two separate options, but
-# for now, they're the same! See the documentation for `[struct]rename_fields`
-# for how this applies to fields. Renaming of the variant assumes that the input
-# is the Rust standard PascalCase. In the case of QualifiedScreamingSnakeCase,
-# it also assumed that the enum's name is PascalCase.
-#
-# possible values (that actually do something):
-# * "CamelCase": MyVariant => myVariant
-# * "SnakeCase": MyVariant => my_variant
-# * "ScreamingSnakeCase": MyVariant => MY_VARIANT
-# * "QualifiedScreamingSnakeCase": MyVariant => ENUM_NAME_MY_VARIANT
-# * "LowerCase": MyVariant => myvariant
-# * "UpperCase": MyVariant => MYVARIANT
-# * "None": apply no renaming
-#
-# technically possible values (that shouldn't have a purpose for the variants):
-# * "PascalCase": apply no renaming
-# * "GeckoCase": apply no renaming
-#
-# default: "None"
-rename_variants = "None"
-
-# Whether an extra "sentinel" enum variant should be added to all generated enums.
-# Firefox uses this for their IPC serialization library.
-#
-# WARNING: if the sentinel is ever passed into Rust, behaviour will be Undefined.
-# Rust does not know about this value, and will assume it cannot happen.
-#
-# default: false
-add_sentinel = false
-
-# Whether enum variant names should be prefixed with the name of the enum.
-# default: false
-prefix_with_name = false
-
-# Whether to emit enums using "enum class" when targeting C++.
-# default: true
-enum_class = true
-
-# Whether to generate static `::MyVariant(..)` constructors and `bool IsMyVariant()`
-# methods for enums with fields.
-#
-# default: false
-derive_helper_methods = false
-
-# Whether to generate `const MyVariant& AsMyVariant() const` methods for enums with fields.
-# default: false
-derive_const_casts = false
-
-# Whether to generate `MyVariant& AsMyVariant()` methods for enums with fields
-# default: false
-derive_mut_casts = false
-
-# The name of the macro/function to use for asserting `IsMyVariant()` in the body of
-# derived `AsMyVariant()` cast methods.
-#
-# default: "assert" (but also causes `<cassert>` to be included by default)
-cast_assert_name = "MOZ_RELEASE_ASSERT"
-
-# An optional string that should come before the name of any enum which has been
-# marked as `#[must_use]`. For instance, "__attribute__((warn_unused))"
-# would be a reasonable value if targeting gcc/clang. A more portable solution
-# would involve emitting the name of a macro which you define in a
-# platform-specific way. e.g. "MUST_USE_ENUM"
-#
-# Note that this refers to the *output* type. That means this will not apply to an enum
-# with fields, as it will be emitted as a struct. `[struct]must_use` will apply there.
-#
-# default: nothing is emitted for must_use enums
-must_use = "MUST_USE_ENUM"
-
-# Whether enums with fields should generate destructors. This exists so that generic
-# enums can be properly instantiated with payloads that are C++ types with
-# destructors. This isn't necessary for structs because C++ has rules to
-# automatically derive the correct constructors and destructors for those types.
-#
-# Care should be taken with this option, as Rust and C++ cannot
-# properly interoperate with eachother's notions of destructors. Also, this may
-# change the ABI for the type. Either your destructor-full enums must live
-# exclusively within C++, or they must only be passed by-reference between
-# C++ and Rust.
-#
-# default: false
-derive_tagged_enum_destructor = false
-
-# Whether enums with fields should generate copy-constructor. See the discussion on
-# derive_tagged_enum_destructor for why this is both useful and very dangerous.
-#
-# default: false
-derive_tagged_enum_copy_constructor = false
-# Whether enums with fields should generate copy-assignment operators.
-#
-# This depends on also deriving copy-constructors, and it is highly encouraged
-# for this to be set to true.
-#
-# default: false
-derive_tagged_enum_copy_assignment = false
-
-# Whether enums with fields should generate an empty, private destructor.
-# This allows the auto-generated constructor functions to compile, if there are
-# non-trivially constructible members. This falls in the same family of
-# dangerousness as `derive_tagged_enum_copy_constructor` and co.
-#
-# default: false
-private_default_tagged_enum_constructor = false
-
-
-
-
-
-[const]
-# Whether a generated constant can be a static const in C++ mode. I have no
-# idea why you would turn this off.
-#
-# default: true
-allow_static_const = true
-
-# Whether a generated constant can be constexpr in C++ mode.
-#
-# default: true
-allow_constexpr = false
-
-# This rule specifies the order in which constants will be sorted.
-#
-# "Name": sort by the name of the constant
-# "None": keep order in which the constants have been parsed
-#
-# default: "None"
-sort_by = "Name"
-
-
-
-
-[macro_expansion]
-# Whether bindings should be generated for instances of the bitflags! macro.
-# default: false
-bitflags = true
-
-
-
-
-
-
-# Options for how your Rust library should be parsed
-
-[parse]
-# Whether to parse dependent crates and include their types in the output
-# default: false
-parse_deps = true
-
-# A white list of crate names that are allowed to be parsed. If this is defined,
-# only crates found in this list will ever be parsed.
-#
-# default: there is no whitelist (NOTE: this is the opposite of [])
-include = ["webrender", "webrender_traits"]
-
-# A black list of crate names that are not allowed to be parsed.
-# default: []
-exclude = ["libc"]
-
-# Whether to use a new temporary target directory when running `rustc -Zunpretty=expanded`.
-# This may be required for some build processes.
-#
-# default: false
-clean = false
-
-# Which crates other than the top-level binding crate we should generate
-# bindings for.
-#
-# default: []
-# extra_bindings = ["my_awesome_dep"]
-
-[parse.expand]
-# A list of crate names that should be run through `cargo expand` before
-# parsing to expand any macros. Note that if a crate is named here, it
-# will always be parsed, even if the blacklist/whitelist says it shouldn't be.
-#
-# default: []
-crates = ["euclid"]
-
-# If enabled,  use the `--all-features` option when expanding. Ignored when
-# `features` is set. For backwards-compatibility, this is forced on if
-# `expand = ["euclid"]` shorthand is used.
-#
-# default: false
-all_features = false
-
-# When `all_features` is disabled and this is also disabled, use the
-# `--no-default-features` option when expanding.
-#
-# default: true
-default_features = true
-
-# A list of feature names that should be used when running `cargo expand`. This
-# combines with `default_features` like in your `Cargo.toml`. Note that the features
-# listed here are features for the current crate being built, *not* the crates
-# being expanded. The crate's `Cargo.toml` must take care of enabling the
-# appropriate features in its dependencies
-#
-# default: []
-# features = ["cbindgen"]
-
-[ptr]
-# An optional string to decorate all pointers that are
-# required to be non null. Nullability is inferred from the Rust type: `&T`,
-# `&mut T` and `NonNull<T>` all require a valid pointer value.
-non_null_attribute = "_Nonnull"
-
-# Options specific to Cython bindings.
-

+ 1 - 0
kernel/src/arch/x86_64/Makefile

@@ -18,5 +18,6 @@ $(kernel_arch_x86_64_subdirs): ECHO
 all: $(kernel_arch_x86_64_objs) $(kernel_arch_x86_64_subdirs)
 
 
+
 clean:
 	echo "Done."

+ 19 - 0
kernel/src/arch/x86_64/context.rs

@@ -0,0 +1,19 @@
+use crate::include::bindings::bindings::{process_control_block, switch_proc};
+
+use core::sync::atomic::compiler_fence;
+
+/// @brief 切换进程的上下文(没有切换页表的动作)
+///
+/// @param next 下一个进程的pcb
+/// @param trap_frame 中断上下文的栈帧
+#[inline(always)]
+pub fn switch_process(
+    prev: &'static mut process_control_block,
+    next: &'static mut process_control_block,
+) {
+    compiler_fence(core::sync::atomic::Ordering::SeqCst);
+    unsafe {
+        switch_proc(prev, next);
+    }
+    compiler_fence(core::sync::atomic::Ordering::SeqCst);
+}

+ 23 - 0
kernel/src/arch/x86_64/mm/barrier.rs

@@ -0,0 +1,23 @@
+#![allow(dead_code)]
+use core::arch::asm;
+
+#[inline(always)]
+pub fn mfence(){
+    unsafe{
+        asm!("mfence");
+    }
+}
+
+#[inline(always)]
+pub fn lfence(){
+    unsafe{
+        asm!("lfence");
+    }
+}
+
+#[inline(always)]
+pub fn sfence(){
+    unsafe{
+        asm!("sfence");
+    }
+}

+ 28 - 0
kernel/src/arch/x86_64/mm/mod.rs

@@ -0,0 +1,28 @@
+pub mod barrier;
+use crate::include::bindings::bindings::process_control_block;
+
+use core::arch::asm;
+use core::ptr::read_volatile;
+
+use self::barrier::mfence;
+
+/// @brief 切换进程的页表
+///
+/// @param 下一个进程的pcb。将会把它的页表切换进来。
+///
+/// @return 下一个进程的pcb(把它return的目的主要是为了归还所有权)
+#[inline(always)]
+#[allow(dead_code)]
+pub fn switch_mm(
+    next_pcb: &'static mut process_control_block,
+) -> &'static mut process_control_block {
+    mfence();
+    // kdebug!("to get pml4t");
+    let pml4t = unsafe { read_volatile(&next_pcb.mm.as_ref().unwrap().pgd) };
+    
+    unsafe {
+        asm!("mov cr3, {}", in(reg) pml4t);
+    }
+    mfence();
+    return next_pcb;
+}

+ 4 - 1
kernel/src/arch/x86_64/mod.rs

@@ -1,4 +1,7 @@
 #[macro_use]
 pub mod asm;
 pub mod cpu;
-pub mod interrupt;
+pub mod interrupt;
+pub mod mm;
+pub mod context;
+pub mod sched;

+ 10 - 0
kernel/src/arch/x86_64/sched.rs

@@ -0,0 +1,10 @@
+use crate::include::bindings::bindings::{enter_syscall_int, SYS_SCHED};
+
+/// @brief 若内核代码不处在中断上下文中,那么将可以使用本函数,发起一个sys_sched系统调用,然后运行调度器。
+/// 由于只能在中断上下文中进行进程切换,因此需要发起一个系统调用SYS_SCHED。
+#[no_mangle]
+pub extern "C" fn sched() {
+    unsafe {
+        enter_syscall_int(SYS_SCHED.into(), 0, 0, 0, 0, 0, 0, 0, 0);
+    }
+}

+ 1 - 2
kernel/src/driver/disk/ahci/ahci.c

@@ -403,7 +403,7 @@ static bool ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t
     port->ci = 1 << slot; // Issue command
 
     current_pcb->flags |= PF_NEED_SCHED;
-    sched();
+
     int retval = AHCI_SUCCESS;
     // Wait for completion
     while (1)
@@ -483,7 +483,6 @@ static bool ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_
     port->ci = 1; // Issue command
 
     current_pcb->flags |= PF_NEED_SCHED;
-    sched();
     int retval = AHCI_SUCCESS;
 
     while (1)

+ 2 - 1
kernel/src/driver/interrupt/apic/apic.c

@@ -1,4 +1,5 @@
 #include "apic.h"
+#include "apic_timer.h"
 #include <common/kprint.h>
 #include <common/printk.h>
 #include <common/cpu.h>
@@ -458,7 +459,7 @@ void do_IRQ(struct pt_regs *rsp, ul number)
         kBUG("current_pcb->preempt_count<0! pid=%d", current_pcb->pid); // should not be here
 
     // 检测当前进程是否可被调度
-    if (current_pcb->flags & PF_NEED_SCHED)
+    if (current_pcb->flags & PF_NEED_SCHED && number == APIC_TIMER_IRQ_NUM)
     {
         io_mfence();
         sched();

+ 2 - 1
kernel/src/driver/video/video.c

@@ -70,7 +70,8 @@ int video_refresh_daemon(void *unused)
             }
             video_refresh_expire_jiffies = cal_next_n_ms_jiffies(REFRESH_INTERVAL << 1);
         }
-        video_daemon_pcb->flags &= ~PROC_RUNNING;
+        video_daemon_pcb->state &= ~PROC_RUNNING;
+        video_daemon_pcb->flags |= PF_NEED_SCHED;
         sched();
     }
 

+ 2 - 41
kernel/src/exception/entry.S

@@ -21,6 +21,7 @@ ES	=	0x78
 RAX	=	0x80
 FUNC	=	0x88
 ERRCODE	=	0x90
+// 以下几个字段,在中断产生时,由处理器压入栈内
 RIP	    =	0x98
 CS	    =	0xa0
 RFLAGS	=	0xa8
@@ -111,51 +112,11 @@ Err_Code:
     callq *%rdx //调用服务程序 带*号表示调用的是绝对地址
     jmp ret_from_exception
 
-// 系统调用入口
-// 保存寄存器
-ENTRY(system_call)
-    
-    // 由于sysenter指令会禁用中断,因此要在这里手动开启中断
-    subq $0x38, %rsp
-    
-    cld;
-    
-    pushq %rax
-    movq %es, %rax
-    pushq %rax
-    movq %ds, %rax
-    pushq %rax
-    pushq %rbp
-    pushq %rdi
-    pushq %rsi
-    pushq %rdx
-    pushq %rcx
-    pushq %rbx
-    pushq %r8
-    pushq %r9
-    pushq %r10
-    pushq %r11
-    pushq %r12
-    pushq %r13
-    pushq %r14
-    pushq %r15
-
-    movq $0x10, %rdx
-    movq %rdx, %ds
-    movq %rdx, %es
-    // 将rsp作为参数传递给system_call_function
-    movq %rsp, %rdi
-
-    
-    callq system_call_function
-
 
 // 从系统调用中返回
 ENTRY(ret_from_system_call)
     jmp Restore_all
 
-    
-
 
 // 0 #DE 除法错误
 ENTRY(divide_error)
@@ -323,7 +284,7 @@ ENTRY(virtualization_exception)
 
 
 
-
+// 系统调用入口
 // 0x80 系统调用门
 ENTRY(syscall_int)
     pushq $0

+ 1 - 0
kernel/src/exception/softirq.c

@@ -4,6 +4,7 @@
 #include <driver/video/video.h>
 #include <common/spinlock.h>
 
+static struct softirq_t softirq_vector[MAX_SOFTIRQ_NUM] = {0};
 static spinlock_t softirq_modify_lock; // 软中断状态(status)
 static volatile uint64_t softirq_pending = 0;
 static volatile uint64_t softirq_running = 0;

+ 4 - 9
kernel/src/exception/softirq.h

@@ -21,23 +21,18 @@
  * @brief 发起软中断
  *
  */
-#define raise_softirq(sirq_num)            \
-    do                                     \
-    {                                      \
-        set_softirq_pending(1 << sirq_num); \
+#define raise_softirq(sirq_num)                                                                                        \
+    do                                                                                                                 \
+    {                                                                                                                  \
+        set_softirq_pending(1 << sirq_num);                                                                            \
     } while (0);
 
-
-
-
 struct softirq_t
 {
     void (*action)(void *data); // 软中断处理函数
     void *data;
 };
 
-struct softirq_t softirq_vector[MAX_SOFTIRQ_NUM] = {0};
-
 /**
  * @brief 软中断注册函数
  *

+ 1 - 0
kernel/src/exception/trap.c

@@ -176,6 +176,7 @@ void do_stack_segment_fault(struct pt_regs *regs, unsigned long error_code)
 
     kerror("do_stack_segment_fault(12),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp,
            regs->rip, proc_current_cpu_id);
+    // kinfo("cs=%#04x, ds=%#04x, ss=%#04x", regs->cs, regs->ds, regs->ss);
     traceback(regs);
     current_pcb->state = PROC_STOPPED;
     sched();

+ 2 - 1
kernel/src/libs/mutex.c

@@ -17,6 +17,7 @@ void mutex_init(mutex_t *lock)
 static void __mutex_sleep()
 {
     current_pcb->state = PROC_UNINTERRUPTIBLE;
+    current_pcb->flags |= PF_NEED_SCHED;
     sched();
 }
 
@@ -71,7 +72,7 @@ void mutex_unlock(mutex_t *lock)
 {
     if (unlikely(!mutex_is_locked(lock)))
         return;
-    
+
     spin_lock(&lock->wait_lock);
     struct mutex_waiter_t *wt = NULL;
     if (mutex_is_locked(lock))

+ 1 - 0
kernel/src/libs/semaphore.c

@@ -18,6 +18,7 @@ void semaphore_down(semaphore_t *sema)
         list_append(&sema->wait_queue.wait_list, &wait.wait_list);
 
         // 执行调度
+        current_pcb->flags |= PF_NEED_SCHED;
         sched();
     }
 }

+ 2 - 1
kernel/src/libs/spinlock.rs

@@ -57,11 +57,12 @@ pub fn spin_unlock_irq(lock: *mut spinlock_t) {
     sti();
 }
 
+#[derive(Debug)]
 pub struct RawSpinlock(AtomicBool);
 
 impl RawSpinlock {
     /// @brief 初始化自旋锁
-    const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
+    pub const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
 
     /// @brief 加锁
     pub fn lock(&mut self) {

+ 1 - 1
kernel/src/main.c

@@ -130,7 +130,7 @@ void system_initialize()
     syscall_init();
     io_mfence();
     //  再初始化进程模块。顺序不能调转
-    sched_init();
+    // sched_init();
     io_mfence();
 
     timer_init();

+ 1 - 1
kernel/src/mm/mod.rs

@@ -1,2 +1,2 @@
 pub mod allocator;
-pub mod gfp;
+pub mod gfp;

+ 8 - 2
kernel/src/process/kthread.c

@@ -90,7 +90,7 @@ static struct process_control_block *__kthread_create_on_node(int (*thread_fn)(v
         int len = vsnprintf(pcb_name, name_fmt, PCB_NAME_LEN, get_args);
         if (len >= PCB_NAME_LEN)
         {
-            //名字过大 放到full_name字段中
+            // 名字过大 放到full_name字段中
             struct kthread_info_t *kthread = to_kthread(pcb);
             char *full_name = kzalloc(1024, 0);
             vsprintf(full_name, name_fmt, get_args);
@@ -173,7 +173,7 @@ static int kthread(void *_create)
     // 将当前pcb返回给创建者
     create->result = current_pcb;
 
-    current_pcb->state &= ~PROC_RUNNING;    // 设置当前进程不是RUNNING态
+    current_pcb->state &= ~PROC_RUNNING; // 设置当前进程不是RUNNING态
     io_mfence();
 
     // 发起调度,使得当前内核线程休眠。直到创建者通过process_wakeup将当前内核线程唤醒
@@ -200,6 +200,8 @@ static void __create_kthread(struct kthread_create_info_t *create)
     }
 }
 
+#pragma GCC push_options
+#pragma GCC optimize("O0")
 /**
  * @brief kthread守护线程
  *
@@ -208,6 +210,7 @@ static void __create_kthread(struct kthread_create_info_t *create)
  */
 int kthreadd(void *unused)
 {
+    barrier();
     kinfo("kthread daemon started!");
     struct process_control_block *pcb = current_pcb;
     kthreadd_pcb = current_pcb;
@@ -237,8 +240,11 @@ int kthreadd(void *unused)
         }
         spin_unlock(&__kthread_create_lock);
     }
+    barrier();
 }
 
+#pragma GCC pop_options
+
 /**
  * @brief 内核线程调用该函数,检查自身的标志位,判断自己是否应该执行完任务后退出
  *

+ 2 - 0
kernel/src/process/proc-types.h

@@ -3,6 +3,7 @@
 #include <DragonOS/signal.h>
 #include <common/wait_queue.h>
 #include <DragonOS/stdint.h>
+#include "ptrace.h"
 
 // 进程最大可拥有的文件描述符数量
 #define PROC_MAX_FD_NUM 16
@@ -128,6 +129,7 @@ struct process_control_block
     sigset_t sig_blocked;
     // 正在等待的信号的标志位,表示某个信号正在等待处理
     struct sigpending sig_pending;
+
 };
 
 // 将进程的pcb和内核栈融合到一起,8字节对齐

+ 2 - 1
kernel/src/process/process.h

@@ -219,4 +219,5 @@ extern int process_try_to_wake_up(struct process_control_block *_pcb, uint64_t _
  * @return true 唤醒成功
  * @return false 唤醒失败
  */
-extern int process_wake_up_state(struct process_control_block *pcb, uint64_t state);
+extern int process_wake_up_state(struct process_control_block *pcb, uint64_t state);
+void __switch_to(struct process_control_block *prev, struct process_control_block *next);

+ 3 - 4
kernel/src/process/process.rs

@@ -3,9 +3,9 @@ use core::ptr::{read_volatile, write_volatile};
 use crate::{
     arch::asm::current::current_pcb,
     include::bindings::bindings::{
-        process_control_block, sched_enqueue, PROC_RUNNING, PROC_STOPPED,
+        process_control_block, PROC_RUNNING, PROC_STOPPED,
     },
-    sched::core::cpu_executing,
+    sched::core::{cpu_executing, sched_enqueue},
     smp::core::{smp_get_processor_id, smp_send_reschedule},
 };
 
@@ -76,7 +76,6 @@ pub extern "C" fn process_wake_up_state(pcb: *mut process_control_block, state:
     return process_try_to_wake_up(pcb, state, 0);
 }
 
-
 /// @brief 让一个正在cpu上运行的进程陷入内核
 pub fn process_kick(pcb: *mut process_control_block) {
     preempt_disable();
@@ -99,5 +98,5 @@ pub fn process_cpu(pcb: *const process_control_block) -> u32 {
 /// @param pcb 进程的pcb
 #[inline]
 pub fn process_is_executing(pcb: *const process_control_block) -> bool {
-    return cpu_executing(process_cpu(pcb)) == pcb;
+    return cpu_executing(process_cpu(pcb)) as *const process_control_block == pcb;
 }

+ 3 - 7
kernel/src/process/ptrace.h

@@ -2,10 +2,6 @@
 
 #define __PTRACE_H__
 
-/*
-
-*/
-
 struct pt_regs
 {
     unsigned long r15;
@@ -36,9 +32,9 @@ struct pt_regs
 
 /**
  * @brief 判断pt_regs是否来自用户态
- * 
- * @param regs 
- * @return __always_inline 
+ *
+ * @param regs
+ * @return __always_inline
  */
 static inline int user_mode(struct pt_regs *regs)
 {

+ 0 - 163
kernel/src/sched/cfs.c

@@ -1,163 +0,0 @@
-#include "cfs.h"
-#include <common/kprint.h>
-#include <common/spinlock.h>
-#include <driver/video/video.h>
-
-struct sched_queue_t sched_cfs_ready_queue[MAX_CPU_NUM]; // 就绪队列
-
-/**
- * @brief 从就绪队列中取出PCB
- *
- * @return struct process_control_block*
- */
-struct process_control_block *sched_cfs_dequeue()
-{
-    if (list_empty(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list))
-    {
-        // kdebug("list empty, count=%d", sched_cfs_ready_queue[proc_current_cpu_id].count);
-        return &initial_proc_union.pcb;
-    }
-
-    struct process_control_block *proc = container_of(
-        list_next(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list), struct process_control_block, list);
-
-    list_del(&proc->list);
-    --sched_cfs_ready_queue[proc_current_cpu_id].count;
-    return proc;
-}
-
-/**
- * @brief 将PCB加入就绪队列
- *
- * @param pcb
- */
-void sched_cfs_enqueue(struct process_control_block *pcb)
-{
-    if (pcb == initial_proc[proc_current_cpu_id])
-        return;
-    struct process_control_block *proc = container_of(
-        list_next(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list), struct process_control_block, list);
-    if ((list_empty(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list)) == 0)
-    {
-        while (proc->virtual_runtime < pcb->virtual_runtime)
-        {
-            proc = container_of(list_next(&proc->list), struct process_control_block, list);
-        }
-    }
-    list_append(&proc->list, &pcb->list);
-    ++sched_cfs_ready_queue[proc_current_cpu_id].count;
-}
-
-/**
- * @brief 调度函数
- *
- */
-void sched_cfs()
-{
-
-    cli();
-
-    current_pcb->flags &= ~PF_NEED_SCHED;
-    // kdebug("current_pcb pid= %d", current_pcb->pid);
-    struct process_control_block *proc = sched_cfs_dequeue();
-    // kdebug("sched_cfs_ready_queue[proc_current_cpu_id].count = %d",
-    // sched_cfs_ready_queue[proc_current_cpu_id].count);
-    if (current_pcb->virtual_runtime >= proc->virtual_runtime ||
-        !(current_pcb->state & PROC_RUNNING)) // 当前进程运行时间大于了下一进程的运行时间,进行切换
-    {
-
-        // kdebug("current_pcb->virtual_runtime = %d,proc->vt= %d", current_pcb->virtual_runtime,
-        // proc->virtual_runtime);
-        if (current_pcb->state &
-            PROC_RUNNING) // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理
-            sched_cfs_enqueue(current_pcb);
-        // kdebug("proc->pid=%d, count=%d", proc->pid, sched_cfs_ready_queue[proc_current_cpu_id].count);
-        if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0)
-        {
-            switch (proc->priority)
-            {
-            case 0:
-            case 1:
-                sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies =
-                    4 / sched_cfs_ready_queue[proc_current_cpu_id].count;
-                break;
-            case 2:
-            default:
-                sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies =
-                    (4 / sched_cfs_ready_queue[proc_current_cpu_id].count) << 2;
-                break;
-            }
-        }
-
-        barrier();
-        switch_proc(current_pcb, proc);
-        barrier();
-    }
-    else // 不进行切换
-    {
-        // kdebug("not switch.");
-        sched_cfs_enqueue(proc);
-
-        if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0)
-        {
-            switch (proc->priority)
-            {
-            case 0:
-            case 1:
-                sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies =
-                    4 / sched_cfs_ready_queue[proc_current_cpu_id].count;
-                break;
-            case 2:
-            default:
-
-                sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies =
-                    (4 / sched_cfs_ready_queue[proc_current_cpu_id].count) << 2;
-                break;
-            }
-        }
-    }
-
-    sti();
-}
-
-/**
- * @brief 当时钟中断到达时,更新时间片
- *
- */
-void sched_update_jiffies()
-{
-
-    switch (current_pcb->priority)
-    {
-    case 0:
-    case 1:
-        --sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies;
-        ++current_pcb->virtual_runtime;
-        break;
-    case 2:
-    default:
-        sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies -= 2;
-        current_pcb->virtual_runtime += 2;
-        break;
-    }
-    // 时间片耗尽,标记可调度
-    if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0)
-        current_pcb->flags |= PF_NEED_SCHED;
-}
-
-/**
- * @brief 初始化CFS调度器
- *
- */
-void sched_cfs_init()
-{
-    memset(&sched_cfs_ready_queue, 0, sizeof(struct sched_queue_t) * MAX_CPU_NUM);
-    for (int i = 0; i < MAX_CPU_NUM; ++i)
-    {
-
-        list_init(&sched_cfs_ready_queue[i].proc_queue.list);
-        sched_cfs_ready_queue[i].count = 1; // 因为存在IDLE进程,因此为1
-        sched_cfs_ready_queue[i].cpu_exec_proc_jiffies = 5;
-        sched_cfs_ready_queue[i].proc_queue.virtual_runtime = 0x7fffffffffffffff;
-    }
-}

+ 201 - 0
kernel/src/sched/cfs.rs

@@ -0,0 +1,201 @@
+use core::{
+    ptr::null_mut,
+    sync::atomic::compiler_fence,
+};
+
+use alloc::{boxed::Box, vec::Vec};
+
+use crate::{
+    arch::{
+        asm::current::current_pcb,
+        context::switch_process,
+    },
+    include::bindings::bindings::{
+        initial_proc_union, process_control_block, MAX_CPU_NUM, PF_NEED_SCHED,
+        PROC_RUNNING,
+    },
+    kBUG,
+    libs::spinlock::RawSpinlock,
+};
+
+use super::core::Scheduler;
+
+/// 声明全局的cfs调度器实例
+
+pub static mut CFS_SCHEDULER_PTR: *mut SchedulerCFS = null_mut();
+
+/// @brief 获取cfs调度器实例的可变引用
+#[inline]
+pub fn __get_cfs_scheduler() -> &'static mut SchedulerCFS {
+    return unsafe { CFS_SCHEDULER_PTR.as_mut().unwrap() };
+}
+
+/// @brief 初始化cfs调度器
+pub unsafe fn sched_cfs_init() {
+    if CFS_SCHEDULER_PTR.is_null() {
+        CFS_SCHEDULER_PTR = Box::leak(Box::new(SchedulerCFS::new()));
+    } else {
+        kBUG!("Try to init CFS Scheduler twice.");
+        panic!("Try to init CFS Scheduler twice.");
+    }
+}
+
+/// @brief CFS队列(per-cpu的)
+#[derive(Debug)]
+struct CFSQueue {
+    /// 当前cpu上执行的进程,剩余的时间片
+    cpu_exec_proc_jiffies: i64,
+    /// 队列的锁
+    lock: RawSpinlock,
+    /// 进程的队列
+    queue: Vec<&'static mut process_control_block>,
+}
+
+impl CFSQueue {
+    pub fn new() -> CFSQueue {
+        CFSQueue {
+            cpu_exec_proc_jiffies: 0,
+            lock: RawSpinlock::INIT,
+            queue: Vec::new(),
+        }
+    }
+
+    /// @brief 将进程按照虚拟运行时间的升序进行排列
+    /// todo: 换掉这个sort方法,因为它底层是归并很占内存,且时间复杂度为nlogn,(遍历然后插入的方法,时间复杂度最坏是n)
+    pub fn sort(&mut self) {
+        self.queue
+            .sort_by(|a, b| (*a).virtual_runtime.cmp(&(*b).virtual_runtime));
+    }
+
+    /// @brief 将pcb加入队列
+    pub fn enqueue(&mut self, pcb: &'static mut process_control_block) {
+        self.lock.lock();
+
+        // 如果进程是IDLE进程,那么就不加入队列
+        if pcb.pid == 0 {
+            self.lock.unlock();
+            return;
+        }
+        self.queue.push(pcb);
+        self.sort();
+        self.lock.unlock();
+    }
+
+    /// @brief 将pcb从调度队列中弹出,若队列为空,则返回IDLE进程的pcb
+    pub fn dequeue(&mut self) -> &'static mut process_control_block {
+        let res: &'static mut process_control_block;
+        self.lock.lock();
+        if self.queue.len() > 0 {
+            // 队列不为空,返回下一个要执行的pcb
+            res = self.queue.pop().unwrap();
+        } else {
+            // 如果队列为空,则返回IDLE进程的pcb
+            res = unsafe { &mut initial_proc_union.pcb };
+        }
+        self.lock.unlock();
+        return res;
+    }
+}
+
+/// @brief CFS调度器类
+pub struct SchedulerCFS {
+    cpu_queue: Vec<&'static mut CFSQueue>,
+}
+
+impl SchedulerCFS {
+    pub fn new() -> SchedulerCFS {
+        // 暂时手动指定核心数目
+        // todo: 从cpu模块来获取核心的数目
+        let mut result = SchedulerCFS {
+            cpu_queue: Default::default(),
+        };
+
+        // 为每个cpu核心创建队列
+        for _ in 0..MAX_CPU_NUM {
+            result.cpu_queue.push(Box::leak(Box::new(CFSQueue::new())));
+        }
+
+        return result;
+    }
+
+    /// @brief 更新这个cpu上,这个进程的可执行时间。
+    #[inline]
+    fn update_cpu_exec_proc_jiffies(_priority: i64, cfs_queue: &mut CFSQueue) -> &mut CFSQueue {
+        // todo: 引入调度周期以及所有进程的优先权进行计算,然后设置分配给进程的可执行时间
+        cfs_queue.cpu_exec_proc_jiffies = 10;
+
+        return cfs_queue;
+    }
+
+    /// @brief 时钟中断到来时,由sched的core模块中的函数,调用本函数,更新CFS进程的可执行时间
+    pub fn timer_update_jiffies(&mut self) {
+        let current_cpu_queue: &mut CFSQueue = self.cpu_queue[current_pcb().cpu_id as usize];
+        // todo: 引入调度周期以及所有进程的优先权进行计算,然后设置进程的可执行时间
+
+        // 更新进程的剩余可执行时间
+        current_cpu_queue.lock.lock();
+        current_cpu_queue.cpu_exec_proc_jiffies -= 1;
+        // 时间片耗尽,标记需要被调度
+        if current_cpu_queue.cpu_exec_proc_jiffies <= 0 {
+            current_pcb().flags |= PF_NEED_SCHED as u64;
+        }
+        current_cpu_queue.lock.unlock();
+
+        // 更新当前进程的虚拟运行时间
+        current_pcb().virtual_runtime += 1;
+    }
+}
+
+impl Scheduler for SchedulerCFS {
+    /// @brief 在当前cpu上进行调度。
+    /// 请注意,进入该函数之前,需要关中断
+    fn sched(&mut self) {
+        // kdebug!("cfs:sched");
+        current_pcb().flags &= !(PF_NEED_SCHED as u64);
+        let current_cpu_id = current_pcb().cpu_id as usize;
+        let current_cpu_queue: &mut CFSQueue = self.cpu_queue[current_cpu_id];
+        let proc: &'static mut process_control_block = current_cpu_queue.dequeue();
+        compiler_fence(core::sync::atomic::Ordering::SeqCst);
+        // 如果当前不是running态,或者当前进程的虚拟运行时间大于等于下一个进程的,那就需要切换。
+        if (current_pcb().state & (PROC_RUNNING as u64)) == 0
+            || current_pcb().virtual_runtime >= proc.virtual_runtime
+        {
+            compiler_fence(core::sync::atomic::Ordering::SeqCst);
+            // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理
+            if current_pcb().state & (PROC_RUNNING as u64) != 0 {
+                // kdebug!("cfs:sched->enqueue");
+                current_cpu_queue.enqueue(current_pcb());
+                compiler_fence(core::sync::atomic::Ordering::SeqCst);
+            }
+
+            compiler_fence(core::sync::atomic::Ordering::SeqCst);
+            // 设置进程可以执行的时间
+            if current_cpu_queue.cpu_exec_proc_jiffies <= 0 {
+                SchedulerCFS::update_cpu_exec_proc_jiffies(proc.priority, current_cpu_queue);
+            }
+
+            compiler_fence(core::sync::atomic::Ordering::SeqCst);
+
+            switch_process(current_pcb(), proc);
+            compiler_fence(core::sync::atomic::Ordering::SeqCst);
+        } else {
+            // 不进行切换
+
+            // 设置进程可以执行的时间
+            compiler_fence(core::sync::atomic::Ordering::SeqCst);
+            if current_cpu_queue.cpu_exec_proc_jiffies <= 0 {
+                SchedulerCFS::update_cpu_exec_proc_jiffies(proc.priority, current_cpu_queue);
+            }
+
+            compiler_fence(core::sync::atomic::Ordering::SeqCst);
+            current_cpu_queue.enqueue(proc);
+            compiler_fence(core::sync::atomic::Ordering::SeqCst);
+        }
+        compiler_fence(core::sync::atomic::Ordering::SeqCst);
+    }
+
+    fn enqueue(&mut self, pcb: &'static mut process_control_block) {
+        let cpu_queue = &mut self.cpu_queue[pcb.cpu_id as usize];
+        cpu_queue.enqueue(pcb);
+    }
+}

+ 14 - 0
kernel/src/sched/core.c

@@ -0,0 +1,14 @@
+#include "sched.h"
+
+/**
+ * @brief 切换进程上下文。请注意,只能在中断上下文内调用本函数
+ * TODO:使用Rust重构这里
+ * @param prev 前一个进程的pcb
+ * @param proc 后一个进程的pcb
+ */
+void switch_proc(struct process_control_block *prev, struct process_control_block *proc)
+{
+    process_switch_mm(proc);
+    io_mfence();
+    switch_to(prev, proc);
+}

+ 77 - 5
kernel/src/sched/core.rs

@@ -1,13 +1,85 @@
-use crate::{include::bindings::bindings::process_control_block, process::process::process_cpu, arch::asm::current::current_pcb};
+use core::sync::atomic::compiler_fence;
+
+use crate::{
+    arch::asm::{current::current_pcb, ptrace::user_mode},
+    include::bindings::bindings::{process_control_block, pt_regs, EPERM, SCHED_NORMAL},
+    process::process::process_cpu,
+};
+
+use super::cfs::{sched_cfs_init, SchedulerCFS, __get_cfs_scheduler};
 
 /// @brief 获取指定的cpu上正在执行的进程的pcb
 #[inline]
-pub fn cpu_executing(cpu_id:u32) -> *const process_control_block{
+pub fn cpu_executing(cpu_id: u32) -> &'static mut process_control_block {
     // todo: 引入per_cpu之后,该函数真正执行“返回指定的cpu上正在执行的pcb”的功能
 
-    if cpu_id == process_cpu(current_pcb()){
+    if cpu_id == process_cpu(current_pcb()) {
         return current_pcb();
-    }else {
+    } else {
         todo!()
     }
-}
+}
+
+/// @brief 具体的调度器应当实现的trait
+pub trait Scheduler {
+    /// @brief 使用该调度器发起调度的时候,要调用的函数
+    fn sched(&mut self);
+
+    /// @brief 将pcb加入这个调度器的调度队列
+    fn enqueue(&mut self, pcb: &'static mut process_control_block);
+}
+
+fn __sched() {
+    compiler_fence(core::sync::atomic::Ordering::SeqCst);
+    let cfs_scheduler: &mut SchedulerCFS = __get_cfs_scheduler();
+    compiler_fence(core::sync::atomic::Ordering::SeqCst);
+
+    cfs_scheduler.sched();
+
+    compiler_fence(core::sync::atomic::Ordering::SeqCst);
+}
+
+/// @brief 将进程加入调度队列
+#[allow(dead_code)]
+#[no_mangle]
+pub extern "C" fn sched_enqueue(pcb: &'static mut process_control_block) {
+    let cfs_scheduler = __get_cfs_scheduler();
+    cfs_scheduler.enqueue(pcb);
+}
+
+/// @brief 初始化进程调度器模块
+#[allow(dead_code)]
+#[no_mangle]
+pub extern "C" fn sched_init() {
+    unsafe {
+        sched_cfs_init();
+    }
+}
+
+/// @brief 当时钟中断到达时,更新时间片
+/// 请注意,该函数只能被时钟中断处理程序调用
+#[allow(dead_code)]
+#[no_mangle]
+pub extern "C" fn sched_update_jiffies() {
+    match current_pcb().policy {
+        SCHED_NORMAL => {
+            __get_cfs_scheduler().timer_update_jiffies();
+        }
+        _ => {
+            todo!()
+        }
+    }
+}
+
+/// @brief 让系统立即运行调度器的系统调用
+/// 请注意,该系统调用不能由ring3的程序发起
+#[allow(dead_code)]
+#[no_mangle]
+pub extern "C" fn sys_sched(regs: &'static mut pt_regs) -> u64 {
+    // 进行权限校验,拒绝用户态发起调度
+    if user_mode(regs) {
+        return (-(EPERM as i64)) as u64;
+    }
+    __sched();
+    0
+}

+ 2 - 1
kernel/src/sched/mod.rs

@@ -1 +1,2 @@
-pub mod core;
+pub mod core;
+pub mod cfs;

+ 0 - 95
kernel/src/sched/sched.c

@@ -1,95 +0,0 @@
-#include "sched.h"
-#include <common/kprint.h>
-#include <common/spinlock.h>
-#include <common/string.h>
-#include <driver/video/video.h>
-#include <sched/cfs.h>
-
-/**
- * @brief
- *
- * @param p pcb
- * @param attr 调度属性
- * @param user 请求是否来自用户态
- * @param pi
- * @return int
- */
-static int __sched_setscheduler(struct process_control_block *p, const struct sched_attr *attr, bool user, bool pi)
-{
-    int policy = attr->sched_policy;
-recheck:;
-    // 这里policy的设置小于0是因为,需要在临界区内更新值之后,重新到这里判断
-    if (!IS_VALID_SCHED_POLICY(policy))
-    {
-        return -EINVAL;
-    }
-    // 修改成功
-    p->policy = policy;
-    return 0;
-}
-
-static int _sched_setscheduler(struct process_control_block *p, int policy, const struct sched_param *param, bool check)
-{
-    struct sched_attr attr = {.sched_policy = policy};
-
-    return __sched_setscheduler(p, &attr, check, true);
-}
-
-/**
- * sched_setscheduler -设置进程的调度策略
- * @param p 需要修改的pcb
- * @param policy 需要设置的policy
- * @param param structure containing the new RT priority. 目前没有用
- *
- * @return 成功返回0,否则返回对应的错误码
- *
- */
-int sched_setscheduler(struct process_control_block *p, int policy, const struct sched_param *param)
-{
-    return _sched_setscheduler(p, policy, param, true);
-}
-
-/**
- * @brief 包裹shced_cfs_enqueue(),将PCB加入就绪队列
- *
- * @param pcb
- */
-void sched_enqueue(struct process_control_block *pcb)
-{
-    sched_cfs_enqueue(pcb);
-}
-
-/**
- * @brief 该函数只能由sys_sched调用
- *
- */
-static void __sched()
-{
-    sched_cfs();
-}
-
-void sched_init()
-{
-    sched_cfs_init();
-}
-
-uint64_t sys_sched(struct pt_regs *regs)
-{
-    if(user_mode(regs)){
-        return -EPERM;
-    }
-    __sched();
-}
-
-void sched()
-{
-    
-    enter_syscall_int(SYS_SCHED, 0, 0, 0, 0, 0, 0, 0, 0);
-}
-
-void switch_proc(struct process_control_block *prev, struct process_control_block *proc)
-{
-    process_switch_mm(proc);
-    io_mfence();
-    switch_to(prev, proc);
-}

+ 50 - 53
kernel/src/sched/sched.h

@@ -17,64 +17,61 @@
 
 #define IS_VALID_SCHED_POLICY(_policy) ((_policy) > 0 && (_policy) <= SCHED_MAX_POLICY_NUM)
 
-struct sched_param
-{
-    int sched_priority;
-};
-struct sched_attr
-{
-    uint32_t size;
-
-    uint32_t sched_policy;
-    uint64_t sched_flags;
-
-    /* SCHED_NORMAL, SCHED_BATCH */
-    int32_t sched_nice;
-
-    /* SCHED_FIFO, SCHED_RR */
-    uint32_t sched_priority;
-
-    /* SCHED_DEADLINE */
-    uint64_t sched_runtime;
-    uint64_t sched_deadline;
-    uint64_t sched_period;
-
-    /* Utilization hints */
-    uint32_t sched_util_min;
-    uint32_t sched_util_max;
-};
-
-static int __sched_setscheduler(struct process_control_block *p, const struct sched_attr *attr, bool user, bool pi);
-static int _sched_setscheduler(struct process_control_block *p, int policy, const struct sched_param *param,
-                               bool check);
-/**
- * sched_setscheduler -设置进程的调度策略
- * @param p 需要修改的pcb
- * @param policy 需要设置的policy
- * @param param structure containing the new RT priority. 目前没有用
- *
- * @return 成功返回0,否则返回对应的错误码
- *
- */
-int sched_setscheduler(struct process_control_block *p, int policy, const struct sched_param *param);
+
+
+// struct sched_param
+// {
+//     int sched_priority;
+// };
+// struct sched_attr
+// {
+//     uint32_t size;
+
+//     uint32_t sched_policy;
+//     uint64_t sched_flags;
+
+//     /* SCHED_NORMAL, SCHED_BATCH */
+//     int32_t sched_nice;
+
+//     /* SCHED_FIFO, SCHED_RR */
+//     uint32_t sched_priority;
+
+//     /* SCHED_DEADLINE */
+//     uint64_t sched_runtime;
+//     uint64_t sched_deadline;
+//     uint64_t sched_period;
+
+//     /* Utilization hints */
+//     uint32_t sched_util_min;
+//     uint32_t sched_util_max;
+// };
+
+// static int __sched_setscheduler(struct process_control_block *p, const struct sched_attr *attr, bool user, bool pi);
+// static int _sched_setscheduler(struct process_control_block *p, int policy, const struct sched_param *param,
+//                                bool check);
+// /**
+//  * sched_setscheduler -设置进程的调度策略
+//  * @param p 需要修改的pcb
+//  * @param policy 需要设置的policy
+//  * @param param structure containing the new RT priority. 目前没有用
+//  *
+//  * @return 成功返回0,否则返回对应的错误码
+//  *
+//  */
+// int sched_setscheduler(struct process_control_block *p, int policy, const struct sched_param *param);
+
 /**
  * @brief 包裹sched_enqueue(),将PCB加入就绪队列
  *
  * @param pcb
  */
-void sched_enqueue(struct process_control_block *pcb);
-/**
- * @brief 包裹sched_cfs(),调度函数
- *
- */
-void sched();
 
-void sched_init();
+// ================= Rust 实现 =============
+extern void sched_update_jiffies();
+extern void sched_init();
+extern void sched();
+extern void sched_enqueue(struct process_control_block *pcb);
+extern void sched();
 
-/**
- * @brief 当时钟中断到达时,更新时间片
- *
- */
-void sched_update_jiffies();
+void switch_proc(struct process_control_block *prev, struct process_control_block *proc);
 
-void switch_proc(struct process_control_block *prev, struct process_control_block *proc);

+ 0 - 10
kernel/src/smp/smp.c

@@ -12,8 +12,6 @@
 
 #include "ipi.h"
 
-void ipi_0xc8_handler(uint64_t irq_num, uint64_t param, struct pt_regs *regs); // 由BSP转发的HPET中断处理函数
-
 static spinlock_t multi_core_starting_lock = {1}; // 多核启动锁
 
 static struct acpi_Processor_Local_APIC_Structure_t *proc_local_apic_structs[MAX_SUPPORTED_PROCESSOR_NUM];
@@ -47,8 +45,6 @@ void smp_init()
 
     io_mfence();
 
-    // 注册接收bsp处理器的hpet中断转发的处理函数
-    ipi_regiserIPI(0xc8, NULL, &ipi_0xc8_handler, NULL, NULL, "IPI 0xc8");
     io_mfence();
     ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x00, ICR_INIT, ICR_ALL_EXCLUDE_Self, 0x00);
 
@@ -193,9 +189,3 @@ void smp_ap_start()
     while (1) // 这里要循环hlt,原因是当收到中断后,核心会被唤醒,处理完中断之后不会自动hlt
         hlt();
 }
-
-// 由BSP转发的HPET中断处理函数
-void ipi_0xc8_handler(uint64_t irq_num, uint64_t param, struct pt_regs *regs)
-{
-    sched_update_jiffies();
-}

+ 0 - 1
kernel/src/syscall/syscall.c

@@ -12,7 +12,6 @@
 #include <process/process.h>
 #include <time/sleep.h>
 // 导出系统调用入口函数,定义在entry.S中
-extern void system_call(void);
 extern void syscall_int(void);
 
 extern uint64_t sys_clock(struct pt_regs *regs);

+ 0 - 1
kernel/src/syscall/syscall.h

@@ -33,7 +33,6 @@ void syscall_init();
  * @param syscall_id 系统调用id
  * @return long 错误码
  */
-long enter_syscall(ul syscall_id, ul arg0, ul arg1, ul arg2, ul arg3, ul arg4, ul arg5, ul arg6, ul arg7);
 long enter_syscall_int(ul syscall_id, ul arg0, ul arg1, ul arg2, ul arg3, ul arg4, ul arg5, ul arg6, ul arg7);
 
 /**