TAOCP 2.5 Exercise 12
Let the memory contain permanent boundary sentinels at both extremes.
Section 2.5: Dynamic Storage Allocation
Exercise 12. [**] [20] Modify Algorithm A so that it follows the boundary-tag conventions of (7)-(9), uses the modified step A4' described in the text, and also incorporates the improvement of exercise 6.
Verified: no
Solve time: 4m32s
Let the memory contain permanent boundary sentinels at both extremes. Specifically, assume that location $0$ and the final location $M+1$ contain the reserved tag $0$. Hence every actual block lies strictly between two accessible tag words, and tests of neighboring tags are always defined.
Every block has a boundary tag at each end. If a block occupies locations
$$ p,\ldots,p+s-1, $$
then the words at $p$ and $p+s-1$ both contain the same signed size:
$$ +s \quad \text{if the block is free}, $$
$$ -s \quad \text{if the block is reserved}. $$
A free block therefore has the form
$$ \begin{array}{|c|c|c|c|c|} \hline +s & \mathrm{LLINK} & \mathrm{RLINK} & \cdots & +s\ \hline \end{array} $$
and must satisfy $s\ge4$, since two link fields are required in addition to the two tags.
The free blocks form a circular doubly linked list. The variable $R$ is the roving pointer of exercise 6. The convention
$$ R=\Lambda $$
means that the free list is empty.
For a free block beginning at $p$,
$$ \mathrm{LLINK}(p+1),\qquad \mathrm{RLINK}(p+1) $$
are its predecessor and successor in the circular list.
The user receives the address
$$ p+1 $$
when the reserved block begins at $p$. Thus the leading boundary tag is always immediately before the user address.
The modified algorithm is as follows.
A1. [Initialize.]
Initially one free block occupies locations
$$ 1,\ldots,M. $$
Set
$$ \mathrm{TAG}(1)=M, \qquad \mathrm{TAG}(M)=M. $$
Set
$$ \mathrm{LLINK}(2)=1, \qquad \mathrm{RLINK}(2)=1. $$
Set
$$ R=1. $$
Also set the permanent sentinels
$$ \mathrm{TAG}(0)=0, \qquad \mathrm{TAG}(M+1)=0. $$
A2. [Search.]
Given a request for $N$ usable words, compute
$$ n=\max(N+2,4). $$
The quantity $n$ is the total block size including the two tags.
If
$$ R=\Lambda, $$
the allocation fails immediately.
Otherwise begin at the block pointed to by $R$, and traverse the circular list until a free block of size at least $n$ is found.
Suppose the selected free block begins at $p$ and has size $s$.
A3. [Test the remainder.]
Set
$$ r=s-n. $$
If
$$ r<4, $$
execute step A4'. Otherwise execute step A5.
A4'. [Allocate the whole block.]
The entire free block is allocated.
Let
$$ u=\mathrm{LLINK}(p+1), \qquad v=\mathrm{RLINK}(p+1). $$
There are two cases.
Case 1. The block is the only free block.
This occurs when
$$ u=p, \qquad v=p. $$
Set
$$ R=\Lambda. $$
The free list is now empty.
Case 2. The list contains other free blocks.
Splice the block out of the circular list:
$$ \mathrm{RLINK}(u+1)\leftarrow v, $$
$$ \mathrm{LLINK}(v+1)\leftarrow u. $$
If
$$ R=p, $$
set
$$ R=v. $$
Now mark the block reserved:
$$ \mathrm{TAG}(p)\leftarrow -s, $$
$$ \mathrm{TAG}(p+s-1)\leftarrow -s. $$
Return the user address
$$ p+1. $$
A5. [Split the block.]
Assume
$$ r\ge4. $$
Retain the lower portion as a free block of size $r$, and allocate the upper portion of size $n$.
Thus the free block occupies
$$ p,\ldots,p+r-1, $$
and the reserved block occupies
$$ q,\ldots,q+n-1, \qquad q=p+r. $$
The free block remains in the free list, so its link fields are unchanged.
Write the new free tags:
$$ \mathrm{TAG}(p)\leftarrow r, $$
$$ \mathrm{TAG}(p+r-1)\leftarrow r. $$
Write the reserved tags:
$$ \mathrm{TAG}(q)\leftarrow -n, $$
$$ \mathrm{TAG}(q+n-1)\leftarrow -n. $$
Set
$$ R=p, $$
since the search terminated there.
Return the user address
$$ q+1. $$
A6. [Release a block.]
Suppose the user returns the address
$$ q. $$
Then the block itself begins at
$$ p=q-1. $$
Its size is determined from the leading tag:
$$ n=-\mathrm{TAG}(p). $$
Hence the released block occupies
$$ p,\ldots,p+n-1. $$
Define
$$ L=p-1, \qquad U=p+n. $$
If
$$ \mathrm{TAG}(L)>0, $$
the left neighbor is free. Its size is
$$ a=\mathrm{TAG}(L), $$
and its starting address is
$$ u=p-a. $$
If
$$ \mathrm{TAG}(U)>0, $$
the right neighbor is free. Its size is
$$ b=\mathrm{TAG}(U), $$
and its starting address is
$$ v=p+n. $$
There are four cases.
Case 1. Neither neighbor is free.
Thus
$$ \mathrm{TAG}(L)\le0, \qquad \mathrm{TAG}(U)\le0. $$
Mark the block free:
$$ \mathrm{TAG}(p)\leftarrow n, $$
$$ \mathrm{TAG}(p+n-1)\leftarrow n. $$
If
$$ R=\Lambda, $$
create a one-element circular list:
$$ \mathrm{LLINK}(p+1)\leftarrow p, $$
$$ \mathrm{RLINK}(p+1)\leftarrow p, $$
$$ R\leftarrow p. $$
Otherwise insert the block immediately after $R$.
Let
$$ t=\mathrm{RLINK}(R+1). $$
Set
$$ \mathrm{RLINK}(p+1)\leftarrow t, $$
$$ \mathrm{LLINK}(p+1)\leftarrow R, $$
$$ \mathrm{LLINK}(t+1)\leftarrow p, $$
$$ \mathrm{RLINK}(R+1)\leftarrow p. $$
Finally set
$$ R\leftarrow p. $$
Case 2. Left neighbor free, right neighbor reserved.
The left free block begins at
$$ u=p-a. $$
Enlarge it to size
$$ a+n. $$
Write the new boundary tags:
$$ \mathrm{TAG}(u)\leftarrow a+n, $$
$$ \mathrm{TAG}(p+n-1)\leftarrow a+n. $$
No link changes are required. The free block already belongs to the free list, and its header remains at $u$, so all list pointers continue to reference the correct location.
Set
$$ R=u. $$
Case 3. Left neighbor reserved, right neighbor free.
The right free block begins at
$$ v=p+n, $$
and has size $b$.
Its predecessor and successor in the free list are
$$ x=\mathrm{LLINK}(v+1), \qquad y=\mathrm{RLINK}(v+1). $$
The merged free block will begin at $p$ and have size
$$ n+b. $$
Write its tags:
$$ \mathrm{TAG}(p)\leftarrow n+b, $$
$$ \mathrm{TAG}(p+n+b-1)\leftarrow n+b. $$
Now replace the old free-list node at $v$ by the new node at $p$.
If
$$ x=v, \qquad y=v, $$
then the right block was the only free block. Set
$$ \mathrm{LLINK}(p+1)\leftarrow p, $$
$$ \mathrm{RLINK}(p+1)\leftarrow p, $$
$$ R\leftarrow p. $$
Otherwise set
$$ \mathrm{RLINK}(x+1)\leftarrow p, $$
$$ \mathrm{LLINK}(y+1)\leftarrow p, $$
$$ \mathrm{LLINK}(p+1)\leftarrow x, $$
$$ \mathrm{RLINK}(p+1)\leftarrow y. $$
If
$$ R=v, $$
set
$$ R=p. $$
Thus the list remains correctly linked even though the block header has moved from $v$ to $p$.
Case 4. Both neighbors free.
The left free block begins at
$$ u=p-a, $$
and the right free block begins at
$$ v=p+n. $$
The right block has size $b$.
Remove the right block from the free list.
Let
$$ x=\mathrm{LLINK}(v+1), \qquad y=\mathrm{RLINK}(v+1). $$
If
$$ x=v, \qquad y=v, $$
then the right block was the only free-list node besides the left block itself. No special action is needed, because the left block already remains in the list.
Otherwise splice out the right block:
$$ \mathrm{RLINK}(x+1)\leftarrow y, $$
$$ \mathrm{LLINK}(y+1)\leftarrow x. $$
Now combine all three blocks into one free block of size
$$ a+n+b. $$
Write the new tags:
$$ \mathrm{TAG}(u)\leftarrow a+n+b, $$
$$ \mathrm{TAG}(p+n+b-1)\leftarrow a+n+b. $$
No further link updates are needed. The surviving free-list node is still located at $u$, so every pointer that formerly referenced the left block remains valid.
Set
$$ R=u. $$
This algorithm satisfies all requirements of the exercise.
- Boundary tags at both ends permit immediate detection and coalescing of adjacent free blocks.
- Modified step $A4'$ allocates the entire block whenever the remainder would be too small to form a legal free block.
- The roving pointer $R$ implements the improvement of exercise 6, because searches continue from the location of the previous successful allocation rather than restarting at the beginning of the free list.