free memory after 100 Mo allocated
This commit is contained in:
parent
8f0aecedec
commit
2fe89da8a2
|
@ -30,6 +30,7 @@ static __thread void **local_tail = NULL;
|
||||||
static __thread void **local_tail_buffer_end = NULL;
|
static __thread void **local_tail_buffer_end = NULL;
|
||||||
static struct double_linked_list *global_tail = NULL;
|
static struct double_linked_list *global_tail = NULL;
|
||||||
static struct double_linked_list *global_head = NULL;
|
static struct double_linked_list *global_head = NULL;
|
||||||
|
static int collect = 0;
|
||||||
static int bufsenqueued = 0;
|
static int bufsenqueued = 0;
|
||||||
static unsigned int lock = 0;
|
static unsigned int lock = 0;
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ int init_thread_comm(struct thread_comm *comm)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
local_tail = new_buffer + (USABLE_BUFFER_BYTES - BYTES_IN_ADDRESS -
|
local_tail = new_buffer + (USABLE_BUFFER_BYTES - BYTES_IN_ADDRESS -
|
||||||
(USABLE_BUFFER_BYTES % (1 << LOG_BYTES_IN_ADDRESS))) + BYTES_IN_ADDRESS; // The second parenthesis is equal to 0
|
(USABLE_BUFFER_BYTES % (1 << LOG_BYTES_IN_ADDRESS))) + BYTES_IN_ADDRESS; /* The second parenthesis is equal to 0 */
|
||||||
local_tail_buffer_end = local_tail;
|
local_tail_buffer_end = local_tail;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +94,7 @@ static void spin_unlock(unsigned int *lock)
|
||||||
: "memory", "cc");
|
: "memory", "cc");
|
||||||
}
|
}
|
||||||
|
|
||||||
void enqueue(struct double_linked_list *list, int arity, int to_tail) // Insert in the shared buffer: tail here is the tail of the shared buffer
|
void enqueue(struct double_linked_list *list, int arity, int to_tail) /* Insert in the shared buffer: tail here is the tail of the shared buffer */
|
||||||
{
|
{
|
||||||
spin_lock(&lock);
|
spin_lock(&lock);
|
||||||
if (to_tail)
|
if (to_tail)
|
||||||
|
@ -135,34 +136,60 @@ void **normalizeTail(int arity)
|
||||||
src++;
|
src++;
|
||||||
buffer_start++;
|
buffer_start++;
|
||||||
}
|
}
|
||||||
return last; // Return the buffer address of the last address (if address goes from 0 to n then it's &buf[n]
|
return last; /* Return the buffer address of the last address (if address goes from 0 to n then it's &buf[n] */
|
||||||
}
|
}
|
||||||
|
|
||||||
void closeAndEnqueueTail(int arity)
|
void closeAndEnqueueTail(int arity)
|
||||||
{
|
{
|
||||||
void **last;
|
void **last;
|
||||||
if ((((uintptr_t) local_tail) & BUFFER_MASK) != 0) // prematurely closed, won't pass here if it comes from insert
|
if ((((uintptr_t) local_tail) & BUFFER_MASK) != 0) /* prematurely closed, won't pass here if it comes from insert */
|
||||||
last = normalizeTail(arity);
|
last = normalizeTail(arity);
|
||||||
else // a full tail buffer
|
else /* a full tail buffer */
|
||||||
last = local_tail_buffer_end - BYTES_IN_ADDRESS; // last space in the buffer before the 8/16 bytes of metadata of the buffer
|
last = local_tail_buffer_end - BYTES_IN_ADDRESS; /* last space in the buffer before the 8/16 bytes of metadata of the buffer */
|
||||||
enqueue((struct double_linked_list *) ((uintptr_t) last + BYTES_IN_ADDRESS), arity, 1);
|
enqueue((struct double_linked_list *) ((uintptr_t) last + BYTES_IN_ADDRESS), arity, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkForAsyncCollection(void)
|
void checkForAsyncCollection(void)
|
||||||
{
|
{
|
||||||
|
if (bufsenqueued >= 102400) /* We use more than 100 Mo */
|
||||||
|
collect = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_pages(struct double_linked_list *list_cur)
|
||||||
|
{
|
||||||
|
if (list_cur == NULL)
|
||||||
|
return;
|
||||||
|
spin_lock(&lock);
|
||||||
|
/*
|
||||||
|
* We may free some buffer allocated after this line is executed, thus
|
||||||
|
* the real number of buffer enqueued could be bigger.
|
||||||
|
* This is done to avoid to keep the lock during the while loop and for
|
||||||
|
* checkForAsyncCollection to first start asking for a collection at
|
||||||
|
* 100 Mo in the *worst* case
|
||||||
|
*/
|
||||||
|
bufsenqueued = 0;
|
||||||
|
spin_unlock(&lock);
|
||||||
|
while (global_head != list_cur) /* We know closeAndEnqueueTail() ask enqueue() to enqueue at tail */
|
||||||
|
{
|
||||||
|
void *buf_start;
|
||||||
|
|
||||||
|
buf_start = (void *) ((uintptr_t) global_head & BUFFER_MASK);
|
||||||
|
global_head = global_head->next;
|
||||||
|
free(buf_start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tailOverflow(int arity)
|
void tailOverflow(int arity)
|
||||||
{
|
{
|
||||||
void *new_buffer;
|
void *new_buffer;
|
||||||
if (local_tail != NULL)
|
if (local_tail != NULL)
|
||||||
closeAndEnqueueTail(arity); // Add the buffer to the tail of the shared buffer
|
closeAndEnqueueTail(arity); /* Add the buffer to the tail of the shared buffer */
|
||||||
if (posix_memalign(&new_buffer, BUFFER_SIZE, BUFFER_SIZE))
|
if (posix_memalign(&new_buffer, BUFFER_SIZE, BUFFER_SIZE))
|
||||||
fprintf(stderr, "Failed to allocate space for queue. Is metadata virtual memory exhausted?");
|
fprintf(stderr, "Failed to allocate space for queue. Is metadata virtual memory exhausted?");
|
||||||
local_tail = (void **) ((uintptr_t) new_buffer + (USABLE_BUFFER_BYTES - BYTES_IN_ADDRESS -
|
local_tail = (void **) ((uintptr_t) new_buffer + (USABLE_BUFFER_BYTES - BYTES_IN_ADDRESS -
|
||||||
(USABLE_BUFFER_BYTES % (arity << LOG_BYTES_IN_ADDRESS))) + BYTES_IN_ADDRESS); // The second parenthesis is equal to 0
|
(USABLE_BUFFER_BYTES % (arity << LOG_BYTES_IN_ADDRESS))) + BYTES_IN_ADDRESS); /* The second parenthesis is equal to 0 */
|
||||||
local_tail_buffer_end = local_tail;
|
local_tail_buffer_end = local_tail;
|
||||||
checkForAsyncCollection(); // possible side-effect of alloc()
|
checkForAsyncCollection(); /* possible side-effect of posix_memalign() */
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(void *addr)
|
void insert(void *addr)
|
||||||
|
@ -175,8 +202,8 @@ void insert(void *addr)
|
||||||
|
|
||||||
void reception(void (*on_receive)(void *))
|
void reception(void (*on_receive)(void *))
|
||||||
{
|
{
|
||||||
struct double_linked_list *list_cur;
|
|
||||||
void **buf_start, **buf_ptr;
|
void **buf_start, **buf_ptr;
|
||||||
|
struct double_linked_list *list_cur = NULL;
|
||||||
|
|
||||||
wait_initialization(); /* Not needed but here for equity with others techniques */
|
wait_initialization(); /* Not needed but here for equity with others techniques */
|
||||||
/* printf("Activate the consumer...\n"); */
|
/* printf("Activate the consumer...\n"); */
|
||||||
|
@ -189,6 +216,11 @@ void reception(void (*on_receive)(void *))
|
||||||
buf_start = (void **) (((uintptr_t) &list_cur->prev) & ~BUFFER_MASK);
|
buf_start = (void **) (((uintptr_t) &list_cur->prev) & ~BUFFER_MASK);
|
||||||
for (buf_ptr = buf_start; buf_ptr != (void **) &list_cur->prev; buf_ptr++)
|
for (buf_ptr = buf_start; buf_ptr != (void **) &list_cur->prev; buf_ptr++)
|
||||||
on_receive(*buf_ptr);
|
on_receive(*buf_ptr);
|
||||||
|
if (collect)
|
||||||
|
{
|
||||||
|
free_pages(list_cur);
|
||||||
|
collect = 0;
|
||||||
|
}
|
||||||
while (cont && (list_cur->next == NULL));
|
while (cont && (list_cur->next == NULL));
|
||||||
} while (cont);
|
} while (cont);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue