# Modified Linux Scheduler
## 編譯 Linux Kernel
1. 從 [Linux 網站](https://www.kernel.org/) 下載 v5.11.11 原始程式碼
2. 使用以下檔案取代 [Modifying the Linux CFS scheduler](https://github.com/arora-ansh/Modified-Linux-Scheduler) 原先 `diff.txt`:
:::spoiler `diff.txt`
```diff
diff -ruN linux3/linux-5.11.11/arch/x86/entry/syscalls/syscall_64.tbl linux4/linux-5.11.11/arch/x86/entry/syscalls/syscall_64.tbl
--- linux3/linux-5.11.11/arch/x86/entry/syscalls/syscall_64.tbl 2020-10-27 13:00:09.125164858 -0700
+++ linux4/linux-5.11.11/arch/x86/entry/syscalls/syscall_64.tbl 2020-11-09 14:43:13.711767973 -0800
@@ -363,6 +363,7 @@
439 common faccessat2 sys_faccessat2
440 common process_madvise sys_process_madvise
441 common epoll_pwait2 sys_epoll_pwait2
+442 common rtinice sys_rtinice
#
# x32-specific system call numbers start at 512 to avoid cache impact
Binary files linux3/linux-5.11.11/certs/signing_key.x509 and linux4/linux-5.11.11/certs/signing_key.x509 differ
diff -ruN linux3/linux-5.11.11/include/linux/sched.h linux4/linux-5.11.11/include/linux/sched.h
--- linux3/linux-5.11.11/include/linux/sched.h 2020-10-16 23:31:22.000000000 -0700
+++ linux4/linux-5.11.11/include/linux/sched.h 2020-11-10 22:19:17.666919549 -0800
@@ -463,6 +463,7 @@
u64 prev_sum_exec_runtime;
u64 nr_migrations;
+ u64 rt_val;
struct sched_statistics statistics;
diff -ruN linux3/linux-5.11.11/kernel/sched/core.c linux4/linux-5.11.11/kernel/sched/core.c
--- linux3/linux-5.11.11/kernel/sched/core.c 2020-10-16 23:31:22.000000000 -0700
+++ linux4/linux-5.11.11/kernel/sched/core.c 2020-11-10 22:16:56.083024806 -0800
@@ -3555,6 +3555,7 @@
p->se.prev_sum_exec_runtime = 0;
p->se.nr_migrations = 0;
p->se.vruntime = 0;
+ p->se.rt_val = 0;
INIT_LIST_HEAD(&p->se.group_node);
#ifdef CONFIG_FAIR_GROUP_SCHED
diff -ruN linux3/linux-5.11.11/kernel/sched/fair.c linux4/linux-5.11.11/kernel/sched/fair.c
--- linux3/linux-5.11.11/kernel/sched/fair.c 2020-10-16 23:31:22.000000000 -0700
+++ linux4/linux-5.11.11/kernel/sched/fair.c 2020-11-12 01:58:19.030370095 -0800
@@ -534,6 +534,15 @@
static inline int entity_before(struct sched_entity *a,
struct sched_entity *b)
{
+ /* In case both process have rt_vals, the one with lower value will be placed on left in the RB Tree (since higher on priority)
+ This is done by returning value of 0 if b is having a lower rt_val, and a value of 1 if a is having a lower rt_val */
+ if (a->rt_val && b->rt_val)
+ return b->rt_val > a->rt_val;
+ else if (a->rt_val)
+ return 1;
+ else if (b->rt_val)
+ return 0;
+ /* Normal functioning if no two processes has real time soft value given */
return (s64)(a->vruntime - b->vruntime) < 0;
}
@@ -844,6 +864,7 @@
struct sched_entity *curr = cfs_rq->curr;
u64 now = rq_clock_task(rq_of(cfs_rq));
u64 delta_exec;
+ u64 cur_rt_val;
if (unlikely(!curr))
return;
@@ -860,8 +881,18 @@
curr->sum_exec_runtime += delta_exec;
schedstat_add(cfs_rq->exec_clock, delta_exec);
- curr->vruntime += calc_delta_fair(delta_exec, curr);
- update_min_vruntime(cfs_rq);
+ cur_rt_val = curr->rt_val;
+ if (!cur_rt_val) {
+ curr->vruntime += calc_delta_fair(delta_exec, curr);
+ update_min_vruntime(cfs_rq);
+ }
+ /* Just as in the case of vruntime, we operate on our s_val with delta_exec value. curr stores scheduler entity of the process in operation */
+ else {
+ if (delta_exec <= cur_rt_val)
+ curr->rt_val = cur_rt_val - delta_exec;
+ else
+ curr->rt_val = 0;
+ }
if (entity_is_task(curr)) {
struct task_struct *curtask = task_of(curr);
diff -ruN linux3/linux-5.11.11/Makefile linux4/linux-5.11.11/Makefile
--- linux3/linux-5.11.11/Makefile 2020-10-27 12:57:13.449981474 -0700
+++ linux4/linux-5.11.11/Makefile 2020-11-09 14:38:10.538349002 -0800
@@ -1098,7 +1098,7 @@
export MODULES_NSDEPS := $(extmod-prefix)modules.nsdeps
ifeq ($(KBUILD_EXTMOD),)
-core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
+core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ rtnice/
vmlinux-dirs := $(patsubst %/,%,$(filter %/, \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
diff -ruN linux3/linux-5.11.11/rtnice/Makefile linux4/linux-5.11.11/rtnice/Makefile
--- linux3/linux-5.11.11/rtnice/Makefile 1969-12-31 16:00:00.000000000 -0800
+++ linux4/linux-5.11.11/rtnice/Makefile 2020-11-09 14:35:38.107727647 -0800
@@ -0,0 +1 @@
+obj-y := rtnice.o
\ No newline at end of file
diff -ruN linux3/linux-5.11.11/rtnice/rtnice.c linux4/linux-5.11.11/rtnice/rtnice.c
--- linux3/linux-5.11.11/rtnice/rtnice.c 1969-12-31 16:00:00.000000000 -0800
+++ linux4/linux-5.11.11/rtnice/rtnice.c 2020-11-10 22:26:28.780166034 -0800
@@ -0,0 +1,41 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/syscalls.h>
+#include <linux/printk.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/proc_fs.h>
+#include <linux/pid.h>
+#include <linux/pid_namespace.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/uaccess.h>
+#include <linux/mm.h>
+
+SYSCALL_DEFINE2(rtnice, int,pid, long, rt_val) {
+
+ struct pid *pid_struct = NULL;
+ struct task_struct *process;
+ unsigned long long s_val;
+
+ if (rt_val < 0 || pid < 0) {
+ return -EINVAL;
+ }
+
+ s_val = rt_val * 1000000000;
+
+ pid_struct = find_get_pid(pid);
+ if (pid_struct == NULL) {
+ return -ESRCH;
+ }
+ process = pid_task(pid_struct, PIDTYPE_PID);
+
+ process->se.rt_val = s_val;
+ printk(KERN_ALERT "Value of real time req of PID: %d changed to %llu succesfully\n", pid, process->se.rt_val);
+
+ return 0;
+
+}
```
:::
3. 將原先 [Modifying the Linux CFS scheduler](https://github.com/arora-ansh/Modified-Linux-Scheduler) 的 `test.c` 與 `test2.c` 內的 syscall 呼叫號碼改為 ==442==
5. 使用 patch 工具變更 Linux 核心原始碼,將 `diff.txt` 與 `linux` 目錄放置在同一層:
```
base
|--linux-5.11.11
|--diff.txt
```
在 base 目錄中執行以下命令:
```shell
patch -p1 < diff.txt
```
:::danger
* 從 github 上下載的 `diff.txt` 必須加上 end of line,否則 patch 時會產生會出錯。 [參考資料](https://unix.stackexchange.com/questions/1395/what-does-patch-unexpectedly-ends-in-middle-of-line-mean)
* 如有自行新增過 syscall,則在 `syscall_64.tbl` 內添加的 `sys_rtinice` 代號以及 `Makefile` 須自行更改。
:::
3. 依照 [建構 User-Mode Linux 的實驗環境](https://hackmd.io/@sysprog/user-mode-linux-env#%E5%BB%BA%E6%A7%8B-User-Mode-Linux-%E7%9A%84%E5%AF%A6%E9%A9%97%E7%92%B0%E5%A2%83) 指示建立 User Mode Linux
## 編譯測試程式碼
新增以下 Makefile:
```diff
all:
gcc -static -fopenmp -o test1 test.c
gcc -static -fopenmp -o test2 test.c
clear:
rm test1 test2
```
`-static` 用來指示靜態編譯,以便在 UML 中執行;`-fopenmp` 使用於 `omp_get_wtime` 函式。
將編譯完的執行檔複製到 UML 的 rootfs 下:
```
cp test1 linux-5.11.11/rootfs
cp test2 linux-5.11.11/rootfs
```
啟動 UML,執行 `test1` 與 `test2`。
## 執行結果
```cpp
/ # ./test1
Without Soft Real-Time Values-
Process finished in 11.104824 seconds
Process finished in 11.094899 seconds
Process finished in 11.080569 seconds
Process finished in 11.177793 seconds
Process finished in 11.146516 seconds
Process finished in 11.128278 seconds
Process finished in 11.210612 seconds
Process finished in 11.190418 seconds
Process finished in 11.221518 seconds
Process finished in 11.246885 seconds
With Soft Real-Time Values-
Value of real time req of PID: 59 changed to 25000000000 succesfully
Process with RT finished in 1.139814 seconds
Value of real time req of PID: 57 changed to 15000000000 succesfully
Process with RT finished in 2.266486 seconds
Value of real time req of PID: 56 changed to 10000000000 succesfully
Process with RT finished in 3.391552 seconds
Value of real time req of PID: 55 changed to 5000000000 succesfully
Process with RT finished in 4.531643 seconds
Value of real time req of PID: 64 changed to 50000000000 succesfully
Process with RT finished in 5.677368 seconds
Value of real time req of PID: 63 changed to 45000000000 succesfully
Process with RT finished in 6.824231 seconds
Value of real time req of PID: 62 changed to 40000000000 succesfully
Process with RT finished in 7.972721 seconds
Value of real time req of PID: 61 changed to 35000000000 succesfully
Process with RT finished in 9.101606 seconds
Value of real time req of PID: 60 changed to 30000000000 succesfully
Process with RT finished in 10.230780 seconds
Value of real time req of PID: 58 changed to 20000000000 succesfully
Process with RT finished in 11.382185 seconds
ERROR CHECK (Y=1 or 2/N=3) 3
/ # ./test2
With Mix of Non Soft-Time and Soft Real-Time Values-
Value of real time req of PID: 72 changed to 700000000000 succesfully
7. with RT 1.132002 seconds
Value of real time req of PID: 73 changed to 800000000000 succesfully
8. with RT 2.269580 seconds
Value of real time req of PID: 67 changed to 200000000000 succesfully
2. with RT 3.458060 seconds
10. 11.185943 seconds
4. 11.205015 seconds
1. 11.215062 seconds
6. 11.224214 seconds
3. 11.233990 seconds
9. 11.235572 seconds
5. 11.228095 seconds
```