int test1(void) { void **ptrs; int i,j; int size; int ret = 0; srandom(0x19730929); ptrs = malloc(N_PTRS*sizeof(void *)); for(i=0; i<N_PTRS; i++){ if ((ptrs[i] = malloc(random_size())) == NULL) { printf("malloc random failed! %i\n", i); ++ret; } } for(i=0; i<N_ALLOCS; i++){ j = random_ptr(); free(ptrs[j]); size = random_size(); ptrs[j] = malloc(size); if (!ptrs[j]) { printf("malloc failed! %d\n", i); ++ret; } memset(ptrs[j],0,size); } for(i=0; i<N_PTRS; i++){ free(ptrs[i]); } return ret; }
static void ts_mem_check(void * arg) { t_mchecker mc = arg; x_thread thread = mc->thread; x_size size; x_size old_size; x_size blocks_in_use = 0; t_Block Initial; t_block initial = &Initial; t_block block; x_int command; x_size discards = 0; x_size frees = 0; x_size allocs = 0; x_size reallocs_g = 0; x_size reallocs_s = 0; /* ** Initialize our own list. */ initial->size = 1024 * 1024 * 30; x_list_init(initial); /* ** ... and check dynamic allocation and deallocation forever ... */ while (1) { /* ** Select the operation: 0 and 1 = allocation, 2 = reallocation, 3 = change owner and 4 = free or discard */ command = x_random() % 5; block = NULL; if (force_next_is_release || global_force_release) { command = 4; force_next_is_release = 0; } else if (force_next_is_allocation) { command = 0; } /* ** If we have released all our blocks due to a global force release command and ** we have no blocks left, we sleep so that other threads can start dumping their ** blocks. */ if (global_force_release && blocks_in_use == 0) { x_thread_sleep(2); } /* ** Only do allocations when we have not all blocks in use. */ if ((command == 1 || command == 0) && (blocks_in_use < max_blocks_in_use)) { size = random_size(); block = allocate_block(mc, initial, size, x_random() & 0x00000001); allocs += 1; if (block == NULL) { force_next_is_release = 1; global_force_release = 1; oempa("No more memory for %d bytes. Global force releasing enabled, %d bytes in use.\n", size, global_in_use); continue; } blocks_in_use += 1; allocations += 1; if (force_next_is_allocation) { force_next_is_allocation = 0; } } else if (command == 2) { block = initial->next; if (block != initial) { size = random_size(); old_size = block->size; block = reallocate_block(mc, initial, block, size); if (old_size < size) { reallocs_g += 1; } else { reallocs_s += 1; } allocs += 1; if (block == NULL) { force_next_is_release = 1; global_force_release = 1; continue; } reallocations += 1; } } else if (command == 3) { block = initial->next; } else { block = initial->next; if (block != initial) { if (x_random() % 5 == 0) { release_block(mc, block, true, 1); discards += 1; } else { release_block(mc, block, true, 0); frees += 1; } blocks_in_use -= 1; releases += 1; } } if (allocs > 0 && allocs % 4000 == 0) { oempa("Thread %p: A %d Rg %d Rs %d D %d F %d\n", thread, allocs, reallocs_g, reallocs_s, discards, frees); force_next_is_allocation = 1; } if (allocs > 0 && allocs % 2000 == 0) { x_thread_sleep((x_random() % 10) + 10); } } }
void Simulator_run(size_t initial_memory, int use_custom_allocator, size_t process_limit) { // seed pseudo-random number generator seed_rand(); // setup non-reentrant variables for Standard Deviation, // which allows Simulator_run to be fully reentrant InitSD(); for (size_t i = 0; i < PROCESS_COUNT; ++i) { // randomize pid, cycles, and memory size for each process processes[i].pid = unique_pid(); processes[i].cycles = random_cycles(); processes[i].size = random_size(); // set process state to ready, and reset time variables. // this allows Simulator_run to be fully reentrant processes[i].state = PROCESS_READY; processes[i].malloc_time = 0; processes[i].free_time = 0; } memory = initial_memory; total_memory = initial_memory; active_process_count = 0; active_process_limit = process_limit; unsigned int timer = 0; unsigned int frame_count = 0; // disable cursor (improves flickering substantially) printf("\033[?25l"); printf("INITIAL MEMORY: %zu\n" "USING CUSTOM ALLOC: %s\n" "PROCESS LIMIT: %zu\n\n", initial_memory, (use_custom_allocator) ? "true" : "false", process_limit); Timer_start(&start_time); // allocate memory pool MemoryPool *memory_pool = NULL; if (use_custom_allocator) { memory_pool = MemoryPool_create(total_memory); } while (1) { // count the total number of running and complete processes running_count = 0; complete_count = 0; for (size_t i = 0; i < PROCESS_COUNT; ++i) { if (processes[i].state == PROCESS_COMPLETE) { ++complete_count; } else if (processes[i].state == PROCESS_RUNNING) { ++running_count; } } // if we've all processes have completed, exit the program if (complete_count == PROCESS_COUNT) { draw_process_table(); break; } // every 50 cycles, attempt to start ready processes if (timer == 49) { timer = 0; // set all ready processes that will fit in memory to running state for (size_t i = 0; i < PROCESS_COUNT; ++i) { if ((active_process_limit == 0 || active_process_count < active_process_limit) && processes[i].state == PROCESS_READY && processes[i].size < memory ) { ++active_process_count; processes[i].state = PROCESS_RUNNING; memory -= processes[i].size; processes[i].cycles_remaining = processes[i].cycles; // attempt to allocate process' memory Timer_start(&malloc_start_time); if (use_custom_allocator) { processes[i].data = my_malloc(memory_pool, processes[i].size); } else { processes[i].data = malloc(processes[i].size); } processes[i].malloc_time = Timer_stop(malloc_start_time, &malloc_end_time); if (processes[i].data == NULL) { printf("Error: Failed to allocate " "memory for process %u\n", processes[i].pid); break; } draw_process_table(); } } } // update running processes for (size_t i = 0; i < PROCESS_COUNT; ++i) { if (processes[i].state == PROCESS_RUNNING) { // if the current process is complete, update the system if (processes[i].cycles_remaining == 0) { --active_process_count; processes[i].state = PROCESS_COMPLETE; memory += processes[i].size; // attempt to free process' memory if (processes[i].data != NULL) { Timer_start(&malloc_start_time); if (use_custom_allocator) { my_free(memory_pool, processes[i].data, processes[i].size); processes[i].data = NULL; } else { free(processes[i].data); processes[i].data = NULL; } processes[i].free_time = Timer_stop(malloc_start_time, &malloc_end_time); } } else { --processes[i].cycles_remaining; } } } // print process table every 25 frames if (frame_count == 24) { frame_count = 0; draw_process_table(); } // update counters and sleep 10 milliseconds ++timer; ++frame_count; sleep_ms(10); } // deallocate memory pool if (use_custom_allocator) { MemoryPool_destroy(memory_pool); } // measure total execution time of simulation double total_time = Timer_stop(start_time, &end_time); for (size_t i = 0; i < PROCESS_COUNT; ++i) { printf("%u, %zu, %zu, %0.3lf, %0.3lf\n", processes[i].pid, processes[i].cycles, processes[i].size, processes[i].malloc_time, processes[i].free_time); } printf("\nTotal Execution Time: %0.3lf ms\n\n", total_time); // re-enable cursor printf("\033[?25h"); }