diff --git a/communication_techniques/src/communication/jikes_barrier.c b/communication_techniques/src/communication/jikes_barrier.c index 0df0aea..0676975 100644 --- a/communication_techniques/src/communication/jikes_barrier.c +++ b/communication_techniques/src/communication/jikes_barrier.c @@ -30,6 +30,7 @@ static __thread void **local_tail = NULL; static __thread void **local_tail_buffer_end = NULL; static struct double_linked_list *global_tail = NULL; static struct double_linked_list *global_head = NULL; +static int collect = 0; static int bufsenqueued = 0; static unsigned int lock = 0; @@ -44,7 +45,7 @@ int init_thread_comm(struct thread_comm *comm) return -1; } 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; return 0; } @@ -93,7 +94,7 @@ static void spin_unlock(unsigned int *lock) : "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); if (to_tail) @@ -135,34 +136,60 @@ void **normalizeTail(int arity) src++; 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 **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); - 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 + 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 */ enqueue((struct double_linked_list *) ((uintptr_t) last + BYTES_IN_ADDRESS), arity, 1); } 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 *new_buffer; 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)) 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 - - (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; - checkForAsyncCollection(); // possible side-effect of alloc() + checkForAsyncCollection(); /* possible side-effect of posix_memalign() */ } void insert(void *addr) @@ -175,8 +202,8 @@ void insert(void *addr) void reception(void (*on_receive)(void *)) { - struct double_linked_list *list_cur; void **buf_start, **buf_ptr; + struct double_linked_list *list_cur = NULL; wait_initialization(); /* Not needed but here for equity with others techniques */ /* 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); for (buf_ptr = buf_start; buf_ptr != (void **) &list_cur->prev; buf_ptr++) on_receive(*buf_ptr); + if (collect) + { + free_pages(list_cur); + collect = 0; + } while (cont && (list_cur->next == NULL)); } while (cont); }