Development News

Memory Page Locking Confusion

With the introduction of the AmigaOS Documentation Wiki and the uploading of the latest Amiga ROM Kernel Reference Manuals we have been given the opportunity to bring the Amiga Operating System’s documentation up to date. Although not complete, several dedicated volunteers have been slowly improving on that documentation.

One of the most confusing changes to the API has proven to be Exec’s new LockMem() and UnlockMem() function calls. These functions are use to lock and unlock memory pages. Normally, a programmer should not have to worry about memory pages nor worry about what the swapper is doing. Such details should be left to the operating system. However, in special circumstances (e.g. device drivers) it may be necessary to use LockMem() and UnlockMem().

What really confused programmers is the fact that we advocated the use of UnlockMem() even when the programmer did not explicitly call LockMem(). The issue was primarily centered on MEMF_SHARED memory which, by default, is automatically locked. That in itself isn’t really a problem. Add in the fact MEMF_ANY memory is translated to MEMF_SHARED memory and you have the potential for a lot of locked memory pages and thus ineffective use of system memory.

AmigaOS programmers are always trying to be helpful. Pretty much everyone jumped on the bandwagon and declared this API change as a travesty of enormous consequence. Why didn’t the FreeVec() function unlock the memory for them? Why must UnlockMem() be provided the size of the memory to unlock? They were very close to rioting.

After much discussion and fact gathering, the AmigaOS development team have officially changed our minds. The new advice is to never call UnlockMem() unless you explicitly called LockMem() in the first place. The wiki has already been updated to reflect this.

AmigaOS programmers are also rather attentive. “What happens to those implicitly locked memory pages when I don’t call UnlockMem()?” The truth of the matter is that some pages will actually be leaked. That is, some of those memory pages will not be moveable and thus not swappable. This does not mean the memory is not available to the system. This means the underlying memory pages cannot be swapped.

Now before resuming the riots, please take a moment and think about this. The system has been running fine for years now without programmers calling UnlockMem() on implicitly locked memory. We only recently explained this on the new documentation wiki. Something deeper is indeed going on here.

Without going into all the internal details, the system will automatically unlock memory that has been freed even if you forgot to call UnlockMem() on that memory. This is not true for every memory allocation but it is true for the majority of the memory in the system. This is why everything has been running fine for years now.

So what is going to happen to those lonely locked pages that can’t be automatically unlocked? The plan is to modify Exec’s discrimination between MEMF_SHARED and MEMF_PRIVATE memory. They will be moving to their own page caches. This effectively eliminates the problem entirely without a single line of code changed in your applications.

We are very sorry for the confusion. In the end, we figured it all out and I think this new advice (only call UnlockMem() if you called LockMem()) is very easy for programmers to follow.