mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-13 01:48:42 +00:00
docs(appdev): update best practices for loop throttling
This commit is contained in:
parent
a3a4494265
commit
d45a19aac1
4 changed files with 14 additions and 13 deletions
|
|
@ -11,7 +11,7 @@ This example demonstrates how to create an empty window that stays active on the
|
|||
* Including `libui.h` and the event structure.
|
||||
* Creating a `ui_window_t` handle.
|
||||
* Creating an infinite event loop using `ui_get_event()`.
|
||||
* Yielding CPU time to the kernel via `sys_yield()`.
|
||||
* Yielding CPU time via `sleep(ms)`.
|
||||
* Declaring app metadata via source annotations.
|
||||
|
||||
---
|
||||
|
|
@ -50,10 +50,11 @@ int main(void) {
|
|||
}
|
||||
}
|
||||
|
||||
// 4. CRITICAL: Yield the remainder of our timeslice
|
||||
// 4. CRITICAL: Throttle our loop to save CPU
|
||||
// If we don't do this, the while(1) loop will consume 100% of the CPU
|
||||
// and starve the rest of the OS!
|
||||
sys_yield();
|
||||
// and starve the rest of the OS! A 10ms sleep allows for ~100 FPS
|
||||
// event polling while letting the CPU actually idle.
|
||||
sys_system(SYSTEM_CMD_SLEEP, 10, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Returning from main will automatically destroy the window and exit the process.
|
||||
|
|
@ -66,7 +67,7 @@ int main(void) {
|
|||
1. **Window Handle (`wid`)**: `ui_window_create` sends a request to the kernel. The kernel allocates the memory for the window and returns a numerical ID (the handle) that we use for all future interactions with that specific window.
|
||||
2. **The Event Loop**: Graphical programs run forever until closed. The `while (1)` loop serves this purpose.
|
||||
3. **Polling**: `ui_get_event` asks the kernel, "Hey, did the user click my window or press a key since the last time I asked?". It is non-blocking, so it immediately returns `false` if nothing happened.
|
||||
4. **CPU Yielding**: Since we are constantly polling in a tight loop, we call `sys_yield()` at the end of the loop frame. This politely tells the OS scheduler, "I'm done checking for events, go ahead and let another program run for a bit."
|
||||
4. **CPU Throttling**: Since we are constantly polling in a loop, we call `sys_system(SYSTEM_CMD_SLEEP, 10, ...)` at the end of the loop frame. This tells the OS scheduler, "I'm done checking for events, don't run me again for at least 10ms." This allows the CPU to actually enter a low-power state and makes the system much smoother.
|
||||
5. **`BOREDOS_APP_DESC` / `BOREDOS_APP_ICONS`**: Embedded into the `.elf` by the build system as a BoredOS NOTE section. The Window Manager reads this at runtime to render the app's icon on the Desktop and in the File Explorer. See [`elf_metadata.md`](../elf_metadata.md) for full details.
|
||||
|
||||
## Running It
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ int main(void) {
|
|||
// Step D: Instruct the compositor to flush our drawing buffer to the physical screen
|
||||
ui_mark_dirty(wid, 0, 0, W_WIDTH, W_HEIGHT);
|
||||
|
||||
// 4. Yield and throttle
|
||||
sys_yield();
|
||||
// 4. Yield and throttle (targeting ~60 FPS)
|
||||
sys_system(SYSTEM_CMD_SLEEP, 16, 0, 0, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -93,4 +93,4 @@ int main(void) {
|
|||
5. **`BOREDOS_APP_DESC` / `BOREDOS_APP_ICONS`**: Embedded into the compiled `.elf` as a BoredOS NOTE section. The Desktop and File Explorer read this to show the game's icon instead of the generic binary icon. See [`elf_metadata.md`](../elf_metadata.md) for full details.
|
||||
|
||||
> [!WARNING]
|
||||
> Because `sys_yield()`'s pause duration depends heavily on CPU load and how many other processes are running (or QEMU emulation speed), tying physics/movement strictly to loops can make the game run faster on faster computers. Advanced developers will want to calculate delta time (time elapsed since the last frame) for smooth motion.
|
||||
> Because `sys_system(SYSTEM_CMD_SLEEP, ...)`'s pause duration depends heavily on CPU load and how many other processes are running (or QEMU emulation speed), tying physics/movement strictly to loops can make the game run faster on faster computers. Advanced developers will want to calculate delta time (time elapsed since the last frame) for smooth motion.
|
||||
|
|
|
|||
|
|
@ -110,8 +110,8 @@ Notes:
|
|||
| 28 | `SYSTEM_CMD_GET_SHELL_CONFIG` | Read shell config value |
|
||||
| 32 | `SYSTEM_CMD_RTC_SET` | Set RTC datetime |
|
||||
| 41 | `SYSTEM_CMD_SET_RAW_MODE` | Terminal raw-mode control |
|
||||
| 43 | `SYSTEM_CMD_YIELD` | Yield scheduler timeslice |
|
||||
| 46 | `SYSTEM_CMD_SLEEP` | Sleep current process |
|
||||
| 43 | `SYSTEM_CMD_YIELD` | Yield scheduler timeslice (Not recommended for idle loops) |
|
||||
| 46 | `SYSTEM_CMD_SLEEP` | Sleep current process (Recommended for throttling) |
|
||||
|
||||
### Network
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ Notes:
|
|||
## Common Wrapper API (`src/userland/libc/syscall.h`)
|
||||
|
||||
Typical wrappers used by apps:
|
||||
- Process/system: `sys_exit`, `sys_yield`, `sys_spawn`, `sys_exec`, `sys_waitpid`, `sys_kill_signal`
|
||||
- Process/system: `sys_exit`, `sys_yield`, `sys_system` (with `SYSTEM_CMD_SLEEP`), `sys_spawn`, `sys_exec`, `sys_waitpid`
|
||||
- Filesystem: `sys_open`, `sys_read`, `sys_write_fs`, `sys_close`, `sys_seek`, `sys_tell`, `sys_size`, `sys_list`
|
||||
- Network: `sys_network_init`, `sys_network_dhcp_acquire`, `sys_udp_send`, `sys_tcp_connect`, `sys_tcp_recv_nb`, `sys_dns_lookup`
|
||||
- TTY: `sys_tty_create`, `sys_tty_read_out`, `sys_tty_write_in`, `sys_tty_set_fg`
|
||||
|
|
|
|||
|
|
@ -68,9 +68,9 @@ Applications must continuously poll for events inside an infinite `$while(1)` lo
|
|||
Returns `true` if an event was waiting in the queue, populating the `ev` structure. Returns `false` if the queue is empty.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Because `ui_get_event` is non-blocking, you must call `sys_yield();` inside your event loop if no event was received. In BoredOS's **Multi-Core (SMP)** architecture, failing to yield will pin a CPU core to 100% usage, potentially starving other processes.
|
||||
> Because `ui_get_event` is non-blocking, you must call `sleep(ms);` or `sys_system(SYSTEM_CMD_SLEEP, ms, ...)` inside your event loop if no event was received.
|
||||
>
|
||||
> All UI syscalls are **Thread-Safe** at the kernel level via the global GUI spinlock.
|
||||
> Historically, BoredOS used `sys_yield()`, but in the **Multi-Core (SMP)** architecture, yielding alone will still pin a CPU core to 100% usage. Using a short sleep (e.g., 5-10ms) ensures your app remains responsive while allowing the CPU to actually idle.
|
||||
|
||||
### Graphical Event Structure
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue