mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-13 00:26:28 +00:00
Comprehensive technical documentation covering: - Hardware: OCS/ECS/AGA custom chip registers, Copper & Blitter deep dives - Boot sequence: cold boot through startup-sequence - Binary format: HUNK executable spec, relocation, debug info - Linking & ABI: .fd files, LVO tables, register calling conventions - Exec kernel: tasks, interrupts, memory, signals, semaphores - AmigaDOS: file I/O, FFS/OFS layout, CLI/Shell scripting - Graphics: planar bitmaps, Copper programming, HAM/EHB modes - Intuition: screens, windows, IDCMP, BOOPSI - Devices: trackdisk, SCSI, serial, timer, audio, keyboard - Libraries: utility, expansion, IFFParse, locale, ARexx - Networking: bsdsocket API, SANA-II, TCP/IP stack comparison - Toolchain: GCC, vasm/vlink, SAS/C, NDK, debugging - Reverse engineering: IDA/Ghidra setup, compiler fingerprints, case studies - CPU & MMU: 68040/060 emulation libs, PMMU, cache management - Driver development: SANA-II, Picasso96/RTG, AHI audio All files include breadcrumb navigation. No local paths or proprietary content.
5 KiB
5 KiB
Tasks and Processes — Structures, States, Scheduling
Overview
AmigaOS uses cooperative/preemptive scheduling. Tasks are the fundamental unit of execution; Processes are Tasks with an additional DOS environment (message port, CLI, segment list). The scheduler runs at each quantum (50 Hz VBL interrupt) and after any Signal() or Wait() call.
struct Task
/* exec/tasks.h */
struct Task {
struct Node tc_Node; /* ln_Type=NT_TASK or NT_PROCESS */
/* ln_Pri = scheduling priority */
/* ln_Name = task name string */
UBYTE tc_Flags; /* TF_LAUNCH, TF_STRIKE, TF_EXCEPT */
UBYTE tc_State; /* TS_RUN, TS_READY, TS_WAIT, TS_EXCEPT */
BYTE tc_IDNestCnt; /* interrupt disable nesting */
BYTE tc_TDNestCnt; /* task disable (Forbid) nesting */
ULONG tc_SigAlloc; /* allocated signal bits mask */
ULONG tc_SigWait; /* signals task is waiting for */
ULONG tc_SigRecvd; /* signals received */
ULONG tc_SigExcept; /* exception signals */
/* ... stack bounds, context, exception handler ... */
APTR tc_SPLower; /* lowest valid stack address */
APTR tc_SPUpper; /* highest valid stack address + 2 */
APTR tc_SPReg; /* saved stack pointer (when not running) */
};
struct Process (extends Task)
/* dos/dosextens.h */
struct Process {
struct Task pr_Task; /* embedded Task */
struct MsgPort pr_MsgPort; /* I/O message port */
UWORD pr_Pad;
BPTR pr_SegList; /* BPTR to segment list */
LONG pr_StackSize;
APTR pr_GlobVec; /* BCPL global vector */
LONG pr_TaskNum; /* CLI task number */
BPTR pr_StackBase; /* base of stack (BPTR) */
LONG pr_Result2; /* secondary result */
BPTR pr_CurrentDir; /* current directory lock */
BPTR pr_CIS; /* current input stream */
BPTR pr_COS; /* current output stream */
APTR pr_ConsoleTask;
APTR pr_FileSystemTask;
BPTR pr_CLI; /* CLI structure (NULL if WB) */
...
struct MsgPort *pr_ReturnAddr; /* return address for CLI tasks */
APTR pr_PktWait;
struct SaveMsg pr_ExitData;
UBYTE *pr_Arguments; /* argument string */
struct MinList pr_LocalVars; /* local shell variables */
ULONG pr_ShellPrivate;
BPTR pr_CES; /* current error stream */
};
Task States
| State | Value | Meaning |
|---|---|---|
TS_INVALID |
0 | Not a valid task |
TS_ADDED |
1 | Just added, not yet scheduled |
TS_RUN |
2 | Currently running (only one task) |
TS_READY |
3 | On the TaskReady list, waiting for CPU |
TS_WAIT |
4 | Blocked on Wait() — on TaskWait list |
TS_EXCEPT |
5 | Handling an exception |
TS_REMOVED |
6 | Removed from scheduling |
Scheduling: Priority-Based Round Robin
The scheduler (exec.library internal) picks the highest-priority task from SysBase→TaskReady. Among equal-priority tasks, they get equal time slices (round-robin).
- Default priority: 0
- Range: −128 to +127 (higher = more CPU)
- OS tasks run at priority 10–20
- Input handler: priority 20
- Disk tasks: priority 10
SetTaskPri(FindTask(NULL), 5); /* raise current task to priority 5 */
Creating Tasks and Processes
/* Simple task (exec level): */
struct Task *t = AllocMem(sizeof(struct Task), MEMF_PUBLIC|MEMF_CLEAR);
t->tc_Node.ln_Name = "MyTask";
t->tc_Node.ln_Pri = 0;
t->tc_SPLower = stack;
t->tc_SPUpper = stack + stacksize;
t->tc_SPReg = (APTR)((ULONG)stack + stacksize);
AddTask(t, myTaskFunc, NULL);
/* DOS Process (with message port, filesystem access): */
struct Process *p = CreateNewProcTags(
NP_Entry, myFunc,
NP_Name, "MyProcess",
NP_StackSize, 8192,
NP_Priority, 0,
TAG_DONE);
Task State Machine
stateDiagram-v2
[*] --> READY : AddTask()
READY --> RUN : Scheduler picks task
RUN --> READY : Quantum expired or higher-priority task
RUN --> WAIT : Wait(signal_mask)
WAIT --> READY : Signal() delivers awaited signals
RUN --> EXCEPT : Exception signal received
EXCEPT --> RUN : Exception handler returns
RUN --> [*] : Task function returns / RemTask()
FindTask and Task Identity
struct Task *me = FindTask(NULL); /* NULL = current task */
printf("Running as: %s\n", me->tc_Node.ln_Name);
/* Check if we are a Process (vs plain Task): */
if (me->tc_Node.ln_Type == NT_PROCESS) {
struct Process *pr = (struct Process *)me;
/* access pr_CLI, pr_MsgPort, etc. */
}
References
- NDK39:
exec/tasks.h,dos/dosextens.h - ADCD 2.1:
AddTask,RemTask,FindTask,SetTaskPri,CreateNewProc - Amiga ROM Kernel Reference Manual: Exec — tasks and scheduling chapter