commits for Spring 2016
added multi-threaded ability to driver provide thread-safe wrapper
This commit is contained in:
parent
f603ce6c85
commit
e40357ee6a
6
Makefile
6
Makefile
@ -4,9 +4,9 @@
|
||||
VERSION = 1
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -O3 -Werror -m32
|
||||
CFLAGS = -Wall -O3 -Werror -m32 -pthread -std=gnu11
|
||||
# for debugging
|
||||
#CFLAGS = -Wall -g -Werror -m32
|
||||
#CFLAGS = -Wall -g -Werror -m32 -pthread -std=gnu11
|
||||
|
||||
SHARED_OBJS = mdriver.o memlib.o fsecs.o fcyc.o clock.o ftimer.o list.o
|
||||
OBJS = $(SHARED_OBJS) mm.o
|
||||
@ -23,7 +23,7 @@ mdriver-gback: $(GBACK_IMPL_OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(GBACK_IMPL_OBJS)
|
||||
|
||||
mdriver.o: mdriver.c fsecs.h fcyc.h clock.h memlib.h config.h mm.h
|
||||
memlib.o: memlib.c memlib.h
|
||||
memlib.o: memlib.c memlib.h config.h
|
||||
mm.o: mm.c mm.h memlib.h
|
||||
fsecs.o: fsecs.c fsecs.h config.h
|
||||
fcyc.o: fcyc.c fcyc.h
|
||||
|
6
config.h
6
config.h
@ -64,13 +64,13 @@
|
||||
/*
|
||||
* Maximum heap size in bytes
|
||||
*/
|
||||
#define MAX_HEAP (20*(1<<20)) /* 20 MB */
|
||||
#define MAX_HEAP (1024*(1<<20)) /* 1024 MB */
|
||||
|
||||
/*****************************************************************************
|
||||
* Set exactly one of these USE_xxx constants to "1" to select a timing method
|
||||
*****************************************************************************/
|
||||
#define USE_FCYC 1 /* cycle counter w/K-best scheme (x86 & Alpha only) */
|
||||
//#define USE_FCYC 1 /* cycle counter w/K-best scheme (x86 & Alpha only) */
|
||||
#define USE_ITIMER 0 /* interval timer (any Unix box) */
|
||||
#define USE_GETTOD 0 /* gettimeofday (any Unix box) */
|
||||
#define USE_GETTOD 1 /* gettimeofday (any Unix box) */
|
||||
|
||||
#endif /* __CONFIG_H */
|
||||
|
264
mdriver.c
264
mdriver.c
@ -15,6 +15,9 @@
|
||||
#include <assert.h>
|
||||
#include <float.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "mm.h"
|
||||
#include "memlib.h"
|
||||
@ -62,16 +65,6 @@ typedef struct {
|
||||
size_t *block_sizes; /* ... and a corresponding array of payload sizes */
|
||||
} trace_t;
|
||||
|
||||
/*
|
||||
* Holds the params to the xxx_speed functions, which are timed by fcyc.
|
||||
* This struct is necessary because fcyc accepts only a pointer array
|
||||
* as input.
|
||||
*/
|
||||
typedef struct {
|
||||
trace_t *trace;
|
||||
range_t *ranges;
|
||||
} speed_t;
|
||||
|
||||
/* Summarizes the important stats for some malloc function on some trace */
|
||||
typedef struct {
|
||||
/* defined for both libc malloc and student malloc package (mm.c) */
|
||||
@ -90,7 +83,6 @@ typedef struct {
|
||||
*******************/
|
||||
int verbose = 0; /* global flag for verbose output */
|
||||
static int errors = 0; /* number of errs found when running student malloc */
|
||||
char msg[MAXLINE]; /* for whenever we need to compose an error message */
|
||||
|
||||
/* Directory where default tracefiles are found */
|
||||
static char tracedir[MAXLINE] = TRACEDIR;
|
||||
@ -108,11 +100,12 @@ static char *default_tracefiles[] = {
|
||||
/* these functions manipulate range lists */
|
||||
static int add_range(range_t **ranges, char *lo, int size,
|
||||
int tracenum, int opnum);
|
||||
static __thread int check_heap_bounds; /* if off, do not check if ranges are within heap bounds */
|
||||
static void remove_range(range_t **ranges, char *lo);
|
||||
static void clear_ranges(range_t **ranges);
|
||||
|
||||
/* These functions read, allocate, and free storage for traces */
|
||||
static trace_t *read_trace(char *tracedir, char *filename);
|
||||
static trace_t *read_trace(char *tracedir, char *filename, int verbose);
|
||||
static void free_trace(trace_t *trace);
|
||||
|
||||
/* Routines for evaluating the correctness and speed of libc malloc */
|
||||
@ -121,9 +114,23 @@ static void eval_libc_speed(void *ptr);
|
||||
|
||||
/* Routines for evaluating correctnes, space utilization, and speed
|
||||
of the student's malloc package in mm.c */
|
||||
static int reset_heap(int tracenum);
|
||||
static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges);
|
||||
static double eval_mm_util(trace_t *trace, int tracenum, range_t **ranges);
|
||||
static int eval_mm_valid_inner(trace_t *trace, int tracenum, range_t **ranges);
|
||||
struct single_run_args_for_valid {
|
||||
char * tracefilename;
|
||||
int tracenum;
|
||||
pthread_barrier_t *go;
|
||||
};
|
||||
struct thread_run_result {
|
||||
double secs; // number of seconds used
|
||||
int heapsize; // size to which memlib heap grew
|
||||
};
|
||||
static void * eval_mm_valid_single(void *);
|
||||
static int eval_mm_util(trace_t *trace, int tracenum, range_t **ranges);
|
||||
static void eval_mm_speed(void *ptr);
|
||||
static void eval_mm_speed_inner(void *ptr);
|
||||
static void * eval_mm_speed_single(void *_args);
|
||||
|
||||
/* Various helper routines */
|
||||
static void printresults(int n, char ** tracefiles, stats_t *stats);
|
||||
@ -132,6 +139,7 @@ static void usage(void);
|
||||
static void unix_error(char *msg);
|
||||
static void malloc_error(int tracenum, int opnum, char *msg);
|
||||
static void app_error(char *msg);
|
||||
static FILE * open_jsonfile(const char * filename_mask);
|
||||
|
||||
/**************
|
||||
* Main routine
|
||||
@ -146,10 +154,10 @@ int main(int argc, char **argv)
|
||||
range_t *ranges = NULL; /* keeps track of block extents for one trace */
|
||||
stats_t *libc_stats = NULL;/* libc stats for each trace */
|
||||
stats_t *mm_stats = NULL; /* mm (i.e. student) stats for each trace */
|
||||
speed_t speed_params; /* input parameters to the xx_speed routines */
|
||||
|
||||
int team_check = 1; /* If set, check team structure (reset by -a) */
|
||||
int run_libc = 0; /* If set, run libc malloc (set by -l) */
|
||||
int nthreads = 0; /* If set to > 0, number of threads for multi-threaded testing. */
|
||||
int autograder = 0; /* If set, emit summary info for autograder (-g) */
|
||||
int use_mmap = 0; /* If set, have memlib use mmap() instead malloc() */
|
||||
|
||||
@ -160,7 +168,7 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Read and interpret the command line arguments
|
||||
*/
|
||||
while ((c = getopt(argc, argv, "nf:t:hvVgal")) != EOF) {
|
||||
while ((c = getopt(argc, argv, "nf:t:hvVgalm:")) != EOF) {
|
||||
switch (c) {
|
||||
case 'n':
|
||||
use_mmap = 1;
|
||||
@ -195,6 +203,9 @@ int main(int argc, char **argv)
|
||||
case 'V': /* Be more verbose than -v */
|
||||
verbose = 2;
|
||||
break;
|
||||
case 'm': /* Include multi-threaded testing */
|
||||
nthreads = atoi(optarg);
|
||||
break;
|
||||
case 'h': /* Print this message */
|
||||
usage();
|
||||
exit(0);
|
||||
@ -257,16 +268,15 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Evaluate the libc malloc package using the K-best scheme */
|
||||
for (i=0; i < num_tracefiles; i++) {
|
||||
trace = read_trace(tracedir, tracefiles[i]);
|
||||
trace = read_trace(tracedir, tracefiles[i], verbose > 1);
|
||||
libc_stats[i].ops = trace->num_ops;
|
||||
if (verbose > 1)
|
||||
printf("Checking libc malloc for correctness, ");
|
||||
libc_stats[i].valid = eval_libc_valid(trace, i);
|
||||
if (libc_stats[i].valid) {
|
||||
speed_params.trace = trace;
|
||||
if (verbose > 1)
|
||||
printf("and performance.\n");
|
||||
libc_stats[i].secs = fsecs(eval_libc_speed, &speed_params);
|
||||
libc_stats[i].secs = fsecs(eval_libc_speed, trace);
|
||||
}
|
||||
free_trace(trace);
|
||||
}
|
||||
@ -284,30 +294,105 @@ int main(int argc, char **argv)
|
||||
if (verbose > 1)
|
||||
printf("\nTesting mm malloc\n");
|
||||
|
||||
/* Allocate the mm stats array, with one stats_t struct per tracefile */
|
||||
mm_stats = (stats_t *)calloc(num_tracefiles, sizeof(stats_t));
|
||||
/* Allocate the mm stats array, with two stats_t struct per tracefile */
|
||||
mm_stats = (stats_t *)calloc((nthreads > 0 ? 2 : 1) * num_tracefiles, sizeof(stats_t));
|
||||
if (mm_stats == NULL)
|
||||
unix_error("mm_stats calloc in main failed");
|
||||
|
||||
/* Initialize the simulated memory system in memlib.c */
|
||||
mem_init(use_mmap);
|
||||
|
||||
int max_total_size = 0;
|
||||
/* Evaluate student's mm malloc package using the K-best scheme */
|
||||
for (i=0; i < num_tracefiles; i++) {
|
||||
trace = read_trace(tracedir, tracefiles[i]);
|
||||
trace = read_trace(tracedir, tracefiles[i], verbose > 1);
|
||||
mm_stats[i].ops = trace->num_ops;
|
||||
if (verbose > 1)
|
||||
printf("Checking mm_malloc for correctness, ");
|
||||
check_heap_bounds = 1;
|
||||
mm_stats[i].valid = eval_mm_valid(trace, i, &ranges);
|
||||
if (mm_stats[i].valid) {
|
||||
if (verbose > 1)
|
||||
printf("efficiency, ");
|
||||
mm_stats[i].util = eval_mm_util(trace, i, &ranges);
|
||||
speed_params.trace = trace;
|
||||
speed_params.ranges = ranges;
|
||||
|
||||
max_total_size = eval_mm_util(trace, i, &ranges);
|
||||
mm_stats[i].util = ((double)max_total_size / (double)mem_heapsize());
|
||||
if (verbose > 1)
|
||||
printf("and performance.\n");
|
||||
mm_stats[i].secs = fsecs(eval_mm_speed, &speed_params);
|
||||
mm_stats[i].secs = fsecs(eval_mm_speed, trace);
|
||||
}
|
||||
|
||||
/* Test multithreaded behavior */
|
||||
if (nthreads) {
|
||||
if (verbose > 1)
|
||||
printf("Checking multithreaded mm_malloc for correctness\n");
|
||||
stats_t * ms = &mm_stats[i+num_tracefiles];
|
||||
ms->ops = trace->num_ops * nthreads;
|
||||
|
||||
struct single_run_args_for_valid args[nthreads];
|
||||
pthread_t threads[nthreads];
|
||||
pthread_barrier_t go;
|
||||
if (pthread_barrier_init(&go, NULL, nthreads)) {
|
||||
perror("pthread_barrier_init");
|
||||
abort();
|
||||
}
|
||||
reset_heap(i);
|
||||
|
||||
for (int j = 0; j < nthreads; j++) {
|
||||
args[j].go = &go;
|
||||
args[j].tracefilename = tracefiles[i];
|
||||
args[j].tracenum = i;
|
||||
if (pthread_create(threads + j, NULL, eval_mm_valid_single, args + j))
|
||||
perror("pthread_create"), exit(-1);
|
||||
}
|
||||
|
||||
ms->valid = 1;
|
||||
for (int j = 0; j < nthreads; j++) {
|
||||
uintptr_t this_run_valid;
|
||||
if (pthread_join(threads[j], (void **)&this_run_valid))
|
||||
perror("pthread_join"), exit(-1);
|
||||
|
||||
if (!this_run_valid)
|
||||
ms->valid = 0;
|
||||
}
|
||||
if (verbose > 1)
|
||||
printf("Result appears to be valid.\n");
|
||||
|
||||
if (!ms->valid) {
|
||||
printf("Result is not valid, skipping further multithreads tests.\n");
|
||||
} else {
|
||||
// we know max_total_size, the total amount of heap memory may vary.
|
||||
// benchmark it a few times and take the average of utilization and speed.
|
||||
const int REPEATS = 2;
|
||||
long heap_size_avg = 0;
|
||||
double runtime_avg = 0.0;
|
||||
for (int k = 0; k < REPEATS; k++) {
|
||||
reset_heap(i);
|
||||
|
||||
for (int j = 0; j < nthreads; j++) {
|
||||
args[j].go = &go;
|
||||
args[j].tracefilename = tracefiles[i];
|
||||
args[j].tracenum = i;
|
||||
if (pthread_create(threads + j, NULL, eval_mm_speed_single, args + j))
|
||||
perror("pthread_create"), exit(-1);
|
||||
}
|
||||
|
||||
for (int j = 0; j < nthreads; j++) {
|
||||
struct thread_run_result *r;
|
||||
if (pthread_join(threads[j], (void **) &r))
|
||||
perror("pthread_join"), exit(-1);
|
||||
if (r) {
|
||||
runtime_avg += r->secs;
|
||||
heap_size_avg += r->heapsize;
|
||||
free(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
runtime_avg /= REPEATS;
|
||||
heap_size_avg /= REPEATS;
|
||||
ms->util = ((double)nthreads * max_total_size) / heap_size_avg;
|
||||
ms->secs = runtime_avg;
|
||||
}
|
||||
}
|
||||
free_trace(trace);
|
||||
}
|
||||
@ -319,6 +404,12 @@ int main(int argc, char **argv)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (nthreads && verbose) {
|
||||
printf("\nResults for multi-threaded mm malloc:\n");
|
||||
printresults(num_tracefiles, tracefiles, mm_stats+num_tracefiles);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Accumulate the aggregate statistics for the student's mm package
|
||||
*/
|
||||
@ -368,10 +459,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/* Write results to JSON file for submission */
|
||||
char jsonfilename[80];
|
||||
snprintf(jsonfilename, sizeof jsonfilename, "results.%d.json", getpid());
|
||||
printf("Writing results to %s for submission to the scoreboard\n", jsonfilename);
|
||||
FILE *json = fopen(jsonfilename, "w");
|
||||
FILE * json = open_jsonfile("results.%d.json");
|
||||
fprintf(json, "{");
|
||||
fprintf(json, " \"results\": ");
|
||||
printresults_as_json(json, num_tracefiles, tracefiles, mm_stats);
|
||||
@ -380,12 +468,25 @@ int main(int argc, char **argv)
|
||||
"{ \"avg_mm_util\": %f, \"avg_mm_throughput\" : %f, \"perfindex\": %f, \"AVG_LIBC_THRUPUT\": %f }\n",
|
||||
avg_mm_util, avg_mm_throughput, perfindex, AVG_LIBC_THRUPUT);
|
||||
}
|
||||
if (nthreads > 0) {
|
||||
fprintf(json, ", \"mtresults\": ");
|
||||
printresults_as_json(json, num_tracefiles, tracefiles, mm_stats+num_tracefiles);
|
||||
}
|
||||
fprintf(json, "}");
|
||||
fclose(json);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static FILE *
|
||||
open_jsonfile(const char * filename_mask)
|
||||
{
|
||||
char jsonfilename[80];
|
||||
snprintf(jsonfilename, sizeof jsonfilename, filename_mask, getpid());
|
||||
printf("Writing results to %s for submission to the scoreboard\n", jsonfilename);
|
||||
return fopen(jsonfilename, "w");
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* The following routines manipulate the range list, which keeps
|
||||
@ -417,8 +518,9 @@ static int add_range(range_t **ranges, char *lo, int size,
|
||||
}
|
||||
|
||||
/* The payload must lie within the extent of the heap */
|
||||
if ((lo < (char *)mem_heap_lo()) || (lo > (char *)mem_heap_hi()) ||
|
||||
(hi < (char *)mem_heap_lo()) || (hi > (char *)mem_heap_hi())) {
|
||||
if (check_heap_bounds && (
|
||||
(lo < (char *)mem_heap_lo()) || (lo > (char *)mem_heap_hi()) ||
|
||||
(hi < (char *)mem_heap_lo()) || (hi > (char *)mem_heap_hi()))) {
|
||||
sprintf(msg, "Payload (%p:%p) lies outside heap (%p:%p)",
|
||||
lo, hi, mem_heap_lo(), mem_heap_hi());
|
||||
malloc_error(tracenum, opnum, msg);
|
||||
@ -490,8 +592,9 @@ static void clear_ranges(range_t **ranges)
|
||||
/*
|
||||
* read_trace - read a trace file and store it in memory
|
||||
*/
|
||||
static trace_t *read_trace(char *tracedir, char *filename)
|
||||
static trace_t *read_trace(char *tracedir, char *filename, int verbose)
|
||||
{
|
||||
char msg[MAXLINE];
|
||||
FILE *tracefile;
|
||||
trace_t *trace;
|
||||
char type[MAXLINE];
|
||||
@ -500,7 +603,7 @@ static trace_t *read_trace(char *tracedir, char *filename)
|
||||
unsigned max_index = 0;
|
||||
unsigned op_index;
|
||||
|
||||
if (verbose > 1)
|
||||
if (verbose)
|
||||
printf("Reading tracefile: %s\n", filename);
|
||||
|
||||
/* Allocate the trace record */
|
||||
@ -590,10 +693,32 @@ void free_trace(trace_t *trace)
|
||||
* and throughput of the libc and mm malloc packages.
|
||||
**********************************************************************/
|
||||
|
||||
static int
|
||||
reset_heap(int tracenum)
|
||||
{
|
||||
/* Reset the heap and free any records in the range list */
|
||||
mem_reset_brk();
|
||||
|
||||
/* Call the mm package's init function */
|
||||
if (mm_init() < 0) {
|
||||
malloc_error(tracenum, 0, "mm_init failed.");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* eval_mm_valid - Check the mm malloc package for correctness
|
||||
*/
|
||||
static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges)
|
||||
{
|
||||
if (!reset_heap(tracenum))
|
||||
return 0;
|
||||
|
||||
return eval_mm_valid_inner(trace, tracenum, ranges);
|
||||
}
|
||||
|
||||
static int eval_mm_valid_inner(trace_t *trace, int tracenum, range_t **ranges)
|
||||
{
|
||||
int i, j;
|
||||
int index;
|
||||
@ -604,15 +729,8 @@ static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges)
|
||||
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;
|
||||
@ -703,6 +821,28 @@ static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *
|
||||
eval_mm_valid_single(void *_args)
|
||||
{
|
||||
struct single_run_args_for_valid * args = _args;
|
||||
|
||||
/* read our own copy of this trace */
|
||||
trace_t * trace = read_trace(tracedir, args->tracefilename, 0);
|
||||
|
||||
// let threads start at approximately the same moment to increase chance
|
||||
// of concurrency-related failures if proper synchronization is not used.
|
||||
if (pthread_barrier_wait(args->go) == PTHREAD_BARRIER_SERIAL_THREAD) {
|
||||
;
|
||||
}
|
||||
range_t *ranges = NULL;
|
||||
check_heap_bounds = 0;
|
||||
int isvalid = eval_mm_valid_inner(trace, args->tracenum, &ranges);
|
||||
assert (sizeof(int) <= sizeof(void*));
|
||||
clear_ranges(&ranges);
|
||||
free_trace(trace);
|
||||
return (void *) isvalid;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -713,8 +853,9 @@ static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges)
|
||||
* doesn't allow the students to decrement the brk pointer, so brk
|
||||
* is always the high water mark of the heap.
|
||||
*
|
||||
* Changed to return max_total_size
|
||||
*/
|
||||
static double eval_mm_util(trace_t *trace, int tracenum, range_t **ranges)
|
||||
static int eval_mm_util(trace_t *trace, int tracenum, range_t **ranges)
|
||||
{
|
||||
int i;
|
||||
int index;
|
||||
@ -793,9 +934,32 @@ static double eval_mm_util(trace_t *trace, int tracenum, range_t **ranges)
|
||||
}
|
||||
}
|
||||
|
||||
return ((double)max_total_size / (double)mem_heapsize());
|
||||
return max_total_size;
|
||||
}
|
||||
|
||||
static void *
|
||||
eval_mm_speed_single(void *_args)
|
||||
{
|
||||
struct single_run_args_for_valid * args = _args;
|
||||
struct timeval stv, etv;
|
||||
|
||||
/* read our own copy of this trace */
|
||||
trace_t * trace = read_trace(tracedir, args->tracefilename, 0);
|
||||
|
||||
// we start the clock here to avoid accounting for thread startup overhead
|
||||
pthread_barrier_wait(args->go);
|
||||
gettimeofday(&stv, NULL);
|
||||
eval_mm_speed_inner(trace);
|
||||
gettimeofday(&etv,NULL);
|
||||
free_trace(trace);
|
||||
if (pthread_barrier_wait(args->go) == PTHREAD_BARRIER_SERIAL_THREAD) {
|
||||
struct thread_run_result *r = malloc(sizeof (*r));
|
||||
r->secs = (etv.tv_sec - stv.tv_sec) + 1E-6*(etv.tv_usec-stv.tv_usec);
|
||||
r->heapsize = mem_heapsize();
|
||||
return r;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* eval_mm_speed - This is the function that is used by fcyc()
|
||||
@ -803,15 +967,21 @@ static double eval_mm_util(trace_t *trace, int tracenum, range_t **ranges)
|
||||
*/
|
||||
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");
|
||||
|
||||
eval_mm_speed_inner(ptr);
|
||||
}
|
||||
|
||||
static void eval_mm_speed_inner(void *ptr)
|
||||
{
|
||||
int i, index, size, newsize;
|
||||
char *p, *newp, *oldp, *block;
|
||||
const trace_t *trace = (trace_t *)ptr;
|
||||
|
||||
|
||||
/* Interpret each trace request */
|
||||
for (i = 0; i < trace->num_ops; i++)
|
||||
switch (trace->ops[i].type) {
|
||||
@ -898,7 +1068,7 @@ 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;
|
||||
trace_t *trace = (trace_t *)ptr;
|
||||
|
||||
for (i = 0; i < trace->num_ops; i++) {
|
||||
switch (trace->ops[i].type) {
|
||||
|
2
memlib.c
2
memlib.c
@ -86,7 +86,7 @@ void *mem_sbrk(int incr)
|
||||
|
||||
if ( (incr < 0) || ((mem_brk + incr) > mem_max_addr)) {
|
||||
errno = ENOMEM;
|
||||
fprintf(stderr, "ERROR: mem_sbrk failed. Ran out of memory...\n");
|
||||
fprintf(stderr, "ERROR: mem_sbrk(%d) failed. Ran out of memory...\n", incr);
|
||||
return NULL;
|
||||
}
|
||||
mem_brk += incr;
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "mm.h"
|
||||
#include "memlib.h"
|
||||
|
||||
#include "mm_ts.c"
|
||||
|
||||
/*
|
||||
* If NEXT_FIT defined use next fit search, else use first fit search
|
||||
*/
|
||||
@ -336,13 +338,15 @@ static void *find_fit(size_t asize)
|
||||
|
||||
static void printblock(void *bp)
|
||||
{
|
||||
size_t hsize, halloc, fsize, falloc;
|
||||
size_t hsize/*, halloc, fsize, falloc*/;
|
||||
|
||||
checkheap(0);
|
||||
hsize = GET_SIZE(HDRP(bp));
|
||||
/*
|
||||
halloc = GET_ALLOC(HDRP(bp));
|
||||
fsize = GET_SIZE(FTRP(bp));
|
||||
falloc = GET_ALLOC(FTRP(bp));
|
||||
*/
|
||||
|
||||
if (hsize == 0) {
|
||||
printf("%p: EOL\n", bp);
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "mm.h"
|
||||
#include "memlib.h"
|
||||
|
||||
#include "mm_ts.c"
|
||||
|
||||
struct boundary_tag {
|
||||
int inuse:1; // inuse bit
|
||||
int size:31; // size of block, in words
|
||||
|
42
mm_ts.c
Normal file
42
mm_ts.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Thread-safety wrapper.
|
||||
* To be included in mm.c - you may assume this file exists, or else
|
||||
* (better!) implement your own version.
|
||||
*
|
||||
* Generally, #including .c files is fragile and not good style.
|
||||
* This is just a stop-gap solution.
|
||||
*/
|
||||
#include <pthread.h>
|
||||
static pthread_mutex_t malloc_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void *_mm_malloc_thread_unsafe(size_t size);
|
||||
void _mm_free_thread_unsafe(void *bp);
|
||||
void *_mm_realloc_thread_unsafe(void *ptr, size_t size);
|
||||
|
||||
void *mm_malloc(size_t size)
|
||||
{
|
||||
pthread_mutex_lock(&malloc_lock);
|
||||
void * p = _mm_malloc_thread_unsafe(size);
|
||||
pthread_mutex_unlock(&malloc_lock);
|
||||
return p;
|
||||
}
|
||||
|
||||
void mm_free(void *bp)
|
||||
{
|
||||
pthread_mutex_lock(&malloc_lock);
|
||||
_mm_free_thread_unsafe(bp);
|
||||
pthread_mutex_unlock(&malloc_lock);
|
||||
}
|
||||
|
||||
void *mm_realloc(void *ptr, size_t size)
|
||||
{
|
||||
pthread_mutex_lock(&malloc_lock);
|
||||
void * p = _mm_realloc_thread_unsafe(ptr, size);
|
||||
pthread_mutex_unlock(&malloc_lock);
|
||||
return p;
|
||||
}
|
||||
|
||||
#define mm_malloc _mm_malloc_thread_unsafe
|
||||
#define mm_free _mm_free_thread_unsafe
|
||||
#define mm_realloc _mm_realloc_thread_unsafe
|
||||
|
Loading…
x
Reference in New Issue
Block a user