Skip to content

Commit

Permalink
Import app docs from the arceos main repo
Browse files Browse the repository at this point in the history
  • Loading branch information
equation314 committed Jul 22, 2024
1 parent 8c86c36 commit a47dd3a
Show file tree
Hide file tree
Showing 19 changed files with 1,458 additions and 9 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Other arguments are the same as ArceOS's [Makefile](https://github.com/arceos-or
For example, to run the [httpserver](rust/net/httpserver/) on `qemu-system-aarch64` with 4 cores and log level `info`:

```bash
make A=apps/net/httpserver ARCH=aarch64 LOG=info SMP=4 run NET=y
make A=rust/net/httpserver ARCH=aarch64 LOG=info SMP=4 run NET=y
```

Note that the `NET=y` argument is required to enable the network device in QEMU. These arguments (`BLK`, `GRAPHIC`, etc.) only take effect at runtime not build time.
Expand All @@ -76,7 +76,7 @@ Note that the `NET=y` argument is required to enable the network device in QEMU.
| [helloworld](rust/helloworld/) | | | A minimal app that just prints a string |
| [exception](rust/exception/) | | | Exception handling test |
| [memtest](rust/memtest/) | alloc | axalloc | Dynamic memory allocation test |
| [display](rust/display/) | display | axdisplay | Graphic/GUI test |
| [display](rust/display/) | display | axdriver, axdisplay | Graphic/GUI test |
| [yield](rust/task/yield/) | multitask | axalloc, axtask | Multi-threaded yielding test |
| [sleep](rust/task/sleep/) | multitask, irq | axalloc, axtask | Thread sleeping test |
| [parallel](rust/task/parallel/) | alloc, multitask | axalloc, axtask | Parallel computing test (to test synchronization & mutex) |
Expand All @@ -85,7 +85,7 @@ Note that the `NET=y` argument is required to enable the network device in QEMU.
| [shell](rust/fs/shell/) | alloc, fs | axalloc, axdriver, axfs | A simple shell that responds to filesystem operations |
| [httpclient](rust/net/httpclient/) | net | axalloc, axdriver, axnet | A simple client that sends an HTTP request and then prints the response |
| [udpserver](rust/net/udpserver/) | net | axalloc, axdriver, axnet | A single-threaded echo server using UDP protocol |
| [echoserver](rust/net/echoserver/) | alloc, multitask, net | axalloc, axdriver, axnet, axtask | A multi-threaded TCP server that reverses messages sent by the client |
| [echoserver](rust/net/echoserver/) | alloc, multitask, net | axalloc, axdriver, axnet, axtask | A multi-threaded TCP server that reverses messages sent by the client |
| [httpserver](rust/net/httpserver/) | alloc, multitask, net | axalloc, axdriver, axnet, axtask | A multi-threaded HTTP server that serves a static web page |
| [bwbench](rust/net/bwbench/) | net | axalloc, axdriver, axnet | Network bandwidth benchmark |

Expand Down
2 changes: 1 addition & 1 deletion c/httpserver/httpserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const char content[] = "<html>\n\
</center>\n\
<hr>\n\
<center>\n\
<i>Powered by <a href=\"https://github.com/arceos-org/arceos/tree/main/apps/net/httpserver\">ArceOS example HTTP server</a> v0.1.0</i>\n\
<i>Powered by <a href=\"https://github.com/arceos-org/arceos-apps/tree/main/c/httpserver\">ArceOS example HTTP server</a> v0.1.0</i>\n\
</center>\n\
</body>\n\
</html>\n\
Expand Down
2 changes: 1 addition & 1 deletion c/iperf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Build and start the [`iperf3`](https://github.com/esnet/iperf) server on ArceOS:

```bash
# in arceos root directory
make A=apps/c/iperf BLK=y NET=y ARCH=<arch> run
make A=c/iperf BLK=y NET=y ARCH=<arch> run
```

## Benchmark
Expand Down
6 changes: 3 additions & 3 deletions c/redis/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

# How to run?
- Run:
- `make A=apps/c/redis/ LOG=error NET=y BLK=y ARCH=aarch64 SMP=4 run`(for aarch64)
- `make A=apps/c/redis/ LOG=error NET=y BLK=y ARCH=x86_64 SMP=4 run`(for x86_64)
- `make A=c/redis/ LOG=error NET=y BLK=y ARCH=aarch64 SMP=4 run`(for aarch64)
- `make A=c/redis/ LOG=error NET=y BLK=y ARCH=x86_64 SMP=4 run`(for x86_64)

# How to test?
- Use `redis-cli -p 5555` to connect to redis-server, and enjoy ArceOS-Redis world!
Expand Down Expand Up @@ -269,7 +269,7 @@ MSET (10 keys): 183150.19 requests per second

## Compile and Run

- `make A=apps/c/redis LOG=error PLATFORM=x86_64-pc-oslab SMP=4 FEATURES=driver-ixgbe,driver-ramdisk IP=10.2.2.2 GW=10.2.2.1`
- `make A=c/redis LOG=error PLATFORM=x86_64-pc-oslab SMP=4 FEATURES=driver-ixgbe,driver-ramdisk IP=10.2.2.2 GW=10.2.2.1`
- Copy `redis_x86_64-pc-oslab.elf` to `/boot`, then reboot.
- Enter `grub` then boot the PC by ArceOS Redis.
- Connect to ArceOS-Redis server by:
Expand Down
106 changes: 106 additions & 0 deletions docs/apps_display.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# INTRODUCTION
| App | Enabled features | Extra modules | Description |
|-|-|-|-|
| [display](../rust/display/) | display | axdriver, axdisplay | Graphic/GUI test |

# RUN

```bash
make A=rust/display GRAPHIC=y LOG=debug run
```

# RESULT

```text
...
[ 0.408067 axdriver:59] Initialize device drivers...
[ 0.410941 driver_virtio:50] Detected virtio MMIO device with vendor id: 0x554D4551, device type: GPU, version: Legacy
[ 0.414473 virtio_drivers::device::gpu:47] Device features EDID | NOTIFY_ON_EMPTY | ANY_LAYOUT | RING_INDIRECT_DESC | RING_EVENT_IDX
[ 0.418886 virtio_drivers::device::gpu:57] events_read: 0x0, num_scanouts: 0x1
[ 0.423408 virtio_drivers::device::gpu:102] => RespDisplayInfo { header: CtrlHeader { hdr_type: Command(4353), flags: 0, fence_id: 0, ctx_id: 0, _padding: 0 }, rect: Rect { x: 0, y: 0, width: 1280, height: 800 }, enabled: 1, flags: 0 }
[ 0.452037 axdriver::virtio:88] created a new Display device: "virtio-gpu"
[ 0.455473 axdisplay:17] Initialize Display subsystem...
[ 0.458124 axdisplay:19] number of Displays: 1
...
...
...
(never end)
```
![display](figures/display.png)

# STEPS

## step1

``` rust
let mut board = DrawingBoard::new();
board.disp.clear(Rgb888::BLACK).unwrap();
```

**flow chart**
```mermaid
graph TD;
A["DrawingBoard::new()"] --> B["display::Display::new()"];
A --> C["embedded_graphics::prelude::Point::new(INIT_X, INIT_Y)"];
B --> D["libax::display::framebuffer_info"]
B --> E["core::slice::from_raw_parts_mut"]
B --> F["embedded_graphics::prelude::Size::new"]
D --> G["axsync::Mutex(axdriver::DisplayDevices)::lock"]
D --> H["axdriver::DisplayDevices::info"]
```

## step2
``` rust
for _ in 0..5 {
board.latest_pos.x += RECT_SIZE as i32 + 20;
board.paint();
framebuffer_flush();
}
...
impl DrawingBoard {
...
fn paint(&mut self) {
Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE))
.into_styled(PrimitiveStyle::with_stroke(Rgb888::RED, 10))
.draw(&mut self.disp)
.ok();
Circle::new(self.latest_pos + Point::new(-70, -300), 150)
.into_styled(PrimitiveStyle::with_fill(Rgb888::BLUE))
.draw(&mut self.disp)
.ok();
Triangle::new(
self.latest_pos + Point::new(0, 150),
self.latest_pos + Point::new(80, 200),
self.latest_pos + Point::new(-120, 300),
)
.into_styled(PrimitiveStyle::with_stroke(Rgb888::GREEN, 10))
.draw(&mut self.disp)
.ok();
let text = "ArceOS";
Text::with_alignment(
text,
self.latest_pos + Point::new(0, 300),
MonoTextStyle::new(&FONT_10X20, Rgb888::YELLOW),
Alignment::Center,
)
.draw(&mut self.disp)
.ok();
}
}
```

**flow chart**
```mermaid
graph TD;
A["DrawingBoard::paint"] --> B["embedded_graphics::primitives::{Circle, PrimitiveStyle, Rectangle, Triangle}"];
A --> C["embedded_graphics::text::{Alignment, Text}"]
B --> D["impl embedded_graphics::draw_target::DrawTarget, embedded_graphics::prelude::OriginDimensions for Display"]
C --> D
```

## step3
``` rust
loop {
core::hint::spin_loop();
}
```
106 changes: 106 additions & 0 deletions docs/apps_echoserver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# INTRODUCTION

| App | Enabled features | Extra modules | Description |
|-|-|-|-|
| [echoserver](../rust/net/echoserver/) | alloc, multitask, net | axalloc, axdriver, axnet, axtask | A multi-threaded TCP server that reverses messages sent by the client |

# RUN

```console
$ make A=rust/net/echoserver NET=y run
...
Hello, echo server!
listen on: 10.0.2.15:5555
```

In another shell, use `telnet` (or `nc`) to connect to localhost (`127.0.0.1`) to view the reversed echo message:

```console
$ telnet localhost 5555
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello
olleh
12345
54321
```

```console
$ nc 127.0.0.1 5555
hello
olleh
12345
54321
```

# STEPS

## step1

[init](./init.md)

After executed all initial actions, then arceos calls `main` function in `echoserver` app.

## step2

`main` calls `accept_loop()`, which will keep processing incoming tcp connection.

```rust
let (addr, port) = (IpAddr::from_str(LOCAL_IP).unwrap(), LOCAL_PORT);
let mut listener = TcpListener::bind((addr, port).into())?;
println!("listen on: {}", listener.local_addr().unwrap());

let mut i = 0;
loop {
match listener.accept() {
...
}
Err(e) => return Err(e),
}
i += 1;
}
```

## step3

Once it receives a tcp connection. It will get a `(stream, addr)` pair from `libax::net`.
`main` task will spawn a task to reverse every package it receives.

```rust
Ok((stream, addr)) => {
info!("new client {}: {}", i, addr);
task::spawn(move || match echo_server(stream) {
Err(e) => error!("client connection error: {:?}", e),
Ok(()) => info!("client {} closed successfully", i),
});
}
```

## step4

Reverse bytes in package it receives.

```rust
fn reverse(buf: &[u8]) -> Vec<u8> {
let mut lines = buf
.split(|&b| b == b'\n')
.map(Vec::from)
.collect::<Vec<_>>();
for line in lines.iter_mut() {
line.reverse();
}
lines.join(&b'\n')
}

fn echo_server(mut stream: TcpStream) -> io::Result {
let mut buf = [0u8; 1024];
loop {
let n = stream.read(&mut buf)?;
if n == 0 {
return Ok(());
}
stream.write_all(reverse(&buf[..n]).as_slice())?;
}
}
```
66 changes: 66 additions & 0 deletions docs/apps_exception.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# INTRODUCTION

| App | Enabled features | Extra modules | Description |
|-|-|-|-|
| [exception](../rust/exception/) | | | Exception handling test |

# RUN

```console
$ make A=rust/exception LOG=debug run
...
Running exception tests...
[ 0.249873 0 axhal::arch::riscv::trap:13] Exception(Breakpoint) @ 0xffffffc0802001e8
Exception tests run OK!
[ 0.068358 0 axtask::api:6] main task exited: exit_code=0
[ 0.069128 0 axhal::platform::qemu_virt_riscv::misc:2] Shutting down...
```

# STEPS

## step1

[init](./init.md)

After executed all initial actions, then arceos calls `main` function in `exception` app.

## step2

``` Rust
fn raise_break_exception() {
unsafe {
#[cfg(target_arch = "x86_64")]
asm!("int3");
#[cfg(target_arch = "aarch64")]
asm!("brk #0");
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
asm!("ebreak");
}
}

#[no_mangle]
fn main() {
println!("Running exception tests...");
raise_break_exception();
println!("Exception tests run OK!");
}
```

**flow chart**

```mermaid
graph TD;
A[" asm!(ebreak)"] --> B["raise exception"];
B --> C["axhal::arch::riscv::trap.S::trap_vector_base"];
C --> D["switch sscratch and sp"];
C -- "from U mode" --> E["Ltrap_entry_u: SAVE_REGS 1; a1 <-- 1"];
C -- "from S mode" --> F["Ltrap_entry_s: SAVE_REGS 0; a1 <-- 0"];
E --> G[axhal::arch::riscv::trap::riscv_trap_handler];
F --> G;
G -- "Trap::Exception(E::Breakpoint)" --> H["handle_breakpoint(&mut tf.sepc)"];
H --> I["debug!(Exception(Breakpoint) @ {:#x} , sepc);*sepc += 2;"];
I -- "from U mode" --> J["Ltrap_entry_u: RESTORE_REGS 1"];
I -- "from S mode" --> K["Ltrap_entry_s: RESTORE_REGS 0"];
J --> L[sret];
K --> L;
```
Loading

0 comments on commit a47dd3a

Please sign in to comment.