Code Paging Guide

Code paging is the application of demand paging to executable code.

Purpose

This document explains the principles of code paging in Symbian platform.

Intended Audience:

This document is intended to be read by those interested in the Symbian platform kernel.

Basics of code paging

Code paging means the use of demand paging to executable code. Demand paging increases the apparent size of available RAM on a device by loading data into RAM when needed. Since the memory locations used by the code cannot be determined before it is loaded, the code needs to be modified when it is paged into RAM.

Classes explained here.

Executable code is paged in and out of memory in accordance with the demand paging algorithm which is discussed in the document. The algorithm involves four basic operations:

  • paging in,

  • aging,

  • rejuvenating, and

  • freeing.

The remainder of this document discusses the kernel side implementation of each of these operations in turn. Most of the work is done by the MemModelDemandPaging class.

Paging in paged code

When a program accesses an item of paged code for the first time the code needs to be paged into RAM. The initial call generates a data abort: this is caught by the exception handler which calls the HandleFault() function of the MemModelDemandPaging class. The function call performs the paging in as follows.

  • Checks the MMU page table entry for the address which caused the data abort. If the entry is not KPteNotPresentEntry then there is no memory mapped at that address and it may need paging in.

  • Verifies that the exception was caused by an access to the code chunk memory region.

  • Finds the code segment which is at the current address.

  • Verifies that the code segment is the one being demand paged.

The HandleFault() function of MemModelDemandPaging then calls the PageIn() function of MemModelDemandPaging, which performs the following steps.

When these calls have completed they return control to the program which caused the data abort.

Aging paged code

The demand paging algorithm defines pages in the live list to be either young or old. When a page changes status from young to old, the kernel changes the MMU mappings for the page to make it inaccessible. It does so by calling the SetOld() function of the MemModelDemandPaging class. The implementation of this procedure is different in the Moving Memory Model and the Multiple Memory Model.

In the Moving Memory Model, the call to SetOld() acts as follows:

  • Finds the MMU page table entry for the page and clears the bits KPtePresentMask.

In the Multiple Memory Model, SetOld() calls the kernel function DoSetCodeOld() which acts as follows:

The status of a page may change during a call to DoSetCodeOld(), either because it has been rejuvenated or paged out. In these cases DoSetCodeOld() simply ends, as the aging operation is no longer appropriate.

Rejuvenating paged code

When a program accesses a program held in an old page, it generates a data abort because the kernel made the page inaccessible when it was set to old. The data abort is caught by the exception handler which calls the HandleFault() function of the MemModelDemandPaging class. It is this call which performs the rejuvenation as follows.

  • Gets the MMU page table entry for the address which caused the abort. If the bits KPtePresentMask are clear then the page needs rejuvenating. If all the bits are clear then the page needs to be paged in, not rejuvenated.

  • Finds the SPageInfo for the page, using the physical address stored in the page table entry.

  • If it finds that the state of the page is EStatePagedDead then the page is dead rather than old and needs to be paged in, not rejuvenated.

  • Updates the page table entry to make the page accessible.

  • Moves the SPageInfo for the page to the beginning of the live list, making it the youngest page in the list.

These steps are performed with the system lock held.

Freeing paged code

When a physical page of RAM holding demand-paged code is needed for other purposes, it must be freed up. The kernel does this by calling the SetFree() function of the MemModelDemandPaging class. The implementation of this procedure is different in the Moving Memory Model and the Multiple Memory Model.

In the Moving Memory Model, the call to SetFree() acts as follows:

In the Multiple Memory Model, the call to SetFree() calls the kernel function DoSetCodeFree() which acts as follows:

  • Examines the bit array DMemModelCodeSegMemory::iOsAsids to determine the processes into which the code segment is loaded.

  • Makes each page inaccessible in turn.