To ensure that all processes are evenly penalized by swap_out( ), the function starts scanning the list from the memory descriptor that was last analyzed in the previous invocation; the address of this memory descriptor is stored in the swap_mm global variable.
For each memory descriptor mm to be considered, the swap_out( ) function increments the usage counter mm->mm_users, thus ensuring that the memory descriptor cannot disappear from the list while the swapping algorithm is working on it. Then, swap_out( ) invokes the swap_out_mm( ) function, passing to it the memory descriptor address mm, the memory zone classzone, and the number of page frames still to be released. Once swap_out_mm( ) returns, swap_out( ) decrements the usage counter mm->mm_users, and then decides whether it should analyze the next memory descriptor in the list or just terminate.
swap_out_mm( ) returns the number of pages of the process that owns the memory descriptor that the function has released. The swap_out( ) function uses this value to update a counter of how many pages have been released since the beginning of its execution; if the counter reaches the value swap_cluster_max, swap_out( ) terminates.
The swap_out_mm( ) function scans the memory regions of the process that owns the memory descriptor mm passed as a parameter. Usually, the function starts analyzing the first memory region object in the mm->mmap list (remember that they are ordered by starting linear addresses). However, if mm is the memory descriptor that was analyzed last in the previous invocation of swap_out( ), swap_out_mm( ) does not restart from the first memory region, but from the memory region that includes the linear address last analyzed in the previous invocation. This linear address is stored in the swap_address field of the memory descriptor; if all memory regions of the process have been analyzed, then the field stores the conventional value task_size.
For each memory region of the process that owns the memory descriptor mm, swap_out_mm( ) invokes the swap_out_vma( ) function, passing to it the number of pages yet to be released, the first linear address to analyze, the memory region object, and the memory descriptor. Again, swap_out_vma( ) returns the number of released pages belonging to the memory region. The loop of swap_out_mm( ) continues until either the requested number of pages is released or all memory regions are considered.
The swap_out_vma( ) function checks that the memory region is swappable (e.g., the flag vm_reserved is cleared). It then starts a sequence in which it considers all entries in the process's Page Global Directory that refer to linear addresses in the memory region. For each such entry, the function invokes the swap_out_pgd( ) function, which in turn considers all entries in a Page Middle Directory corresponding to address intervals in the memory region. For each such entry, swap_out_pgd( ) invokes the swap_out_pmd( ) function, which considers all entries in a Page Table referencing pages in the memory region. Also, swap_out_pmd( ) invokes the try_to_swap_out( ) function, which finally attempts to swap out the page. As usual, this chain of function invocations breaks as soon as the requested number of released page frames is reached.
Was this article helpful?