backup
This commit is contained in:
parent
06fac933c2
commit
b4f942f678
6 changed files with 174 additions and 37 deletions
|
|
@ -1,10 +1,10 @@
|
|||
CC=gcc
|
||||
CFLAGS=-std=c99 -pedantic -Werror -Wall -Wextra -Wvla -fvisibility=hidden -fPIC
|
||||
CPPFLAGS=D_DEFAULT_SOURCE
|
||||
CPPFLAGS= -D_DEFAULT_SOURCE
|
||||
LDFLAGS= -shared -Wl --no-undefined
|
||||
|
||||
SRCS=
|
||||
OBJS=${SRC:.c=.o}
|
||||
SRCS=src/malloc.c src/helpers/helpers.c src/helpers/allocate.c
|
||||
OBJS=${SRCS:.c=.o}
|
||||
TARGET=libmalloc.so
|
||||
|
||||
library: $(OBJS)
|
||||
|
|
|
|||
70
malloc/src/helpers/allocate.c
Normal file
70
malloc/src/helpers/allocate.c
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#include "allocate.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
void *allocate_block(struct bucket *biquette, int block_number)
|
||||
{
|
||||
if (block_number == -1)
|
||||
return NULL;
|
||||
|
||||
// Update header
|
||||
unsigned char byte_mask = 1 << ((block_number % 8) - 1);
|
||||
biquette->alloc_blk_cnt++;
|
||||
biquette->free_map[block_number / 8] &= byte_mask;
|
||||
|
||||
// Compute block address
|
||||
return get_block(biquette, block_number);
|
||||
}
|
||||
|
||||
struct bucket *create_bucket(size_t min_alloc_size)
|
||||
{
|
||||
// Round up
|
||||
size_t alloc_size;
|
||||
if (min_alloc_size > PAGE_SIZE - sizeof(struct bucket))
|
||||
// Huge page
|
||||
alloc_size = min_alloc_size;
|
||||
else
|
||||
// Regular page
|
||||
alloc_size = s2p(min_alloc_size);
|
||||
|
||||
// Get page
|
||||
void *page =
|
||||
mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, -1, 0);
|
||||
|
||||
if (page == NULL)
|
||||
return NULL;
|
||||
|
||||
// Init bucket
|
||||
struct bucket *header = page;
|
||||
header->block_size = alloc_size;
|
||||
header->alloc_blk_cnt = 0;
|
||||
memset(header->free_map, 0, FREE_LIST_SIZE);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
void free_block(void *ptr, struct bucket **list)
|
||||
{
|
||||
// Compute header location and block number
|
||||
struct bucket *header = get_page_begin(ptr);
|
||||
|
||||
// free in map and update size
|
||||
int block_number; // ...
|
||||
unsigned char byte_mask = 1 << ((block_number % 8) - 1);
|
||||
header->free_map[block_number / 8] &= ~byte_mask;
|
||||
|
||||
// Huge page
|
||||
if (header->block_size > BUCKET_SIZE)
|
||||
// Delete bucket
|
||||
header->alloc_blk_cnt = 0;
|
||||
|
||||
// free bucket if necessary
|
||||
if (header->alloc_blk_cnt == 0)
|
||||
{
|
||||
bucket_list_remove(list, header);
|
||||
munmap(ptr, 1);
|
||||
}
|
||||
}
|
||||
13
malloc/src/helpers/allocate.h
Normal file
13
malloc/src/helpers/allocate.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef ALLOCATE_H
|
||||
#define ALLOCATE_H
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void *allocate_block(struct bucket *biquette, int block_number);
|
||||
struct bucket *create_bucket(size_t min_alloc_size);
|
||||
void bucket_append(struct bucket **head, struct bucket *elt);
|
||||
void free_block(void *ptr, struct bucket **list);
|
||||
|
||||
#endif // ! ALLOCATE_H
|
||||
|
|
@ -1,8 +1,5 @@
|
|||
#include "helpers.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
// Returns the smallest power of 2 greater or equal to s
|
||||
size_t s2p(size_t s)
|
||||
{
|
||||
|
|
@ -33,44 +30,47 @@ size_t s2p(size_t s)
|
|||
return n;
|
||||
}
|
||||
|
||||
void *find_free_block(struct bucket *buck)
|
||||
int find_free_block(struct bucket *buck)
|
||||
{
|
||||
unsigned maplength = buck->block_size / 8;
|
||||
unsigned maplength = PAGE_SIZE / buck->block_size / 8;
|
||||
// for each block
|
||||
for (unsigned i = 0; i < maplength; i++)
|
||||
{
|
||||
unsigned char map_byte = buck->free_list[i];
|
||||
unsigned char map_byte = buck->free_map[i];
|
||||
unsigned char bit = 1;
|
||||
// Test byte
|
||||
for (unsigned j = 0; j < 8; j <<= 1)
|
||||
{
|
||||
if (map_byte & bit) // Test if free
|
||||
return get_data_begin(buck) + (buck->block_size * (i * 8 + j));
|
||||
return i * 8 + j;
|
||||
|
||||
bit <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct bucket *create_bucket(size_t min_alloc_size)
|
||||
void *get_block(struct bucket *biquette, int block_number)
|
||||
{
|
||||
// Round up
|
||||
size_t alloc_size = s2p(min_alloc_size);
|
||||
// Get page
|
||||
void *page =
|
||||
mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, -1, 0);
|
||||
|
||||
if (page == NULL)
|
||||
if (block_number == -1)
|
||||
return NULL;
|
||||
|
||||
// Init bucket
|
||||
struct bucket *header = page;
|
||||
header->block_size = alloc_size;
|
||||
memset(header->free_list, 0, FREE_LIST_SIZE);
|
||||
char *data_begin = get_data_begin(biquette);
|
||||
return data_begin + (biquette->block_size * (block_number));
|
||||
}
|
||||
|
||||
return header;
|
||||
int get_block_number(struct bucket *biquette, void *block)
|
||||
{
|
||||
if (block == NULL || biquette == NULL)
|
||||
return -1;
|
||||
|
||||
char *block_nul = block;
|
||||
void *biquetteounette = biquette;
|
||||
char *biquette_cherie = biquetteounette;
|
||||
|
||||
return (block_nul - biquette_cherie - sizeof(struct bucket))
|
||||
/ biquette->block_size;
|
||||
}
|
||||
|
||||
// Gets a bucket with at least a block_size of size
|
||||
|
|
@ -99,7 +99,7 @@ void *get_page_begin(void *ptr)
|
|||
return pointeur_alacon + quelenfer;
|
||||
}
|
||||
|
||||
void bucket_append(struct bucket **head, struct bucket *elt)
|
||||
void bucket_list_append(struct bucket **head, struct bucket *elt)
|
||||
{
|
||||
struct bucket *list_elt = *head;
|
||||
if (list_elt == NULL)
|
||||
|
|
@ -114,3 +114,27 @@ void bucket_append(struct bucket **head, struct bucket *elt)
|
|||
}
|
||||
list_elt->next = elt;
|
||||
}
|
||||
|
||||
// Removes a bucket from the list pointed by head
|
||||
void bucket_list_remove(struct bucket **head, struct bucket *elt)
|
||||
{
|
||||
struct bucket *list_elt = *head;
|
||||
if (list_elt == NULL)
|
||||
return;
|
||||
|
||||
if (*head == elt)
|
||||
{
|
||||
*head = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
while (list_elt->next != NULL)
|
||||
{
|
||||
if (list_elt->next == elt)
|
||||
{
|
||||
list_elt->next = list_elt->next->next;
|
||||
return;
|
||||
}
|
||||
list_elt = list_elt->next;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef HELPERS_H
|
||||
#define HELPERS_H
|
||||
|
||||
// #define PAGE_SIZE (size_t) sysconf(_SC_PAGE_SIZE)
|
||||
// #define PAGE_SIZE sysconf(_SC_PAGE_SIZE)
|
||||
#define PAGE_SIZE 4096
|
||||
#define MIN_BLOCK_SIZE 8
|
||||
#define FREE_LIST_SIZE PAGE_SIZE / MIN_BLOCK_SIZE / sizeof(unsigned char)
|
||||
|
|
@ -13,19 +13,24 @@
|
|||
struct bucket
|
||||
{
|
||||
unsigned block_size;
|
||||
unsigned char free_list[FREE_LIST_SIZE]; // 4096 / MIN_BLOCK_SIZE /
|
||||
// sizeof(unsigned char)
|
||||
unsigned char free_map[FREE_LIST_SIZE]; // Keeps track of allocations
|
||||
// If block_size > MIN_BLOCK_SIZE
|
||||
// It will use a consecutive
|
||||
// representation
|
||||
unsigned short alloc_blk_cnt; // Counts the number of allocated blocks
|
||||
struct bucket *next;
|
||||
|
||||
size_t checksum;
|
||||
};
|
||||
|
||||
#define BUCKET_SIZE PAGE_SIZE - sizeof(struct bucket)
|
||||
|
||||
size_t s2p(size_t n);
|
||||
void *find_free_block(struct bucket *buck);
|
||||
struct bucket *create_bucket(size_t min_alloc_size);
|
||||
int find_free_block(struct bucket *buck);
|
||||
struct bucket *get_bucket(struct bucket *head, size_t size);
|
||||
void *get_data_begin(struct bucket *biquette);
|
||||
void *get_page_begin(void *ptr);
|
||||
void bucket_append(struct bucket **head, struct bucket *elt);
|
||||
void *get_block(struct bucket* biquette, int block_number);
|
||||
void bucket_list_append(struct bucket **head, struct bucket *elt);
|
||||
void bucket_list_remove(struct bucket **head, struct bucket *elt);
|
||||
|
||||
#endif // ! HELPERS_H
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "helpers/allocate.h"
|
||||
#include "helpers/helpers.h"
|
||||
|
||||
struct bucket *head = NULL;
|
||||
|
|
@ -14,14 +16,13 @@ __attribute__((visibility("default"))) void *malloc(size_t size)
|
|||
while (buck != NULL)
|
||||
{
|
||||
// Find adequate block
|
||||
void *block = find_free_block(buck);
|
||||
if (block != NULL)
|
||||
return block;
|
||||
int block_number = find_free_block(buck);
|
||||
if (block_number != -1)
|
||||
return get_block(buck, block_number);
|
||||
else
|
||||
{
|
||||
// No free space -> loop
|
||||
buck = get_bucket(buck->next, size);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -34,14 +35,38 @@ __attribute__((visibility("default"))) void free(void *ptr)
|
|||
{
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
free_block(ptr, &head);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) void *realloc(void *ptr, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
if (ptr == NULL)
|
||||
return malloc(size);
|
||||
|
||||
struct bucket *header = get_page_begin(ptr);
|
||||
if (header == NULL)
|
||||
return NULL; // Shouldn't get here
|
||||
|
||||
if (header->block_size >= size)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
void *new_ptr = malloc(size);
|
||||
memcpy(new_ptr, ptr, header->block_size);
|
||||
free(ptr);
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) void *calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
return NULL;
|
||||
char *res = malloc(nmemb * size);
|
||||
memset(res, 0, nmemb * size);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue