commits for Spring 2016

added multi-threaded ability to driver
provide thread-safe wrapper
This commit is contained in:
CS3214 Class Account 2016-03-30 01:15:21 -04:00
parent f603ce6c85
commit e40357ee6a
7 changed files with 274 additions and 56 deletions

View File

@ -4,9 +4,9 @@
VERSION = 1 VERSION = 1
CC = gcc CC = gcc
CFLAGS = -Wall -O3 -Werror -m32 CFLAGS = -Wall -O3 -Werror -m32 -pthread -std=gnu11
# for debugging # 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 SHARED_OBJS = mdriver.o memlib.o fsecs.o fcyc.o clock.o ftimer.o list.o
OBJS = $(SHARED_OBJS) mm.o OBJS = $(SHARED_OBJS) mm.o
@ -23,7 +23,7 @@ mdriver-gback: $(GBACK_IMPL_OBJS)
$(CC) $(CFLAGS) -o $@ $(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 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 mm.o: mm.c mm.h memlib.h
fsecs.o: fsecs.c fsecs.h config.h fsecs.o: fsecs.c fsecs.h config.h
fcyc.o: fcyc.c fcyc.h fcyc.o: fcyc.c fcyc.h

View File

@ -64,13 +64,13 @@
/* /*
* Maximum heap size in bytes * 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 * 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_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 */ #endif /* __CONFIG_H */

264
mdriver.c
View File

@ -15,6 +15,9 @@
#include <assert.h> #include <assert.h>
#include <float.h> #include <float.h>
#include <time.h> #include <time.h>
#include <stdint.h>
#include <pthread.h>
#include <sys/time.h>
#include "mm.h" #include "mm.h"
#include "memlib.h" #include "memlib.h"
@ -62,16 +65,6 @@ typedef struct {
size_t *block_sizes; /* ... and a corresponding array of payload sizes */ size_t *block_sizes; /* ... and a corresponding array of payload sizes */
} trace_t; } 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 */ /* Summarizes the important stats for some malloc function on some trace */
typedef struct { typedef struct {
/* defined for both libc malloc and student malloc package (mm.c) */ /* 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 */ int verbose = 0; /* global flag for verbose output */
static int errors = 0; /* number of errs found when running student malloc */ 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 */ /* Directory where default tracefiles are found */
static char tracedir[MAXLINE] = TRACEDIR; static char tracedir[MAXLINE] = TRACEDIR;
@ -108,11 +100,12 @@ static char *default_tracefiles[] = {
/* these functions manipulate range lists */ /* these functions manipulate range lists */
static int add_range(range_t **ranges, char *lo, int size, static int add_range(range_t **ranges, char *lo, int size,
int tracenum, int opnum); 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 remove_range(range_t **ranges, char *lo);
static void clear_ranges(range_t **ranges); static void clear_ranges(range_t **ranges);
/* These functions read, allocate, and free storage for traces */ /* 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); static void free_trace(trace_t *trace);
/* Routines for evaluating the correctness and speed of libc malloc */ /* 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 /* Routines for evaluating correctnes, space utilization, and speed
of the student's malloc package in mm.c */ 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 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(void *ptr);
static void eval_mm_speed_inner(void *ptr);
static void * eval_mm_speed_single(void *_args);
/* Various helper routines */ /* Various helper routines */
static void printresults(int n, char ** tracefiles, stats_t *stats); 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 unix_error(char *msg);
static void malloc_error(int tracenum, int opnum, char *msg); static void malloc_error(int tracenum, int opnum, char *msg);
static void app_error(char *msg); static void app_error(char *msg);
static FILE * open_jsonfile(const char * filename_mask);
/************** /**************
* Main routine * Main routine
@ -146,10 +154,10 @@ int main(int argc, char **argv)
range_t *ranges = NULL; /* keeps track of block extents for one trace */ range_t *ranges = NULL; /* keeps track of block extents for one trace */
stats_t *libc_stats = NULL;/* libc stats for each trace */ stats_t *libc_stats = NULL;/* libc stats for each trace */
stats_t *mm_stats = NULL; /* mm (i.e. student) 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 team_check = 1; /* If set, check team structure (reset by -a) */
int run_libc = 0; /* If set, run libc malloc (set by -l) */ 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 autograder = 0; /* If set, emit summary info for autograder (-g) */
int use_mmap = 0; /* If set, have memlib use mmap() instead malloc() */ 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 * 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) { switch (c) {
case 'n': case 'n':
use_mmap = 1; use_mmap = 1;
@ -195,6 +203,9 @@ int main(int argc, char **argv)
case 'V': /* Be more verbose than -v */ case 'V': /* Be more verbose than -v */
verbose = 2; verbose = 2;
break; break;
case 'm': /* Include multi-threaded testing */
nthreads = atoi(optarg);
break;
case 'h': /* Print this message */ case 'h': /* Print this message */
usage(); usage();
exit(0); exit(0);
@ -257,16 +268,15 @@ int main(int argc, char **argv)
/* Evaluate the libc malloc package using the K-best scheme */ /* Evaluate the libc malloc package using the K-best scheme */
for (i=0; i < num_tracefiles; i++) { 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; libc_stats[i].ops = trace->num_ops;
if (verbose > 1) if (verbose > 1)
printf("Checking libc malloc for correctness, "); printf("Checking libc malloc for correctness, ");
libc_stats[i].valid = eval_libc_valid(trace, i); libc_stats[i].valid = eval_libc_valid(trace, i);
if (libc_stats[i].valid) { if (libc_stats[i].valid) {
speed_params.trace = trace;
if (verbose > 1) if (verbose > 1)
printf("and performance.\n"); 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); free_trace(trace);
} }
@ -284,30 +294,105 @@ int main(int argc, char **argv)
if (verbose > 1) if (verbose > 1)
printf("\nTesting mm malloc\n"); printf("\nTesting mm malloc\n");
/* Allocate the mm stats array, with one stats_t struct per tracefile */ /* Allocate the mm stats array, with two stats_t struct per tracefile */
mm_stats = (stats_t *)calloc(num_tracefiles, sizeof(stats_t)); mm_stats = (stats_t *)calloc((nthreads > 0 ? 2 : 1) * num_tracefiles, sizeof(stats_t));
if (mm_stats == NULL) if (mm_stats == NULL)
unix_error("mm_stats calloc in main failed"); unix_error("mm_stats calloc in main failed");
/* Initialize the simulated memory system in memlib.c */ /* Initialize the simulated memory system in memlib.c */
mem_init(use_mmap); mem_init(use_mmap);
int max_total_size = 0;
/* Evaluate student's mm malloc package using the K-best scheme */ /* Evaluate student's mm malloc package using the K-best scheme */
for (i=0; i < num_tracefiles; i++) { 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; mm_stats[i].ops = trace->num_ops;
if (verbose > 1) if (verbose > 1)
printf("Checking mm_malloc for correctness, "); printf("Checking mm_malloc for correctness, ");
check_heap_bounds = 1;
mm_stats[i].valid = eval_mm_valid(trace, i, &ranges); mm_stats[i].valid = eval_mm_valid(trace, i, &ranges);
if (mm_stats[i].valid) { if (mm_stats[i].valid) {
if (verbose > 1) if (verbose > 1)
printf("efficiency, "); printf("efficiency, ");
mm_stats[i].util = eval_mm_util(trace, i, &ranges);
speed_params.trace = trace; max_total_size = eval_mm_util(trace, i, &ranges);
speed_params.ranges = ranges; mm_stats[i].util = ((double)max_total_size / (double)mem_heapsize());
if (verbose > 1) if (verbose > 1)
printf("and performance.\n"); 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); free_trace(trace);
} }
@ -319,6 +404,12 @@ int main(int argc, char **argv)
printf("\n"); 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 * 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 */ /* Write results to JSON file for submission */
char jsonfilename[80]; FILE * json = open_jsonfile("results.%d.json");
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");
fprintf(json, "{"); fprintf(json, "{");
fprintf(json, " \"results\": "); fprintf(json, " \"results\": ");
printresults_as_json(json, num_tracefiles, tracefiles, mm_stats); 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\": %f, \"avg_mm_throughput\" : %f, \"perfindex\": %f, \"AVG_LIBC_THRUPUT\": %f }\n",
avg_mm_util, avg_mm_throughput, perfindex, AVG_LIBC_THRUPUT); 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, "}"); fprintf(json, "}");
fclose(json); fclose(json);
exit(0); 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 * 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 */ /* The payload must lie within the extent of the heap */
if ((lo < (char *)mem_heap_lo()) || (lo > (char *)mem_heap_hi()) || if (check_heap_bounds && (
(hi < (char *)mem_heap_lo()) || (hi > (char *)mem_heap_hi())) { (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)", sprintf(msg, "Payload (%p:%p) lies outside heap (%p:%p)",
lo, hi, mem_heap_lo(), mem_heap_hi()); lo, hi, mem_heap_lo(), mem_heap_hi());
malloc_error(tracenum, opnum, msg); 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 * 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; FILE *tracefile;
trace_t *trace; trace_t *trace;
char type[MAXLINE]; char type[MAXLINE];
@ -500,7 +603,7 @@ static trace_t *read_trace(char *tracedir, char *filename)
unsigned max_index = 0; unsigned max_index = 0;
unsigned op_index; unsigned op_index;
if (verbose > 1) if (verbose)
printf("Reading tracefile: %s\n", filename); printf("Reading tracefile: %s\n", filename);
/* Allocate the trace record */ /* Allocate the trace record */
@ -590,10 +693,32 @@ void free_trace(trace_t *trace)
* and throughput of the libc and mm malloc packages. * 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 * eval_mm_valid - Check the mm malloc package for correctness
*/ */
static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges) 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 i, j;
int index; int index;
@ -604,15 +729,8 @@ static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges)
char *p; char *p;
/* Reset the heap and free any records in the range list */ /* Reset the heap and free any records in the range list */
mem_reset_brk();
clear_ranges(ranges); 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 */ /* Interpret each operation in the trace in order */
for (i = 0; i < trace->num_ops; i++) { for (i = 0; i < trace->num_ops; i++) {
index = trace->ops[i].index; index = trace->ops[i].index;
@ -703,6 +821,28 @@ static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges)
return 1; 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 * 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 * 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 * doesn't allow the students to decrement the brk pointer, so brk
* is always the high water mark of the heap. * 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 i;
int index; 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() * 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) 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 */ /* Reset the heap and initialize the mm package */
mem_reset_brk(); mem_reset_brk();
if (mm_init() < 0) if (mm_init() < 0)
app_error("mm_init failed in eval_mm_speed"); 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 */ /* Interpret each trace request */
for (i = 0; i < trace->num_ops; i++) for (i = 0; i < trace->num_ops; i++)
switch (trace->ops[i].type) { switch (trace->ops[i].type) {
@ -898,7 +1068,7 @@ static void eval_libc_speed(void *ptr)
int i; int i;
int index, size, newsize; int index, size, newsize;
char *p, *newp, *oldp, *block; 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++) { for (i = 0; i < trace->num_ops; i++) {
switch (trace->ops[i].type) { switch (trace->ops[i].type) {

View File

@ -86,7 +86,7 @@ void *mem_sbrk(int incr)
if ( (incr < 0) || ((mem_brk + incr) > mem_max_addr)) { if ( (incr < 0) || ((mem_brk + incr) > mem_max_addr)) {
errno = ENOMEM; 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; return NULL;
} }
mem_brk += incr; mem_brk += incr;

View File

@ -11,6 +11,8 @@
#include "mm.h" #include "mm.h"
#include "memlib.h" #include "memlib.h"
#include "mm_ts.c"
/* /*
* If NEXT_FIT defined use next fit search, else use first fit search * 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) static void printblock(void *bp)
{ {
size_t hsize, halloc, fsize, falloc; size_t hsize/*, halloc, fsize, falloc*/;
checkheap(0); checkheap(0);
hsize = GET_SIZE(HDRP(bp)); hsize = GET_SIZE(HDRP(bp));
/*
halloc = GET_ALLOC(HDRP(bp)); halloc = GET_ALLOC(HDRP(bp));
fsize = GET_SIZE(FTRP(bp)); fsize = GET_SIZE(FTRP(bp));
falloc = GET_ALLOC(FTRP(bp)); falloc = GET_ALLOC(FTRP(bp));
*/
if (hsize == 0) { if (hsize == 0) {
printf("%p: EOL\n", bp); printf("%p: EOL\n", bp);

View File

@ -20,6 +20,8 @@
#include "mm.h" #include "mm.h"
#include "memlib.h" #include "memlib.h"
#include "mm_ts.c"
struct boundary_tag { struct boundary_tag {
int inuse:1; // inuse bit int inuse:1; // inuse bit
int size:31; // size of block, in words int size:31; // size of block, in words

42
mm_ts.c Normal file
View 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