Buddy Memory Allocator |
In a buddy system, the entire memory space available for allocation is initially treated as a single block whose size is a power of 2. When the first request is made, if its size is greater than half of the initial block then the entire block is allocated. Otherwise, the block is split in two equal companion buddies. If the size of the request is greater than half of one of the buddies, then allocate one to it. Otherwise, one of the buddies is split in half again. This method continues until the smallest block greater than or equal to the size of the request is found and allocated to it.
In this method, when a process terminates the buddy block that was allocated to it is freed. Whenever possible, an unnallocated buddy is merged with a companion buddy in order to form a larger free block. Two blocks are said to be companion buddies if they resulted from the split of the same direct parent block.
The following figure illustrates the buddy system at work, considering a 1024k (1-megabyte) initial block and the process requests as shown at the left of the table.
Your task is to implement a buddy memory manager and simulate it at work. You will be given the upper and lower sizes admissible for blocks in the system and a list of requests. A request is made for a process and it may either be for a block of a certain size or just an indication of termination. Requests should be attended in a firstcome firstserved basis. After serving all requests, your program should display the state of the buddy system at that point, indicating which processes are in memory and which blocks are free.
Notice that, whenever there is a request that corresponds to a block of size s, your program should select the block of that size that was most recently declared free. Furthermore, when a block is split in two, the left-one (lower addresses) should be selected before the right-one.
You can assume that the list of requests is such that all requests can always be served. In other words, you can make the following assumptions: no process will request more than the available memory; processes are uniquely identified while active; and no request for process termination is issued before its corresponding request for memory allocation.
The first line of input consists of two numbers, U and L, that determine the upper (2Uk) and lower (2Lk) block sizes admissable. You can assume U > L > 0. The following input lines are requests being made, one per line. A request is defined by two values, P and S, where P is a capital letter that identifies the process associated with the request, and S ( 0) is a number. If S > 0 then it is a memory block request; Otherwise (S = 0) it is a request indicating that process P has terminated.
The output must list the state of the buddy immediatly after
having served the last request. This corresponds to listing
the processes still in memory, if any, and the free blocks
(holes) available. Processes and holes must be listed in a
left to right order as you traverse the buddy (i.e. from lower
addresses towards upper memory addresses). The output
format for processes is P : S, P is the process identifier and S
its size, and for holes is Hole:S where S is the size of
the free block.
1 10 4 A 70 B 35 C 80 A 0 D 60 B 0
Hole:128 Hole:64 D:60 C:80 Hole:128 Hole:512