Skip to content

Commit

Permalink
malloclab added & tsh updated
Browse files Browse the repository at this point in the history
  • Loading branch information
Seterplus committed Dec 18, 2014
1 parent 3951164 commit e2326d0
Show file tree
Hide file tree
Showing 82 changed files with 1,238,622 additions and 2 deletions.
26 changes: 26 additions & 0 deletions malloclab/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#
# Makefile for the malloc lab driver
#
CC = gcc
CFLAGS = -Wall -Wextra -Werror -O2 -g -DDRIVER -std=gnu99

OBJS = mdriver.o mm.o memlib.o fsecs.o fcyc.o clock.o ftimer.o

all: mdriver

mdriver: $(OBJS)
$(CC) $(CFLAGS) -o mdriver $(OBJS)

mdriver.o: mdriver.c fsecs.h fcyc.h clock.h memlib.h config.h mm.h
memlib.o: memlib.c memlib.h
mm.o: mm.c mm.h memlib.h
fsecs.o: fsecs.c fsecs.h config.h
fcyc.o: fcyc.c fcyc.h
ftimer.o: ftimer.c ftimer.h config.h
clock.o: clock.c clock.h

clean:
rm -f *~ *.o mdriver



45 changes: 45 additions & 0 deletions malloclab/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#####################################################################
# CS:APP Malloc Lab
# Handout files for students
######################################################################

***********
Main Files:
***********

mdriver
Once you've run make, run ./mdriver to test your solution.

traces/
Directory that contains the trace files that the driver uses
to test your solution. Files orners.rep, short2.rep, and malloc.rep
are tiny trace files that you can use for debugging correctness.

**********************************
Other support files for the driver
**********************************

config.h Configures the malloc lab driver
fsecs.{c,h} Wrapper function for the different timer packages
clock.{c,h} Routines for accessing the Pentium and Alpha cycle counters
fcyc.{c,h} Timer functions based on cycle counters
ftimer.{c,h} Timer functions based on interval timers and gettimeofday()
memlib.{c,h} Models the heap and sbrk function

*******************************
Building and running the driver
*******************************
To build the driver, type "make" to the shell.

To run the driver on a tiny test trace:

unix> ./mdriver -V -f traces/malloc.rep

To get a list of the driver flags:

unix> ./mdriver -h

The -V option prints out helpful tracing information



297 changes: 297 additions & 0 deletions malloclab/clock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
/*
* clock.c - Routines for using the cycle counters on x86,
* Alpha, and Sparc boxes.
*
* Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
* May not be used, modified, or copied without permission.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/times.h>
#include "clock.h"


/*******************************************************
* Machine dependent functions
*
* Note: the constants __i386__ and __alpha
* are set by GCC when it calls the C preprocessor
* You can verify this for yourself using gcc -v.
*******************************************************/

#if defined(__i386__) || defined(__x86_64__)
/*******************************************************
* Pentium versions of start_counter() and get_counter()
*******************************************************/


/* $begin x86cyclecounter */
/* Initialize the cycle counter */
static unsigned cyc_hi = 0;
static unsigned cyc_lo = 0;


/* Set *hi and *lo to the high and low order bits of the cycle counter.
Implementation requires assembly code to use the rdtsc instruction. */
void access_counter(unsigned *hi, unsigned *lo)
{
asm("rdtsc; movl %%edx,%0; movl %%eax,%1" /* Read cycle counter */
: "=r" (*hi), "=r" (*lo) /* and move results to */
: /* No input */ /* the two outputs */
: "%edx", "%eax");
}

/* Record the current value of the cycle counter. */
void start_counter()
{
access_counter(&cyc_hi, &cyc_lo);
}

/* Return the number of cycles since the last call to start_counter. */
double get_counter()
{
unsigned ncyc_hi, ncyc_lo;
unsigned hi, lo, borrow;
double result;

/* Get cycle counter */
access_counter(&ncyc_hi, &ncyc_lo);

/* Do double precision subtraction */
lo = ncyc_lo - cyc_lo;
borrow = lo > ncyc_lo;
hi = ncyc_hi - cyc_hi - borrow;
result = (double) hi * (1 << 30) * 4 + lo;
if (result < 0) {
fprintf(stderr, "Error: counter returns neg value: %.0f\n", result);
}
return result;
}
/* $end x86cyclecounter */

#elif defined(__alpha)

/****************************************************
* Alpha versions of start_counter() and get_counter()
***************************************************/

/* Initialize the cycle counter */
static unsigned cyc_hi = 0;
static unsigned cyc_lo = 0;


/* Use Alpha cycle timer to compute cycles. Then use
measured clock speed to compute seconds
*/

/*
* counterRoutine is an array of Alpha instructions to access
* the Alpha's processor cycle counter. It uses the rpcc
* instruction to access the counter. This 64 bit register is
* divided into two parts. The lower 32 bits are the cycles
* used by the current process. The upper 32 bits are wall
* clock cycles. These instructions read the counter, and
* convert the lower 32 bits into an unsigned int - this is the
* user space counter value.
* NOTE: The counter has a very limited time span. With a
* 450MhZ clock the counter can time things for about 9
* seconds. */
static unsigned int counterRoutine[] =
{
0x601fc000u,
0x401f0000u,
0x6bfa8001u
};

/* Cast the above instructions into a function. */
static unsigned int (*counter)(void)= (void *)counterRoutine;


void start_counter()
{
/* Get cycle counter */
cyc_hi = 0;
cyc_lo = counter();
}

double get_counter()
{
unsigned ncyc_hi, ncyc_lo;
unsigned hi, lo, borrow;
double result;
ncyc_lo = counter();
ncyc_hi = 0;
lo = ncyc_lo - cyc_lo;
borrow = lo > ncyc_lo;
hi = ncyc_hi - cyc_hi - borrow;
result = (double) hi * (1 << 30) * 4 + lo;
if (result < 0) {
fprintf(stderr, "Error: Cycle counter returning negative value: %.0f\n", result);
}
return result;
}

#else

/****************************************************************
* All the other platforms for which we haven't implemented cycle
* counter routines. Newer models of sparcs (v8plus) have cycle
* counters that can be accessed from user programs, but since there
* are still many sparc boxes out there that don't support this, we
* haven't provided a Sparc version here.
***************************************************************/

void start_counter()
{
printf("ERROR: You are trying to use a start_counter routine in clock.c\n");
printf("that has not been implemented yet on this platform.\n");
printf("Please choose another timing package in config.h.\n");
exit(1);
}

double get_counter()
{
printf("ERROR: You are trying to use a get_counter routine in clock.c\n");
printf("that has not been implemented yet on this platform.\n");
printf("Please choose another timing package in config.h.\n");
exit(1);
}
#endif




/*******************************
* Machine-independent functions
******************************/
double ovhd()
{
/* Do it twice to eliminate cache effects */
int i;
double result;

for (i = 0; i < 2; i++) {
start_counter();
result = get_counter();
}
return result;
}

/* $begin mhz */
/* Get the clock rate from /proc */
double mhz_full(int verbose, int sleeptime __attribute__((unused)))
{
static char buf[2048];

FILE *fp = fopen("/proc/cpuinfo", "r");
double mhz = 0.0;

while (fgets(buf, 2048, fp)) {
if (strstr(buf, "cpu MHz")) {
sscanf(buf, "cpu MHz\t: %lf", &mhz);
break;
}
}
fclose(fp);
if (verbose)
printf("Processor clock rate ~= %.1f MHz\n", mhz);
return mhz;

#if 0
double rate;

start_counter();
sleep(sleeptime);
rate = get_counter() / (1e6*sleeptime);
if (verbose)
printf("Processor clock rate ~= %.1f MHz\n", rate);
return rate;
#endif
}
/* $end mhz */

/* Version using a default sleeptime */
double mhz(int verbose)
{
return mhz_full(verbose, 2);
}

/** Special counters that compensate for timer interrupt overhead */

static double cyc_per_tick = 0.0;

#define NEVENT 100
#define THRESHOLD 1000
#define RECORDTHRESH 3000

/* Attempt to see how much time is used by timer interrupt */
static void callibrate(int verbose)
{
double oldt;
struct tms t;
clock_t oldc;
int e = 0;

times(&t);
oldc = t.tms_utime;
start_counter();
oldt = get_counter();
while (e <NEVENT) {
double newt = get_counter();

if (newt-oldt >= THRESHOLD) {
clock_t newc;
times(&t);
newc = t.tms_utime;
if (newc > oldc) {
double cpt = (newt-oldt)/(newc-oldc);
if ((cyc_per_tick == 0.0 || cyc_per_tick > cpt) && cpt > RECORDTHRESH)
cyc_per_tick = cpt;
/*
if (verbose)
printf("Saw event lasting %.0f cycles and %d ticks. Ratio = %f\n",
newt-oldt, (int) (newc-oldc), cpt);
*/
e++;
oldc = newc;
}
oldt = newt;
}
}
if (verbose)
printf("Setting cyc_per_tick to %f\n", cyc_per_tick);
}

static clock_t start_tick = 0;

void start_comp_counter()
{
struct tms t;

if (cyc_per_tick == 0.0)
callibrate(0);
times(&t);
start_tick = t.tms_utime;
start_counter();
}

double get_comp_counter()
{
double time = get_counter();
double ctime;
struct tms t;
clock_t ticks;

times(&t);
ticks = t.tms_utime - start_tick;
ctime = time - ticks*cyc_per_tick;
/*
printf("Measured %.0f cycles. Ticks = %d. Corrected %.0f cycles\n",
time, (int) ticks, ctime);
*/
return ctime;
}

22 changes: 22 additions & 0 deletions malloclab/clock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* Routines for using cycle counter */

/* Start the counter */
void start_counter();

/* Get # cycles since counter started */
double get_counter();

/* Measure overhead for counter */
double ovhd();

/* Determine clock rate of processor (using a default sleeptime) */
double mhz(int verbose);

/* Determine clock rate of processor, having more control over accuracy */
double mhz_full(int verbose, int sleeptime);

/** Special counters that compensate for timer interrupt overhead */

void start_comp_counter();

double get_comp_counter();
Loading

0 comments on commit e2326d0

Please sign in to comment.