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.
158 lines
4 KiB
Markdown
158 lines
4 KiB
Markdown
[← Home](../README.md) · [Exec Kernel](README.md)
|
|
|
|
# Lists and Nodes — MinList, List, Node, MinNode
|
|
|
|
## Overview
|
|
|
|
AmigaOS uses **intrusive doubly-linked lists** throughout exec: the task list, library list, device list, memory list, port list, and more all use the same `List`/`Node` structures defined in `exec/lists.h`.
|
|
|
|
---
|
|
|
|
## Structures
|
|
|
|
```c
|
|
/* exec/nodes.h — NDK39 */
|
|
|
|
struct Node {
|
|
struct Node *ln_Succ; /* pointer to next node (NULL at tail sentinel) */
|
|
struct Node *ln_Pred; /* pointer to prev node (NULL at head sentinel) */
|
|
UBYTE ln_Type; /* node type — NT_TASK, NT_LIBRARY, NT_MEMORY... */
|
|
BYTE ln_Pri; /* scheduling priority (used by Enqueue) */
|
|
char *ln_Name; /* optional name string (NULL = anonymous) */
|
|
};
|
|
|
|
struct MinNode {
|
|
struct MinNode *mln_Succ;
|
|
struct MinNode *mln_Pred;
|
|
/* no type, priority, or name — minimal overhead */
|
|
};
|
|
```
|
|
|
|
```c
|
|
/* exec/lists.h — NDK39 */
|
|
|
|
struct List {
|
|
struct Node *lh_Head; /* first node (or tail sentinel if empty) */
|
|
struct Node *lh_Tail; /* always NULL — marks end of list */
|
|
struct Node *lh_TailPred; /* last node (or head sentinel if empty) */
|
|
UBYTE lh_Type; /* list type */
|
|
UBYTE lh_pad;
|
|
};
|
|
|
|
struct MinList {
|
|
struct MinNode *mlh_Head;
|
|
struct MinNode *mlh_Tail; /* always NULL */
|
|
struct MinNode *mlh_TailPred;
|
|
};
|
|
```
|
|
|
|
### Node Type Constants
|
|
|
|
```c
|
|
/* exec/nodes.h */
|
|
#define NT_UNKNOWN 0
|
|
#define NT_TASK 1 /* exec Task */
|
|
#define NT_INTERRUPT 2 /* Interrupt server */
|
|
#define NT_DEVICE 3 /* Device */
|
|
#define NT_MSGPORT 4 /* MsgPort */
|
|
#define NT_MESSAGE 5 /* Message */
|
|
#define NT_FREEMSG 6
|
|
#define NT_REPLYMSG 7
|
|
#define NT_RESOURCE 8
|
|
#define NT_LIBRARY 9 /* Library */
|
|
#define NT_MEMORY 10 /* MemHeader */
|
|
#define NT_SOFTINT 11
|
|
#define NT_FONT 12
|
|
#define NT_PROCESS 13 /* dos.library Process */
|
|
#define NT_SEMAPHORE 14
|
|
#define NT_SIGNALSEM 15 /* SignalSemaphore */
|
|
#define NT_BOOTNODE 16
|
|
#define NT_KICKMEM 17
|
|
#define NT_GRAPHICS 18
|
|
#define NT_DEATHMESSAGE 19
|
|
```
|
|
|
|
---
|
|
|
|
## Initialising a List
|
|
|
|
```c
|
|
/* Stack-allocated list: */
|
|
struct List myList;
|
|
NewList(&myList); /* sets up sentinel pointers — mandatory */
|
|
|
|
/* Or use NEWLIST() macro: */
|
|
NEWLIST(&myList);
|
|
```
|
|
|
|
---
|
|
|
|
## Adding and Removing Nodes
|
|
|
|
```c
|
|
/* Add at head (highest LRU position): */
|
|
AddHead(&myList, &myNode); /* LVO -240 */
|
|
|
|
/* Add at tail: */
|
|
AddTail(&myList, &myNode); /* LVO -246 */
|
|
|
|
/* Remove from wherever it is (no list pointer needed): */
|
|
Remove(&myNode); /* LVO -252 */
|
|
|
|
/* Priority-ordered insert (by ln_Pri, high first): */
|
|
Enqueue(&myList, &myNode); /* LVO -270 */
|
|
```
|
|
|
|
---
|
|
|
|
## Walking a List
|
|
|
|
```c
|
|
struct Node *node, *next;
|
|
for (node = myList.lh_Head; node->ln_Succ != NULL; node = node->ln_Succ) {
|
|
/* process node */
|
|
}
|
|
```
|
|
|
|
Safe removal while iterating (save next before removing):
|
|
```c
|
|
for (node = myList.lh_Head; (next = node->ln_Succ) != NULL; node = next) {
|
|
if (should_remove(node)) Remove(node);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Finding a Node by Name
|
|
|
|
```c
|
|
struct Node *found = FindName(&SysBase->LibList, "dos.library");
|
|
/* Returns NULL if not found */
|
|
/* Always call under Forbid() if the list may change */
|
|
```
|
|
|
|
---
|
|
|
|
## How the Sentinel Works
|
|
|
|
The AmigaOS list design uses a **3-pointer layout** that avoids special-casing empty lists and end-of-list checks:
|
|
|
|
```
|
|
lh_Head ──→ [ Node A ]──→ [ Node B ]──→ [ tail sentinel ]
|
|
lh_Tail = NULL (always)
|
|
lh_TailPred ──────────────────────────→ [ Node B ]
|
|
|
|
Empty list:
|
|
lh_Head ──→ [ tail sentinel ]
|
|
lh_TailPred ──→ [ head sentinel ]
|
|
```
|
|
|
|
Walking stops when `ln_Succ == NULL` — that is the tail sentinel's `lh_Tail` field.
|
|
|
|
---
|
|
|
|
## References
|
|
|
|
- NDK39: `exec/nodes.h`, `exec/lists.h`
|
|
- ADCD 2.1: `AddHead`, `AddTail`, `Remove`, `Enqueue`, `FindName`, `NewList`
|
|
- *Amiga ROM Kernel Reference Manual: Exec* — lists chapter
|