mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-13 00:26:28 +00:00
docs(amiga): complete AmigaOS 3.1/3.2 developer reference — 172 files across 17 sections
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.
This commit is contained in:
parent
f07a368bf1
commit
21751c0025
172 changed files with 19701 additions and 0 deletions
142
06_exec_os/message_ports.md
Normal file
142
06_exec_os/message_ports.md
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
[← Home](../README.md) · [Exec Kernel](README.md)
|
||||
|
||||
# Message Ports — MsgPort, Message, PutMsg, GetMsg, WaitPort
|
||||
|
||||
## Overview
|
||||
|
||||
AmigaOS inter-task communication uses a **message passing** system. Tasks send `Message` structures to `MsgPort` queues. The receiving task either polls (`GetMsg`) or blocks (`WaitPort`) for incoming messages. No shared memory is touched without the message handshake.
|
||||
|
||||
---
|
||||
|
||||
## Core Structures
|
||||
|
||||
```c
|
||||
/* exec/ports.h — NDK39 */
|
||||
|
||||
struct MsgPort {
|
||||
struct Node mp_Node; /* ln_Name = port name (for public ports) */
|
||||
UBYTE mp_Flags; /* PA_SIGNAL, PA_SOFTINT, PA_IGNORE */
|
||||
UBYTE mp_SigBit; /* signal bit used for PA_SIGNAL ports */
|
||||
APTR mp_SigTask; /* task to signal on message arrival */
|
||||
struct List mp_MsgList; /* queue of pending messages */
|
||||
};
|
||||
|
||||
struct Message {
|
||||
struct Node mn_Node; /* ln_Type = NT_MESSAGE */
|
||||
struct MsgPort *mn_ReplyPort; /* port to send reply to (or NULL) */
|
||||
UWORD mn_Length; /* total size of message including header */
|
||||
};
|
||||
```
|
||||
|
||||
`mp_Flags` values:
|
||||
|
||||
| Value | Constant | Meaning |
|
||||
|---|---|---|
|
||||
| 0 | `PA_SIGNAL` | Signal `mp_SigTask` when message arrives |
|
||||
| 1 | `PA_SOFTINT` | Trigger software interrupt |
|
||||
| 2 | `PA_IGNORE` | Do not wake the task (polling only) |
|
||||
|
||||
---
|
||||
|
||||
## Creating a Message Port
|
||||
|
||||
```c
|
||||
struct MsgPort *port = CreateMsgPort(); /* exec.library LVO -732 (OS 2.0+) */
|
||||
/* or manually for OS 1.x compatibility: */
|
||||
struct MsgPort *port = AllocMem(sizeof(struct MsgPort), MEMF_PUBLIC|MEMF_CLEAR);
|
||||
port->mp_Node.ln_Type = NT_MSGPORT;
|
||||
port->mp_Flags = PA_SIGNAL;
|
||||
port->mp_SigBit = AllocSignal(-1); /* any free signal bit */
|
||||
port->mp_SigTask = FindTask(NULL); /* signal current task */
|
||||
NewList(&port->mp_MsgList);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sending a Message
|
||||
|
||||
```c
|
||||
/* PutMsg: add message to queue, signal receiver */
|
||||
PutMsg(target_port, (struct Message *)my_msg);
|
||||
/* Non-blocking — returns immediately */
|
||||
```
|
||||
|
||||
PutMsg can be called from interrupt context.
|
||||
|
||||
---
|
||||
|
||||
## Receiving Messages
|
||||
|
||||
```c
|
||||
/* Block until at least one message arrives: */
|
||||
WaitPort(my_port);
|
||||
|
||||
/* Then drain the queue: */
|
||||
struct MyMsg *msg;
|
||||
while ((msg = (struct MyMsg *)GetMsg(my_port)) != NULL) {
|
||||
/* process msg */
|
||||
ReplyMsg((struct Message *)msg); /* send reply if mn_ReplyPort != NULL */
|
||||
}
|
||||
```
|
||||
|
||||
### GetMsg (non-blocking poll)
|
||||
|
||||
```c
|
||||
struct Message *msg = GetMsg(my_port);
|
||||
/* Returns NULL if queue is empty */
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Public Named Ports
|
||||
|
||||
```c
|
||||
/* Register a port so others can find it by name: */
|
||||
port->mp_Node.ln_Name = "myapp.port";
|
||||
Forbid();
|
||||
AddPort(port);
|
||||
Permit();
|
||||
|
||||
/* From another task: */
|
||||
Forbid();
|
||||
struct MsgPort *remote = FindPort("myapp.port");
|
||||
Permit();
|
||||
if (remote) PutMsg(remote, my_msg);
|
||||
|
||||
/* Cleanup: */
|
||||
Forbid();
|
||||
RemPort(port);
|
||||
Permit();
|
||||
```
|
||||
|
||||
`Forbid()` is required around `FindPort`/`AddPort`/`RemPort` to prevent the task list from changing mid-operation.
|
||||
|
||||
---
|
||||
|
||||
## Reply Pattern
|
||||
|
||||
The standard request-reply idiom:
|
||||
|
||||
```c
|
||||
/* Sender: */
|
||||
my_msg->mn_ReplyPort = reply_port;
|
||||
PutMsg(server_port, &my_msg->mn_Message);
|
||||
WaitPort(reply_port);
|
||||
struct MyMsg *reply = (struct MyMsg *)GetMsg(reply_port);
|
||||
/* reply now contains the server's response */
|
||||
|
||||
/* Server: */
|
||||
WaitPort(server_port);
|
||||
struct MyMsg *req = (struct MyMsg *)GetMsg(server_port);
|
||||
/* process req... */
|
||||
req->result = 42;
|
||||
ReplyMsg(&req->mn_Message); /* sends back to req->mn_ReplyPort */
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- NDK39: `exec/ports.h`, `exec/messages.h`
|
||||
- ADCD 2.1: `CreateMsgPort`, `PutMsg`, `GetMsg`, `WaitPort`, `ReplyMsg`
|
||||
- *Amiga ROM Kernel Reference Manual: Exec* — messages and ports chapter
|
||||
Loading…
Add table
Add a link
Reference in a new issue