Skip to content

Instantly share code, notes, and snippets.

@huynhsamha
Created March 8, 2018 12:58
Show Gist options
  • Save huynhsamha/183213fd0ff3d41ae741aaff0bd218a3 to your computer and use it in GitHub Desktop.
Save huynhsamha/183213fd0ff3d41ae741aaff0bd218a3 to your computer and use it in GitHub Desktop.
aligned malloc() and free() custom with sbrk()
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/types.h>
#include <unistd.h>
#include "ex1.h"
#define ERROR_ON_SBRK (void *)-1
info_block *find_free_block(unsigned int size)
{
info_block *cur = head;
while (cur)
{
if (cur->is_free && cur->size >= size)
return cur; // free block meet size requirement
cur = cur->next;
}
return NULL;
}
void *allocate_aligned_block(unsigned int size, unsigned int align)
{
void *p_cur, *p_block, *p_info_block;
int cur, offset;
// allocate block for info block
if (sbrk(sizeof(info_block)) == ERROR_ON_SBRK)
return NULL;
p_cur = sbrk(0);
cur = (uintptr_t)p_cur;
// Get offset
offset = cur % align;
if (offset > 0)
offset = align - offset;
// increase offset to align
if (sbrk(offset) == ERROR_ON_SBRK)
return NULL;
// get pointer to block
p_block = sbrk(0);
// increase block size
if (sbrk(size) == ERROR_ON_SBRK)
return NULL;
// info block is behind block
p_info_block = p_block - sizeof(info_block);
return p_info_block;
}
void *aligned_malloc(unsigned int size, unsigned int align)
{
void *return_block;
info_block *info;
void *new_block;
// find in current list have free block meet size requirement.
info = find_free_block(size);
if (info)
{
// Found here
info->is_free = 0; // not free now
return_block = (void *)(info + 1);
printf("Old block: Info at %lu - Block at %lu\n", (uintptr_t)info, (uintptr_t)return_block);
return return_block;
}
// Not found any good free block
// new block allocated with size must have info_block
new_block = allocate_aligned_block(size, align);
if (new_block == NULL)
return NULL; // cannot allocate new block
// store info block
info = new_block;
info->size = size;
info->is_free = 0;
info->next = NULL;
// Update state of list via head and tail
if (!head)
head = info;
if (tail)
tail->next = info;
tail = info;
// Return new block
return_block = (void *)(info + 1);
printf("New block: Info at %lu - Block at %lu\n", (uintptr_t)info, (uintptr_t)return_block);
return return_block;
}
void * aligned_free(void *block)
{
info_block *info;
info_block *tmp;
void *program_break;
if (!block) return NULL;
// retrive block info
info = (info_block *)block - 1;
// get current program break;
program_break = sbrk(0);
// block to free is the last block in list, should update *tail and program break
if (block + info->size == program_break)
{
if (head == tail)
// no any left blocks
head = tail = NULL;
else
{
tmp = head;
// find the block point to end block
while (tmp)
{
if (tmp->next == tail)
{
tmp->next = NULL;
tail = tmp;
}
tmp = tmp->next;
}
}
// release memory of last block to OS
sbrk(0 - sizeof(info_block) - info->size);
printf("Release memory to OS\n");
return sbrk(0);
}
// block to free is internal list, only update status free of info_block
info->is_free = 1;
return sbrk(0);
}
#ifndef ALIGNED_MALLOC_FREE_SYSCALL
#define ALIGNED_MALLOC_FREE_SYSCALL
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/types.h>
#include <unistd.h>
// Store info about block
typedef struct info_block
{
int size;
int is_free;
struct info_block *next;
} info_block;
// Linked list allocated block
static info_block *head, *tail;
void * aligned_malloc(unsigned int size, unsigned int align);
void * aligned_free(void * ptr);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ex1.h"
int power(int x, int m)
{
if (m == 0)
return 1;
int tmp = power(x, m / 2);
if (m % 2 == 0)
return tmp * tmp;
return tmp * tmp * x;
}
int main()
{
printf("Initialize program break by printf one line\n");
int align = power(2, 20);
int size_2 = 2 * sizeof(int);
int size_5 = 5 * sizeof(int);
printf("sizeof(info_block) = %lu\n", sizeof(info_block));
printf("size_5 = %d\n", size_5);
printf("size_2 = %d\n", size_2);
printf("align = %d\n", align);
// malloc [a-b-c-d]
int *a = (int *)aligned_malloc(size_5, align);
int *b = (int *)aligned_malloc(size_5, align);
int *c = (int *)aligned_malloc(size_5, align);
int *d = (int *)aligned_malloc(size_5, align);
// free internal [a-b-c@5-d]
aligned_free(c);
// malloc intenal [a-b-e-d]
int *e = (int *)aligned_malloc(size_2, align);
// free internal [a-b@5-e-d]
aligned_free(b);
// malloc internal [a-f-e-d]
int *f = (int *)aligned_malloc(size_5, align);
// free last block [a-f-e]
aligned_free(d);
// malloc new block [a-f-e-g-h]
int *g = (int *)aligned_malloc(size_2, align);
int *h = (int *)aligned_malloc(size_5, align);
// free small block [a-f-e-g@2-h]
aligned_free(g);
// malloc large block [a-f-e-g@2-h-i]
int *i = (int *)aligned_malloc(size_5, align);
// free block g is free [a-f-e-g-h-i]
aligned_free(g);
// free all
aligned_free(a);
aligned_free(f);
aligned_free(e);
aligned_free(h);
aligned_free(i);
/************* RESULT ************
Initialize program break by printf one line
sizeof(info_block) = 16
size_5 = 20
size_2 = 8
align = 1048576
New block: Info at 31457264 - Block at 31457280
New block: Info at 32505840 - Block at 32505856
New block: Info at 33554416 - Block at 33554432
New block: Info at 34602992 - Block at 34603008
Old block: Info at 33554416 - Block at 33554432
Old block: Info at 32505840 - Block at 32505856
Release memory to OS
New block: Info at 34602992 - Block at 34603008
New block: Info at 35651568 - Block at 35651584
New block: Info at 36700144 - Block at 36700160
Release memory to OS
**********************************/
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment