# Buddy Memory Allocation Program | Set 2 (Deallocation)

Prerequisite – Buddy Allocation | Set 1
Question: Write a program to implement the buddy system of memory allocation and deallocation in Operating Systems.

Explanation –
As we already know from Set 1, the allocation is done via the usage of free lists. Now, for deallocation, we will maintain an extra data structure-a Map (unordered_set in C++, HashMap in Java) with the starting address of segment as key and size of the segment as value and update it whenever an allocation request comes. Now, when deallocation request comes, we will first check the map to see if it is a valid request. If so, we will then add the block to the free list tracking blocks of its sizes. Then, we will search the free list to see if it’s buddy is free-if so, we will merge the blocks and place them on the free list above them (which tracks blocks of double the size), else we will not coalesce and simply return after that.

How to know which block is a given block’s buddy?

Let us define two terms-buddyNumber and buddyAddress. The buddyNumber of a block is calculated by the formula:

`(base_address-starting_address_of_main_memory)/block_size`

We note that this is always an integer, as both numerator and denominator are powers of 2. Now, a block will be another block’s buddy if both of them were formed by the splitting of the same bigger block. For example, if 4 consecutive allocation requests of 16 bytes come, we will end up with blocks 0-15, 16-31, 32-47, 48-63 where blocks 0-15 and 16-31 are buddies (as they were formed by splitting block 0-32) but 0-15 and 32-47 aren’t. The buddyAddress of a block is the starting index of its buddy block, given by the formula:

```block_starting_address+block_size (if buddyNumber is even)

Thus, all we have to do is find this buddyAddress in the free list (by comparing with all the starting addresses in that particular list), and if present, coalescing can be done.

Examples:
Let us see how the algorithm proceeds by tracking a memory block of size 128 KB. Initially, the free list is: {}, {}, {}, {}, {}, {}, {}, { (0, 127) }

• Allocation Request: 16 bytes
No such block found, so we traverse up and split the 0-127 block into 0-63, 64-127; we add 64-127 to list tracking 64 byte blocks and pass 0-63 downwards; again it is split into 0-31 and 32-63; we add 32-63 to list tracking 32 byte blocks, passing 0-31 downwards; one more spli is done and 0-15 is returned to user while 16-31 is added to free list tracking 16 byte blocks.
List is: {}, {}, {}, {}, { (16, 31) }, { (32, 63) }, { (64, 127) }, {}
• Allocation Request: 16 bytes
Straight up memory segment 16-31 will be allocated as it already exists.
List is: {}, {}, {}, {}, {}, { (32, 63) }, { (64, 127) }, {}
• Allocation Request: 16 bytes
No such block found, so we will traverse up to block 32-63 and split it to blocks 32-47 and 48-63; we will add 48-63 to list tracking 16 byte blocks and return 32-47 to user.
List is: {}, {}, {}, {}, { (48, 63) }, {}, { (64, 127) }, {}
• Allocation Request: 16 bytes
Straight up memory segment 48-63 will be allocated as it already exists.
List is: {}, {}, {}, {}, {}, {}, { (64, 127) }, {}
• Deallocation Request: StartIndex = 0
Deallocation will be done but no coalesscing is possible as it’s buddyNumber is 0 and buddyAddress is 16 (via the formula), none of which is in the free list.
List is: {}, {}, {}, {}, { (0, 15) }, {}, { (64, 127) }, {}
• Deallocation Request: StartIndex = 9
Result: Invalid request, as this segmeent was never allocated.
List is: {}, {}, {}, {}, { (0, 15) }, {}, { (64, 127) }, {}
• Deallocation Request: StartIndex = 32
Deallocation will be done but no coalesscing is possible as the buddyNumber of the blocks are 0 and 2 buddyAddress of the blocks are 16 and 48, repectively, none of which is in the free list.
List is: {}, {}, {}, {}, { (0, 15), (32-47) }, {}, { (64, 127) }, {}
• Deallocation Request: StartIndex = 16
Deallocation will be done and coealsecing of the blocks 0-15 and 16-31 will also be done as the buddyAddress of block 16-31 is 0, which is present in the free list tracking 16 byte blocks.
List is: {}, {}, {}, {}, { (32-47) }, { (0, 31) }, { (64, 127) }, {} Figure – Buddy algorithm-allocation and deallocation

Implementation –
Below is the complete program.

## Java

 `import` `java.io.*; ` `import` `java.util.*; ` ` `  `class` `Buddy { ` ` `  `    ``// Inner class to store lower ` `    ``// and upper bounds of the allocated memory ` `    ``class` `Pair { ` `         `  `        ``int` `lb, ub; ` `        ``Pair(``int` `a, ``int` `b) ` `        ``{ ` `            ``lb = a; ` `            ``ub = b; ` `        ``} ` `    ``} ` ` `  `    ``// Size of main memory ` `    ``int` `size; ` ` `  `    ``// Array to track all ` `    ``// the free nodes of various sizes ` `    ``ArrayList arr[]; ` `     `  `    ``// Hashmap to store the starting ` `    ``// address and size of allocated segment ` `    ``// Key is starting address, size is value ` `    ``HashMap hm; ` `     `  `    ``// Else compiler will give warning ` `    ``// about generic array creation ` `    ``@SuppressWarnings``(``"unchecked"``) ` `    ``Buddy(``int` `s) ` `    ``{ ` `         `  `        ``size = s; ` `        ``hm = ``new` `HashMap<>(); ` `         `  `        ``// Gives us all possible powers of 2 ` `        ``int` `x = (``int``)Math.ceil(Math.log(s) / Math.log(``2``)); ` ` `  `        ``// One extra element is added ` `        ``// to simplify arithmetic calculations ` `        ``arr = ``new` `ArrayList[x + ``1``]; ` ` `  `        ``for` `(``int` `i = ``0``; i <= x; i++) ` `            ``arr[i] = ``new` `ArrayList<>(); ` ` `  `        ``// Initially, only the largest block is free ` `        ``// and hence is on the free list ` `        ``arr[x].add(``new` `Pair(``0``, size - ``1``)); ` `    ``} ` `     `  `    ``void` `allocate(``int` `s) ` `    ``{ ` ` `  `        ``// Calculate which free list to search to get the ` `        ``// smallest block large enough to fit the request ` `        ``int` `x = (``int``)Math.ceil(Math.log(s) / Math.log(``2``)); ` ` `  `        ``int` `i; ` `        ``Pair temp = ``null``; ` ` `  `        ``// We already have such a block ` `        ``if` `(arr[x].size() > ``0``) { ` ` `  `            ``// Remove from free list ` `            ``// as it will be allocated now ` `            ``temp = (Pair)arr[x].remove(``0``); ` `            ``System.out.println(``"Memory from "` `+ temp.lb ` `                            ``+ ``" to "` `+ temp.ub + ``" allocated"``); ` `                             `  `            ``// Store in HashMap ` `            ``hm.put(temp.lb, temp.ub - temp.lb + ``1``); ` `            ``return``; ` `        ``} ` ` `  `        ``// If not, search for a larger block ` `        ``for` `(i = x + ``1``; i < arr.length; i++) { ` ` `  `            ``if` `(arr[i].size() == ``0``) ` `                ``continue``; ` ` `  `            ``// Found a larger block, so break ` `            ``break``; ` `        ``} ` ` `  `        ``// This would be true if no such block was found ` `        ``// and array was exhausted ` `        ``if` `(i == arr.length) { ` `             `  `            ``System.out.println(``"Sorry, failed to allocate memory"``); ` `            ``return``; ` `        ``} ` ` `  `        ``// Remove the first block ` `        ``temp = (Pair)arr[i].remove(``0``); ` ` `  `        ``i--; ` ` `  `        ``// Traverse down the list ` `        ``for` `(; i >= x; i--) { ` ` `  `            ``// Divide the block in two halves ` `            ``// lower index to half-1 ` `            ``Pair newPair = ``new` `Pair(temp.lb, temp.lb ` `                                    ``+ (temp.ub - temp.lb) / ``2``); ` ` `  `            ``// half to upper index ` `            ``Pair newPair2 = ``new` `Pair(temp.lb ` `                                    ``+ (temp.ub - temp.lb + ``1``) / ``2``, ` `                                    ``temp.ub); ` ` `  `            ``// Add them to next list ` `            ``// which is tracking blocks of smaller size ` `            ``arr[i].add(newPair); ` `            ``arr[i].add(newPair2); ` ` `  `            ``// Remove a block to continue the downward pass ` `            ``temp = (Pair)arr[i].remove(``0``); ` `        ``} ` ` `  `        ``// Finally inform the user ` `        ``// of the allocated location in memory ` `        ``System.out.println(``"Memory from "` `+ temp.lb ` `                        ``+ ``" to "` `+ temp.ub + ``" allocated"``); ` ` `  `        ``// Store in HashMap ` `        ``hm.put(temp.lb, temp.ub - temp.lb + ``1``); ` `    ``} ` `    ``void` `deallocate(``int` `s) ` `    ``{ ` `        ``// Invalid reference, as this was never allocated ` `        ``if` `(!hm.containsKey(s)) { ` `            ``System.out.println(``"Sorry, invalid free request"``); ` `            ``return``; ` `        ``} ` ` `  `        ``// Get the list which will track free blocks  ` `        ``// of this size ` `        ``int` `x = (``int``)Math.ceil(Math.log(hm.get(s))  ` `                                        ``/ Math.log(``2``)); ` `        ``int` `i, buddyNumber, buddyAddress; ` ` `  `        ``// Add it to the free list ` `        ``arr[x].add(``new` `Pair(s, s + (``int``)Math.pow(``2``, x) - ``1``)); ` `        ``System.out.println(``"Memory block from "` `+ s + ``" to "`  `                           ``+ (s + (``int``)Math.pow(``2``, x) - ``1``) + ``" freed"``); ` ` `  ` `  `        ``// Calculate it's buddy number and buddyAddress. The ` `        ``// base address is implicitly 0 in this program, so no ` `        ``// subtraction is necessary for calculating buddyNumber ` `        ``buddyNumber = s / hm.get(s); ` `     `  `        ``if` `(buddyNumber % ``2` `!= ``0``) { ` `            ``buddyAddress = s - (``int``)Math.pow(``2``, x); ` `        ``} ` `         `  `        ``else` `{ ` `            ``buddyAddress = s + (``int``)Math.pow(``2``, x); ` `        ``} ` `         `  `         `  `        ``// Search in the free list for buddy ` `        ``for` `(i = ``0``; i < arr[x].size(); i++) { ` `             `  `             `  `            ``// This indicates the buddy is also free ` `            ``if` `(arr[x].get(i).lb == buddyAddress) { ` `                 `  `                ``// Buddy is the block after block  ` `                ``// with this base address ` `                ``if` `(buddyNumber % ``2` `== ``0``) { ` `                     `  `                    ``// Add to appropriate free list ` `                    ``arr[x + ``1``].add(``new` `Pair(s, s  ` `                                  ``+ ``2` `* ((``int``)Math.pow(``2``, x)) - ``1``)); ` `                    ``System.out.println(``"Coalescing of blocks starting at "` `                                            ``+ s + ``" and "` `                                            ``+ buddyAddress + ``" was done"``); ` `                ``} ` `                 `  `                ``// Buddy is the block before block  ` `                ``// with this base address ` `                ``else` `{ ` `                     `  `                    ``// Add to appropriate free list ` `                    ``arr[x + ``1``].add(``new` `Pair(buddyAddress, ` `                                    ``buddyAddress + ``2` `* ((``int``)Math.pow(``2``, x))  ` `                                                                         ``- ``1``)); ` `                    ``System.out.println(``"Coalescing of blocks starting at "` `                                                ``+ buddyAddress + ``" and "`  `                                                ``+ s + ``" was done"``); ` `                ``} ` ` `  `                ``// Remove the individual segements  ` `                ``// as they have coalesced ` `                ``arr[x].remove(i); ` `                ``arr[x].remove(arr[x].size() - ``1``); ` `                ``break``; ` `            ``} ` `        ``} ` ` `  `        ``// Remove entry from HashMap ` `        ``hm.remove(s); ` `    ``} ` `     `  `    ``public` `static` `void` `main(String args[]) ``throws` `IOException ` `    ``{ ` `        ``int` `initialMemory = ``0``, type = -``1``, val = ``0``; ` `         `  `        ``// Uncomment below section for interactive I/O ` `        ``/*Scanner sc=new Scanner(System.in); ` `        ``initialMemory = sc.nextInt(); ` `        ``Buddy obj=new Buddy(initialMemory); ` `        ``while(true) ` `        ``{ ` `            ``type = sc.nextInt(); ` `            ``if(type==-1) ` `            ``break; ` `            ``else if(type==1) ` `            ``{ ` `                ``val=sc.nextInt(); ` `                ``obj.allocate(val); ` `            ``} ` `            ``else ` `            ``{ ` `                ``val=sc.nextInt(); ` `                ``obj.deallocate(val); ` `            ``} ` `        ``}*/` `         `  `        ``initialMemory = ``128``; ` `        ``Buddy obj = ``new` `Buddy(initialMemory); ` `        ``obj.allocate(``16``); ` `        ``obj.allocate(``16``); ` `        ``obj.allocate(``16``); ` `        ``obj.allocate(``16``); ` `        ``obj.deallocate(``0``); ` `        ``obj.deallocate(``9``); ` `        ``obj.deallocate(``32``); ` `        ``obj.deallocate(``16``); ` `    ``} ` `} `

## C#

 `using` `System; ` `using` `System.Collections.Generic; ` ` `  `public` `class` `Buddy ` `{ ` ` `  `    ``// Inner class to store lower ` `    ``// and upper bounds of the  ` `    ``// allocated memory ` `    ``class` `Pair ` `    ``{ ` `        ``public` `int` `lb, ub; ` `        ``public` `Pair(``int` `a, ``int` `b) ` `        ``{ ` `            ``lb = a; ` `            ``ub = b; ` `        ``} ` `    ``} ` ` `  `    ``// Size of main memory ` `    ``int` `size; ` ` `  `    ``// Array to track all ` `    ``// the free nodes of various sizes ` `    ``List []arr; ` `     `  `    ``// Hashmap to store the starting ` `    ``// address and size of allocated segment ` `    ``// Key is starting address, size is value ` `    ``Dictionary<``int``, ``int``> hm; ` `     `  `    ``// Else compiler will give warning ` `    ``// about generic array creation ` `    ``Buddy(``int` `s) ` `    ``{ ` `         `  `        ``size = s; ` `        ``hm = ``new` `Dictionary<``int``, ``int``>(); ` `         `  `        ``// Gives us all possible powers of 2 ` `        ``int` `x = (``int``)Math.Ceiling(Math.Log(s) /  ` `                                  ``Math.Log(2)); ` ` `  `        ``// One extra element is added ` `        ``// to simplify arithmetic calculations ` `        ``arr = ``new` `List[x + 1]; ` ` `  `        ``for` `(``int` `i = 0; i <= x; i++) ` `            ``arr[i] = ``new` `List(); ` ` `  `        ``// Initially, only the largest block is  ` `        ``// free and hence is on the free list ` `        ``arr[x].Add(``new` `Pair(0, size - 1)); ` `    ``} ` `     `  `    ``void` `allocate(``int` `s) ` `    ``{ ` ` `  `        ``// Calculate which free list to  ` `        ``// search to get the smallest block ` `        ``// large enough to fit the request ` `        ``int` `x = (``int``)Math.Ceiling(Math.Log(s) / ` `                                  ``Math.Log(2)); ` ` `  `        ``int` `i; ` `        ``Pair temp = ``null``; ` ` `  `        ``// We already have such a block ` `        ``if` `(arr[x].Count > 0) ` `        ``{ ` ` `  `            ``// Remove from free list ` `            ``// as it will be allocated now ` `            ``temp = (Pair)arr[x]; ` `            ``arr[x].RemoveAt(0); ` `            ``Console.WriteLine(``"Memory from "` `+ temp.lb +  ` `                       ``" to "` `+ temp.ub + ``" allocated"``); ` `                             `  `            ``// Store in Dictionary ` `            ``hm.Add(temp.lb, temp.ub - temp.lb + 1); ` `            ``return``; ` `        ``} ` ` `  `        ``// If not, search for a larger block ` `        ``for` `(i = x + 1; i < arr.Length; i++) ` `        ``{ ` `            ``if` `(arr[i].Count == 0) ` `                ``continue``; ` ` `  `            ``// Found a larger block, so break ` `            ``break``; ` `        ``} ` ` `  `        ``// This would be true if no such block ` `        ``// was found and array was exhausted ` `        ``if` `(i == arr.Length) ` `        ``{ ` `            ``Console.WriteLine(``"Sorry, failed to"` `+  ` `                              ``" allocate memory"``); ` `            ``return``; ` `        ``} ` ` `  `        ``// Remove the first block ` `        ``temp = (Pair)arr[i]; ` `        ``arr[i].RemoveAt(0); ` ` `  `        ``i--; ` ` `  `        ``// Traverse down the list ` `        ``for` `(; i >= x; i--) ` `        ``{ ` ` `  `            ``// Divide the block in two halves ` `            ``// lower index to half-1 ` `            ``Pair newPair = ``new` `Pair(temp.lb, temp.lb +  ` `                                   ``(temp.ub - temp.lb) / 2); ` ` `  `            ``// half to upper index ` `            ``Pair newPair2 = ``new` `Pair(temp.lb + (temp.ub -  ` `                                     ``temp.lb + 1) / 2, temp.ub); ` ` `  `            ``// Add them to next list ` `            ``// which is tracking blocks of  ` `            ``// smaller size ` `            ``arr[i].Add(newPair); ` `            ``arr[i].Add(newPair2); ` ` `  `            ``// Remove a block to continue  ` `            ``// the downward pass ` `            ``temp = (Pair)arr[i]; ` `            ``arr[i].RemoveAt(0); ` `        ``} ` ` `  `        ``// Finally inform the user ` `        ``// of the allocated location in memory ` `        ``Console.WriteLine(``"Memory from "` `+ temp.lb +  ` `                   ``" to "` `+ temp.ub + ``" allocated"``); ` ` `  `        ``// Store in Dictionary ` `        ``hm.Add(temp.lb, temp.ub - temp.lb + 1); ` `    ``} ` `     `  `    ``void` `deallocate(``int` `s) ` `    ``{ ` `         `  `        ``// Invalid reference,  ` `        ``// as this was never allocated ` `        ``if` `(!hm.ContainsKey(s)) ` `        ``{ ` `            ``Console.WriteLine(``"Sorry, invalid free request"``); ` `            ``return``; ` `        ``} ` ` `  `        ``// Get the list which will track free blocks  ` `        ``// of this size ` `        ``int` `x = (``int``)Math.Ceiling(Math.Log(hm[s]) /  ` `                                  ``Math.Log(2)); ` `        ``int` `i, buddyNumber, buddyAddress; ` ` `  `        ``// Add it to the free list ` `        ``arr[x].Add(``new` `Pair(s, s +  ` `                  ``(``int``)Math.Pow(2, x) - 1)); ` `        ``Console.WriteLine(``"Memory block from "` `+ s +  ` `                                       ``" to "` `+ (s +  ` `               ``(``int``)Math.Pow(2, x) - 1) + ``" freed"``); ` ` `  ` `  `        ``// Calculate it's buddy number and  ` `        ``// buddyAddress. The base address is ` `        ``// implicitly 0 in this program,  ` `        ``// so no subtraction is necessary for ` `        ``// calculating buddyNumber ` `        ``buddyNumber = s / hm[s]; ` `     `  `        ``if` `(buddyNumber % 2 != 0) ` `        ``{ ` `            ``buddyAddress = s - (``int``)Math.Pow(2, x); ` `        ``} ` `        ``else`  `        ``{ ` `            ``buddyAddress = s + (``int``)Math.Pow(2, x); ` `        ``} ` `         `  `        ``// Search in the free list for buddy ` `        ``for` `(i = 0; i < arr[x].Count; i++)  ` `        ``{ ` `             `  `            ``// This indicates the buddy is also free ` `            ``if` `(arr[x][i].lb == buddyAddress) ` `            ``{ ` `                 `  `                ``// Buddy is the block after block  ` `                ``// with this base address ` `                ``if` `(buddyNumber % 2 == 0)  ` `                ``{ ` `                     `  `                    ``// Add to appropriate free list ` `                    ``arr[x + 1].Add(``new` `Pair(s, s + 2 *  ` `                                 ``((``int``)Math.Pow(2, x)) - 1)); ` `                    ``Console.WriteLine(``"Coalescing of blocks starting at "` `+  ` `                                 ``s + ``" and "` `+ buddyAddress + ``" was done"``); ` `                ``} ` `                 `  `                ``// Buddy is the block before block  ` `                ``// with this base address ` `                ``else`  `                ``{ ` `                     `  `                    ``// Add to appropriate free list ` `                    ``arr[x + 1].Add(``new` `Pair(buddyAddress,  ` `                                            ``buddyAddress +  ` `                                  ``2 * ((``int``)Math.Pow(2, x)) - 1)); ` `                    ``Console.WriteLine(``"Coalescing of blocks starting at "` `+  ` `                                 ``buddyAddress + ``" and "` `+ s + ``" was done"``); ` `                ``} ` ` `  `                ``// Remove the individual segements  ` `                ``// as they have coalesced ` `                ``arr[x].RemoveAt(i); ` `                ``arr[x].RemoveAt(arr[x].Count - 1); ` `                ``break``; ` `            ``} ` `        ``} ` ` `  `        ``// Remove entry from Dictionary ` `        ``hm.Remove(s); ` `    ``} ` `     `  `    ``// Driver Code ` `    ``public` `static` `void` `Main(String []args) ` `    ``{ ` `        ``int` `initialMemory = 0; ` `        ``initialMemory = 128; ` `        ``Buddy obj = ``new` `Buddy(initialMemory); ` `        ``obj.allocate(16); ` `        ``obj.allocate(16); ` `        ``obj.allocate(16); ` `        ``obj.allocate(16); ` `        ``obj.deallocate(0); ` `        ``obj.deallocate(9); ` `        ``obj.deallocate(32); ` `        ``obj.deallocate(16); ` `    ``} ` `} ` ` `  `// This code is contributed by 29AjayKumar `

Output:

```Memory from 0 to 15 allocated
Memory from 16 to 31 allocated
Memory from 32 to 47 allocated
Memory from 48 to 63 allocated
Memory block from 0 to 15 freed
Sorry, invalid free request
Memory block from 32 to 47 freed
Memory block from 16 to 31 freed
Coalescing of blocks starting at 0 and 16 was done
```

Time Complexity –
As already discussed in set 1, time complexity of allocation is O(log(n)). For deallocation, in the worst case, all the allocated blocks can be of size 1 unit, which will then require O(n) time to scan the list for coalescing. However, in practice, it is highly unlikely that such an allocation will happen so it is generally much faster than linear time.

My Personal Notes arrow_drop_up CSE B Tech 4th Year at IIT Bhubaneswar||Summer Intern 2018 IIT Roorkee||Summer Intern 2019 Goldman Sachs

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.

Improved By : Akanksha_Rai, 29AjayKumar