📄 mtest.c
字号:
trace->ops[op_index].type = ALLOC; trace->ops[op_index].index = index; trace->ops[op_index].size = size; max_index = (index > max_index) ? index : max_index; break; case 'r': fscanf(tracefile, "%u %u", &index, &size); trace->ops[op_index].type = REALLOC; trace->ops[op_index].index = index; trace->ops[op_index].size = size; max_index = (index > max_index) ? index : max_index; break; case 'f': fscanf(tracefile, "%ud", &index); trace->ops[op_index].type = FREE; trace->ops[op_index].index = index; break; default: printf("Bogus type character (%c) in tracefile %s\n", type[0], filename); exit(1); } op_index++; } fclose(tracefile); assert(max_index == trace->num_ids - 1); assert(trace->num_ops == op_index); return trace;}/* * free_trace - Free the trace record and the three arrays it points * to, all of which were allocated in read_trace(). */void free_trace(trace_t *trace){ free(trace->ops); /* free the three arrays... */ free(trace->blocks); free(trace->block_sizes); free(trace); /* and the trace record itself... */}/********************************************************************** * The following functions evaluate the correctness, space utilization, * and throughput of the libc and mm malloc packages. **********************************************************************//* * eval_mm_valid - Check the mm malloc package for correctness */static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges) { int i, j; int index; int size; int oldsize; char *newp; char *oldp; char *p; /* Reset the heap and free any records in the range list */ mem_reset_brk(); clear_ranges(ranges); /* Call the mm package's init function */ if (mm_init() < 0) { malloc_error(tracenum, 0, "mm_init failed."); return 0; } /* Interpret each operation in the trace in order */ for (i = 0; i < trace->num_ops; i++) { index = trace->ops[i].index; size = trace->ops[i].size; switch (trace->ops[i].type) { case ALLOC: /* mm_malloc */ /* Call the student's malloc */ if ((p = mm_malloc(size)) == NULL) { malloc_error(tracenum, i, "mm_malloc failed."); return 0; } /* * Test the range of the new block for correctness and add it * to the range list if OK. The block must be be aligned properly, * and must not overlap any currently allocated block. */ if (add_range(ranges, p, size, tracenum, i) == 0) return 0; /* ADDED: cgw * fill range with low byte of index. This will be used later * if we realloc the block and wish to make sure that the old * data was copied to the new block */ memset(p, index & 0xFF, size); /* Remember region */ trace->blocks[index] = p; trace->block_sizes[index] = size; break; case REALLOC: /* mm_realloc */ /* Call the student's realloc */ oldp = trace->blocks[index]; if ((newp = mm_realloc(oldp, size)) == NULL) { malloc_error(tracenum, i, "mm_realloc failed."); return 0; } /* Remove the old region from the range list */ remove_range(ranges, oldp); /* Check new block for correctness and add it to range list */ if (add_range(ranges, newp, size, tracenum, i) == 0) return 0; /* ADDED: cgw * Make sure that the new block contains the data from the old * block and then fill in the new block with the low order byte * of the new index */ oldsize = trace->block_sizes[index]; if (size < oldsize) oldsize = size; for (j = 0; j < oldsize; j++) { if (newp[j] != (index & 0xFF)) { malloc_error(tracenum, i, "mm_realloc did not preserve the " "data from old block"); return 0; } } memset(newp, index & 0xFF, size); /* Remember region */ trace->blocks[index] = newp; trace->block_sizes[index] = size; break; case FREE: /* mm_free */ /* Remove region from list and call student's free function */ p = trace->blocks[index]; remove_range(ranges, p); mm_free(p); break; default: app_error("Nonexistent request type in eval_mm_valid"); } } /* As far as we know, this is a valid malloc package */ return 1;}/* * eval_mm_util - Evaluate the space utilization of the student's package * The idea is to remember the high water mark "hwm" of the heap for * an optimal allocator, i.e., no gaps and no internal fragmentation. * Utilization is the ratio hwm/heapsize, where heapsize is the * size of the heap in bytes after running the student's malloc * package on the trace. Note that our implementation of mem_sbrk() * doesn't allow the students to decrement the brk pointer, so brk * is always the high water mark of the heap. * */static double eval_mm_util(trace_t *trace, int tracenum, range_t **ranges){ int i; int index; int size, newsize, oldsize; int max_total_size = 0; int total_size = 0; char *p; char *newp, *oldp; /* initialize the heap and the mm malloc package */ mem_reset_brk(); if (mm_init() < 0) app_error("mm_init failed in eval_mm_util"); for (i = 0; i < trace->num_ops; i++) { switch (trace->ops[i].type) { case ALLOC: /* mm_alloc */ index = trace->ops[i].index; size = trace->ops[i].size; if ((p = mm_malloc(size)) == NULL) app_error("mm_malloc failed in eval_mm_util"); /* Remember region and size */ trace->blocks[index] = p; trace->block_sizes[index] = size; /* Keep track of current total size * of all allocated blocks */ total_size += size; /* Update statistics */ max_total_size = (total_size > max_total_size) ? total_size : max_total_size; break; case REALLOC: /* mm_realloc */ index = trace->ops[i].index; newsize = trace->ops[i].size; oldsize = trace->block_sizes[index]; oldp = trace->blocks[index]; if ((newp = mm_realloc(oldp,newsize)) == NULL) app_error("mm_realloc failed in eval_mm_util"); /* Remember region and size */ trace->blocks[index] = newp; trace->block_sizes[index] = newsize; /* Keep track of current total size * of all allocated blocks */ total_size += (newsize - oldsize); /* Update statistics */ max_total_size = (total_size > max_total_size) ? total_size : max_total_size; break; case FREE: /* mm_free */ index = trace->ops[i].index; size = trace->block_sizes[index]; p = trace->blocks[index]; mm_free(p); /* Keep track of current total size * of all allocated blocks */ total_size -= size; break; default: app_error("Nonexistent request type in eval_mm_util"); } } return ((double)max_total_size / (double)mem_heapsize());}/* * eval_mm_speed - This is the function that is used by fcyc() * to measure the running time of the mm malloc package. */static void eval_mm_speed(void *ptr){ int i, index, size, newsize; char *p, *newp, *oldp, *block; trace_t *trace = ((speed_t *)ptr)->trace; /* Reset the heap and initialize the mm package */ mem_reset_brk(); if (mm_init() < 0) app_error("mm_init failed in eval_mm_speed"); /* Interpret each trace request */ for (i = 0; i < trace->num_ops; i++) switch (trace->ops[i].type) { case ALLOC: /* mm_malloc */ index = trace->ops[i].index; size = trace->ops[i].size; if ((p = mm_malloc(size)) == NULL) app_error("mm_malloc error in eval_mm_speed"); trace->blocks[index] = p; break; case REALLOC: /* mm_realloc */ index = trace->ops[i].index; newsize = trace->ops[i].size; oldp = trace->blocks[index]; if ((newp = mm_realloc(oldp,newsize)) == NULL) app_error("mm_realloc error in eval_mm_speed"); trace->blocks[index] = newp; break; case FREE: /* mm_free */ index = trace->ops[i].index; block = trace->blocks[index]; mm_free(block); break; default: app_error("Nonexistent request type in eval_mm_valid"); }}/* * eval_libc_valid - We run this function to make sure that the * libc malloc can run to completion on the set of traces. * We'll be conservative and terminate if any libc malloc call fails. * */static int eval_libc_valid(trace_t *trace, int tracenum){ int i, newsize; char *p, *newp, *oldp; for (i = 0; i < trace->num_ops; i++) { switch (trace->ops[i].type) { case ALLOC: /* malloc */ if ((p = malloc(trace->ops[i].size)) == NULL) { malloc_error(tracenum, i, "libc malloc failed"); unix_error("System message"); } trace->blocks[trace->ops[i].index] = p; break; case REALLOC: /* realloc */ newsize = trace->ops[i].size; oldp = trace->blocks[trace->ops[i].index]; if ((newp = realloc(oldp, newsize)) == NULL) { malloc_error(tracenum, i, "libc realloc failed"); unix_error("System message"); } trace->blocks[trace->ops[i].index] = newp; break; case FREE: /* free */ free(trace->blocks[trace->ops[i].index]); break; default: app_error("invalid operation type in eval_libc_valid"); } } return 1;}/* * eval_libc_speed - This is the function that is used by fcyc() to * measure the running time of the libc malloc package on the set * of traces. */static void eval_libc_speed(void *ptr){ int i; int index, size, newsize; char *p, *newp, *oldp, *block; trace_t *trace = ((speed_t *)ptr)->trace; for (i = 0; i < trace->num_ops; i++) { switch (trace->ops[i].type) { case ALLOC: /* malloc */ index = trace->ops[i].index; size = trace->ops[i].size; if ((p = malloc(size)) == NULL) unix_error("malloc failed in eval_libc_speed"); trace->blocks[index] = p; break; case REALLOC: /* realloc */ index = trace->ops[i].index; newsize = trace->ops[i].size; oldp = trace->blocks[index]; if ((newp = realloc(oldp, newsize)) == NULL) unix_error("realloc failed in eval_libc_speed\n"); trace->blocks[index] = newp; break; case FREE: /* free */ index = trace->ops[i].index; block = trace->blocks[index]; free(block); break; } }}/************************************* * Some miscellaneous helper routines ************************************//* * printresults - prints a performance summary for some malloc package */static void printresults(int n, stats_t *stats) { int i; double secs = 0; double ops = 0; double util = 0; /* Print the individual results for each trace */ printf("%5s%7s %5s%8s%10s%6s\n", "trace", " valid", "util", "ops", "secs", "Kops"); for (i=0; i < n; i++) { if (stats[i].valid) { printf("%2d%10s%5.0f%%%8.0f%10.6f%6.0f\n", i, "yes", stats[i].util*100.0, stats[i].ops, stats[i].secs, (stats[i].ops/1e3)/stats[i].secs); secs += stats[i].secs; ops += stats[i].ops; util += stats[i].util; } else { printf("%2d%10s%6s%8s%10s%6s\n", i, "no", "-", "-", "-", "-"); } } /* Print the aggregate results for the set of traces */ if (errors == 0) { printf("%12s%5.0f%%%8.0f%10.6f%6.0f\n", "Total ", (util/n)*100.0, ops, secs, (ops/1e3)/secs); } else { printf("%12s%6s%8s%10s%6s\n", "Total ", "-", "-", "-", "-"); }}/* * app_error - Report an arbitrary application error */void app_error(char *msg) { printf("%s\n", msg); exit(1);}/* * unix_error - Report a Unix-style error */void unix_error(char *msg) { printf("%s: %s\n", msg, strerror(errno)); exit(1);}/* * malloc_error - Report an error returned by the mm_malloc package */void malloc_error(int tracenum, int opnum, char *msg){ errors++; printf("ERROR [trace %d, line %d]: %s\n", tracenum, LINENUM(opnum), msg);}/* * usage - Explain the command line arguments */static void usage(void) { fprintf(stderr, "Usage: mtest [-hvVal] [-f <file>]\n"); fprintf(stderr, "Options\n"); fprintf(stderr, "\t-a Don't check the team structure.\n"); fprintf(stderr, "\t-f <file> Use <file> as the trace file.\n"); fprintf(stderr, "\t-h Print this message.\n"); fprintf(stderr, "\t-l Run libc malloc as well.\n"); fprintf(stderr, "\t-v Print per-trace performance breakdowns.\n"); fprintf(stderr, "\t-V Print additional debug info.\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -