118 lines
3.9 KiB
Markdown
118 lines
3.9 KiB
Markdown
# taskswitch -- Cooperative Task Switching Library
|
|
|
|
Cooperative (non-preemptive) multitasking library for DJGPP/DPMI (DOS
|
|
protected mode). Built as `libtasks.lib` -- a DXE3 module loaded by
|
|
the DVX loader.
|
|
|
|
|
|
## Why Cooperative
|
|
|
|
DOS is single-threaded with no kernel scheduler. DPMI provides no
|
|
thread or timer-based preemption. The DVX GUI event model is
|
|
inherently single-threaded (one compositor, one input queue, one
|
|
window stack). Cooperative switching lets each task yield at safe
|
|
points, avoiding the need for synchronization primitives entirely.
|
|
|
|
|
|
## Scheduling Algorithm
|
|
|
|
Credit-based weighted fair-share, round-robin within a credit epoch.
|
|
|
|
Each task receives `(priority + 1)` credits per scheduling round.
|
|
Tasks run round-robin, consuming one credit per turn. When all
|
|
credits are spent, every ready task is refilled.
|
|
|
|
| Priority | Constant | Credits/Round | Relative Share |
|
|
|----------|----------|---------------|----------------|
|
|
| 0 | `TS_PRIORITY_LOW` | 1 | ~4% |
|
|
| 5 | `TS_PRIORITY_NORMAL` | 6 | ~22% |
|
|
| 10 | `TS_PRIORITY_HIGH` | 11 | ~41% |
|
|
|
|
Higher-priority tasks run proportionally more often but never starve
|
|
lower ones. A priority-10 task gets 11 turns per round while a
|
|
priority-0 task gets 1.
|
|
|
|
|
|
## Task States
|
|
|
|
| State | Description |
|
|
|-------|-------------|
|
|
| `TaskStateReady` | Eligible for scheduling |
|
|
| `TaskStateRunning` | Currently executing (cosmetic marker) |
|
|
| `TaskStatePaused` | Skipped until resumed |
|
|
| `TaskStateTerminated` | Slot available for reuse |
|
|
|
|
|
|
## API Reference
|
|
|
|
| Function | Description |
|
|
|----------|-------------|
|
|
| `tsInit()` | Initialize task system; calling context becomes task 0 (main) |
|
|
| `tsShutdown()` | Shut down and free all resources |
|
|
| `tsCreate(name, entry, arg, stackSize, priority)` | Create a new task; returns task ID |
|
|
| `tsYield()` | Yield CPU to next eligible task (credit-based round-robin) |
|
|
| `tsPause(taskId)` | Pause a task (implicit yield if self) |
|
|
| `tsResume(taskId)` | Resume a paused task (refills credits) |
|
|
| `tsSetPriority(taskId, priority)` | Set priority (refills credits immediately) |
|
|
| `tsGetPriority(taskId)` | Get task priority |
|
|
| `tsGetState(taskId)` | Get task state |
|
|
| `tsCurrentId()` | Get currently running task's ID |
|
|
| `tsGetName(taskId)` | Get task name |
|
|
| `tsExit()` | Terminate calling task (never returns) |
|
|
| `tsKill(taskId)` | Forcibly terminate another task |
|
|
| `tsRecoverToMain()` | Force scheduler back to task 0 after crash longjmp |
|
|
| `tsActiveCount()` | Count of non-terminated tasks |
|
|
|
|
### Error Codes
|
|
|
|
| Constant | Value | Description |
|
|
|----------|-------|-------------|
|
|
| `TS_OK` | 0 | Success |
|
|
| `TS_ERR_INIT` | -1 | Initialization failure |
|
|
| `TS_ERR_PARAM` | -2 | Invalid parameter |
|
|
| `TS_ERR_FULL` | -3 | No available task slots |
|
|
| `TS_ERR_NOMEM` | -4 | Stack allocation failed |
|
|
| `TS_ERR_STATE` | -5 | Invalid state transition |
|
|
|
|
### Constants
|
|
|
|
| Constant | Value | Description |
|
|
|----------|-------|-------------|
|
|
| `TS_DEFAULT_STACK_SIZE` | 32768 | Default stack size (32KB) |
|
|
| `TS_NAME_MAX` | 32 | Maximum task name length |
|
|
|
|
|
|
## Task 0 (Main Task)
|
|
|
|
Task 0 is special:
|
|
* Cannot be killed or paused
|
|
* Uses the process stack directly (no separate allocation)
|
|
* `tsRecoverToMain()` always returns control here after a crash
|
|
* The DVX shell runs as task 0 with `TS_PRIORITY_HIGH`
|
|
|
|
|
|
## Crash Recovery
|
|
|
|
`tsRecoverToMain()` is called after `longjmp` from a signal handler
|
|
that fired in a non-main task. It fixes the scheduler's `currentIdx`
|
|
to point back to task 0. The crashed task is NOT cleaned up by this
|
|
call -- `tsKill()` must be called separately afterward.
|
|
|
|
|
|
## Files
|
|
|
|
| File | Description |
|
|
|------|-------------|
|
|
| `taskswitch.h` | Public API header |
|
|
| `taskswitch.c` | Complete implementation (context switch, scheduler, stack management) |
|
|
| `Makefile` | Builds `bin/libs/libtasks.lib` |
|
|
|
|
|
|
## Build
|
|
|
|
```
|
|
make # builds bin/libs/libtasks.lib
|
|
make clean # removes objects and library
|
|
```
|
|
|
|
No dependencies. Exports all symbols matching `_ts*`.
|