AROS Vision
Modern and free Amiga-Compatible Experience on Amiga and PC
Article 13: Amiga Memory Management in Depth
In the previous articles, we explored how the Amiga hardware and operating system work together. We have already encountered Chip RAM and Fast RAM several times.
Now it is time to look at memory from the operating system's point of view.
How does AmigaOS know which memory is available? How does a program request memory? How does the operating system decide where that memory comes from? And why can a program specifically request Chip RAM or Fast RAM?
To understand this, we need to look at the memory management provided by Exec, the core of AmigaOS.
1. Memory Is a Shared Resource
Several parts of the Amiga need memory at the same time.
For example:
the operating system itself
applications
libraries
device drivers
file buffers
graphics
sound samples
disk buffers
temporary application data
The problem is that programs cannot simply choose arbitrary memory addresses.
Imagine two programs both deciding to use the same area of RAM.
One program could overwrite the data belonging to the other.
AmigaOS therefore needs a memory manager that keeps track of which memory is available and which memory is already in use.
This job is handled primarily by Exec.
2. Exec as the Memory Manager
Exec provides the fundamental memory-management services used by Amiga software.
Programs can ask Exec for a block of memory and later return that memory when it is no longer required.
Conceptually:
Application
|
| request memory
v
Exec
|
| find suitable free memory
v
+----------------+
| Available RAM |
+----------------+
|
v
Allocated block
The application therefore normally does not need to know exactly where the available physical memory is located.
It asks Exec for memory.
Exec finds an appropriate block and returns its address.
3. The Amiga Does Not Have Just One Kind of RAM
Memory management on the Amiga is slightly more interesting than on systems where RAM can be treated as one uniform pool.
A typical Amiga may contain several different memory regions.
For example:
Memory
|
+-- Chip RAM
|
+-- Fast RAM
|
+-- Expansion Fast RAM
These areas do not necessarily have the same capabilities.
The most important distinction is between:
Chip RAM
Fast RAM
The operating system therefore needs to know not only how much memory is available, but also what kind of memory it is.
4. Chip RAM
Chip RAM can be accessed both by the CPU and by the Amiga custom-chip subsystem.
This is essential for data used by DMA.
Typical examples include:
display bitplanes
sprites
audio samples
Copper lists
Blitter source or destination data
some disk DMA buffers
A simplified view is:
Chip RAM
^
|
+-------+-------+
| |
CPU Custom Chips
The CPU can access this memory, but the hardware can access it as well.
That makes Chip RAM extremely useful.
It also makes it a valuable resource that should not be wasted unnecessarily.
5. Fast RAM
Fast RAM is different.
In the classic Amiga architecture, the custom chips cannot normally use Fast RAM directly for their DMA operations.
It is primarily available to the CPU.
Fast RAM
^
|
CPU
Custom Chips ---X
This limitation is also its advantage.
Because the custom-chip DMA system does not compete with the CPU for access to Fast RAM, CPU programs can often execute considerably faster when their code and data are located there.
Fast RAM is therefore ideal for things such as:
program code
calculations
application data
data structures
buffers that do not require custom-chip access
6. Why the Operating System Must Know the Difference
Suppose a graphics program needs memory for a bitmap that will be displayed by the Amiga chipset.
If Exec placed this bitmap in Fast RAM, the CPU could access it, but the classic custom-chip hardware could not fetch the required display data from it.
The program therefore needs a way to say:
Give me memory that the custom chips can access.
Conversely, suppose a program requires a large working buffer for calculations.
There may be no reason to consume valuable Chip RAM.
The program could instead say:
Give me Fast RAM if possible.
This is one reason AmigaOS associates attributes with memory.
7. Memory Attributes
Programs can specify properties of the memory they require.
Two of the best-known memory flags are:
MEMF_CHIP
and
MEMF_FAST
MEMF_CHIP requests memory suitable for access by the Amiga custom chips.
MEMF_FAST requests Fast RAM.
There are other flags as well.
For example:
MEMF_CLEAR
asks Exec to clear the allocated memory before returning it to the application.
Conceptually, a program might request:
Allocate:
10000 bytes
+
Chip accessible
+
clear memory
first
Exec then searches for a suitable block.
8. AllocMem()
One of the classic Exec functions used for allocating memory is:
AllocMem()
Conceptually:
pointer = AllocMem(size, requirements);
For example:
buffer = AllocMem(4096, MEMF_CHIP);
This requests a 4096-byte block of Chip RAM.
If suitable memory is available, Exec returns a pointer to it.
If the request cannot be satisfied, the result is effectively a null pointer.
A real program must therefore check whether the allocation succeeded.
Application
|
| AllocMem()
v
Exec
|
+--> Find suitable memory
|
+--> Reserve block
|
v
Address returned
9.
Allocating Fast RAM
A program can similarly request Fast RAM:
buffer = AllocMem(4096, MEMF_FAST);
Exec now looks for a memory region with the required attributes.
This allows software to make much better use of machines equipped with memory expansions.
Instead of consuming Chip RAM for everything, software can reserve it for data that really needs to be visible to the custom chips.
10. Returning Memory with FreeMem()
Allocated memory should be returned when it is no longer required.
The traditional counterpart to AllocMem() is:
FreeMem()
Conceptually:
FreeMem(buffer, 4096);
The memory becomes available for future allocations.
The complete life cycle therefore looks like this:
Request memory
|
v
AllocMem()
|
v
Use memory
|
v
FreeMem()
|
v
Memory becomes available again
Programs that repeatedly allocate memory without freeing it create a memory leak.
On an Amiga with only a few megabytes, or even hundreds of kilobytes of usable memory, such leaks can become noticeable very quickly.
11. How Exec Keeps Track of Memory
Internally, Exec maintains information describing the available memory regions.
At a simplified level, you can imagine something like:
Exec Memory System
+--------------------------+
| Memory Region |
| Type: Chip RAM |
| Address range: ... |
| Free blocks: ... |
+--------------------------+
+--------------------------+
| Memory Region |
| Type: Fast RAM |
| Address range: ... |
| Free blocks: ... |
+--------------------------+
+--------------------------+
| Memory Region |
| Type: Expansion RAM |
| Address range: ... |
| Free blocks: ... |
+--------------------------+
Exec does not have to assume that all RAM forms one physically continuous region.
This is important because Amiga memory expansions can exist at different locations in the processor's address space.
12. Memory Lists and Memory Headers
Exec represents available memory through structures traditionally associated with its internal memory list.
Memory regions are described by structures known as MemHeader structures.
A memory header describes a region and includes information about characteristics such as:
its address range
its attributes
available memory
free blocks within the region
This means the memory system can manage several physically separate RAM areas.
Conceptually:
Exec
|
+-- MemHeader
| |
| +-- Chip RAM
|
+-- MemHeader
| |
| +-- Fast RAM
|
+-- MemHeader
|
+-- Expansion RAM
This flexible design fits the Amiga particularly well because the machine was designed to support expansion hardware.
13. Free Memory Is Divided into Blocks
Within a memory region, some parts may already be allocated while others remain free.
For example:
Memory region
+----------------+
| Used |
+----------------+
| Free |
+----------------+
| Used |
+----------------+
| Free |
+----------------+
| Used |
+----------------+
The free areas can be tracked so that Exec can satisfy later allocation requests.
If a program asks for 20 KB, Exec must locate a single suitable free block large enough to satisfy the request.
This leads us to an important problem.
14. Memory Fragmentation
Suppose there are 100 KB of free memory.
That sounds like enough for a program requesting 60 KB.
But consider this layout:
+----------------+
| Free 30 KB |
+----------------+
| Used |
+----------------+
| Free 25 KB |
+----------------+
| Used |
+----------------+
| Free 45 KB |
+----------------+
Total free memory:
30 + 25 + 45 = 100 KB
But the largest single free block is only:
45 KB
A request for a continuous 60 KB block can therefore fail.
This condition is called memory fragmentation.
15. Why Fragmentation Matters on an Amiga
Fragmentation can matter particularly on systems with limited RAM.
A program might report an out-of-memory condition even though the system apparently still has a significant amount of free memory.
The important distinction is between:
total free memory
and:
largest available continuous block
A large graphics buffer, bitmap, audio buffer or other structure may require one continuous area.
If the remaining memory is divided into many smaller pieces, the allocation can fail.
16. Why Chip RAM Should Be Preserved
One of the most important practical consequences of the Amiga memory architecture is that Chip RAM is a special resource.
Imagine a computer containing:
2 MB Chip RAM
8 MB Fast RAM
If an application allocates ordinary calculation buffers in Chip RAM unnecessarily,
it reduces the amount available for:
screens
bitmaps
graphics
sound samples
Copper lists
other DMA-related data
Good Amiga software therefore tries to place CPU-only data in Fast RAM whenever appropriate.
Conceptually:
Chip RAM
--------
Screen
Bitmaps
Sprites
Sound
Copper list
Fast RAM
--------
Program code
Variables
Tables
Calculation buffers
Application data
This is not an absolute rule, but it is a useful design principle.
17. What Happens When Fast RAM Is Added?
Adding Fast RAM can improve an Amiga in two ways.
The most obvious improvement is simply:
more available memory
But there is another important advantage:
reduced contention for Chip RAM
Program code and CPU-oriented data can reside in Fast RAM while the custom chips continue to operate on Chip RAM.
Simplified:
CPU
/ </span>
/ </span>
Fast RAM Chip RAM
|
Agnus
/ | </span>
Video Audio Blitter
The CPU can perform much of its work using Fast RAM while DMA activity continues in Chip RAM.
That is one of the reasons adding Fast RAM to a classic Amiga can improve performance by more than simply increasing the amount of available memory.
18. Accelerator Memory
The effect becomes even more important with accelerator cards.
An accelerator may contain:
a faster 68020, 68030, 68040 or 68060
local Fast RAM
its own high-speed memory interface
sometimes caches and additional controller logic
A simplified configuration might look like:
Accelerator
+--------------+
| Fast CPU |
| |
| Local RAM |
+--------------+
|
|
Amiga system
|
Chip RAM
|
Custom chipset
CPU code and data in accelerator Fast RAM can often be accessed much faster than Chip RAM.
In such a machine, the difference between CPU-oriented Fast RAM and shared Chip RAM becomes even more significant.
19. The CPU Still Needs Chip RAM
Fast RAM does not replace Chip RAM completely.
Even an Amiga with a large amount of Fast RAM still needs Chip RAM for many operations involving the classic custom chipset.
For example:
Program code -> Fast RAM
Game logic -> Fast RAM
Large lookup table -> Fast RAM
Bitplanes -> Chip RAM
Sprites -> Chip RAM
Audio samples -> Chip RAM
Copper list -> Chip RAM
A program therefore often uses both memory types simultaneously.
20. Example: A Simple Graphics Program
Imagine a graphics program.
It needs:
Program code
GUI data
Calculation buffers
Displayed bitmap
A sensible distribution might be:
FAST RAM
+----------------------+
| Program code |
| GUI structures |
| Calculation buffers |
+----------------------+
CHIP RAM
+----------------------+
| Display bitmap |
+----------------------+
The CPU performs calculations using Fast RAM.
When graphics data must be displayed through the custom chipset, the necessary bitmap resides in Chip RAM.
This illustrates one of the most important ideas behind Amiga memory management:
Memory should be allocated according to what needs to access it.
21. CPU Access Versus DMA Access
The distinction becomes even clearer when we consider DMA.
For ordinary CPU processing: CPU -> Fast RAM
is usually desirable.
For hardware DMA: Custom Chip -> Chip RAM is required on the classic architecture.
This creates two parallel worlds:
CPU
/ </span>
/ </span>
Fast RAM Chip RAM
^
|
DMA
|
+--------+--------+
| | |
Bitplane Audio Blitter
The software developer must understand which world a particular piece of data belongs to.
22. Memory Allocation Is Dynamic
Amiga applications do not necessarily reserve all their memory permanently when they start.
They can request and return memory while running.
For example:
Program starts
|
+-- allocate main structures
|
Open picture
|
+-- allocate bitmap
|
Process picture
|
Close picture
|
+-- free bitmap
|
Program exits
|
+-- free remaining memory
This makes efficient use of limited RAM, but it also means applications must manage allocated resources carefully.
23. What Happens When Allocation Fails?
Programs should never assume that a memory allocation succeeds.
Consider:
buffer = AllocMem(100000, MEMF_CHIP);
Exec may be unable to find a sufficiently large Chip RAM block.
The application must therefore check the returned pointer before using it.
Conceptually:
Request memory
|
v
Memory available?
/ </span>
Yes No
| |
Return Return
pointer failure
Trying to use a nonexistent allocation can result in crashes or corrupted memory.
Careful resource checking is therefore an important part of Amiga programming.
24. Memory Protection: An Important Limitation
Classic AmigaOS memory management should not be confused with the protected virtual-memory systems found in modern operating systems.
Traditional AmigaOS generally operates within a shared address space.
This means applications do not normally live inside strongly isolated virtual address spaces.
Consequently, a faulty application can potentially overwrite:
another application's memory
operating-system structures
library data
important pointers
This is one reason software bugs involving invalid pointers can result in a complete system crash rather than merely terminating one application.
The famous Guru Meditation errors are closely associated with the consequences of serious system and software faults.
25. No Traditional Virtual Memory
Classic AmigaOS also does not depend on the large virtual-memory model familiar from modern desktop operating systems.
Traditionally:
Allocated memory
|
v
Actual RAM
When memory is exhausted, the operating system cannot simply assume that gigabytes of disk-backed virtual memory are available.
Memory efficiency therefore mattered enormously to Amiga developers.
A program running on a 512 KB or 1 MB machine had to use its resources carefully.
26. Why the Amiga Approach Was Powerful
The Amiga memory system combines several interesting ideas:
dynamic allocation
multiple memory regions
memory attributes
hardware-aware allocation
expansion memory support
DMA-accessible memory
CPU-oriented Fast RAM
Rather than pretending that every byte of RAM is identical, the operating system understands that different memory regions may have different capabilities.
That reflects the philosophy of the entire Amiga architecture.
The operating system, CPU and custom hardware were designed to cooperate closely.
27. The Big Picture
We can now combine the major components:
Application
|
Memory request
|
v
Exec
|
+------------+------------+
| |
Fast RAM Chip RAM
| |
v v
CPU CPU + Custom Chips
|
DMA
+--------+--------+
| | |
Graphics Audio Blitter
Exec provides the abstraction.
The application specifies what kind of memory it needs.
Exec selects a suitable region.
The hardware characteristics determine what that memory can ultimately be used for.
Conclusion
Memory management on the Amiga is much more than simply keeping track of free RAM.
The operating system must understand that different memory regions have different capabilities.
Chip RAM is shared between the CPU and the custom-chip subsystem and is required for many DMA operations.
Fast RAM is intended primarily for the CPU and can significantly improve performance by allowing processor activity to avoid contention with the custom chips.
Exec connects these hardware characteristics with software through its memory-management system.
Functions such as:
AllocMem()
FreeMem()
allow applications to dynamically obtain and release memory, while attributes such as:
MEMF_CHIP
MEMF_FAST
MEMF_CLEAR
allow software to describe what kind of memory it needs.
Understanding this system explains a lot of classic Amiga behavior: why adding Fast RAM can make a computer noticeably faster, why Chip RAM can run out even when Fast RAM remains available, why DMA data must be placed carefully, and why memory fragmentation can cause allocations to fail.
Most importantly, it demonstrates one of the defining characteristics of the Amiga:
Memory management is closely connected to the hardware architecture itself.
That close relationship between CPU, memory, Exec and the custom chips is one of the reasons the Amiga remains such an interesting system to study.