Skip to content

Commit

Permalink
wip(lab/5): add counter
Browse files Browse the repository at this point in the history
  • Loading branch information
GZTimeWalker committed Mar 2, 2024
1 parent a5e0059 commit bc74bdf
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
27 changes: 27 additions & 0 deletions docs/labs/0x05/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,8 @@ pub struct ProcessData {

但在多核处理器下,`Semaphore` 的实现可能会涉及到多个核心的并发访问,因此需要使用 `Mutex` 来提供更细粒度的锁保护。在进行添加、删除操作时,对 `RwLock` 使用 `write` 获取写锁,而在进行 `signal`、`wait` 操作时,对 `RwLock` 使用 `read` 来获取更好的性能和控制。

综上考量,这里就保留了 `Mutex` 的使用。

请参考实验代码给出的相关注释内容,完成信号量的实现。最后将 `Semaphore` 的操作层层向上传递(或者说自上向下层层委托具体实现),实现作为系统调用的 `sys_sem`

```rust
Expand All @@ -539,6 +541,31 @@ pub fn sys_sem(args: &SyscallArgs, context: &mut ProcessContext) {

#### 多线程计数器

在所给代码的 `pkg/app/counter` 中实现了一个多线程计数器,多个线程对一个共享的计数器进行累加操作,最终输出计数器的值。

为了提供足够大的可能性来触发竞态条件,该程序使用了一些手段来刻意构造一个临界区,这部分代码不应被修改。

你需要通过上述**两种方式**,分别保护该临界区,使得计数器的值最终为 `800`

!!! note "尝试修改代码,使用**两组线程**分别测试 `SpinLock``Semaphore`"

一个参考代码行为如下,你可以在 `test_spin` 和 `test_semaphore` 中分别继续 `fork` 更多的进程用来实际测试:

```rust
fn main() -> isize {
let pid = sys_fork();

if pid == 0 {
test_semaphore();
} else {
test_spin();
sys_wait_pid(pid);
}

0
}
```

#### 哲学家的晚饭

#### 消息队列
Expand Down
7 changes: 7 additions & 0 deletions src/0x05/pkg/app/counter/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "ysos_counter"
version = "0.1.0"
edition = "2021"

[dependencies]
lib = { path="../../lib", package="yslib"}
68 changes: 68 additions & 0 deletions src/0x05/pkg/app/counter/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#![no_std]
#![no_main]

use lib::*;

extern crate lib;

const THREAD_COUNT: usize = 8;
static mut COUNTER: isize = 0;

fn main() -> isize {
let mut pids = [0u16; THREAD_COUNT];

for i in 0..THREAD_COUNT {
let pid = sys_fork();
if pid == 0 {
do_counter_inc();
sys_exit(0);
} else {
pids[i] = pid; // only parent knows child's pid
}
}

let cpid = sys_get_pid();
println!("process #{} holds threads: {:?}", cpid, &pids);
sys_stat();

for i in 0..THREAD_COUNT {
println!("#{} waiting for #{}...", cpid, pids[i]);
sys_wait_pid(pids[i]);
}

println!("COUNTER result: {}", unsafe { COUNTER });

0
}

fn do_counter_inc() {
for _ in 0..100 {
// FIXME: protect the critical section
inc_counter();
}
}

/// Increment the counter
///
/// this function simulate a critical section by delay
/// DO NOT MODIFY THIS FUNCTION
fn inc_counter() {
unsafe {
delay();
let mut val = COUNTER;
delay();
val += 1;
delay();
COUNTER = val;
}
}

#[inline(never)]
#[no_mangle]
fn delay() {
for _ in 0..0x100 {
core::hint::spin_loop();
}
}

entry!(main);

0 comments on commit bc74bdf

Please sign in to comment.