mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-11-29 10:27:39 +08:00
Add memalloc for testing memory operations.
This commit is contained in:
parent
279301f6bf
commit
ef3982d66b
@ -19,11 +19,9 @@ CFLAGS = -c -g -W \
|
||||
|
||||
###########################################################
|
||||
#Check system:
|
||||
SYSLIB =
|
||||
CHECKSYSRES = @echo "Unknow system type!";exit 1
|
||||
UNIXNAME = $(shell uname -sm)
|
||||
UNIXTYPE = LINUX
|
||||
polarssl =
|
||||
shared_ldflags =
|
||||
|
||||
ifeq ($(CC),)
|
||||
CC = g++
|
||||
@ -42,6 +40,17 @@ ifeq ($(findstring clang++, $(CC)), clang++)
|
||||
-Wno-invalid-offsetof
|
||||
endif
|
||||
|
||||
# For Linux
|
||||
ifeq ($(findstring Linux, $(UNIXNAME)), Linux)
|
||||
shared_ldflags += -lunwind -lunwind-x86_64 -lz -lpthread
|
||||
endif
|
||||
|
||||
# For Darwin
|
||||
ifeq ($(findstring Darwin, $(UNIXNAME)), Darwin)
|
||||
CFLAGS += -D_XOPEN_SOURCE -Wno-deprecated-declarations
|
||||
shared_ldflags += -lz -lpthread
|
||||
endif
|
||||
|
||||
#Find system type.
|
||||
ifneq ($(SYSPATH),)
|
||||
CHECKSYSRES = @echo "System is $(shell uname -sm)"
|
||||
@ -53,7 +62,6 @@ LIB_PATH_DST = .
|
||||
DEF_PATH_DST = ./debug
|
||||
|
||||
CFLAGS += -I.
|
||||
shared_ldflags = -lunwind -lunwind-x86_64 -lz -lpthread
|
||||
|
||||
#Project's objs
|
||||
OBJS_DST = $(patsubst %.cpp, $(OBJ_PATH_DST)/%.o, $(notdir $(wildcard ./*.cpp)))
|
||||
|
@ -3,7 +3,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <ucontext.h>
|
||||
#include <libunwind.h>
|
||||
#include "libmm.h"
|
||||
|
||||
static void stacktrace(void)
|
||||
{
|
||||
@ -35,8 +37,6 @@ static void stacktrace(void)
|
||||
}
|
||||
}
|
||||
|
||||
typedef void *(*malloc_fn)(size_t);
|
||||
static malloc_fn __malloc_fn = NULL;
|
||||
static size_t total_size = 0;
|
||||
static bool __check = false;
|
||||
static pthread_mutex_t __lock;
|
||||
@ -45,7 +45,6 @@ static pthread_once_t once_control = PTHREAD_ONCE_INIT;
|
||||
|
||||
static void once_init(void)
|
||||
{
|
||||
__malloc_fn = (malloc_fn) dlsym(RTLD_NEXT, "malloc");
|
||||
pthread_mutex_init(&__lock, NULL);
|
||||
}
|
||||
|
||||
@ -69,7 +68,7 @@ void *malloc(size_t size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = __malloc_fn(size);
|
||||
ptr = mymalloc(size);
|
||||
if (ptr && __check) {
|
||||
if (size == 8208) {
|
||||
//abort();
|
||||
|
@ -5,6 +5,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *mymalloc(size_t size);
|
||||
void print_mem_list();
|
||||
|
||||
//void start_check(void);
|
||||
//void stop_check(void);
|
||||
|
||||
|
169
test/libmm/memalloc.cpp
Normal file
169
test/libmm/memalloc.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
// Copy from https://github.com/arjun024/memalloc
|
||||
/* Only for the debug printf */
|
||||
#include <stdio.h>
|
||||
#include "libmm.h"
|
||||
|
||||
typedef char ALIGN[16];
|
||||
|
||||
union header {
|
||||
struct {
|
||||
size_t size;
|
||||
unsigned is_free;
|
||||
union header *next;
|
||||
} s;
|
||||
/* force the header to be aligned to 16 bytes */
|
||||
ALIGN stub;
|
||||
};
|
||||
typedef union header header_t;
|
||||
|
||||
header_t *head = NULL, *tail = NULL;
|
||||
pthread_mutex_t global_malloc_lock;
|
||||
|
||||
static header_t *get_free_block(size_t size)
|
||||
{
|
||||
header_t *curr = head;
|
||||
while(curr) {
|
||||
/* see if there's a free block that can accomodate requested size */
|
||||
if (curr->s.is_free && curr->s.size >= size)
|
||||
return curr;
|
||||
curr = curr->s.next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free(void *block)
|
||||
{
|
||||
header_t *header, *tmp;
|
||||
/* program break is the end of the process's data segment */
|
||||
void *programbreak;
|
||||
|
||||
if (!block)
|
||||
return;
|
||||
pthread_mutex_lock(&global_malloc_lock);
|
||||
header = (header_t*)block - 1;
|
||||
/* sbrk(0) gives the current program break address */
|
||||
programbreak = sbrk(0);
|
||||
|
||||
/*
|
||||
Check if the block to be freed is the last one in the
|
||||
linked list. If it is, then we could shrink the size of the
|
||||
heap and release memory to OS. Else, we will keep the block
|
||||
but mark it as free.
|
||||
*/
|
||||
if ((char*)block + header->s.size == programbreak) {
|
||||
if (head == tail) {
|
||||
head = tail = NULL;
|
||||
} else {
|
||||
tmp = head;
|
||||
while (tmp) {
|
||||
if(tmp->s.next == tail) {
|
||||
tmp->s.next = NULL;
|
||||
tail = tmp;
|
||||
}
|
||||
tmp = tmp->s.next;
|
||||
}
|
||||
}
|
||||
/*
|
||||
sbrk() with a negative argument decrements the program break.
|
||||
So memory is released by the program to OS.
|
||||
*/
|
||||
sbrk(0 - header->s.size - sizeof(header_t));
|
||||
/* Note: This lock does not really assure thread
|
||||
safety, because sbrk() itself is not really
|
||||
thread safe. Suppose there occurs a foregin sbrk(N)
|
||||
after we find the program break and before we decrement
|
||||
it, then we end up realeasing the memory obtained by
|
||||
the foreign sbrk().
|
||||
*/
|
||||
pthread_mutex_unlock(&global_malloc_lock);
|
||||
return;
|
||||
}
|
||||
header->s.is_free = 1;
|
||||
pthread_mutex_unlock(&global_malloc_lock);
|
||||
}
|
||||
|
||||
void *mymalloc(size_t size)
|
||||
{
|
||||
size_t total_size;
|
||||
void *block;
|
||||
header_t *header;
|
||||
if (!size)
|
||||
return NULL;
|
||||
pthread_mutex_lock(&global_malloc_lock);
|
||||
header = get_free_block(size);
|
||||
if (header) {
|
||||
/* Woah, found a free block to accomodate requested memory. */
|
||||
header->s.is_free = 0;
|
||||
pthread_mutex_unlock(&global_malloc_lock);
|
||||
return (void*)(header + 1);
|
||||
}
|
||||
/* We need to get memory to fit in the requested block and header from OS. */
|
||||
total_size = sizeof(header_t) + size;
|
||||
block = sbrk(total_size);
|
||||
if (block == (void*) -1) {
|
||||
pthread_mutex_unlock(&global_malloc_lock);
|
||||
return NULL;
|
||||
}
|
||||
header = (header_t*) block;
|
||||
header->s.size = size;
|
||||
header->s.is_free = 0;
|
||||
header->s.next = NULL;
|
||||
if (!head)
|
||||
head = header;
|
||||
if (tail)
|
||||
tail->s.next = header;
|
||||
tail = header;
|
||||
pthread_mutex_unlock(&global_malloc_lock);
|
||||
return (void*)(header + 1);
|
||||
}
|
||||
|
||||
void *calloc(size_t num, size_t nsize)
|
||||
{
|
||||
size_t size;
|
||||
void *block;
|
||||
if (!num || !nsize)
|
||||
return NULL;
|
||||
size = num * nsize;
|
||||
/* check mul overflow */
|
||||
if (nsize != size / num)
|
||||
return NULL;
|
||||
block = mymalloc(size);
|
||||
if (!block)
|
||||
return NULL;
|
||||
memset(block, 0, size);
|
||||
return block;
|
||||
}
|
||||
|
||||
void *realloc(void *block, size_t size)
|
||||
{
|
||||
header_t *header;
|
||||
void *ret;
|
||||
if (!block || !size)
|
||||
return mymalloc(size);
|
||||
header = (header_t*)block - 1;
|
||||
if (header->s.size >= size)
|
||||
return block;
|
||||
ret = mymalloc(size);
|
||||
if (ret) {
|
||||
/* Relocate contents to the new bigger block */
|
||||
memcpy(ret, block, header->s.size);
|
||||
/* Free the old memory block */
|
||||
free(block);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* A debug function to print the entire link list */
|
||||
void print_mem_list()
|
||||
{
|
||||
header_t *curr = head;
|
||||
printf("head = %p, tail = %p \n", (void*)head, (void*)tail);
|
||||
while(curr) {
|
||||
printf("addr = %p, size = %zu, is_free=%u, next=%p\n",
|
||||
(void*)curr, curr->s.size, curr->s.is_free, (void*)curr->s.next);
|
||||
curr = curr->s.next;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user