void *apmalloc(size_t size) { if (size == 0) return NULL; size_t request_size = ALIGN(size + sizeof(header_t)); // if it's more than our last bin's capacity, just mmap it if (request_size >= (1 << MAX_BINS)) { request_size = round_to_next_page(request_size); void *ptr = MMAP(request_size); if (ptr == MAP_FAILED) return NULL; header_t *header = (header_t*)ptr; header->size = request_size; return (void*)(header + 1); } // look for free blocks in our lists for (unsigned int request_bin = bin_index(request_size); request_bin < MAX_BINS; request_bin++) { header_t *candidate = free_list[request_bin]; while (candidate != NULL) { // we found a suitable block if (candidate->size >= request_size) { // take this block out of the free list if (candidate->prev) candidate->prev->next = candidate->next; if (candidate->next) candidate->next->prev = candidate->prev; if (!(candidate->prev || candidate->next)) free_list[request_bin] = NULL; // if there's a remainder, add it back to the appropriate list if (candidate->size > request_size) { header_t *remainder = (header_t*)((char*)candidate + request_size); remainder->size = candidate->size - request_size; apfree(remainder + 1); candidate->size = request_size; } return (void*)(candidate + 1); } candidate = candidate->next; } } // no block big enough found, request and split a big chunk void *ptr = MMAP(PAGE_SIZE); if (ptr == MAP_FAILED) return NULL; header_t *remainder = (header_t*)((char*)ptr + request_size); remainder->size = PAGE_SIZE - request_size; apfree(remainder + 1); header_t *header = (header_t*)ptr; header->size = request_size; return (void*)(header + 1); }
void apfree(void *ptr) { if (ptr == NULL) return; header_t *header = (header_t*)ptr - 1; // if it's bigger than our last bin's capacity, we used mmap if (header->size >= (1 << MAX_BINS)) { munmap(header, header->size); } else { unsigned int index = bin_index(header->size); header_t *previous = NULL, *current = free_list[index]; while (current != NULL && current < header) { previous = current; current = current->next; } if (previous) previous->next = header; else free_list[index] = header; header->prev = previous; if (current) current->prev = header; header->next = current; // coalesce if ((char*)header + header->size == (char*)current) { header->size += current->size; header->next = current->next; if (current->next) current->next->prev = header; } if (previous && ((char*)previous + previous->size == (char*)header)) { previous->size += header->size; previous->next = header->next; if (header->next) header->next->prev = previous; } } }
void read_input(void) { FILE *in; int i, j, *nbin, *nsim; in = input ? fopen(input, "r") : stdin; if (in == NULL) message_fatal("Unable to open input file"); skip_comment(in); if (fscanf(in, "%d", &sim_count) != 1) message_fatal("Unable to read number of simulations"); if (sim_count <= 0) message_fatal("Expected positive number of simulations"); bias_x = xmalloc(sim_count * sizeof(*bias_x)); bias_k = xmalloc(sim_count * sizeof(*bias_k)); log_nbin = xmalloc(bin_count * sizeof(*log_nbin)); log_nsim = xmalloc(sim_count * sizeof(*log_nsim)); nbin = xmalloc(bin_count * sizeof(*nbin)); nsim = xmalloc(sim_count * sizeof(*nsim)); for (i = 0; i < bin_count; i++) nbin[i] = 0; for (i = 0; i < sim_count; i++) { double x; int npt; if (fscanf(in, "%lf %lf", &bias_x[i], &bias_k[i]) != 2) message_fatal("Error reading bias info"); if (fscanf(in, "%d", &npt) != 1) message_fatal("Error reading point count"); if (npt <= 0) message_fatal("Expected positive number of points"); nsim[i] = 0; for (j = 0; j < npt; j++) { if (fscanf(in, "%lf", &x) != 1) message_fatal("Error reading data points"); if (period > 0) { if (x > 0) while (x > period) x -= period; else while (x < 0) x += period; } if (x > hist_min && x < hist_max) { nbin[bin_index(x)]++; nsim[i]++; } } message(V_VERBOSE, "Added %d of %d points from window %d", nsim[i], npt, i + 1); } for (i = 0; i < bin_count; i++) log_nbin[i] = log(nbin[i]); for (i = 0; i < sim_count; i++) log_nsim[i] = log(nsim[i]); if (in != stdin) fclose(in); free(nbin); free(nsim); }