SlideShare a Scribd company logo
1 of 156
assign4-2/.DS_Store
assign4-2/assign4_part2/mymem.h
#include <stddef.h>
typedef enum strategies_enum
{
NotSet = 0,
Best = 1,
Worst = 2,
First = 3,
Next = 4
} strategies;
char *strategy_name(strategies strategy);
strategies strategyFromString(char * strategy);
void initmem(strategies strategy, size_t sz);
void *mymalloc(size_t requested);
void myfree(void* block);
int mem_holes();
int mem_allocated();
int mem_free();
int mem_total();
int mem_largest_free();
int mem_small_free(int size);
char mem_is_alloc(void *ptr);
void* mem_pool();
void print_memory();
void print_memory_status();
void try_mymem(int argc, char **argv);
assign4-2/assign4_part2/memorytests.c
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <time.h>
#include <unistd.h>
#include "mymem.h"
#include "testrunner.h"
/* performs a randomized test:
totalSize == the total size of the memory pool, as passed to
initmem2
totalSize must be less than 10,000 * minBlockSize
fillRatio == when the allocated memory is >= fillRatio *
totalSize, a block is freed;
otherwise, a new block is allocated.
If a block cannot be allocated, this is tallied and a
random block is freed immediately thereafter in the next
iteration
minBlockSize, maxBlockSize == size for allocated blocks
is picked uniformly at random between these two numbers,
inclusive
*/
void do_randomized_test(int strategyToUse, int totalSize, float
fillRatio, int minBlockSize, int maxBlockSize, int iterations)
{
void * pointers[10000];
int storedPointers = 0;
int strategy;
int lbound = 1;
int ubound = 4;
int smallBlockSize = maxBlockSize/10;
if (strategyToUse>0)
lbound=ubound=strategyToUse;
FILE *log;
log = fopen("tests.log","a");
if(log == NULL) {
perror("Can't append to log file.n");
return;
}
fprintf(log,"Running randomized tests: pool size == %d,
fill ratio == %f, block size is from %d to %d, %d
iterationsn",totalSize,fillRatio,minBlockSize,maxBlockSize,iter
ations);
fclose(log);
for (strategy = lbound; strategy <= ubound; strategy++)
{
double sum_largest_free = 0;
double sum_hole_size = 0;
double sum_allocated = 0;
int failed_allocations = 0;
double sum_small = 0;
struct timespec execstart, execend;
int force_free = 0;
int i;
storedPointers = 0;
initmem(strategy,totalSize);
clock_gettime(CLOCK_REALTIME, &execstart);
for (i = 0; i < iterations; i++)
{
if ( (i % 10000)==0 )
srand ( time(NULL) );
if (!force_free && (mem_free() > (totalSize *
(1-fillRatio))))
{
int newBlockSize =
(rand()%(maxBlockSize-minBlockSize+1))+minBlockSize;
/* allocate */
void * pointer = mymalloc(newBlockSize);
if (pointer != NULL)
pointers[storedPointers++] = pointer;
else
{
failed_allocations++;
force_free = 1;
}
}
else
{
int chosen;
void * pointer;
/* free */
force_free = 0;
if (storedPointers == 0)
continue;
chosen = rand() % storedPointers;
pointer = pointers[chosen];
pointers[chosen] = pointers[storedPointers-
1];
storedPointers--;
myfree(pointer);
}
sum_largest_free += mem_largest_free();
sum_hole_size += (mem_free() / mem_holes());
sum_allocated += mem_allocated();
sum_small += mem_small_free(smallBlockSize);
}
clock_gettime(CLOCK_REALTIME, &execend);
log = fopen("tests.log","a");
if(log == NULL) {
perror("Can't append to log file.n");
return;
}
fprintf(log,"t=== %s
===n",strategy_name(strategy));
fprintf(log,"tTest took %.2fms.n", (execend.tv_sec -
execstart.tv_sec) * 1000 + (execend.tv_nsec - execstart.tv_nsec)
/ 1000000.0);
fprintf(log,"tAverage hole size:
%fn",sum_hole_size/iterations);
fprintf(log,"tAverage largest free block:
%fn",sum_largest_free/iterations);
fprintf(log,"tAverage allocated bytes:
%fn",sum_allocated/iterations);
fprintf(log,"tAverage number of small blocks:
%fn",sum_small/iterations);
fprintf(log,"tFailed allocations:
%dn",failed_allocations);
fclose(log);
}
}
/* run randomized tests against the various strategies with
various parameters */
int do_stress_tests(int argc, char **argv)
{
int strategy = strategyFromString(*(argv+1));
unlink("tests.log"); // We want a new log file
do_randomized_test(strategy,10000,0.25,1,1000,10000);
do_randomized_test(strategy,10000,0.25,1,2000,10000);
do_randomized_test(strategy,10000,0.25,1000,2000,10000)
;
do_randomized_test(strategy,10000,0.25,1,3000,10000);
do_randomized_test(strategy,10000,0.25,1,4000,10000);
do_randomized_test(strategy,10000,0.25,1,5000,10000);
do_randomized_test(strategy,10000,0.5,1,1000,10000);
do_randomized_test(strategy,10000,0.5,1,2000,10000);
do_randomized_test(strategy,10000,0.5,1000,2000,10000);
do_randomized_test(strategy,10000,0.5,1,3000,10000);
do_randomized_test(strategy,10000,0.5,1,4000,10000);
do_randomized_test(strategy,10000,0.5,1,5000,10000);
do_randomized_test(strategy,10000,0.5,1000,1000,10000);
/* watch what happens with this test!...why? */
do_randomized_test(strategy,10000,0.75,1,1000,10000);
do_randomized_test(strategy,10000,0.75,500,1000,10000);
do_randomized_test(strategy,10000,0.75,1,2000,10000);
do_randomized_test(strategy,10000,0.9,1,500,10000);
return 0; /* you nominally pass for surviving without
segfaulting */
}
/* basic sequential allocation of single byte blocks */
int test_alloc_1(int argc, char **argv) {
strategies strategy;
int lbound = 1;
int ubound = 4;
if (strategyFromString(*(argv+1))>0)
lbound=ubound=strategyFromString(*(argv+1));
for (strategy = lbound; strategy <= ubound; strategy++)
{
int correct_holes = 0;
int correct_alloc = 100;
int correct_largest_free = 0;
int i;
void* lastPointer = NULL;
initmem(strategy,100);
for (i = 0; i < 100; i++)
{
void* pointer = mymalloc(1);
if ( i > 0 && pointer != (lastPointer+1) )
{
printf("Allocation with %s was not
sequential at %i; expected %p, actual %pn",
strategy_name(strategy), i,lastPointer+1,pointer);
return 1;
}
lastPointer = pointer;
}
if (mem_holes() != correct_holes)
{
printf("Holes not counted as %d with %sn",
correct_holes, strategy_name(strategy));
return 1;
}
if (mem_allocated() != correct_alloc)
{
printf("Allocated memory not reported as %d
with %sn", correct_alloc, strategy_name(strategy));
return 1;
}
if (mem_largest_free() != correct_largest_free)
{
printf("Largest memory block free not reported
as %d with %sn", correct_largest_free,
strategy_name(strategy));
return 1;
}
}
return 0;
}
/* alloc, alloc, free, alloc */
int test_alloc_2(int argc, char **argv) {
strategies strategy;
int lbound = 1;
int ubound = 4;
if (strategyFromString(*(argv+1))>0)
lbound=ubound=strategyFromString(*(argv+1));
for (strategy = lbound; strategy <= ubound; strategy++)
{
int correct_holes;
int correct_alloc;
int correct_largest_free;
int correct_small;
void* first;
void* second;
void* third;
int correctThird;
initmem(strategy,100);
first = mymalloc(10);
second = mymalloc(1);
myfree(first);
third = mymalloc(1);
if (second != (first+10))
{
printf("Second allocation failed; allocated at
incorrect offset with strategy %s", strategy_name(strategy));
return 1;
}
correct_alloc = 2;
correct_small = (strategy == First || strategy == Best);
switch (strategy)
{
case Best:
correctThird = (third == first);
correct_holes = 2;
correct_largest_free = 89;
break;
case Worst:
correctThird = (third == second+1);
correct_holes = 2;
correct_largest_free = 88;
break;
case First:
correctThird = (third == first);
correct_holes = 2;
correct_largest_free = 89;
break;
case Next:
correctThird = (third == second+1);
correct_holes = 2;
correct_largest_free = 88;
break;
case NotSet:
break;
}
if (!correctThird)
{
printf("Third allocation failed; allocated at
incorrect offset with %s", strategy_name(strategy));
return 1;
}
if (mem_holes() != correct_holes)
{
printf("Holes counted as %d, should be %d with
%sn", mem_holes(), correct_holes, strategy_name(strategy));
return 1;
}
if (mem_small_free(9) != correct_small)
{
printf("Small holes counted as %d, should be %d
with %sn", mem_small_free(9), correct_small,
strategy_name(strategy));
return 1;
}
if (mem_allocated() != correct_alloc)
{
printf("Memory reported as %d, should be %d
with %sn", mem_allocated(0), correct_alloc,
strategy_name(strategy));
return 1;
}
if (mem_largest_free() != correct_largest_free)
{
printf("Largest memory block free reported as
%d, should be %d with %sn", mem_largest_free(),
correct_largest_free, strategy_name(strategy));
return 1;
}
}
return 0;
}
/* basic sequential allocation followed by 50 frees */
int test_alloc_3(int argc, char **argv) {
strategies strategy;
int lbound = 1;
int ubound = 4;
if (strategyFromString(*(argv+1))>0)
lbound=ubound=strategyFromString(*(argv+1));
for (strategy = lbound; strategy <= ubound; strategy++)
{
int correct_holes = 50;
int correct_alloc = 50;
int correct_largest_free = 1;
int i;
void* lastPointer = NULL;
initmem(strategy,100);
for (i = 0; i < 100; i++)
{
void* pointer = mymalloc(1);
if ( i > 0 && pointer != (lastPointer+1) )
{
printf("Allocation with %s was not
sequential at %i; expected %p, actual %pn",
strategy_name(strategy), i,lastPointer+1,pointer);
return 1;
}
lastPointer = pointer;
}
for (i = 1; i < 100; i+= 2)
{
myfree(mem_pool() + i);
}
if (mem_holes() != correct_holes)
{
printf("Holes not counted as %d with %sn",
correct_holes, strategy_name(strategy));
return 1;
}
if (mem_allocated() != correct_alloc)
{
printf("Memory not reported as %d with %sn",
correct_alloc, strategy_name(strategy));
return 1;
}
if (mem_largest_free() != correct_largest_free)
{
printf("Largest memory block free not reported
as %d with %sn", correct_largest_free,
strategy_name(strategy));
return 1;
}
for(i=0;i<100;i++) {
if(mem_is_alloc(mem_pool()+i) == i%2) {
printf("Byte %d in memory claims to ",i);
if(i%2)
printf("not ");
printf("be allocated. It should ");
if(!i%2)
printf("not ");
printf("be allocated.n");
return 1;
}
}
}
return 0;
}
/* basic sequential allocation followed by 50 frees, then another
50 allocs */
int test_alloc_4(int argc, char **argv) {
strategies strategy;
int lbound = 1;
int ubound = 4;
if (strategyFromString(*(argv+1))>0)
lbound=ubound=strategyFromString(*(argv+1));
for (strategy = lbound; strategy <= ubound; strategy++)
{
int correct_holes = 0;
int correct_alloc = 100;
int correct_largest_free = 0;
int i;
void* lastPointer = NULL;
initmem(strategy,100);
for (i = 0; i < 100; i++)
{
void* pointer = mymalloc(1);
if ( i > 0 && pointer != (lastPointer+1) )
{
printf("Allocation with %s was not
sequential at %i; expected %p, actual %pn",
strategy_name(strategy), i,lastPointer+1,pointer);
return 1;
}
lastPointer = pointer;
}
for (i = 1; i < 100; i+= 2)
{
myfree(mem_pool() + i);
}
for (i = 1; i < 100; i+=2)
{
void* pointer = mymalloc(1);
if ( i > 1 && pointer != (lastPointer+2) )
{
printf("Second allocation with %s was not
sequential at %i; expected %p, actual %pn",
strategy_name(strategy), i,lastPointer+1,pointer);
return 1;
}
lastPointer = pointer;
}
if (mem_holes() != correct_holes)
{
printf("Holes not counted as %d with %sn",
correct_holes, strategy_name(strategy));
return 1;
}
if (mem_allocated() != correct_alloc)
{
printf("Memory not reported as %d with %sn",
correct_alloc, strategy_name(strategy));
return 1;
}
if (mem_largest_free() != correct_largest_free)
{
printf("Largest memory block free not reported
as %d with %sn", correct_largest_free,
strategy_name(strategy));
return 1;
}
}
return 0;
}
int run_memory_tests(int argc, char **argv)
{
if (argc < 3)
{
printf("Usage: mem -test <test> <strategy> n");
return 0;
}
set_testrunner_default_timeout(20);
/* Tests can be invoked by matching their name or their
suite name or 'all'*/
testentry_t tests[] = {
{"alloc1","suite1",test_alloc_1},
{"alloc2","suite2",test_alloc_2},
{"alloc3","suite1",test_alloc_3},
{"alloc4","suite2",test_alloc_4},
{"stress","suite3",do_stress_tests},
};
return
run_testrunner(argc,argv,tests,sizeof(tests)/sizeof(testentry_t));
}
int main(int argc, char **argv)
{
if( argc < 2) {
printf("Usage: mem -test <test> <strategy> | mem -try <arg1>
<arg2> ... n");
exit(-1);
}
else if (!strcmp(argv[1],"-test"))
return run_memory_tests(argc-1,argv+1);
else if (!strcmp(argv[1],"-try")) {
try_mymem(argc-1,argv+1);
return 0;
} else {
printf("Usage: mem -test <test> <strategy> | mem -try <arg1>
<arg2> ... n");
exit(-1);
}
}
assign4-2/assign4_part2/testrunner.h
typedef int (*test_fp) (int, char **);
typedef struct
{
char *name;
char *suite;
test_fp test_function;
} testentry_t;
int run_testrunner(int argc, char **argv, testentry_t *entries,int
entry_count);
void set_testrunner_default_timeout(int s);
void set_testrunner_timeout(int s);
assign4-2/assign4_part2/README.txt
LMP2: Memory Management
=======================
This machine problem will focus on memory. You will
implement your own
version of malloc() and free(), using a variety of allocation
strategies.
You will be implementing a memory manager for a block of
memory. You will
implement routines for allocating and deallocating memory, and
keeping track of
what memory is in use. You will implement four strategies for
selecting in
which block to place a new requested memory black:
1) First-fit: select the first suitable block with smallest
address.
2) Best-fit: select the smallest suitable block.
3) Worst-fit: select the largest suitable block.
4) Next-fit: select the first suitable block after
the last block allocated (with wraparound
from end to beginning).
Here, "suitable" means "free, and large enough to fit the new
data".
Here are the functions you will need to implement:
initmem():
Initialize memory structures.
mymalloc():
Like malloc(), this allocates a new block of memory.
myfree():
Like free(), this deallocates a block of memory.
mem_holes():
How many free blocks are in memory?
mem_allocated():
How much memory is currently allocated?
mem_free():
How much memory is NOT allocated?
mem_largest_free():
How large is the largest free block?
mem_small_free():
How many small unallocated blocks are currently in memory?
mem_is_alloc():
Is a particular byte allocated or not?
We have given you a structure to use to implement these
functions. It is a
doubly-linked list of blocks in memory (both allocated and free
blocks). Every
malloc and free can create new blocks, or combine existing
blocks. You may
modify this structure, or even use a different one entirely.
However, do not
change function prototypes or files other than mymem.c.
IMPORTANT NOTE: Regardless of how you implement
memory management, make sure
that there are no adjacent free blocks. Any such blocks should
be merged into
one large block.
We have also given you a few functions to help you monitor
what happens when you
call your functions. Most important is the try_mymem()
function. If you run
your code with "mem -try <args>", it will call this function,
which you can use
to demonstrate the effects of your memory operations. These
functions have no
effect on test code, so use them to your advantage.
Running your code:
After running "make", run
1) "mem" to see the available tests and strategies.
2) "mem -test <test> <strategy>" to test your code with our
tests.
3) "mem -try <args>" to run your code with your own tests
(the try_mymem function).
You can also use "make test" and "make stage1-test" for testing.
"make
stage1-test" only runs the tests relevant to stage 1.
As in previous MPs, running "mem -test -f0 ..." will allow tests
to run even
after previous tests have failed. Similarly, using "all" for a test
or strategy
name runs all of the tests or strategies. Note that if "all" is
selected as the
strategy, the 4 tests are shown as one.
One of the tests, "stress", runs an assortment of randomized
tests on each
strategy. The results of the tests are placed in "tests.out" . You
may want to
view this file to see the relative performance of each strategy.
Stage 1
-------
Implement all the above functions, for the first-fit strategy. Use
"mem -test
all first" to test your implementation.
Stage 2
-------
A) Implement the other three strategies: worst-fit, best-fit, and
next-fit. The
strategy is passed to initmem(), and stored in the global variable
"myStrategy".
Some of your functions will need to check this variable to
implement the
correct strategy.
You can test your code with "mem -test all worst", etc., or test
all 4 together
with "mem -test all all". The latter command does not test the
strategies
separately; your code passes the test only if all four strategies
pass.
Questions
=========
1) Why is it so important that adjacent free blocks not be left as
such? What
would happen if they were permitted?
2) Which function(s) need to be concerned about adjacent free
blocks?
3) Name one advantage of each strategy.
4) Run the stress test on all strategies, and look at the results
(tests.out).
What is the significance of "Average largest free block"?
Which strategy
generally has the best performance in this metric? Why do you
think this is?
5) In the stress test results (see Question 4), what is the
significance of
"Average number of small blocks"? Which strategy generally
has the best
performance in this metric? Why do you think this is?
6) Eventually, the many mallocs and frees produces many small
blocks scattered
across the memory pool. There may be enough space to allocate
a new block, but
not in one place. It is possible to compact the memory, so all
the free blocks
are moved to one large free block. How would you implement
this in the system
you have built?
7) If you did implement memory compaction, what changes
would you need to make
in how such a system is invoked (i.e. from a user's perspective)?
8) How would you use the system you have built to implement
realloc? (Brief
explanation; no code)
9) Which function(s) need to know which strategy is being
used? Briefly explain
why this/these and not others.
10) Give one advantage of implementing memory management
using a linked list
over a bit array, where every bit tells whether its corresponding
byte is
allocated.
assign4-2/assign4_part2/mymem.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "mymem.h"
#include <time.h>
/* The main structure for implementing memory allocation.
* You may change this to fit your implementation.
*/
struct memoryList
{
// doubly-linked list
struct memoryList *last;
struct memoryList *next;
int size; // How many bytes in this block?
char alloc; // 1 if this block is allocated,
// 0 if this block is free.
void *ptr; // location of block in memory pool.
};
strategies myStrategy = NotSet; // Current strategy
size_t mySize;
void *myMemory = NULL;
static struct memoryList *head;
static struct memoryList *next;
/* initmem must be called prior to mymalloc and myfree.
initmem may be called more than once in a given exeuction;
when this occurs, all memory you previously malloc'ed
*must* be freed,
including any existing bookkeeping data.
strategy must be one of the following:
- "best" (best-fit)
- "worst" (worst-fit)
- "first" (first-fit)
- "next" (next-fit)
sz specifies the number of bytes that will be available, in
total, for all mymalloc requests.
*/
void initmem(strategies strategy, size_t sz)
{
myStrategy = strategy;
/* all implementations will need an actual block of
memory to use */
mySize = sz;
if (myMemory != NULL) free(myMemory); /* in case this
is not the first time initmem2 is called */
/* TODO: release any other memory you were using for
bookkeeping when doing a re-initialization! */
myMemory = malloc(sz);
/* TODO: Initialize memory management structure. */
}
/* Allocate a block of memory with the requested size.
* If the requested block is not available, mymalloc returns
NULL.
* Otherwise, it returns a pointer to the newly allocated block.
* Restriction: requested >= 1
*/
void *mymalloc(size_t requested)
{
assert((int)myStrategy > 0);
switch (myStrategy)
{
case NotSet:
return NULL;
case First:
return NULL;
case Best:
return NULL;
case Worst:
return NULL;
case Next:
return NULL;
}
return NULL;
}
/* Frees a block of memory previously allocated by mymalloc.
*/
void myfree(void* block)
{
return;
}
/****** Memory status/property functions ******
* Implement these functions.
* Note that when we refer to "memory" here, we mean the
* memory pool this module manages via
initmem/mymalloc/myfree.
*/
/* Get the number of contiguous areas of free space in memory.
*/
int mem_holes()
{
return 0;
}
/* Get the number of bytes allocated */
int mem_allocated()
{
return 0;
}
/* Number of non-allocated bytes */
int mem_free()
{
return 0;
}
/* Number of bytes in the largest contiguous area of unallocated
memory */
int mem_largest_free()
{
return 0;
}
/* Number of free blocks smaller than "size" bytes. */
int mem_small_free(int size)
{
return 0;
}
char mem_is_alloc(void *ptr)
{
return 0;
}
/*
* Feel free to use these functions, but do not modify them.
* The test code uses them, but you may ind them useful.
*/
//Returns a pointer to the memory pool.
void *mem_pool()
{
return myMemory;
}
// Returns the total number of bytes in the memory pool. */
int mem_total()
{
return mySize;
}
// Get string name for a strategy.
char *strategy_name(strategies strategy)
{
switch (strategy)
{
case Best:
return "best";
case Worst:
return "worst";
case First:
return "first";
case Next:
return "next";
default:
return "unknown";
}
}
// Get strategy from name.
strategies strategyFromString(char * strategy)
{
if (!strcmp(strategy,"best"))
{
return Best;
}
else if (!strcmp(strategy,"worst"))
{
return Worst;
}
else if (!strcmp(strategy,"first"))
{
return First;
}
else if (!strcmp(strategy,"next"))
{
return Next;
}
else
{
return 0;
}
}
/*
* These functions are for you to modify however you see fit.
These will not
* be used in tests, but you may find them useful for debugging.
*/
/* Use this function to print out the current contents of memory.
*/
void print_memory()
{
return;
}
/* Use this function to track memory allocation performance.
* This function does not depend on your implementation,
* but on the functions you wrote above.
*/
void print_memory_status()
{
printf("%d out of %d bytes
allocated.n",mem_allocated(),mem_total());
printf("%d bytes are free in %d holes; maximum
allocatable block is %d
bytes.n",mem_free(),mem_holes(),mem_largest_free());
printf("Average hole size is
%f.nn",((float)mem_free())/mem_holes());
}
/* Use this function to see what happens when your malloc and
free
* implementations are called. Run "mem -try <args>" to call
this function.
* We have given you a simple example to start.
*/
void try_mymem(int argc, char **argv) {
strategies strat;
void *a, *b, *c, *d, *e;
if(argc > 1)
strat = strategyFromString(argv[1]);
else
strat = First;
/* A simple example.
Each algorithm should produce a different layout. */
initmem(strat,500);
a = mymalloc(100);
b = mymalloc(100);
c = mymalloc(100);
myfree(b);
d = mymalloc(50);
myfree(a);
e = mymalloc(25);
print_memory();
print_memory_status();
}
assign4-2/assign4_part2/testrunner.c
/*
A simple testrunner framework
Original Author: L. Angrave
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include "testrunner.h"
#include "mymem.h"
/* Constants */
#define false (0)
#define true (1)
#define test_killed (2)
/* defaults */
static int default_timeout_seconds=5;
static int timeout_seconds;
void set_testrunner_default_timeout(int s) {
assert(s>0);
default_timeout_seconds=s;
}
void set_testrunner_timeout(int s) {
assert(s>0);
timeout_seconds=s;
}
/* --- Helper macros and functions --- */
#define DIE(mesg)
{fprintf(stderr,"n%s(%d):%sn",__fname__,__LINE__,mesg);
exit(1);}
static int eql( char*s1, char*s2) {return
s1&&s2&&!strcmp(s1,s2);}
/* Callback function for qsort on strings */
static int mystrcmp( const void *p1, const void *p2) {
return eql( ( char*)p1, ( char*)p2);
}
/* Stats of all tests run so far */
typedef struct
{
int ran, passed, failed;
} stats_t;
/* -- Signal handlers -- */
static pid_t child_pid;
static int sent_child_timeout_kill_signal;
static void kill_child_signal_handler(intsigno) {
if(!child_pid) return;
char m[]="-Timeout(Killing test process)-";
write(0,m,sizeof(m)-1);
kill(child_pid,SIGKILL);
sent_child_timeout_kill_signal=1;
}
/* Internal function to run a test as a forked child. The child
process is terminated if it runs for more than a few seconds */
static int invoke_test_with_timelimit(testentry_t* test, int
redirect_stdouterr,int argc, char **argv)
{
char fname[255];
int wait_status;
pid_t wait_val;
struct sigaction action;
assert(!child_pid);
assert(test && test->test_function && test->name);
set_testrunner_timeout(default_timeout_seconds);
errno=0;
child_pid = fork ();
if (child_pid == -1) {
fprintf(stderr,"-fork failed so running test inline-");
return test->test_function (argc, argv);
}
if (child_pid == 0)
{
if(redirect_stdouterr) {
snprintf(fname,(int)sizeof(fname),"stdout-
%s.txt",test->name);
fname[sizeof(fname)-1]=0;
freopen(fname, "w", stdout);
memcpy(fname+3,"err",3);
freopen(fname, "w", stderr);
}
exit(test->test_function(argc,argv));
}else {
wait_status=-1;
sigemptyset(&action.sa_mask);
action.sa_handler=kill_child_signal_handler;
sigaction(SIGALRM,&action,NULL);
sent_child_timeout_kill_signal=0;
alarm(timeout_seconds);
wait_val = waitpid (child_pid, &wait_status, 0);
int child_exited_normally= WIFEXITED
(wait_status);
int child_exit_value=WEXITSTATUS (wait_status);
int
child_term_by_signal=WIFSIGNALED(wait_status);
int child_term_signal=WTERMSIG(wait_status);
if(child_term_by_signal) {
fprintf(stderr,"testrunner:Test terminated by
signal %dn",child_term_signal);
fprintf(stderr,"testrunner:waitpid returned %d
(child_pid=%d,wait_status=%d)",wait_val,child_pid,wait_status
);
}
if(child_pid != wait_val)
fprintf(stderr,"testrunner: strange... wait_val !=
child_pidn");
int passed= (child_pid == wait_val) &&
(child_exit_value==0) && (child_exited_normally!=0);
alarm(0);
kill(child_pid,SIGKILL);
child_pid=0;
return sent_child_timeout_kill_signal ? test_killed :
passed ? 0 : 1;
}
}
/*
* run a test and update the stats. The main guts of this
functionality is provided by invoke_test_with_timelimit
* This outer wrapper updates thes output and statistics before
and after running the test.
*/
static int
run_one_test (stats_t * stats, testentry_t * test, int
redirect_stdouterr,int argc, char **argv)
{
int test_result;
assert (stats && test->name && argc > 0 && argv && *argv);
stats->ran++;
stats->failed++;
printf ("%2d.%-20s:", stats->ran, test->name);
fflush(stdout);
test_result=invoke_test_with_timelimit(test,redirect_stdout
err,argc,argv);
if (test_result == 0)
{
stats->failed--;
stats->passed++;
}
printf(":%sn", (test_result == 0 ? "pass" : test_result ==
2 ? "TIMEOUT * " : "FAIL *"));
return test_result!=0;
}
/* Help functionality to print out sorted list of test names and
suite names */
static void print_targets(testentry_t tests[], int count) {
char**array;
char *previous;
int i;
array=(char**)calloc(sizeof(char*),count);
/* Sort the test names and print unique entries*/
for(i=0;i<count;i++) array[i]=tests[i].name;
qsort(array,count,sizeof(array[0]),mystrcmp);
printf("nValid tests : all");
for(i=0,previous="";i<count; i++)
if(!eql(previous,array[i])) printf(" %s",(previous=array[i]));
/* Sort the suite names and print unique entries*/
for(i=0;i<count;i++) array[i]=tests[i].suite;
qsort(array, count,sizeof(array[0]),mystrcmp);
printf("nValid suites:");
for(i=0,previous="";i<count; i++)
if(!eql(previous,array[i])) printf(" %s",(previous=array[i]));
printf("nValid strategies: all ");
for(i=1;i<5;i++)
printf("%s ",strategy_name(i));
printf("n");
}
/*
* Main entry point for test harness
*/
int
run_testrunner(int argc, char **argv,testentry_t tests[],int
test_count)
{
char *test_name, *target;
int i;
stats_t stats;
int
target_matched,max_errors_before_quit,redirect_stdouterr;
memset (&stats, 0, sizeof (stats));
max_errors_before_quit=1;
redirect_stdouterr=0;
assert (tests != NULL);
assert(test_count>0);
assert (argc > 0 && argv && *argv);
while(true) {
target = argc > 1 ? argv[1] : "";
assert (target);
if(*target!='-') break;
argc--;argv++;
if(target[1]=='f' && target[2])
max_errors_before_quit=atoi(target+1);
else if(target[1]=='r')
redirect_stdouterr=1;
}
target_matched = false;
for (i=0;i<test_count && (max_errors_before_quit<1 ||
stats.failed != max_errors_before_quit);i++) {
test_name = tests[i].name;
assert(test_name);
assert(tests[i].suite);
assert(tests[i].test_function);
if (eql(target,test_name)||eql(target,"all") || eql
(target,tests[i].suite) ) {
if(!target_matched) printf("Running tests...n");
target_matched = true;
run_one_test (&stats, &tests[i],redirect_stdouterr, argc -
1,argv + 1);
}
}
if (!target_matched)
{
fprintf (stderr, "Test '%s' not found",
(strlen(target)>0?target : "(empty)"));
print_targets(tests,test_count);
}
else {
printf ("nTest Results:%d tests,%d passed,%d failed.n",
stats.ran,
stats.passed, stats.failed);
}
return stats.passed == stats.ran && target_matched ? 0 : 1;
}
assign4-2/assign4_part2/Makefile
CC = gcc
CCOPTS = -c -g -Wall
LINKOPTS = -g
EXEC=mem
OBJECTS=testrunner.o mymem.o memorytests.o
all: $(EXEC)
$(EXEC): $(OBJECTS)
$(CC) $(LINKOPTS) -o [email protected] $^ -lrt
%.o:%.c
$(CC) $(CCOPTS) -o [email protected] $^
clean:
- $(RM) $(EXEC)
- $(RM) $(OBJECTS)
- $(RM) *~
- $(RM) core.*
test: mem
./mem -test -f0 all all
stage1-test: mem
./mem -test -f0 all first
pretty:
indent *.c *.h -kr
assign4-2/assign4_part2/tests.log
Running randomized tests: pool size == 10000, fill ratio ==
0.250000, block size is from 1 to 1000, 10000 iterations
=== best ===
Test took 0.18ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.16ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.15ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.15ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.250000, block size is from 1 to 2000, 10000 iterations
=== best ===
Test took 0.19ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.15ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.14ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.18ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.250000, block size is from 1000 to 2000, 10000 iterations
=== best ===
Test took 0.19ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.19ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.17ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.17ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.250000, block size is from 1 to 3000, 10000 iterations
=== best ===
Test took 0.19ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.17ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.17ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.17ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.250000, block size is from 1 to 4000, 10000 iterations
=== best ===
Test took 0.20ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.18ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.19ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.19ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.250000, block size is from 1 to 5000, 10000 iterations
=== best ===
Test took 0.20ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.21ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.20ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.20ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.500000, block size is from 1 to 1000, 10000 iterations
=== best ===
Test took 0.20ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.20ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.20ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.20ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.500000, block size is from 1 to 2000, 10000 iterations
=== best ===
Test took 0.13ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.12ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.12ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.12ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.500000, block size is from 1000 to 2000, 10000 iterations
=== best ===
Test took 0.12ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.12ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.12ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.11ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.500000, block size is from 1 to 3000, 10000 iterations
=== best ===
Test took 0.11ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.10ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.10ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.10ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.500000, block size is from 1 to 4000, 10000 iterations
=== best ===
Test took 0.11ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.10ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.13ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.12ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.500000, block size is from 1 to 5000, 10000 iterations
=== best ===
Test took 0.10ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.09ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.500000, block size is from 1000 to 1000, 10000 iterations
=== best ===
Test took 0.09ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.10ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.750000, block size is from 1 to 1000, 10000 iterations
=== best ===
Test took 0.09ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.750000, block size is from 500 to 1000, 10000 iterations
=== best ===
Test took 0.09ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.09ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.09ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.10ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.750000, block size is from 1 to 2000, 10000 iterations
=== best ===
Test took 0.10ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
Running randomized tests: pool size == 10000, fill ratio ==
0.900000, block size is from 1 to 500, 10000 iterations
=== best ===
Test took 0.09ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== worst ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== first ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
=== next ===
Test took 0.08ms.
Average hole size: 0.000000
Average largest free block: 0.000000
Average allocated bytes: 0.000000
Average number of small blocks: 0.000000
Failed allocations: 0
assign4-2/assign4_part1/setup.sh
#!/bin/sh
#*************** YOU SHOULD NOT MODIFY ANYTHING
IN THIS FILE ***************
rm -rf ./testdata
mkdir -p
./testdata/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20
echo -n "Hello" > ./testdata/hello.txt
echo -n "OldFile" > ./testdata/oldfile.txt
cp ./testdata/hello.txt ./testdata/1/2/3/4/5/6/7/8/9/10/
cp ./testdata/oldfile.txt ./testdata/1/2/3/4/5/6/7/8/9/
touch -m -d 20050101 ./testdata/oldfile.txt
touch -a -d 20050103 ./testdata/oldfile.txt
if [ ! -f /tmp/bigtestscratchfile2forLMP1 ] ; then
echo "Creating large file (first time only)"
cat /usr/lib/*.so >/tmp/bigtestscratchfile2forLMP1
chmod 644 /tmp/bigtestscratchfile2forLMP1
fi
ln -s /tmp/bigtestscratchfile2forLMP1 ./testdata/bigfile
exit 0
assign4-2/assign4_part1/restart.c
/*************** YOU SHOULD NOT MODIFY ANYTHING
IN THIS FILE ***************/
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/wait.h>
#include "restart.h"
#define BLKSIZE PIPE_BUF
#define MILLION 1000000L
#define D_MILLION 1000000.0
/* Private functions */
static int gettimeout(struct timeval end, struct timeval
*timeoutp)
{
gettimeofday(timeoutp, NULL);
timeoutp->tv_sec = end.tv_sec - timeoutp->tv_sec;
timeoutp->tv_usec = end.tv_usec - timeoutp->tv_usec;
if (timeoutp->tv_usec >= MILLION) {
timeoutp->tv_sec++;
timeoutp->tv_usec -= MILLION;
}
if (timeoutp->tv_usec < 0) {
timeoutp->tv_sec--;
timeoutp->tv_usec += MILLION;
}
if ((timeoutp->tv_sec < 0) ||
((timeoutp->tv_sec == 0) && (timeoutp->tv_usec == 0))) {
errno = ETIME;
return -1;
}
return 0;
}
/* Restart versions of traditional functions */
int r_close(int fildes)
{
int retval;
while (retval = close(fildes), retval == -1 && errno ==
EINTR);
return retval;
}
int r_dup2(int fildes, int fildes2)
{
int retval;
while (retval = dup2(fildes, fildes2), retval == -1 && errno
== EINTR);
return retval;
}
int r_open2(const char *path, int oflag)
{
int retval;
while (retval = open(path, oflag), retval == -1 && errno ==
EINTR);
return retval;
}
int r_open3(const char *path, int oflag, mode_t mode)
{
int retval;
while (retval = open(path, oflag, mode), retval == -1
&& errno == EINTR);
return retval;
}
ssize_t r_read(int fd, void *buf, size_t size)
{
ssize_t retval;
while (retval = read(fd, buf, size), retval == -1 && errno ==
EINTR);
return retval;
}
pid_t r_wait(int *stat_loc)
{
pid_t retval;
while (((retval = wait(stat_loc)) == -1) && (errno ==
EINTR));
return retval;
}
pid_t r_waitpid(pid_t pid, int *stat_loc, int options)
{
pid_t retval;
while (((retval = waitpid(pid, stat_loc, options)) == -1) &&
(errno == EINTR));
return retval;
}
ssize_t r_write(int fd, void *buf, size_t size)
{
char *bufp;
size_t bytestowrite;
ssize_t byteswritten;
size_t totalbytes;
for (bufp = buf, bytestowrite = size, totalbytes = 0;
bytestowrite > 0;
bufp += byteswritten, bytestowrite -= byteswritten) {
byteswritten = write(fd, bufp, bytestowrite);
if ((byteswritten) == -1 && (errno != EINTR))
return -1;
if (byteswritten == -1)
byteswritten = 0;
totalbytes += byteswritten;
}
return totalbytes;
}
/* Utility functions */
struct timeval add2currenttime(double seconds)
{
struct timeval newtime;
gettimeofday(&newtime, NULL);
newtime.tv_sec += (int) seconds;
newtime.tv_usec += (int) ((seconds - (int) seconds) *
D_MILLION + 0.5);
if (newtime.tv_usec >= MILLION) {
newtime.tv_sec++;
newtime.tv_usec -= MILLION;
}
return newtime;
}
int copyfile(int fromfd, int tofd)
{
int bytesread;
int totalbytes = 0;
while ((bytesread = readwrite(fromfd, tofd)) > 0)
totalbytes += bytesread;
return totalbytes;
}
ssize_t readblock(int fd, void *buf, size_t size)
{
char *bufp;
ssize_t bytesread;
size_t bytestoread;
size_t totalbytes;
for (bufp = buf, bytestoread = size, totalbytes = 0;
bytestoread > 0; bufp += bytesread, bytestoread -=
bytesread) {
bytesread = read(fd, bufp, bytestoread);
if ((bytesread == 0) && (totalbytes == 0))
return 0;
if (bytesread == 0) {
errno = EINVAL;
return -1;
}
if ((bytesread) == -1 && (errno != EINTR))
return -1;
if (bytesread == -1)
bytesread = 0;
totalbytes += bytesread;
}
return totalbytes;
}
int readline(int fd, char *buf, int nbytes)
{
int numread = 0;
int returnval;
while (numread < nbytes - 1) {
returnval = read(fd, buf + numread, 1);
if ((returnval == -1) && (errno == EINTR))
continue;
if ((returnval == 0) && (numread == 0))
return 0;
if (returnval == 0)
break;
if (returnval == -1)
return -1;
numread++;
if (buf[numread - 1] == 'n') {
buf[numread] = '0';
return numread;
}
}
errno = EINVAL;
return -1;
}
ssize_t readtimed(int fd, void *buf, size_t nbyte, double
seconds)
{
struct timeval timedone;
timedone = add2currenttime(seconds);
if (waitfdtimed(fd, timedone) == -1)
return (ssize_t) (-1);
return r_read(fd, buf, nbyte);
}
int readwrite(int fromfd, int tofd)
{
char buf[BLKSIZE];
int bytesread;
if ((bytesread = r_read(fromfd, buf, BLKSIZE)) < 0)
return -1;
if (bytesread == 0)
return 0;
if (r_write(tofd, buf, bytesread) < 0)
return -1;
return bytesread;
}
int readwriteblock(int fromfd, int tofd, char *buf, int size)
{
int bytesread;
bytesread = readblock(fromfd, buf, size);
if (bytesread != size) /* can only be 0 or -1 */
return bytesread;
return r_write(tofd, buf, size);
}
int waitfdtimed(int fd, struct timeval end)
{
fd_set readset;
int retval;
struct timeval timeout;
if ((fd < 0) || (fd >= FD_SETSIZE)) {
errno = EINVAL;
return -1;
}
FD_ZERO(&readset);
FD_SET(fd, &readset);
if (gettimeout(end, &timeout) == -1)
return -1;
while (((retval =
select(fd + 1, &readset, NULL, NULL, &timeout)) == -
1)
&& (errno == EINTR)) {
if (gettimeout(end, &timeout) == -1)
return -1;
FD_ZERO(&readset);
FD_SET(fd, &readset);
}
if (retval == 0) {
errno = ETIME;
return -1;
}
if (retval == -1)
return -1;
return 0;
}
assign4-2/assign4_part1/lmp1_tests.c
/*************** YOU SHOULD NOT MODIFY ANYTHING
IN THIS FILE ***************/
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/stat.h>
#include <string.h>
#include "testrunner.h"
#include "fileio.h"
#include "util.h"
/* CONSTANTS */
/* These constants work in tandem with test data created by
setup.sh */
#define TESTDATA_DIR "testdata/"
#define NEW_FILE "testdata/newfile.txt"
#define OLD_FILE "testdata/oldfile.txt"
#define HELLO_FILE "testdata/hello.txt"
#define BIG_FILE "testdata/bigfile"
#define NO_SUCH_FILE "testdata/no_such_file"
#define NEW_DIR "testdata/newdir"
#define SUBDIR1_DIR "testdata/1"
extern int bonnie_main(int, const char **);
/* Remove testdata subdirectory (assumes that the current
directory has not
changed. */
void teardown()
{
if (system("./teardown.sh"))
fprintf(stderr, "nteardown failedn");
}
/* Create test data and register the clean up function */
void setup()
{
quit_if(system("./setup.sh"));
quit_if(atexit(teardown));
errno = 0;
}
/* ---------- Suite 1 Tests --------------- */
/* test file_read() */
int test_file_read(int argc, const char **argv)
{
char b[255], dots[sizeof(b)];
int bytes_read, i;
setup();
quit_if(IOERR_INVALID_ARGS != file_read(HELLO_FILE,
0, b, 0));
quit_if(IOERR_INVALID_ARGS !=
file_read(HELLO_FILE, 0, NULL, sizeof(b)));
quit_if(IOERR_INVALID_ARGS != file_read(HELLO_FILE,
-1, b, sizeof(b)));
quit_if(IOERR_INVALID_ARGS != file_read(NULL, 0, b,
sizeof(b)));
quit_if(IOERR_INVALID_PATH !=
file_read(NO_SUCH_FILE, 0, b, sizeof(b)));
bytes_read = file_read(HELLO_FILE, 0, b, sizeof(b));
quit_if(bytes_read != 5);
quit_if(strncmp("Hello", b, 5));
bytes_read = file_read(HELLO_FILE, 1, b, sizeof(b));
quit_if(bytes_read != 4);
quit_if(strncmp("ello", b, 4));
bytes_read = file_read(HELLO_FILE, -1, b, sizeof(b));
quit_if(bytes_read >= 0);
for (i = 0; i < sizeof(dots); i++) {
b[i] = dots[i] = i == sizeof(dots) - 1 ? '0' : '.';
}
bytes_read = file_read(BIG_FILE, 1, b, sizeof(b));
quit_if(bytes_read != sizeof(b));
quit_if(!memcmp(b, dots, sizeof(b)));
return 0;
}
/* Test file_info() */
int test_file_info(int argc, const char **argv)
{
char b[255], ftype[2];
int sz, params;
long accessed, modified;
char fmt[] = "Size:%d Accessed:%d Modified:%d Type %s";
setup();
// Test invalid arguments
quit_if(IOERR_INVALID_ARGS != file_info(HELLO_FILE,
b, 0));
quit_if(IOERR_INVALID_ARGS != file_info(HELLO_FILE,
NULL, sizeof(b)));
quit_if(IOERR_INVALID_ARGS != file_info(NULL, b,
sizeof(b)));
// Test stat on old file
quit_if(file_info(OLD_FILE, b, sizeof(b)));
params = sscanf(b, fmt, &sz, &accessed, &modified,
&ftype);
quit_if(params != 4);
int one_day = 86400;
int jan1_2005 = 1104534000; // seconds since epoch
int jan3_2005 = jan1_2005 + one_day + one_day;
quit_if(modified < jan1_2005 || modified > jan1_2005 +
one_day);
quit_if(accessed < jan3_2005 || accessed > jan3_2005 +
one_day);
return 0;
}
/* Test file_write() */
int test_file_write(int argc, const char **argv)
{
char b[] = "qwertyuiop", b2[255];
setup();
// Test invalid arguments
quit_if(IOERR_INVALID_ARGS !=
file_write(NEW_FILE, 0, NULL, sizeof(b)));
quit_if(IOERR_INVALID_ARGS != file_write(NULL, 0, b,
sizeof(b)));
// Test new file
quit_if(sizeof(b) != file_write(NEW_FILE, 0, b, sizeof(b)));
quit_if(strlen(b) + 1 != file_read(NEW_FILE, 0, b2,
sizeof(b2)));
quit_if(strncmp(b, b2, strlen(b)));
return 0;
}
/* ---------- Suite 3 Tests --------------- */
/* Test the higher level function file_create. */
int test_file_create(int argc, const char **argv)
{
char pattern[] = "ab", b[255];
int repeat = 10;
char expected[] = "abababababababababab";
setup();
quit_if(file_create(NEW_FILE, pattern, repeat));
quit_if(strlen(expected) != file_read(NEW_FILE, 0, b,
sizeof(b)));
quit_if(strncmp(expected, b, strlen(expected)));
return 0;
}
/* Test file_removal. */
int test_file_remove(int argc, const char **argv)
{
setup();
quit_if(IOERR_INVALID_ARGS != file_remove(NULL));
// Test correct removal
quit_if(file_remove(OLD_FILE));
// Cant remove twice
quit_if(IOERR_INVALID_PATH !=
file_remove(OLD_FILE));
return 0;
}
/* ---------- Suite 2 Tests --------------- */
/* Test dir_create (directory create)*/
int test_dir_create(int argc, const char **argv)
{
setup();
quit_if(IOERR_INVALID_ARGS != dir_create(NULL));
quit_if(IOERR_INVALID_PATH !=
dir_create(HELLO_FILE));
quit_if(dir_create(NEW_DIR));
struct stat s;
quit_if(stat(NEW_DIR, &s) == -1);
quit_if(!S_ISDIR(s.st_mode))
return 0;
}
/* Test dir_list (directory listing) */
int test_dir_list(int argc, const char **argv)
{
char b[10000], *next_line, *last, names_found[10000];
int entries;
setup();
quit_if(IOERR_INVALID_ARGS != dir_list(NULL, b,
sizeof(b)));
quit_if(IOERR_INVALID_ARGS != dir_list(HELLO_FILE,
NULL, sizeof(b)));
quit_if(IOERR_INVALID_ARGS != dir_list(HELLO_FILE,
b, 0));
quit_if(IOERR_INVALID_PATH !=
dir_list(NO_SUCH_FILE, b, sizeof(b)));
quit_if(IOERR_INVALID_PATH != dir_list(HELLO_FILE,
b, sizeof(b)));
quit_if(IOERR_BUFFER_TOO_SMALL !=
dir_list(TESTDATA_DIR, b, 1));
quit_if(dir_list(TESTDATA_DIR, b, sizeof(b)));
quit_if(!memchr(b, 0, sizeof(b))); // check terminating
nul byte
entries = 0;
names_found[0] = '|';
names_found[1] = '0';
next_line = strtok_r(b, "n", &last);
while (next_line) {
int args_read;
char name[256];
entries++;
args_read = sscanf(next_line, "%255s", name);
quit_if(args_read != 1);
quit_if(strlen(names_found) + strlen(name) + 2 >=
sizeof(names_found));
strcat(names_found, name);
strcat(names_found, "|");
next_line = strtok_r(NULL, "n", &last);
}
quit_if(!strstr(names_found, "|1|"));
quit_if(!strstr(names_found, "|.|"));
quit_if(!strstr(names_found, "|..|"));
quit_if(!strstr(names_found, "|hello.txt|"));
quit_if(!strstr(names_found, "|oldfile.txt|"));
quit_if(!strstr(names_found, "|bigfile|"));
quit_if(entries != 6);
return 0;
}
/* ---------- Suite 4 Tests --------------- */
/* Test file_checksum */
int test_file_checksum(int argc, const char **argv)
{
setup();
char hello[] = "Hello";
unsigned short cksum = checksum(hello, strlen(hello), 0);
quit_if(IOERR_INVALID_ARGS != file_checksum(NULL));
quit_if(cksum != file_checksum(HELLO_FILE));
return 0;
}
/* in setup.sh()
mkdir -p
./testdata/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20
cp ./testdata/hello.txt ./testdata/1/2/3/4/5/6/7/8/9/10/
cp ./testdata/oldfile.txt ./testdata/1/2/3/4/5/6/7/8/9/
This checksum algorithm commutes so we can calculate the the
final checksum as follows...
*/
/* Test dir_checksum */
int test_dir_checksum(int argc, const char **argv)
{
setup();
char dname[10];
int i;
unsigned short cksum;
int cksum2;
quit_if(IOERR_INVALID_ARGS != dir_checksum(NULL));
cksum = checksum("OldFile", 7, checksum("Hello", 5, 0));
for (i = 2; i <= 20; i++) {
sprintf(dname, "%d", i);
cksum = checksum(dname, strlen(dname), cksum);
}
cksum2 = dir_checksum(SUBDIR1_DIR);
quit_if(0 > cksum2);
quit_if(cksum != cksum2);
return 0;
}
/*
* Main entry point for test harness
*/
int run_lmp1_tests(int argc, const char **argv)
{
/* Tests can be invoked by matching their name or their suite
name or 'all' */
testentry_t tests[] = {
{"read", "suite1", test_file_read},
{"info", "suite1", test_file_info},
{"write", "suite1", test_file_write},
{"dirlist", "suite2", test_dir_list},
{"dircreate", "suite2", test_dir_create},
{"remove", "suite3", test_file_remove},
{"create", "suite3", test_file_create},
{"filechecksum", "suite4", test_file_checksum},
{"dirchecksum", "suite4", test_dir_checksum}
};
return run_testrunner(argc, argv, tests,
sizeof(tests) / sizeof(testentry_t));
}
/* The real main function. */
int main(int argc, const char **argv)
{
if (argc > 1 && !strcmp(argv[1], "-test")) {
return run_lmp1_tests(argc - 1, argv + 1);
} else {
return bonnie_main(argc, argv);
}
}
assign4-2/assign4_part1/fileio.c
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include "restart.h"
#include "fileio.h"
#if 1
#define VERBOSE(p) (p)
#else
#define VERBOSE(p) (0)
#endif
int file_read(char *path, int offset, void *buffer, size_t
bufbytes)
{
return IOERR_NOT_YET_IMPLEMENTED;
}
int file_info(char *path, void *buffer, size_t bufbytes)
{
if (!path || !buffer || bufbytes < 1)
return IOERR_INVALID_ARGS;
return IOERR_NOT_YET_IMPLEMENTED;
}
int file_write(char *path, int offset, void *buffer, size_t
bufbytes)
{
return IOERR_NOT_YET_IMPLEMENTED;
}
int file_create(char *path, char *pattern, int repeatcount)
{
return IOERR_NOT_YET_IMPLEMENTED;
}
int file_remove(char *path)
{
return IOERR_NOT_YET_IMPLEMENTED;
}
int dir_create(char *path)
{
return IOERR_NOT_YET_IMPLEMENTED;
}
int dir_list(char *path, void *buffer, size_t bufbytes)
{
return IOERR_NOT_YET_IMPLEMENTED;
}
int file_checksum(char *path)
{
return IOERR_NOT_YET_IMPLEMENTED;
}
int dir_checksum(char *path)
{
return IOERR_NOT_YET_IMPLEMENTED;
}
assign4-2/assign4_part1/util.c
/*************** YOU SHOULD NOT MODIFY ANYTHING
IN THIS FILE ***************/
/* execl*/
#include <unistd.h>
/* errno */
#include <errno.h>
/* waitpid,WEXITSTATUS*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <wait.h>
/* fprintf*/
#include <stdio.h>
#include <string.h>
#include "util.h"
/* Print a detailed error message to the given file descriptor.
The pointers f,mesg,src can be null. */
void print_error(FILE * f, int errn, char *mesg, char *src, int
line)
{
char errmesg[255];
*errmesg = '0';
if (strerror_r(errn, errmesg, sizeof(errmesg)))
strcpy(errmesg, "Unknown");
fprintf(f ? f : stderr, "nFAILED AT %s(%d); %s%s.
errno=%d(%s)n",
src ? src : "notset", line, mesg ? "because " : "",
mesg ? mesg : "", errn, errmesg);
}
/* Print a detailed error message and then exit with a status
value of 1.*/
void quit_with_message(int errn, char *mesg, char *src, int
line)
{
print_error(stderr, errn, mesg, src, line);
exit(1);
}
/* Calculate a very simple checksum for a character buffer.*/
unsigned short checksum(char *buffer, size_t sz, unsigned short
val)
{
if ((!buffer) || (!sz))
return val;
while ((sz--) > 0) {
val += *(buffer++);
}
return val;
}
assign4-2/assign4_part1/Makefile
CC = gcc
CCOPTS = -Wall -c -g
LINKOPTS = -g -pthread -lrt
EXEC = lmp1
OBJECTS = restart.o testrunner.o fileio.o lmp1_tests.o bonnie.o
util.o
all: $(EXEC)
$(EXEC): $(OBJECTS)
$(CC) $(LINKOPTS) -o [email protected] $^
%.o: %.c
$(CC) $(CCOPTS) -o [email protected] $^
test:
./$(EXEC) -test -f0 all
clean:
- $(RM) $(EXEC)
- $(RM) $(OBJECTS)
- $(RM) *~
- $(RM) core.*
- $(RM) -rf testdata
pretty:
indent *.c *.h -kr
assign4-2/assign4_part1/bonnie.c
/*
* This is a file system benchmark which attempts to study
bottlenecks -
* it is named 'Bonnie' after Bonnie Raitt, who knows how to
use one.
*
* Commentary on Bonnie's operations may be found at
* http://www.textuality.com/bonnie/intro.html
*
* COPYRIGHT NOTICE:
* Copyright (c) Tim Bray, 1990-1996.
*
*/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#if defined(SysV)
#include <limits.h>
#include <sys/times.h>
#else
#include <sys/resource.h>
#endif
#define IntSize (sizeof(int))
/*
* N.B. in seeker_reports, CPU appears and Start/End time, but
not Elapsed,
* so position 1 is re-used; icky data coupling.
*/
#define CPU (0)
#define Elapsed (1)
#define StartTime (1)
#define EndTime (2)
#define Seeks (4000)
#define UpdateSeek (10)
#define SeekProcCount (3)
#define Chunk (16384)
/* labels for the tests, used as an array index */
typedef enum {
Putc, ReWrite, FastWrite, Getc, FastRead, Lseek, TestCount
} tests_t;
static double cpu_so_far();
static void doseek(off_t where, int fd, int update);
static void get_delta_t(tests_t test);
static void io_error(char *message);
static void newfile(char *name, int *fd, FILE * *stream, int
create);
static void fill_file_char();
static void fill_file_block();
static void file_read_rewrite_block();
static void file_read_getc();
static void file_read_chunk();
#if defined(SysV)
/* System V wrappers for randomizers */
static long random();
static void srandom(int seed);
#endif
static void report(char *machine, off_t size);
static double time_so_far();
static void timestamp();
static void usage();
/*
* Housekeeping variables to build up timestamps for the tests;
* global to make it easy to keep track of the progress of time.
* all of this could have been done with non-global variables,
* but the code is easier to read this way and I don't anticipate
* much software engineering down the road
*/
static int basetime; /* when we started */
static double delta[(int) TestCount][2]; /* array of DeltaT
values */
static double last_cpustamp = 0.0; /* for computing delta-t */
static double last_timestamp = 0.0; /* for computing delta-t */
char name[Chunk];
FILE *stream;
int fd;
off_t words;
off_t size;
int buf[Chunk / IntSize];
int bufindex;
int chars[256];
int next;
/* entry point for LMP1 */
int bonnie_main(int argc, char **argv)
{
int child;
char *dir;
double first_start;
double last_stop;
int lseek_count = 0;
char *machine;
int seek_control[2];
int seek_feedback[2];
char seek_tickets[Seeks + SeekProcCount];
double seeker_report[3];
fd = -1;
basetime = (int) time((time_t *) NULL);
size = 100;
dir = ".";
machine = "";
/* parse the argument sent from the command line */
for (next = 1; next < argc; next++) {
if (strcmp(argv[next], "-s") == 0)
size = atol(argv[++next]);
else if (strcmp(argv[next], "-m") == 0)
machine = argv[++next];
else
usage();
}
if (size < 1) {
usage();
}
/*
CHECK SYSTEM CAPABILITY:
We proceed to check the size of files because 32-bit
machines has a limit
*/
if (sizeof(off_t) <= 4 && size > 2047) {
fprintf(stderr, "File too large for 32-bit machine, sorryn");
exit(1);
}
sprintf(name, "%s/LMP1.%d", dir, getpid());
/* The size is in Megabytes, and is rounded down to
multiples of Chunk */
size *= (1024 * 1024);
size = Chunk * (size / Chunk);
fprintf(stderr, "File '%s', size: %ldn", name, size);
fill_file_char(name, &fd, &stream); /* For specific details
please go down to the body of this function */
file_read_rewrite_block(name, &fd, &stream); /* For
specific details please go down to the body of this function */
fill_file_block(name, &fd, &stream); /* For specific details
please go down to the body of this function */
file_read_getc(name, &fd, &stream); /* For specific details
please go down to the body of this function */
/* use the frequency count */
for (words = 0; words < 256; words++)
sprintf((char *) buf, "%d", chars[words]);
file_read_chunk(name, &fd, &stream); /* For specific
details please go down to the body of this function */
/* use the frequency count */
for (words = 0; words < 256; words++)
sprintf((char *) buf, "%d", chars[words]);
/*
* Now test random seeks; first, set up for communicating
with children.
* The object of this e game is to do "Seeks" lseek() calls as
quickly
* as possible. So we'll farm them out among
SeekProcCount processes.
* We'll control them by writing 1-byte tickets down a pipe
which
* the children all read. We write "Seeks" bytes with val 1,
whichever
* child happens to get them does it and the right number of
seeks get
* done.
* The idea is that since the write() of the tickets is probably
* atomic, the parent process likely won't get scheduled
while the
* children are seeking away. If you draw a picture of the
likely
* timelines for three children, it seems likely that the seeks
will
* overlap very nicely with the process scheduling with the
effect
* that there will *always* be a seek() outstanding on the
file.
* Question: should the file be opened *before* the fork, so
that
* all the children are lseeking on the same underlying file
object?
*/
if (pipe(seek_feedback) == -1 || pipe(seek_control) == -1)
io_error("pipe");
for (next = 0; next < Seeks; next++)
seek_tickets[next] = 1;
for (; next < (Seeks + SeekProcCount); next++)
seek_tickets[next] = 0;
/* launch some parallel seek processes */
for (next = 0; next < SeekProcCount; next++) { /* for each
seek proc */
if ((child = fork()) == -1)
io_error("fork");
else if (child == 0) { /* child process */
/* set up and wait for the go-ahead */
close(seek_feedback[0]);
close(seek_control[1]);
newfile(name, &fd, &stream, 0);
srandom(getpid());
fprintf(stderr, "Seeker %d...", next + 1);
/* wait for the go-ahead */
if (read(seek_control[0], seek_tickets, 1) != 1)
io_error("read ticket");
timestamp();
seeker_report[StartTime] = time_so_far();
/* loop until we read a 0 ticket back from our parent */
while (seek_tickets[0]) { /* until Mom says stop */
doseek((long) (random() % (size / Chunk)), fd,
((lseek_count++ % UpdateSeek) == 0));
if (read(seek_control[0], seek_tickets, 1) != 1)
io_error("read ticket");
} /* until Mom says stop */
if (close(fd) == -1)
io_error("close after seek");
/* report to parent */
get_delta_t(Lseek);
seeker_report[EndTime] = time_so_far();
seeker_report[CPU] = delta[(int) Lseek][CPU];
if (write
(seek_feedback[1], seeker_report,
sizeof(seeker_report)) != sizeof(seeker_report))
io_error("pipe write");
exit(0);
} /* child process */
} /* for each seek proc */
/*
* Back in the parent; in an effort to ensure the children get
an even
* start, wait a few seconds for them to get scheduled, open
their
* files & so on.
*/
close(seek_feedback[1]);
close(seek_control[0]);
sleep(5);
fprintf(stderr, "start 'em...");
if (write(seek_control[1], seek_tickets, sizeof(seek_tickets))
!=
sizeof(seek_tickets))
io_error("write tickets");
/* read back from children */
for (next = 0; next < SeekProcCount; next++) { /* for each
child */
if (read
(seek_feedback[0], (char *) seeker_report,
sizeof(seeker_report)) != sizeof(seeker_report))
io_error("pipe read");
/*
* each child writes back its CPU, start & end times. The
elapsed time
* to do all the seeks is the time the first child started
until the
* time the last child stopped
*/
delta[(int) Lseek][CPU] += seeker_report[CPU];
if (next == 0) {/* first time */
first_start = seeker_report[StartTime];
last_stop = seeker_report[EndTime];
} /* first time */
else { /* not first time */
first_start = (first_start < seeker_report[StartTime]) ?
first_start : seeker_report[StartTime];
last_stop = (last_stop > seeker_report[EndTime]) ?
last_stop : seeker_report[EndTime];
} /* not first time */
if (wait(&child) == -1)
io_error("wait");
fprintf(stderr, "done...");
} /* for each child */
fprintf(stderr, "n");
delta[(int) Lseek][Elapsed] = last_stop - first_start;
report(machine, size);
unlink(name);
return EXIT_SUCCESS;
}
/****************************************************
*****************/
/* FUNCTION report */
/****************************************************
*****************/
/* INPUT: Machine description and size of file
*/
/****************************************************
*****************/
/* PROCESS: */
/* 1. Print in the monitor the results from the */
/* operations the program supports. */
/****************************************************
*****************/
/* OUTPUT: doesn´t return any value because it is void
*/
/****************************************************
*****************/
static void report(char *machine, off_t size)
{
printf(" ");
printf
("-------Sequential Output-------- ---Sequential Input-- --
Random--n");
printf(" ");
printf
("-Per Char- --Block--- -Rewrite-- -Per Char- --Block--- --
Seeks---n");
printf("Machine MB ");
printf("K/sec %%CPU K/sec %%CPU K/sec %%CPU K/sec
%%CPU K/sec ");
printf("%%CPU /sec %%CPUn");
printf("%-8.8s %4ld ", machine, size / (1024 * 1024));
printf("%5d %4.1f %5d %4.1f %5d %4.1f ",
(int) (((double) size) / (delta[(int) Putc][Elapsed] *
1024.0)),
delta[(int) Putc][CPU] / delta[(int) Putc][Elapsed] *
100.0,
(int) (((double) size) /
(delta[(int) FastWrite][Elapsed] * 1024.0)),
delta[(int) FastWrite][CPU] / delta[(int)
FastWrite][Elapsed] *
100.0,
(int) (((double) size) /
(delta[(int) ReWrite][Elapsed] * 1024.0)),
delta[(int) ReWrite][CPU] / delta[(int)
ReWrite][Elapsed] *
100.0);
printf("%5d %4.1f %5d %4.1f ",
(int) (((double) size) / (delta[(int) Getc][Elapsed] *
1024.0)),
delta[(int) Getc][CPU] / delta[(int) Getc][Elapsed] *
100.0,
(int) (((double) size) /
(delta[(int) FastRead][Elapsed] * 1024.0)),
delta[(int) FastRead][CPU] / delta[(int)
FastRead][Elapsed] *
100.0);
printf("%5.1f %4.1fn",
((double) Seeks) / delta[(int) Lseek][Elapsed],
delta[(int) Lseek][CPU] / delta[(int) Lseek][Elapsed] *
100.0);
}
/****************************************************
*****************/
/* FUNCTION newfile */
/****************************************************
*****************/
/* INPUT: Name of the file, File Descriptor, Buffer, Create Flag
*/
/****************************************************
*****************/
/* PROCESS: */
/* 1. If Create Flag is one */
/* i) Checks if the file is unlinked */
/* a) If it is not returns error */
/* ii) Obatain File Descriptor with proper parameters
*/
/* and flags.NOTE: Use man pages to view the specific
*/
/* parameters open uses. Make sure you understand
*/
/* the return values, and see the errors the function */
/* returns) */
/* Else Create flag is not equal to zero */
/* Obtain file descriptor with proper parameters and
*/
/* flags.(NOTE: Use man pages to view the specific
*/
/* parameters open uses. Make sure you understand
*/
/* the return values, and see the errors the function */
/* returns) */
/* 2. Fill buffer when calling fdopen with proper */
/* parameters and flags.(NOTE: Use man pages to view
the */
/* specific parameters open uses. Make sure you
understand */
/* the return values, and see the errors the function */
/* returns) */
/* 3. Check stream */
/****************************************************
*****************/
/* OUTPUT: doesn´t return any value because it is void
*/
/****************************************************
*****************/
static void newfile(char *name, int *fd, FILE ** stream, int
create)
{
if (create) {
if (unlink(name) == -1 && *fd != -1)
io_error("unlink");
*fd = open(name, O_RDWR | O_CREAT | O_EXCL,
0777);
} else
*fd = open(name, O_RDWR, 0777);
if (*fd == -1)
io_error(name);
*stream = fdopen(*fd, "r+");
if (*stream == NULL)
io_error("fdopen");
}
/****************************************************
*****************/
/* FUNCTION fill_file_char */
/****************************************************
*****************/
/* INPUT: does not receive any parameter */
/****************************************************
*****************/
/* PROCESS: */
/* 1. Open file */
/* 2. Record timestamp */
/* 3. For cycle to fill the file one character at a time*/
/* until it reaches the EndOfFile(EOF) */
/* 4. Close file */
/* 5. Call get_delta_t to find the performance of putc */
/****************************************************
*****************/
/* OUTPUT: doesn´t return any value because it is void
*/
/****************************************************
*****************/
static void fill_file_char()
{
fprintf(stderr, "FUNCTION fill_file_char() start...");
newfile(name, &fd, &stream, 1);
timestamp();
for (words = 0; words < size; words++)
if (putc(words & 0x7f, stream) == EOF)
io_error("putc");
if (fclose(stream) == -1)
io_error("fclose after putc");
get_delta_t(Putc);
fprintf(stderr, "...done FUNCTION file_fill_char()n");
}
/****************************************************
*****************/
/* FUNCTION fill_file_block */
/****************************************************
*****************/
/* INPUT: does not receive any parameter */
/****************************************************
*****************/
/* PROCESS: */
/* 1. Open file */
/* 2. Initialize every position of the buffer */
/* 3. Record timestamp */
/* 4. FOR cycle so for each word you need to: */
/* i) properly set the buffer index so that it points */
/* at the correct position. */
/* ii) Call write.(NOTE: Use man pages to view the
*/
/* specific parameters write uses. Make sure you */
/* understand the return values, and see the errors */
/* the function returns) */
/* 4. Close file */
/* 5. Call get_delta_t to find the performance of putc */
/****************************************************
*****************/
/* OUTPUT: doesn´t return any value because it is void
*/
/****************************************************
*****************/
static void fill_file_block()
{
fprintf(stderr, "FUNCTION fill_file_block() start...");
newfile(name, &fd, &stream, 1);
for (words = 0; words < Chunk / IntSize; words++)
buf[words] = 0;
timestamp();
for (words = bufindex = 0; words < (size / Chunk); words++)
{
if (bufindex == (Chunk / IntSize))
bufindex = 0;
buf[bufindex++]++;
if (write(fd, (char *) buf, Chunk) == -1)
io_error("write(2)");
}
if (close(fd) == -1)
io_error("close after fast write");
get_delta_t(FastWrite);
fprintf(stderr, "...done FUNCTION fill_file_block()n");
}
/****************************************************
*****************/
/* FUNCTION file_read_rewrite_block */
/****************************************************
*****************/
/* INPUT: does not receive any parameter */
/****************************************************
*****************/
/* PROCESS: */
/* 1. Open file */
/* 2. Call lseek. (NOTE: Use man pages to view the
*/
/* specific parameters lseek uses. Make sure you
*/
/* understand the return values, and see the errors the
*/
/* function returns) */
/* 3. Record timestamp */
/* 4. Make sure the buffer index point to zero */
/* 5. Call read. (NOTE: Use man pages to view the
*/
/* specific parameters read uses. Make sure you
*/
/* understand the return values, and see the errors the
*/
/* function returns) */
/* 6. While we can read a block, increment the index to
*/
/* point to the the next position. Call lseek and call */
/* write.(NOTE: Use man pages to view the specific
*/
/* parameters write uses. Make sure you understand the
*/
/* return values,and see the errors the function */
/* returns) */
/* Call read until the while condition is false. */
/* 7. Close file */
/* 8. Call get_delta_t to find the performance of putc */
/****************************************************
*****************/
/* OUTPUT: doesn´t return any value because it is void
*/
/****************************************************
*****************/
static void file_read_rewrite_block()
{
fprintf(stderr, "FUNCTION file_read_rewrite() start...");
newfile(name, &fd, &stream, 0);
if (lseek(fd, (off_t) 0, 0) == (off_t) - 1)
io_error("lseek(2) before rewrite");
fprintf(stderr, "Rewriting");
timestamp();
bufindex = 0;
if ((words = read(fd, (char *) buf, Chunk)) == -1)
io_error("rewrite read");
while (words == Chunk) {
if (bufindex == Chunk / IntSize)
bufindex = 0;
buf[bufindex++]++;
if (lseek(fd, (off_t) - words, 1) == -1)
io_error("relative lseek(2)");
if (write(fd, (char *) buf, words) == -1)
io_error("re write(2)");
if ((words = read(fd, (char *) buf, Chunk)) == -1)
io_error("rwrite read");
}
if (close(fd) == -1)
io_error("close after rewrite");
get_delta_t(ReWrite);
fprintf(stderr, "...done FUNCTION
file_read_rewrite_block()n");
}
/****************************************************
*****************/
/* FUNCTION file_read_getc */
/****************************************************
*****************/
/* INPUT: does not receive any parameter */
/****************************************************
*****************/
/* PROCESS: */
/* 1. Open file */
/* 2. Initialize every position of the buffer words */
/* 3. Record timestamp */
/* 4. FOR cycle to fill the file 1 byte at a time until */
/* it reaches the EndOfFile(EOF).Make sure you notice
*/
/* the increment of the index pointing at chars */
/* 7. Close file */
/* 8. Call get_delta_t to find the performance of getc */
/****************************************************
*****************/
/* OUTPUT: doesn´t return any value because it is void
*/
/****************************************************
*****************/
static void file_read_getc()
{
fprintf(stderr, "FUNCTION fill_read_getc() start...");
newfile(name, &fd, &stream, 0);
for (words = 0; words < 256; words++)
chars[words] = 0;
timestamp();
for (words = 0; words < size; words++) {
if ((next = getc(stream)) == EOF)
io_error("getc(3)");
chars[next]++;
}
if (fclose(stream) == -1)
io_error("fclose after getc");
get_delta_t(Getc);
fprintf(stderr, "...done FUNCTION file_read_getc()n");
}
/****************************************************
*****************/
/* FUNCTION file_read_chunk */
/****************************************************
*****************/
/* INPUT: does not receive any parameter */
/****************************************************
*****************/
/* PROCESS: */
/* 1. Open file */
/* 2. Call lseek().(NOTE:Use man pages to view the
*/
/* specific */
/* parameters write uses. Make sure you understand the
*/
/* return values,and see the errors the function */
/* returns) */
/* 3. Record timestamp */
/* 6. DO cycle read a block.(NOTE: Use man pages to
view*/
/* the specific parameters read uses. Make sure you
*/
/* understand the return values, and see the errors the
*/
/* function returns) Call read until the while condition is
*/
/* false. */
/* 7. Close file */
/* 8. Call get_delta_t to find the performance of getc */
/****************************************************
*****************/
/* OUTPUT: doesn´t return any value because it is void
*/
/****************************************************
*****************/
static void file_read_chunk()
{
fprintf(stderr, "FUNCTION file_read_chunk() start...");
newfile(name, &fd, &stream, 0);
if (lseek(fd, (off_t) 0, 0) == -1)
io_error("lseek before read");
timestamp();
do {
if ((words = read(fd, (char *) buf, Chunk)) == -1)
io_error("read(2)");
chars[buf[abs(buf[0]) % (Chunk / IntSize)] & 0x7f]++;
} while (words);
if (close(fd) == -1)
io_error("close after read");
get_delta_t(FastRead);
fprintf(stderr, "...done FUNCTION file_read_chunk()n");
}
/****************************************************
*****************/
/* FUNCTION usage */
/****************************************************
*****************/
/* INPUT: does not receive any parameter */
/****************************************************
*****************/
/* PROCESS: */
/* 1. Presents all the options the program has */
/****************************************************
*****************/
/* OUTPUT: doesn´t return any value because it is void
*/
/****************************************************
*****************/
static void usage()
{
fprintf(stderr, "usage: ./lmp1 [-s size-in-Mb] [-m machine-
label]n");
exit(1);
}
/****************************************************
*****************/
/* FUNCTION timestamp */
/****************************************************
*****************/
/* INPUT: does not receive any parameter */
/****************************************************
*****************/
/* PROCESS: */
/* 1. Call time_so_far() and store it in last_timestamp */
/* 2. Call cpu_so_far() and store it in last_cpustamp */
/****************************************************
*****************/
/* OUTPUT: doesn´t return any value because it is void
*/
/****************************************************
*****************/
static void timestamp()
{
last_timestamp = time_so_far();
last_cpustamp = cpu_so_far();
}
/****************************************************
*****************/
/* FUNCTION get_delta_t */
/****************************************************
*****************/
/* INPUT: Receives the structure tests_t */
/****************************************************
*****************/
/* PROCESS: */
/* 1. Identifies the procedure that was executed */
/* 2. Calls time_so_far() and deletes the value of */
/* of the global variable last_timestamp obtaining the
time */
/* the procedure spent. */
/* 3. Calls cpu_so_far() and substracts the value of */
/* of the global variable last_cpustamp obtaining the
*/
/* amount of CPU procedure spent. */
/****************************************************
*****************/
/* OUTPUT: doesn´t return any value because it is void
*/
/****************************************************
*****************/
static void get_delta_t(test)
tests_t test;
{
int which = (int) test;
delta[which][Elapsed] = time_so_far() - last_timestamp;
delta[which][CPU] = cpu_so_far() - last_cpustamp;
}
/****************************************************
*****************/
/* FUNCTION cpu_so_far */
/****************************************************
*****************/
/* INPUT: does not receive any parameter */
/****************************************************
*****************/
/* PROCESS: */
/* 1. Identifies the System to check some variables */
/* if SysV */
/* i) Creates a structure tms. */
/* ii) returns the CPU time after adding over */
/* certain fields in the tms structure. */
/* Else */
/* i) Creates a structure rusage. */
/* ii) Calls getrusage().(NOTE: Use man pages */
/* to view the specific parameters write uses. */
/* Make sure you understand the return values, */
/* and see the errors the function returns). */
/* iii) returns the CPU time after adding over */
/* certain fields in the rusage structure. */
/****************************************************
*****************/
/* OUTPUT: return the CPU usage until the time it has been
called */
/****************************************************
*****************/
static double cpu_so_far()
{
#if defined(SysV)
struct tms tms;
if (times(&tms) == -1)
io_error("times");
return ((double) tms.tms_utime) / ((double)
sysconf(_SC_CLK_TCK)) +
((double) tms.tms_stime) / ((double)
sysconf(_SC_CLK_TCK));
#else
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
return ((double) rusage.ru_utime.tv_sec) +
(((double) rusage.ru_utime.tv_usec) / 1000000.0) +
((double) rusage.ru_stime.tv_sec) +
(((double) rusage.ru_stime.tv_usec) / 1000000.0);
#endif
}
/****************************************************
*****************/
/* FUNCTION time_so_far */
/****************************************************
*****************/
/* INPUT: does not receive any parameter */
/****************************************************
*****************/
/* PROCESS: */
/* 1. Identifies the System to check some variables */
/* if SysV */
/* i) Creates a structure tms. */
/* ii) Call the times function and assign the */
/* value it returns to the variable val */
/* iii) returns the CPU time after dividing val*/
/* by the returning value from sysconf() */
/* Else */
/* i) Creates a structure timeval tp. */
/* ii) Calls gettimeofday().(NOTE:Use man
pages*/
/* to view the specific parameters */
/* gettimeofday uses. Make sure you understand
*/
/* the return values, and see the errors the */
/* function returns). */
/* iii) returns the CPU time after substractin */
/* certain fields in the tp structure. */
/****************************************************
*****************/
/* OUTPUT: return the time it has been used */
/****************************************************
*****************/
static double time_so_far()
{
#if defined(SysV)
int val;
struct tms tms;
if ((val = times(&tms)) == -1)
io_error("times");
return ((double) val) / ((double) sysconf(_SC_CLK_TCK));
#else
struct timeval tp;
if (gettimeofday(&tp, (struct timezone *) NULL) == -1)
io_error("gettimeofday");
return ((double) (tp.tv_sec - basetime)) +
(((double) tp.tv_usec) / 1000000.0);
#endif
}
/****************************************************
*****************/
/* FUNCTION io_error */
/****************************************************
*****************/
/* INPUT: Receives the error string */
/****************************************************
*****************/
/* PROCESS: */
/* 1. Call perror().(NOTE:Use man pages to view the
*/
/* specific parameters gettimeofday uses. Make sure you
*/
/* understand the return values, and see the errors the
*/
/* function returns). */
/* 2. Call exit().(NOTE:Use man pages to view the
*/
/* specific parameters gettimeofday uses. Make sure you
*/
/* understand the return values, and see the errors the
*/
/* function returns). */
/****************************************************
*****************/
/* OUTPUT: return the time it has been used */
/****************************************************
*****************/
static void io_error(char *message)
{
char buf[Chunk];
sprintf(buf, "Program: drastic I/O error (%s)", message);
perror(buf);
exit(1);
}
/*
* Do a typical-of-something random I/O. Any serious
application that
* has a random I/O bottleneck is going to be smart enough to
operate
* in a page mode.
* The 'where' argument is used as a chunk number
* To keep the cache from getting too clever, some pages must
be updated.
* However an application that updated each of many random
pages that
* it looked at is hard to imagine.
* However, it would be wrong to put the update percentage in
as a
* parameter - the effect is too nonlinear.
*/
static void doseek(off_t where, int fd, int update)
{
int buf[Chunk / IntSize];
off_t probe;
off_t size;
probe = where * Chunk;
if (lseek(fd, probe, 0) != probe)
io_error("lseek in doseek");
if ((size = read(fd, (char *) buf, Chunk)) == -1)
io_error("read in doseek");
/* every so often, update a block */
if (update) { /* update this block */
/* touch a word */
buf[((int) random() % (size / IntSize - 2)) + 1]--;
if (lseek(fd, (long) probe, 0) != probe)
io_error("lseek in doseek update");
if (write(fd, (char *) buf, size) == -1)
io_error("write in doseek");
} /* update this block */
}
#if defined(SysV)
static char randseed[32];
static void srandom(int seed)
{
sprintf(randseed, "%06d", seed);
}
static long random()
{
return nrand48(randseed);
}
#endif
assign4-2/assign4_part1/testrunner.h
/*************** YOU SHOULD NOT MODIFY ANYTHING
IN THIS FILE ***************/
typedef int (*test_fp) (int, const char **);
typedef struct {
const char *name;
const char *suite;
test_fp test_function;
} testentry_t;
int run_testrunner(int argc, const char **argv, testentry_t *
entries,
int entry_count);
void set_testrunner_default_timeout(int s);
void set_testrunner_timeout(int s);
assign4-2/assign4_part1/teardown.sh
#!/bin/sh
#*************** YOU SHOULD NOT MODIFY ANYTHING
IN THIS FILE ***************
rm -rf ./testdata
assign4-2/assign4_part1/restart.h
/*************** YOU SHOULD NOT MODIFY ANYTHING
IN THIS FILE ***************/
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#ifndef ETIME
#define ETIME ETIMEDOUT
#endif
struct timeval add2currenttime(double seconds);
int copyfile(int fromfd, int tofd);
int r_close(int fildes);
int r_dup2(int fildes, int fildes2);
int r_open2(const char *path, int oflag);
int r_open3(const char *path, int oflag, mode_t mode);
ssize_t r_read(int fd, void *buf, size_t size);
pid_t r_wait(int *stat_loc);
pid_t r_waitpid(pid_t pid, int *stat_loc, int options);
ssize_t r_write(int fd, void *buf, size_t size);
ssize_t readblock(int fd, void *buf, size_t size);
int readline(int fd, char *buf, int nbytes);
ssize_t readtimed(int fd, void *buf, size_t nbyte, double
seconds);
int readwrite(int fromfd, int tofd);
int readwriteblock(int fromfd, int tofd, char *buf, int size);
int waitfdtimed(int fd, struct timeval end);
assign4-2/assign4_part1/util.h
/*************** YOU SHOULD NOT MODIFY ANYTHING
IN THIS FILE ***************/
#include <stdlib.h>
/* stdlib required for size_t */
#define quit_if_ne(p1,p2) {if((p1) != (p2))
quit_with_message((int)errno,"" #p1 "!=" #p2
,__FILE__,__LINE__);}
#define quit_if(mutley) {if(mutley)
quit_with_message((int)errno, #mutley,__FILE__,__LINE__);}
#define quit(mesg)
{quit_with_message((int)errno,mesg,__FILE__,__LINE__);}
void quit_with_message(int errn, char *mesg, char *src, int
line);
unsigned short checksum(char *buffer, size_t sz, unsigned short
val);
assign4-2/assign4_part1/fileio.h
#include <stdlib.h>
#define IOERR_INVALID_ARGS (-1)
#define IOERR_INVALID_PATH (-2)
#define IOERR_POSIX (-3)
#define IOERR_BUFFER_TOO_SMALL (-4)
#define IOERR_NOT_YET_IMPLEMENTED (-5)
/* You will implement all of the following functions in fileio.c.
*/
/*
ERROR HANDLING
These functions will support basic error handling:
If the arguments are bad (e.g., a pointer is NULL), then the
function should immediately return
IOERR_INVALID_ARGS.
If a POSIX error occurs, the function should return
IOERR_POSIX,
unless the error is due to a bad path, in which case the return
value is IOERR_INVALID_PATH.
These functions do not return if a POSIX function is
interrupted by
a signal; only dirlist returns IOERR_BUFFER_TOO_SMALL
(see below).
You may find some of the library functions in restart.c
useful.
COMMON PARAMETERS
path - file to be read
offest - where to start reading/writing from
buffer - buffer to write bytes into
bufbytes - maximum number of bytes to read
FUNCTION DESCRIPTIONS
int file_read(char *path, int offset, void *buffer, size_t
bufbytes);
Reads bytes from a file into the buffer.
Return value: >=0 number of bytes read, <0 ERROR (see
above)
int file_info(char *path, void *buffer, size_t bufbytes)
Writes into buffer a string that describes meta information
about
the file. The string is in format:
"Size:NNN Accessed:NNN Modified:NNN Type X"
X can be 'f' or 'd' (file or directory, respectively)
Size is in bytes
Accessed and Modified - accessed and modified times
(seconds since epoch)
int file_write(char *path, int offset, void *buffer, size_t
bufbytes);
Writes bytes from 'buffer' into file 'path' at position 'offset'.
Return value: >0 number of bytes written, <0 ERROR (see
above)
int file_create(char *path, char *pattern, int repeatcount);
Creates a new file with the string 'pattern' repeated
'repeatcount'
times.
Return value:0 Success , <0 ERROR (see above)
int file_remove(char *path);
Removes an existing file if it exists.
Return value: 0 file removed, <0 ERROR (see above)
int dir_create(char *path);
Creates a new directory.
Return value: 0 directory created, <0 ERROR (see above)
int dir_list(char *path, void *buffer, size_t bufbytes);
Writes a list file and directory names inside path (including
"."
and ".." entries). Each entry is line terminated with the
newline
character 'n'.
Return value: 0 success, <0 ERROR (see above)
Returns IOERR_BUFFER_TOO_SMALL if the buffer is not
large enough to
write all entries.
Hint: man opendir, readdir, closedir
int file_checksum(char *path)
Calculates a checksum value calculated by summing all the
bytes of a
file using an unsigned short.
Return value: >=0 checksum value, <0 ERROR (see above)
Hint: use the checksum function in util.c
int dir_checksum(char *path);
Recursively calculated a checksum: checksums of regular
files are
calculated using file_checksum; directory entries are
traversed,
also the subdirectory names are included in the checksum
calculation
See lmp1_tests.c for details of what we are looking for.
Return value: >=0 checksum value, <0 ERROR (see above)
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx
assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx

More Related Content

Similar to assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx

Sorting programs
Sorting programsSorting programs
Sorting programs
Varun Garg
 
Can you give an example of a binary heap programCan you give an .pdf
Can you give an example of a binary heap programCan you give an .pdfCan you give an example of a binary heap programCan you give an .pdf
Can you give an example of a binary heap programCan you give an .pdf
arorasales234
 
Input output functions
Input output functionsInput output functions
Input output functions
hyderali123
 
13. dynamic allocation
13. dynamic allocation13. dynamic allocation
13. dynamic allocation
웅식 전
 
Hacking Parse.y with ujihisa
Hacking Parse.y with ujihisaHacking Parse.y with ujihisa
Hacking Parse.y with ujihisa
ujihisa
 
__MACOSX._assign3assign3.DS_Store__MACOSXassign3._.D.docx
__MACOSX._assign3assign3.DS_Store__MACOSXassign3._.D.docx__MACOSX._assign3assign3.DS_Store__MACOSXassign3._.D.docx
__MACOSX._assign3assign3.DS_Store__MACOSXassign3._.D.docx
odiliagilby
 

Similar to assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx (20)

DMA.pptx
DMA.pptxDMA.pptx
DMA.pptx
 
Sorting programs
Sorting programsSorting programs
Sorting programs
 
Cpds lab
Cpds labCpds lab
Cpds lab
 
Lab Question
Lab QuestionLab Question
Lab Question
 
Потоки в перле изнутри
Потоки в перле изнутриПотоки в перле изнутри
Потоки в перле изнутри
 
C Exam Help
C Exam Help C Exam Help
C Exam Help
 
Can you give an example of a binary heap programCan you give an .pdf
Can you give an example of a binary heap programCan you give an .pdfCan you give an example of a binary heap programCan you give an .pdf
Can you give an example of a binary heap programCan you give an .pdf
 
Dynamic memory allocation
Dynamic memory allocationDynamic memory allocation
Dynamic memory allocation
 
C Homework Help
C Homework HelpC Homework Help
C Homework Help
 
Vcs29
Vcs29Vcs29
Vcs29
 
3. chapter ii
3. chapter ii3. chapter ii
3. chapter ii
 
Input output functions
Input output functionsInput output functions
Input output functions
 
QA Auotmation Java programs,theory
QA Auotmation Java programs,theory QA Auotmation Java programs,theory
QA Auotmation Java programs,theory
 
13. dynamic allocation
13. dynamic allocation13. dynamic allocation
13. dynamic allocation
 
Using standard libraries like stdio and sdtlib.h and using stats.h a.pdf
Using standard libraries like stdio and sdtlib.h and using stats.h a.pdfUsing standard libraries like stdio and sdtlib.h and using stats.h a.pdf
Using standard libraries like stdio and sdtlib.h and using stats.h a.pdf
 
Sysprog 13
Sysprog 13Sysprog 13
Sysprog 13
 
Pointers and Dynamic Memory Allocation
Pointers and Dynamic Memory AllocationPointers and Dynamic Memory Allocation
Pointers and Dynamic Memory Allocation
 
Cse115 lecture08repetitionstructures part02
Cse115 lecture08repetitionstructures part02Cse115 lecture08repetitionstructures part02
Cse115 lecture08repetitionstructures part02
 
Hacking Parse.y with ujihisa
Hacking Parse.y with ujihisaHacking Parse.y with ujihisa
Hacking Parse.y with ujihisa
 
__MACOSX._assign3assign3.DS_Store__MACOSXassign3._.D.docx
__MACOSX._assign3assign3.DS_Store__MACOSXassign3._.D.docx__MACOSX._assign3assign3.DS_Store__MACOSXassign3._.D.docx
__MACOSX._assign3assign3.DS_Store__MACOSXassign3._.D.docx
 

More from festockton

Learning ResourcesRequired ReadingsToseland, R. W., & Ri.docx
Learning ResourcesRequired ReadingsToseland, R. W., & Ri.docxLearning ResourcesRequired ReadingsToseland, R. W., & Ri.docx
Learning ResourcesRequired ReadingsToseland, R. W., & Ri.docx
festockton
 
Learning about Language by Observing and ListeningThe real.docx
Learning about Language by Observing and ListeningThe real.docxLearning about Language by Observing and ListeningThe real.docx
Learning about Language by Observing and ListeningThe real.docx
festockton
 
Learning about Language by Observing and ListeningThe real voy.docx
Learning about Language by Observing and ListeningThe real voy.docxLearning about Language by Observing and ListeningThe real voy.docx
Learning about Language by Observing and ListeningThe real voy.docx
festockton
 
LEARNING OUTCOMES1. Have knowledge and understanding of the pri.docx
LEARNING OUTCOMES1. Have knowledge and understanding of the pri.docxLEARNING OUTCOMES1. Have knowledge and understanding of the pri.docx
LEARNING OUTCOMES1. Have knowledge and understanding of the pri.docx
festockton
 
Leadership Style What do people do when they are leadingAssignme.docx
Leadership Style What do people do when they are leadingAssignme.docxLeadership Style What do people do when they are leadingAssignme.docx
Leadership Style What do people do when they are leadingAssignme.docx
festockton
 
Lawday. Court of Brightwaltham holden on Monday next after Ascension.docx
Lawday. Court of Brightwaltham holden on Monday next after Ascension.docxLawday. Court of Brightwaltham holden on Monday next after Ascension.docx
Lawday. Court of Brightwaltham holden on Monday next after Ascension.docx
festockton
 
law43665_fm_i-xx i 010719 1032 AMStakeholders, Eth.docx
law43665_fm_i-xx i 010719  1032 AMStakeholders, Eth.docxlaw43665_fm_i-xx i 010719  1032 AMStakeholders, Eth.docx
law43665_fm_i-xx i 010719 1032 AMStakeholders, Eth.docx
festockton
 

More from festockton (20)

Learning ResourcesRequired ReadingsToseland, R. W., & Ri.docx
Learning ResourcesRequired ReadingsToseland, R. W., & Ri.docxLearning ResourcesRequired ReadingsToseland, R. W., & Ri.docx
Learning ResourcesRequired ReadingsToseland, R. W., & Ri.docx
 
LeamosEscribamos Completa el párrafo con las formas correctas de lo.docx
LeamosEscribamos Completa el párrafo con las formas correctas de lo.docxLeamosEscribamos Completa el párrafo con las formas correctas de lo.docx
LeamosEscribamos Completa el párrafo con las formas correctas de lo.docx
 
Leadership via vision is necessary for success. Discuss in detail .docx
Leadership via vision is necessary for success. Discuss in detail .docxLeadership via vision is necessary for success. Discuss in detail .docx
Leadership via vision is necessary for success. Discuss in detail .docx
 
Learning about Language by Observing and ListeningThe real.docx
Learning about Language by Observing and ListeningThe real.docxLearning about Language by Observing and ListeningThe real.docx
Learning about Language by Observing and ListeningThe real.docx
 
Learning Accomplishment Profile-Diagnostic Spanish Language Edit.docx
Learning Accomplishment Profile-Diagnostic Spanish Language Edit.docxLearning Accomplishment Profile-Diagnostic Spanish Language Edit.docx
Learning Accomplishment Profile-Diagnostic Spanish Language Edit.docx
 
Learning about Language by Observing and ListeningThe real voy.docx
Learning about Language by Observing and ListeningThe real voy.docxLearning about Language by Observing and ListeningThe real voy.docx
Learning about Language by Observing and ListeningThe real voy.docx
 
LEARNING OUTCOMES1. Have knowledge and understanding of the pri.docx
LEARNING OUTCOMES1. Have knowledge and understanding of the pri.docxLEARNING OUTCOMES1. Have knowledge and understanding of the pri.docx
LEARNING OUTCOMES1. Have knowledge and understanding of the pri.docx
 
Leadership Style What do people do when they are leadingAssignme.docx
Leadership Style What do people do when they are leadingAssignme.docxLeadership Style What do people do when they are leadingAssignme.docx
Leadership Style What do people do when they are leadingAssignme.docx
 
Leadership Throughout HistoryHistory is filled with tales of leade.docx
Leadership Throughout HistoryHistory is filled with tales of leade.docxLeadership Throughout HistoryHistory is filled with tales of leade.docx
Leadership Throughout HistoryHistory is filled with tales of leade.docx
 
Lean Inventory Management1. Why do you think lean inventory manage.docx
Lean Inventory Management1. Why do you think lean inventory manage.docxLean Inventory Management1. Why do you think lean inventory manage.docx
Lean Inventory Management1. Why do you think lean inventory manage.docx
 
Leadership varies widely by culture and personality. An internationa.docx
Leadership varies widely by culture and personality. An internationa.docxLeadership varies widely by culture and personality. An internationa.docx
Leadership varies widely by culture and personality. An internationa.docx
 
Leadership is the ability to influence people toward the attainment .docx
Leadership is the ability to influence people toward the attainment .docxLeadership is the ability to influence people toward the attainment .docx
Leadership is the ability to influence people toward the attainment .docx
 
Lawday. Court of Brightwaltham holden on Monday next after Ascension.docx
Lawday. Court of Brightwaltham holden on Monday next after Ascension.docxLawday. Court of Brightwaltham holden on Monday next after Ascension.docx
Lawday. Court of Brightwaltham holden on Monday next after Ascension.docx
 
law43665_fm_i-xx i 010719 1032 AMStakeholders, Eth.docx
law43665_fm_i-xx i 010719  1032 AMStakeholders, Eth.docxlaw43665_fm_i-xx i 010719  1032 AMStakeholders, Eth.docx
law43665_fm_i-xx i 010719 1032 AMStakeholders, Eth.docx
 
Leaders face many hurdles when leading in multiple countries. There .docx
Leaders face many hurdles when leading in multiple countries. There .docxLeaders face many hurdles when leading in multiple countries. There .docx
Leaders face many hurdles when leading in multiple countries. There .docx
 
Last year Angelina Jolie had a double mastectomy because of re.docx
Last year Angelina Jolie had a double mastectomy because of re.docxLast year Angelina Jolie had a double mastectomy because of re.docx
Last year Angelina Jolie had a double mastectomy because of re.docx
 
Leaders face many hurdles when leading in multiple countries. Ther.docx
Leaders face many hurdles when leading in multiple countries. Ther.docxLeaders face many hurdles when leading in multiple countries. Ther.docx
Leaders face many hurdles when leading in multiple countries. Ther.docx
 
Leaders today must be able to create a compelling vision for the org.docx
Leaders today must be able to create a compelling vision for the org.docxLeaders today must be able to create a compelling vision for the org.docx
Leaders today must be able to create a compelling vision for the org.docx
 
Law enforcement professionals and investigators use digital fore.docx
Law enforcement professionals and investigators use digital fore.docxLaw enforcement professionals and investigators use digital fore.docx
Law enforcement professionals and investigators use digital fore.docx
 
LAW and Economics 4 questionsLaw And EconomicsTextsCoote.docx
LAW and Economics 4 questionsLaw And EconomicsTextsCoote.docxLAW and Economics 4 questionsLaw And EconomicsTextsCoote.docx
LAW and Economics 4 questionsLaw And EconomicsTextsCoote.docx
 

Recently uploaded

Transparency, Recognition and the role of eSealing - Ildiko Mazar and Koen No...
Transparency, Recognition and the role of eSealing - Ildiko Mazar and Koen No...Transparency, Recognition and the role of eSealing - Ildiko Mazar and Koen No...
Transparency, Recognition and the role of eSealing - Ildiko Mazar and Koen No...
EADTU
 

Recently uploaded (20)

OSCM Unit 2_Operations Processes & Systems
OSCM Unit 2_Operations Processes & SystemsOSCM Unit 2_Operations Processes & Systems
OSCM Unit 2_Operations Processes & Systems
 
Diuretic, Hypoglycemic and Limit test of Heavy metals and Arsenic.-1.pdf
Diuretic, Hypoglycemic and Limit test of Heavy metals and Arsenic.-1.pdfDiuretic, Hypoglycemic and Limit test of Heavy metals and Arsenic.-1.pdf
Diuretic, Hypoglycemic and Limit test of Heavy metals and Arsenic.-1.pdf
 
Introduction to TechSoup’s Digital Marketing Services and Use Cases
Introduction to TechSoup’s Digital Marketing  Services and Use CasesIntroduction to TechSoup’s Digital Marketing  Services and Use Cases
Introduction to TechSoup’s Digital Marketing Services and Use Cases
 
80 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÀNH PHỐ HỒ CHÍ MINH NĂ...
80 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÀNH PHỐ HỒ CHÍ MINH NĂ...80 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÀNH PHỐ HỒ CHÍ MINH NĂ...
80 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÀNH PHỐ HỒ CHÍ MINH NĂ...
 
TỔNG HỢP HƠN 100 ĐỀ THI THỬ TỐT NGHIỆP THPT TOÁN 2024 - TỪ CÁC TRƯỜNG, TRƯỜNG...
TỔNG HỢP HƠN 100 ĐỀ THI THỬ TỐT NGHIỆP THPT TOÁN 2024 - TỪ CÁC TRƯỜNG, TRƯỜNG...TỔNG HỢP HƠN 100 ĐỀ THI THỬ TỐT NGHIỆP THPT TOÁN 2024 - TỪ CÁC TRƯỜNG, TRƯỜNG...
TỔNG HỢP HƠN 100 ĐỀ THI THỬ TỐT NGHIỆP THPT TOÁN 2024 - TỪ CÁC TRƯỜNG, TRƯỜNG...
 
COMMUNICATING NEGATIVE NEWS - APPROACHES .pptx
COMMUNICATING NEGATIVE NEWS - APPROACHES .pptxCOMMUNICATING NEGATIVE NEWS - APPROACHES .pptx
COMMUNICATING NEGATIVE NEWS - APPROACHES .pptx
 
FSB Advising Checklist - Orientation 2024
FSB Advising Checklist - Orientation 2024FSB Advising Checklist - Orientation 2024
FSB Advising Checklist - Orientation 2024
 
Details on CBSE Compartment Exam.pptx1111
Details on CBSE Compartment Exam.pptx1111Details on CBSE Compartment Exam.pptx1111
Details on CBSE Compartment Exam.pptx1111
 
AIM of Education-Teachers Training-2024.ppt
AIM of Education-Teachers Training-2024.pptAIM of Education-Teachers Training-2024.ppt
AIM of Education-Teachers Training-2024.ppt
 
Tatlong Kwento ni Lola basyang-1.pdf arts
Tatlong Kwento ni Lola basyang-1.pdf artsTatlong Kwento ni Lola basyang-1.pdf arts
Tatlong Kwento ni Lola basyang-1.pdf arts
 
Andreas Schleicher presents at the launch of What does child empowerment mean...
Andreas Schleicher presents at the launch of What does child empowerment mean...Andreas Schleicher presents at the launch of What does child empowerment mean...
Andreas Schleicher presents at the launch of What does child empowerment mean...
 
Wellbeing inclusion and digital dystopias.pptx
Wellbeing inclusion and digital dystopias.pptxWellbeing inclusion and digital dystopias.pptx
Wellbeing inclusion and digital dystopias.pptx
 
When Quality Assurance Meets Innovation in Higher Education - Report launch w...
When Quality Assurance Meets Innovation in Higher Education - Report launch w...When Quality Assurance Meets Innovation in Higher Education - Report launch w...
When Quality Assurance Meets Innovation in Higher Education - Report launch w...
 
diagnosting testing bsc 2nd sem.pptx....
diagnosting testing bsc 2nd sem.pptx....diagnosting testing bsc 2nd sem.pptx....
diagnosting testing bsc 2nd sem.pptx....
 
Michaelis Menten Equation and Estimation Of Vmax and Tmax.pptx
Michaelis Menten Equation and Estimation Of Vmax and Tmax.pptxMichaelis Menten Equation and Estimation Of Vmax and Tmax.pptx
Michaelis Menten Equation and Estimation Of Vmax and Tmax.pptx
 
How to setup Pycharm environment for Odoo 17.pptx
How to setup Pycharm environment for Odoo 17.pptxHow to setup Pycharm environment for Odoo 17.pptx
How to setup Pycharm environment for Odoo 17.pptx
 
Understanding Accommodations and Modifications
Understanding  Accommodations and ModificationsUnderstanding  Accommodations and Modifications
Understanding Accommodations and Modifications
 
Observing-Correct-Grammar-in-Making-Definitions.pptx
Observing-Correct-Grammar-in-Making-Definitions.pptxObserving-Correct-Grammar-in-Making-Definitions.pptx
Observing-Correct-Grammar-in-Making-Definitions.pptx
 
Transparency, Recognition and the role of eSealing - Ildiko Mazar and Koen No...
Transparency, Recognition and the role of eSealing - Ildiko Mazar and Koen No...Transparency, Recognition and the role of eSealing - Ildiko Mazar and Koen No...
Transparency, Recognition and the role of eSealing - Ildiko Mazar and Koen No...
 
PANDITA RAMABAI- Indian political thought GENDER.pptx
PANDITA RAMABAI- Indian political thought GENDER.pptxPANDITA RAMABAI- Indian political thought GENDER.pptx
PANDITA RAMABAI- Indian political thought GENDER.pptx
 

assign4-2.DS_Storeassign4-2assign4_part2mymem.h#include.docx

  • 1. assign4-2/.DS_Store assign4-2/assign4_part2/mymem.h #include <stddef.h> typedef enum strategies_enum { NotSet = 0, Best = 1, Worst = 2, First = 3, Next = 4 } strategies; char *strategy_name(strategies strategy); strategies strategyFromString(char * strategy);
  • 2. void initmem(strategies strategy, size_t sz); void *mymalloc(size_t requested); void myfree(void* block); int mem_holes(); int mem_allocated(); int mem_free(); int mem_total(); int mem_largest_free(); int mem_small_free(int size); char mem_is_alloc(void *ptr); void* mem_pool(); void print_memory(); void print_memory_status(); void try_mymem(int argc, char **argv); assign4-2/assign4_part2/memorytests.c #include <errno.h> #include <stdlib.h>
  • 3. #include <string.h> #include <stdio.h> #include <assert.h> #include <time.h> #include <unistd.h> #include "mymem.h" #include "testrunner.h" /* performs a randomized test: totalSize == the total size of the memory pool, as passed to initmem2 totalSize must be less than 10,000 * minBlockSize fillRatio == when the allocated memory is >= fillRatio * totalSize, a block is freed; otherwise, a new block is allocated. If a block cannot be allocated, this is tallied and a random block is freed immediately thereafter in the next iteration minBlockSize, maxBlockSize == size for allocated blocks
  • 4. is picked uniformly at random between these two numbers, inclusive */ void do_randomized_test(int strategyToUse, int totalSize, float fillRatio, int minBlockSize, int maxBlockSize, int iterations) { void * pointers[10000]; int storedPointers = 0; int strategy; int lbound = 1; int ubound = 4; int smallBlockSize = maxBlockSize/10; if (strategyToUse>0) lbound=ubound=strategyToUse; FILE *log; log = fopen("tests.log","a"); if(log == NULL) {
  • 5. perror("Can't append to log file.n"); return; } fprintf(log,"Running randomized tests: pool size == %d, fill ratio == %f, block size is from %d to %d, %d iterationsn",totalSize,fillRatio,minBlockSize,maxBlockSize,iter ations); fclose(log); for (strategy = lbound; strategy <= ubound; strategy++) { double sum_largest_free = 0; double sum_hole_size = 0; double sum_allocated = 0; int failed_allocations = 0; double sum_small = 0; struct timespec execstart, execend; int force_free = 0;
  • 6. int i; storedPointers = 0; initmem(strategy,totalSize); clock_gettime(CLOCK_REALTIME, &execstart); for (i = 0; i < iterations; i++) { if ( (i % 10000)==0 ) srand ( time(NULL) ); if (!force_free && (mem_free() > (totalSize * (1-fillRatio)))) { int newBlockSize = (rand()%(maxBlockSize-minBlockSize+1))+minBlockSize; /* allocate */ void * pointer = mymalloc(newBlockSize); if (pointer != NULL)
  • 7. pointers[storedPointers++] = pointer; else { failed_allocations++; force_free = 1; } } else { int chosen; void * pointer; /* free */ force_free = 0; if (storedPointers == 0) continue;
  • 8. chosen = rand() % storedPointers; pointer = pointers[chosen]; pointers[chosen] = pointers[storedPointers- 1]; storedPointers--; myfree(pointer); } sum_largest_free += mem_largest_free(); sum_hole_size += (mem_free() / mem_holes()); sum_allocated += mem_allocated(); sum_small += mem_small_free(smallBlockSize); } clock_gettime(CLOCK_REALTIME, &execend);
  • 9. log = fopen("tests.log","a"); if(log == NULL) { perror("Can't append to log file.n"); return; } fprintf(log,"t=== %s ===n",strategy_name(strategy)); fprintf(log,"tTest took %.2fms.n", (execend.tv_sec - execstart.tv_sec) * 1000 + (execend.tv_nsec - execstart.tv_nsec) / 1000000.0); fprintf(log,"tAverage hole size: %fn",sum_hole_size/iterations); fprintf(log,"tAverage largest free block: %fn",sum_largest_free/iterations); fprintf(log,"tAverage allocated bytes: %fn",sum_allocated/iterations); fprintf(log,"tAverage number of small blocks: %fn",sum_small/iterations); fprintf(log,"tFailed allocations: %dn",failed_allocations); fclose(log);
  • 10. } } /* run randomized tests against the various strategies with various parameters */ int do_stress_tests(int argc, char **argv) { int strategy = strategyFromString(*(argv+1)); unlink("tests.log"); // We want a new log file do_randomized_test(strategy,10000,0.25,1,1000,10000); do_randomized_test(strategy,10000,0.25,1,2000,10000); do_randomized_test(strategy,10000,0.25,1000,2000,10000) ; do_randomized_test(strategy,10000,0.25,1,3000,10000); do_randomized_test(strategy,10000,0.25,1,4000,10000);
  • 11. do_randomized_test(strategy,10000,0.25,1,5000,10000); do_randomized_test(strategy,10000,0.5,1,1000,10000); do_randomized_test(strategy,10000,0.5,1,2000,10000); do_randomized_test(strategy,10000,0.5,1000,2000,10000); do_randomized_test(strategy,10000,0.5,1,3000,10000); do_randomized_test(strategy,10000,0.5,1,4000,10000); do_randomized_test(strategy,10000,0.5,1,5000,10000); do_randomized_test(strategy,10000,0.5,1000,1000,10000); /* watch what happens with this test!...why? */ do_randomized_test(strategy,10000,0.75,1,1000,10000); do_randomized_test(strategy,10000,0.75,500,1000,10000); do_randomized_test(strategy,10000,0.75,1,2000,10000); do_randomized_test(strategy,10000,0.9,1,500,10000); return 0; /* you nominally pass for surviving without
  • 12. segfaulting */ } /* basic sequential allocation of single byte blocks */ int test_alloc_1(int argc, char **argv) { strategies strategy; int lbound = 1; int ubound = 4; if (strategyFromString(*(argv+1))>0) lbound=ubound=strategyFromString(*(argv+1)); for (strategy = lbound; strategy <= ubound; strategy++) { int correct_holes = 0; int correct_alloc = 100; int correct_largest_free = 0; int i;
  • 13. void* lastPointer = NULL; initmem(strategy,100); for (i = 0; i < 100; i++) { void* pointer = mymalloc(1); if ( i > 0 && pointer != (lastPointer+1) ) { printf("Allocation with %s was not sequential at %i; expected %p, actual %pn", strategy_name(strategy), i,lastPointer+1,pointer); return 1; } lastPointer = pointer; } if (mem_holes() != correct_holes) { printf("Holes not counted as %d with %sn", correct_holes, strategy_name(strategy));
  • 14. return 1; } if (mem_allocated() != correct_alloc) { printf("Allocated memory not reported as %d with %sn", correct_alloc, strategy_name(strategy)); return 1; } if (mem_largest_free() != correct_largest_free) { printf("Largest memory block free not reported as %d with %sn", correct_largest_free, strategy_name(strategy)); return 1; } }
  • 15. return 0; } /* alloc, alloc, free, alloc */ int test_alloc_2(int argc, char **argv) { strategies strategy; int lbound = 1; int ubound = 4; if (strategyFromString(*(argv+1))>0) lbound=ubound=strategyFromString(*(argv+1)); for (strategy = lbound; strategy <= ubound; strategy++) { int correct_holes; int correct_alloc;
  • 16. int correct_largest_free; int correct_small; void* first; void* second; void* third; int correctThird; initmem(strategy,100); first = mymalloc(10); second = mymalloc(1); myfree(first); third = mymalloc(1); if (second != (first+10)) { printf("Second allocation failed; allocated at incorrect offset with strategy %s", strategy_name(strategy)); return 1;
  • 17. } correct_alloc = 2; correct_small = (strategy == First || strategy == Best); switch (strategy) { case Best: correctThird = (third == first); correct_holes = 2; correct_largest_free = 89; break; case Worst: correctThird = (third == second+1); correct_holes = 2; correct_largest_free = 88; break; case First:
  • 18. correctThird = (third == first); correct_holes = 2; correct_largest_free = 89; break; case Next: correctThird = (third == second+1); correct_holes = 2; correct_largest_free = 88; break; case NotSet: break; } if (!correctThird) { printf("Third allocation failed; allocated at incorrect offset with %s", strategy_name(strategy)); return 1;
  • 19. } if (mem_holes() != correct_holes) { printf("Holes counted as %d, should be %d with %sn", mem_holes(), correct_holes, strategy_name(strategy)); return 1; } if (mem_small_free(9) != correct_small) { printf("Small holes counted as %d, should be %d with %sn", mem_small_free(9), correct_small, strategy_name(strategy)); return 1; } if (mem_allocated() != correct_alloc) { printf("Memory reported as %d, should be %d
  • 20. with %sn", mem_allocated(0), correct_alloc, strategy_name(strategy)); return 1; } if (mem_largest_free() != correct_largest_free) { printf("Largest memory block free reported as %d, should be %d with %sn", mem_largest_free(), correct_largest_free, strategy_name(strategy)); return 1; } } return 0; } /* basic sequential allocation followed by 50 frees */
  • 21. int test_alloc_3(int argc, char **argv) { strategies strategy; int lbound = 1; int ubound = 4; if (strategyFromString(*(argv+1))>0) lbound=ubound=strategyFromString(*(argv+1)); for (strategy = lbound; strategy <= ubound; strategy++) { int correct_holes = 50; int correct_alloc = 50; int correct_largest_free = 1; int i; void* lastPointer = NULL; initmem(strategy,100); for (i = 0; i < 100; i++)
  • 22. { void* pointer = mymalloc(1); if ( i > 0 && pointer != (lastPointer+1) ) { printf("Allocation with %s was not sequential at %i; expected %p, actual %pn", strategy_name(strategy), i,lastPointer+1,pointer); return 1; } lastPointer = pointer; } for (i = 1; i < 100; i+= 2) { myfree(mem_pool() + i); } if (mem_holes() != correct_holes) {
  • 23. printf("Holes not counted as %d with %sn", correct_holes, strategy_name(strategy)); return 1; } if (mem_allocated() != correct_alloc) { printf("Memory not reported as %d with %sn", correct_alloc, strategy_name(strategy)); return 1; } if (mem_largest_free() != correct_largest_free) { printf("Largest memory block free not reported as %d with %sn", correct_largest_free, strategy_name(strategy)); return 1; }
  • 24. for(i=0;i<100;i++) { if(mem_is_alloc(mem_pool()+i) == i%2) { printf("Byte %d in memory claims to ",i); if(i%2) printf("not "); printf("be allocated. It should "); if(!i%2) printf("not "); printf("be allocated.n"); return 1; } } } return 0; }
  • 25. /* basic sequential allocation followed by 50 frees, then another 50 allocs */ int test_alloc_4(int argc, char **argv) { strategies strategy; int lbound = 1; int ubound = 4; if (strategyFromString(*(argv+1))>0) lbound=ubound=strategyFromString(*(argv+1)); for (strategy = lbound; strategy <= ubound; strategy++) { int correct_holes = 0; int correct_alloc = 100; int correct_largest_free = 0; int i; void* lastPointer = NULL;
  • 26. initmem(strategy,100); for (i = 0; i < 100; i++) { void* pointer = mymalloc(1); if ( i > 0 && pointer != (lastPointer+1) ) { printf("Allocation with %s was not sequential at %i; expected %p, actual %pn", strategy_name(strategy), i,lastPointer+1,pointer); return 1; } lastPointer = pointer; } for (i = 1; i < 100; i+= 2) { myfree(mem_pool() + i); }
  • 27. for (i = 1; i < 100; i+=2) { void* pointer = mymalloc(1); if ( i > 1 && pointer != (lastPointer+2) ) { printf("Second allocation with %s was not sequential at %i; expected %p, actual %pn", strategy_name(strategy), i,lastPointer+1,pointer); return 1; } lastPointer = pointer; } if (mem_holes() != correct_holes) { printf("Holes not counted as %d with %sn", correct_holes, strategy_name(strategy)); return 1; }
  • 28. if (mem_allocated() != correct_alloc) { printf("Memory not reported as %d with %sn", correct_alloc, strategy_name(strategy)); return 1; } if (mem_largest_free() != correct_largest_free) { printf("Largest memory block free not reported as %d with %sn", correct_largest_free, strategy_name(strategy)); return 1; } } return 0; }
  • 29. int run_memory_tests(int argc, char **argv) { if (argc < 3) { printf("Usage: mem -test <test> <strategy> n"); return 0; } set_testrunner_default_timeout(20); /* Tests can be invoked by matching their name or their suite name or 'all'*/ testentry_t tests[] = { {"alloc1","suite1",test_alloc_1}, {"alloc2","suite2",test_alloc_2}, {"alloc3","suite1",test_alloc_3}, {"alloc4","suite2",test_alloc_4}, {"stress","suite3",do_stress_tests}, };
  • 30. return run_testrunner(argc,argv,tests,sizeof(tests)/sizeof(testentry_t)); } int main(int argc, char **argv) { if( argc < 2) { printf("Usage: mem -test <test> <strategy> | mem -try <arg1> <arg2> ... n"); exit(-1); } else if (!strcmp(argv[1],"-test")) return run_memory_tests(argc-1,argv+1); else if (!strcmp(argv[1],"-try")) { try_mymem(argc-1,argv+1); return 0; } else { printf("Usage: mem -test <test> <strategy> | mem -try <arg1>
  • 31. <arg2> ... n"); exit(-1); } } assign4-2/assign4_part2/testrunner.h typedef int (*test_fp) (int, char **); typedef struct { char *name; char *suite; test_fp test_function; } testentry_t; int run_testrunner(int argc, char **argv, testentry_t *entries,int entry_count); void set_testrunner_default_timeout(int s); void set_testrunner_timeout(int s); assign4-2/assign4_part2/README.txt LMP2: Memory Management ======================= This machine problem will focus on memory. You will implement your own
  • 32. version of malloc() and free(), using a variety of allocation strategies. You will be implementing a memory manager for a block of memory. You will implement routines for allocating and deallocating memory, and keeping track of what memory is in use. You will implement four strategies for selecting in which block to place a new requested memory black: 1) First-fit: select the first suitable block with smallest address. 2) Best-fit: select the smallest suitable block. 3) Worst-fit: select the largest suitable block. 4) Next-fit: select the first suitable block after the last block allocated (with wraparound from end to beginning). Here, "suitable" means "free, and large enough to fit the new data". Here are the functions you will need to implement: initmem(): Initialize memory structures. mymalloc(): Like malloc(), this allocates a new block of memory. myfree(): Like free(), this deallocates a block of memory. mem_holes(): How many free blocks are in memory?
  • 33. mem_allocated(): How much memory is currently allocated? mem_free(): How much memory is NOT allocated? mem_largest_free(): How large is the largest free block? mem_small_free(): How many small unallocated blocks are currently in memory? mem_is_alloc(): Is a particular byte allocated or not? We have given you a structure to use to implement these functions. It is a doubly-linked list of blocks in memory (both allocated and free blocks). Every malloc and free can create new blocks, or combine existing blocks. You may modify this structure, or even use a different one entirely. However, do not change function prototypes or files other than mymem.c. IMPORTANT NOTE: Regardless of how you implement memory management, make sure that there are no adjacent free blocks. Any such blocks should be merged into one large block. We have also given you a few functions to help you monitor what happens when you call your functions. Most important is the try_mymem() function. If you run
  • 34. your code with "mem -try <args>", it will call this function, which you can use to demonstrate the effects of your memory operations. These functions have no effect on test code, so use them to your advantage. Running your code: After running "make", run 1) "mem" to see the available tests and strategies. 2) "mem -test <test> <strategy>" to test your code with our tests. 3) "mem -try <args>" to run your code with your own tests (the try_mymem function). You can also use "make test" and "make stage1-test" for testing. "make stage1-test" only runs the tests relevant to stage 1. As in previous MPs, running "mem -test -f0 ..." will allow tests to run even after previous tests have failed. Similarly, using "all" for a test or strategy name runs all of the tests or strategies. Note that if "all" is selected as the strategy, the 4 tests are shown as one. One of the tests, "stress", runs an assortment of randomized tests on each strategy. The results of the tests are placed in "tests.out" . You may want to view this file to see the relative performance of each strategy. Stage 1
  • 35. ------- Implement all the above functions, for the first-fit strategy. Use "mem -test all first" to test your implementation. Stage 2 ------- A) Implement the other three strategies: worst-fit, best-fit, and next-fit. The strategy is passed to initmem(), and stored in the global variable "myStrategy". Some of your functions will need to check this variable to implement the correct strategy. You can test your code with "mem -test all worst", etc., or test all 4 together with "mem -test all all". The latter command does not test the strategies separately; your code passes the test only if all four strategies pass. Questions ========= 1) Why is it so important that adjacent free blocks not be left as such? What would happen if they were permitted? 2) Which function(s) need to be concerned about adjacent free blocks?
  • 36. 3) Name one advantage of each strategy. 4) Run the stress test on all strategies, and look at the results (tests.out). What is the significance of "Average largest free block"? Which strategy generally has the best performance in this metric? Why do you think this is? 5) In the stress test results (see Question 4), what is the significance of "Average number of small blocks"? Which strategy generally has the best performance in this metric? Why do you think this is? 6) Eventually, the many mallocs and frees produces many small blocks scattered across the memory pool. There may be enough space to allocate a new block, but not in one place. It is possible to compact the memory, so all the free blocks are moved to one large free block. How would you implement this in the system you have built? 7) If you did implement memory compaction, what changes would you need to make in how such a system is invoked (i.e. from a user's perspective)? 8) How would you use the system you have built to implement realloc? (Brief explanation; no code) 9) Which function(s) need to know which strategy is being used? Briefly explain why this/these and not others.
  • 37. 10) Give one advantage of implementing memory management using a linked list over a bit array, where every bit tells whether its corresponding byte is allocated. assign4-2/assign4_part2/mymem.c #include <stdlib.h> #include <string.h> #include <stdio.h> #include <assert.h> #include "mymem.h" #include <time.h> /* The main structure for implementing memory allocation. * You may change this to fit your implementation. */ struct memoryList
  • 38. { // doubly-linked list struct memoryList *last; struct memoryList *next; int size; // How many bytes in this block? char alloc; // 1 if this block is allocated, // 0 if this block is free. void *ptr; // location of block in memory pool. }; strategies myStrategy = NotSet; // Current strategy size_t mySize; void *myMemory = NULL; static struct memoryList *head;
  • 39. static struct memoryList *next; /* initmem must be called prior to mymalloc and myfree. initmem may be called more than once in a given exeuction; when this occurs, all memory you previously malloc'ed *must* be freed, including any existing bookkeeping data. strategy must be one of the following: - "best" (best-fit) - "worst" (worst-fit) - "first" (first-fit) - "next" (next-fit) sz specifies the number of bytes that will be available, in total, for all mymalloc requests. */
  • 40. void initmem(strategies strategy, size_t sz) { myStrategy = strategy; /* all implementations will need an actual block of memory to use */ mySize = sz; if (myMemory != NULL) free(myMemory); /* in case this is not the first time initmem2 is called */ /* TODO: release any other memory you were using for bookkeeping when doing a re-initialization! */ myMemory = malloc(sz); /* TODO: Initialize memory management structure. */
  • 41. } /* Allocate a block of memory with the requested size. * If the requested block is not available, mymalloc returns NULL. * Otherwise, it returns a pointer to the newly allocated block. * Restriction: requested >= 1 */ void *mymalloc(size_t requested) { assert((int)myStrategy > 0); switch (myStrategy) { case NotSet: return NULL; case First:
  • 42. return NULL; case Best: return NULL; case Worst: return NULL; case Next: return NULL; } return NULL; } /* Frees a block of memory previously allocated by mymalloc. */ void myfree(void* block) { return; }
  • 43. /****** Memory status/property functions ****** * Implement these functions. * Note that when we refer to "memory" here, we mean the * memory pool this module manages via initmem/mymalloc/myfree. */ /* Get the number of contiguous areas of free space in memory. */ int mem_holes() { return 0; } /* Get the number of bytes allocated */ int mem_allocated() { return 0; }
  • 44. /* Number of non-allocated bytes */ int mem_free() { return 0; } /* Number of bytes in the largest contiguous area of unallocated memory */ int mem_largest_free() { return 0; } /* Number of free blocks smaller than "size" bytes. */ int mem_small_free(int size) { return 0;
  • 45. } char mem_is_alloc(void *ptr) { return 0; } /* * Feel free to use these functions, but do not modify them. * The test code uses them, but you may ind them useful. */ //Returns a pointer to the memory pool. void *mem_pool() { return myMemory; }
  • 46. // Returns the total number of bytes in the memory pool. */ int mem_total() { return mySize; } // Get string name for a strategy. char *strategy_name(strategies strategy) { switch (strategy) { case Best: return "best"; case Worst: return "worst"; case First:
  • 47. return "first"; case Next: return "next"; default: return "unknown"; } } // Get strategy from name. strategies strategyFromString(char * strategy) { if (!strcmp(strategy,"best")) { return Best; } else if (!strcmp(strategy,"worst")) { return Worst;
  • 48. } else if (!strcmp(strategy,"first")) { return First; } else if (!strcmp(strategy,"next")) { return Next; } else { return 0; } } /* * These functions are for you to modify however you see fit. These will not
  • 49. * be used in tests, but you may find them useful for debugging. */ /* Use this function to print out the current contents of memory. */ void print_memory() { return; } /* Use this function to track memory allocation performance. * This function does not depend on your implementation, * but on the functions you wrote above. */ void print_memory_status() { printf("%d out of %d bytes allocated.n",mem_allocated(),mem_total()); printf("%d bytes are free in %d holes; maximum
  • 50. allocatable block is %d bytes.n",mem_free(),mem_holes(),mem_largest_free()); printf("Average hole size is %f.nn",((float)mem_free())/mem_holes()); } /* Use this function to see what happens when your malloc and free * implementations are called. Run "mem -try <args>" to call this function. * We have given you a simple example to start. */ void try_mymem(int argc, char **argv) { strategies strat; void *a, *b, *c, *d, *e; if(argc > 1) strat = strategyFromString(argv[1]); else strat = First;
  • 51. /* A simple example. Each algorithm should produce a different layout. */ initmem(strat,500); a = mymalloc(100); b = mymalloc(100); c = mymalloc(100); myfree(b); d = mymalloc(50); myfree(a); e = mymalloc(25); print_memory(); print_memory_status(); }
  • 52. assign4-2/assign4_part2/testrunner.c /* A simple testrunner framework Original Author: L. Angrave */ #include <sys/types.h> #include <sys/wait.h> #include <errno.h> #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <unistd.h> #include "testrunner.h" #include "mymem.h"
  • 53. /* Constants */ #define false (0) #define true (1) #define test_killed (2) /* defaults */ static int default_timeout_seconds=5; static int timeout_seconds; void set_testrunner_default_timeout(int s) { assert(s>0); default_timeout_seconds=s; } void set_testrunner_timeout(int s) { assert(s>0); timeout_seconds=s; }
  • 54. /* --- Helper macros and functions --- */ #define DIE(mesg) {fprintf(stderr,"n%s(%d):%sn",__fname__,__LINE__,mesg); exit(1);} static int eql( char*s1, char*s2) {return s1&&s2&&!strcmp(s1,s2);} /* Callback function for qsort on strings */ static int mystrcmp( const void *p1, const void *p2) { return eql( ( char*)p1, ( char*)p2); } /* Stats of all tests run so far */ typedef struct { int ran, passed, failed; } stats_t;
  • 55. /* -- Signal handlers -- */ static pid_t child_pid; static int sent_child_timeout_kill_signal; static void kill_child_signal_handler(intsigno) { if(!child_pid) return; char m[]="-Timeout(Killing test process)-"; write(0,m,sizeof(m)-1); kill(child_pid,SIGKILL); sent_child_timeout_kill_signal=1; } /* Internal function to run a test as a forked child. The child process is terminated if it runs for more than a few seconds */ static int invoke_test_with_timelimit(testentry_t* test, int redirect_stdouterr,int argc, char **argv) {
  • 56. char fname[255]; int wait_status; pid_t wait_val; struct sigaction action; assert(!child_pid); assert(test && test->test_function && test->name); set_testrunner_timeout(default_timeout_seconds); errno=0; child_pid = fork (); if (child_pid == -1) { fprintf(stderr,"-fork failed so running test inline-"); return test->test_function (argc, argv); }
  • 57. if (child_pid == 0) { if(redirect_stdouterr) { snprintf(fname,(int)sizeof(fname),"stdout- %s.txt",test->name); fname[sizeof(fname)-1]=0; freopen(fname, "w", stdout); memcpy(fname+3,"err",3); freopen(fname, "w", stderr); } exit(test->test_function(argc,argv)); }else { wait_status=-1; sigemptyset(&action.sa_mask); action.sa_handler=kill_child_signal_handler; sigaction(SIGALRM,&action,NULL);
  • 58. sent_child_timeout_kill_signal=0; alarm(timeout_seconds); wait_val = waitpid (child_pid, &wait_status, 0); int child_exited_normally= WIFEXITED (wait_status); int child_exit_value=WEXITSTATUS (wait_status); int child_term_by_signal=WIFSIGNALED(wait_status); int child_term_signal=WTERMSIG(wait_status); if(child_term_by_signal) { fprintf(stderr,"testrunner:Test terminated by signal %dn",child_term_signal); fprintf(stderr,"testrunner:waitpid returned %d (child_pid=%d,wait_status=%d)",wait_val,child_pid,wait_status ); } if(child_pid != wait_val)
  • 59. fprintf(stderr,"testrunner: strange... wait_val != child_pidn"); int passed= (child_pid == wait_val) && (child_exit_value==0) && (child_exited_normally!=0); alarm(0); kill(child_pid,SIGKILL); child_pid=0; return sent_child_timeout_kill_signal ? test_killed : passed ? 0 : 1; } } /* * run a test and update the stats. The main guts of this functionality is provided by invoke_test_with_timelimit * This outer wrapper updates thes output and statistics before and after running the test.
  • 60. */ static int run_one_test (stats_t * stats, testentry_t * test, int redirect_stdouterr,int argc, char **argv) { int test_result; assert (stats && test->name && argc > 0 && argv && *argv); stats->ran++; stats->failed++; printf ("%2d.%-20s:", stats->ran, test->name); fflush(stdout); test_result=invoke_test_with_timelimit(test,redirect_stdout err,argc,argv);
  • 61. if (test_result == 0) { stats->failed--; stats->passed++; } printf(":%sn", (test_result == 0 ? "pass" : test_result == 2 ? "TIMEOUT * " : "FAIL *")); return test_result!=0; } /* Help functionality to print out sorted list of test names and suite names */ static void print_targets(testentry_t tests[], int count) { char**array; char *previous; int i; array=(char**)calloc(sizeof(char*),count);
  • 62. /* Sort the test names and print unique entries*/ for(i=0;i<count;i++) array[i]=tests[i].name; qsort(array,count,sizeof(array[0]),mystrcmp); printf("nValid tests : all"); for(i=0,previous="";i<count; i++) if(!eql(previous,array[i])) printf(" %s",(previous=array[i])); /* Sort the suite names and print unique entries*/ for(i=0;i<count;i++) array[i]=tests[i].suite; qsort(array, count,sizeof(array[0]),mystrcmp); printf("nValid suites:"); for(i=0,previous="";i<count; i++) if(!eql(previous,array[i])) printf(" %s",(previous=array[i])); printf("nValid strategies: all ");
  • 63. for(i=1;i<5;i++) printf("%s ",strategy_name(i)); printf("n"); } /* * Main entry point for test harness */ int run_testrunner(int argc, char **argv,testentry_t tests[],int test_count) { char *test_name, *target; int i; stats_t stats;
  • 64. int target_matched,max_errors_before_quit,redirect_stdouterr; memset (&stats, 0, sizeof (stats)); max_errors_before_quit=1; redirect_stdouterr=0; assert (tests != NULL); assert(test_count>0); assert (argc > 0 && argv && *argv); while(true) { target = argc > 1 ? argv[1] : ""; assert (target); if(*target!='-') break; argc--;argv++; if(target[1]=='f' && target[2]) max_errors_before_quit=atoi(target+1); else if(target[1]=='r')
  • 65. redirect_stdouterr=1; } target_matched = false; for (i=0;i<test_count && (max_errors_before_quit<1 || stats.failed != max_errors_before_quit);i++) { test_name = tests[i].name; assert(test_name); assert(tests[i].suite); assert(tests[i].test_function); if (eql(target,test_name)||eql(target,"all") || eql (target,tests[i].suite) ) { if(!target_matched) printf("Running tests...n"); target_matched = true; run_one_test (&stats, &tests[i],redirect_stdouterr, argc - 1,argv + 1); } }
  • 66. if (!target_matched) { fprintf (stderr, "Test '%s' not found", (strlen(target)>0?target : "(empty)")); print_targets(tests,test_count); } else { printf ("nTest Results:%d tests,%d passed,%d failed.n", stats.ran, stats.passed, stats.failed); } return stats.passed == stats.ran && target_matched ? 0 : 1; } assign4-2/assign4_part2/Makefile CC = gcc CCOPTS = -c -g -Wall
  • 67. LINKOPTS = -g EXEC=mem OBJECTS=testrunner.o mymem.o memorytests.o all: $(EXEC) $(EXEC): $(OBJECTS) $(CC) $(LINKOPTS) -o [email protected] $^ -lrt %.o:%.c $(CC) $(CCOPTS) -o [email protected] $^ clean: - $(RM) $(EXEC) - $(RM) $(OBJECTS) - $(RM) *~ - $(RM) core.*
  • 68. test: mem ./mem -test -f0 all all stage1-test: mem ./mem -test -f0 all first pretty: indent *.c *.h -kr assign4-2/assign4_part2/tests.log Running randomized tests: pool size == 10000, fill ratio == 0.250000, block size is from 1 to 1000, 10000 iterations === best === Test took 0.18ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.16ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000
  • 69. Failed allocations: 0 === first === Test took 0.15ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.15ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.250000, block size is from 1 to 2000, 10000 iterations === best === Test took 0.19ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.15ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.14ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000
  • 70. Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.18ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.250000, block size is from 1000 to 2000, 10000 iterations === best === Test took 0.19ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.19ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.17ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.17ms. Average hole size: 0.000000 Average largest free block: 0.000000
  • 71. Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.250000, block size is from 1 to 3000, 10000 iterations === best === Test took 0.19ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.17ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.17ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.17ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.250000, block size is from 1 to 4000, 10000 iterations === best ===
  • 72. Test took 0.20ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.18ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.19ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.19ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.250000, block size is from 1 to 5000, 10000 iterations === best === Test took 0.20ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0
  • 73. === worst === Test took 0.21ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.20ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.20ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.500000, block size is from 1 to 1000, 10000 iterations === best === Test took 0.20ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.20ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000
  • 74. Failed allocations: 0 === first === Test took 0.20ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.20ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.500000, block size is from 1 to 2000, 10000 iterations === best === Test took 0.13ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.12ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.12ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000
  • 75. Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.12ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.500000, block size is from 1000 to 2000, 10000 iterations === best === Test took 0.12ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.12ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.12ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.11ms. Average hole size: 0.000000 Average largest free block: 0.000000
  • 76. Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.500000, block size is from 1 to 3000, 10000 iterations === best === Test took 0.11ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.10ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.10ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.10ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.500000, block size is from 1 to 4000, 10000 iterations === best ===
  • 77. Test took 0.11ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.10ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.13ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.12ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.500000, block size is from 1 to 5000, 10000 iterations === best === Test took 0.10ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0
  • 78. === worst === Test took 0.09ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.500000, block size is from 1000 to 1000, 10000 iterations === best === Test took 0.09ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000
  • 79. Failed allocations: 0 === first === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.10ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.750000, block size is from 1 to 1000, 10000 iterations === best === Test took 0.09ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000
  • 80. Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.750000, block size is from 500 to 1000, 10000 iterations === best === Test took 0.09ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.09ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.09ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.10ms. Average hole size: 0.000000 Average largest free block: 0.000000
  • 81. Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.750000, block size is from 1 to 2000, 10000 iterations === best === Test took 0.10ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 Running randomized tests: pool size == 10000, fill ratio == 0.900000, block size is from 1 to 500, 10000 iterations === best ===
  • 82. Test took 0.09ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === worst === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === first === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 === next === Test took 0.08ms. Average hole size: 0.000000 Average largest free block: 0.000000 Average allocated bytes: 0.000000 Average number of small blocks: 0.000000 Failed allocations: 0 assign4-2/assign4_part1/setup.sh #!/bin/sh #*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE *************** rm -rf ./testdata mkdir -p
  • 83. ./testdata/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20 echo -n "Hello" > ./testdata/hello.txt echo -n "OldFile" > ./testdata/oldfile.txt cp ./testdata/hello.txt ./testdata/1/2/3/4/5/6/7/8/9/10/ cp ./testdata/oldfile.txt ./testdata/1/2/3/4/5/6/7/8/9/ touch -m -d 20050101 ./testdata/oldfile.txt touch -a -d 20050103 ./testdata/oldfile.txt if [ ! -f /tmp/bigtestscratchfile2forLMP1 ] ; then echo "Creating large file (first time only)" cat /usr/lib/*.so >/tmp/bigtestscratchfile2forLMP1 chmod 644 /tmp/bigtestscratchfile2forLMP1 fi ln -s /tmp/bigtestscratchfile2forLMP1 ./testdata/bigfile exit 0 assign4-2/assign4_part1/restart.c /*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/ #include <errno.h> #include <fcntl.h> #include <limits.h> #include <string.h> #include <sys/select.h> #include <sys/time.h> #include <sys/wait.h> #include "restart.h" #define BLKSIZE PIPE_BUF #define MILLION 1000000L #define D_MILLION 1000000.0
  • 84. /* Private functions */ static int gettimeout(struct timeval end, struct timeval *timeoutp) { gettimeofday(timeoutp, NULL); timeoutp->tv_sec = end.tv_sec - timeoutp->tv_sec; timeoutp->tv_usec = end.tv_usec - timeoutp->tv_usec; if (timeoutp->tv_usec >= MILLION) { timeoutp->tv_sec++; timeoutp->tv_usec -= MILLION; } if (timeoutp->tv_usec < 0) { timeoutp->tv_sec--; timeoutp->tv_usec += MILLION; } if ((timeoutp->tv_sec < 0) || ((timeoutp->tv_sec == 0) && (timeoutp->tv_usec == 0))) { errno = ETIME; return -1; } return 0; } /* Restart versions of traditional functions */ int r_close(int fildes) { int retval; while (retval = close(fildes), retval == -1 && errno == EINTR); return retval; } int r_dup2(int fildes, int fildes2)
  • 85. { int retval; while (retval = dup2(fildes, fildes2), retval == -1 && errno == EINTR); return retval; } int r_open2(const char *path, int oflag) { int retval; while (retval = open(path, oflag), retval == -1 && errno == EINTR); return retval; } int r_open3(const char *path, int oflag, mode_t mode) { int retval; while (retval = open(path, oflag, mode), retval == -1 && errno == EINTR); return retval; } ssize_t r_read(int fd, void *buf, size_t size) { ssize_t retval; while (retval = read(fd, buf, size), retval == -1 && errno == EINTR); return retval; } pid_t r_wait(int *stat_loc) { pid_t retval; while (((retval = wait(stat_loc)) == -1) && (errno ==
  • 86. EINTR)); return retval; } pid_t r_waitpid(pid_t pid, int *stat_loc, int options) { pid_t retval; while (((retval = waitpid(pid, stat_loc, options)) == -1) && (errno == EINTR)); return retval; } ssize_t r_write(int fd, void *buf, size_t size) { char *bufp; size_t bytestowrite; ssize_t byteswritten; size_t totalbytes; for (bufp = buf, bytestowrite = size, totalbytes = 0; bytestowrite > 0; bufp += byteswritten, bytestowrite -= byteswritten) { byteswritten = write(fd, bufp, bytestowrite); if ((byteswritten) == -1 && (errno != EINTR)) return -1; if (byteswritten == -1) byteswritten = 0; totalbytes += byteswritten; } return totalbytes; } /* Utility functions */ struct timeval add2currenttime(double seconds) {
  • 87. struct timeval newtime; gettimeofday(&newtime, NULL); newtime.tv_sec += (int) seconds; newtime.tv_usec += (int) ((seconds - (int) seconds) * D_MILLION + 0.5); if (newtime.tv_usec >= MILLION) { newtime.tv_sec++; newtime.tv_usec -= MILLION; } return newtime; } int copyfile(int fromfd, int tofd) { int bytesread; int totalbytes = 0; while ((bytesread = readwrite(fromfd, tofd)) > 0) totalbytes += bytesread; return totalbytes; } ssize_t readblock(int fd, void *buf, size_t size) { char *bufp; ssize_t bytesread; size_t bytestoread; size_t totalbytes; for (bufp = buf, bytestoread = size, totalbytes = 0; bytestoread > 0; bufp += bytesread, bytestoread -= bytesread) { bytesread = read(fd, bufp, bytestoread); if ((bytesread == 0) && (totalbytes == 0)) return 0;
  • 88. if (bytesread == 0) { errno = EINVAL; return -1; } if ((bytesread) == -1 && (errno != EINTR)) return -1; if (bytesread == -1) bytesread = 0; totalbytes += bytesread; } return totalbytes; } int readline(int fd, char *buf, int nbytes) { int numread = 0; int returnval; while (numread < nbytes - 1) { returnval = read(fd, buf + numread, 1); if ((returnval == -1) && (errno == EINTR)) continue; if ((returnval == 0) && (numread == 0)) return 0; if (returnval == 0) break; if (returnval == -1) return -1; numread++; if (buf[numread - 1] == 'n') { buf[numread] = '0'; return numread; } } errno = EINVAL; return -1;
  • 89. } ssize_t readtimed(int fd, void *buf, size_t nbyte, double seconds) { struct timeval timedone; timedone = add2currenttime(seconds); if (waitfdtimed(fd, timedone) == -1) return (ssize_t) (-1); return r_read(fd, buf, nbyte); } int readwrite(int fromfd, int tofd) { char buf[BLKSIZE]; int bytesread; if ((bytesread = r_read(fromfd, buf, BLKSIZE)) < 0) return -1; if (bytesread == 0) return 0; if (r_write(tofd, buf, bytesread) < 0) return -1; return bytesread; } int readwriteblock(int fromfd, int tofd, char *buf, int size) { int bytesread; bytesread = readblock(fromfd, buf, size); if (bytesread != size) /* can only be 0 or -1 */ return bytesread; return r_write(tofd, buf, size); }
  • 90. int waitfdtimed(int fd, struct timeval end) { fd_set readset; int retval; struct timeval timeout; if ((fd < 0) || (fd >= FD_SETSIZE)) { errno = EINVAL; return -1; } FD_ZERO(&readset); FD_SET(fd, &readset); if (gettimeout(end, &timeout) == -1) return -1; while (((retval = select(fd + 1, &readset, NULL, NULL, &timeout)) == - 1) && (errno == EINTR)) { if (gettimeout(end, &timeout) == -1) return -1; FD_ZERO(&readset); FD_SET(fd, &readset); } if (retval == 0) { errno = ETIME; return -1; } if (retval == -1) return -1; return 0; } assign4-2/assign4_part1/lmp1_tests.c /*************** YOU SHOULD NOT MODIFY ANYTHING
  • 91. IN THIS FILE ***************/ #include <unistd.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <sys/stat.h> #include <string.h> #include "testrunner.h" #include "fileio.h" #include "util.h" /* CONSTANTS */ /* These constants work in tandem with test data created by setup.sh */ #define TESTDATA_DIR "testdata/" #define NEW_FILE "testdata/newfile.txt" #define OLD_FILE "testdata/oldfile.txt" #define HELLO_FILE "testdata/hello.txt" #define BIG_FILE "testdata/bigfile" #define NO_SUCH_FILE "testdata/no_such_file" #define NEW_DIR "testdata/newdir" #define SUBDIR1_DIR "testdata/1" extern int bonnie_main(int, const char **); /* Remove testdata subdirectory (assumes that the current directory has not changed. */ void teardown() { if (system("./teardown.sh")) fprintf(stderr, "nteardown failedn"); }
  • 92. /* Create test data and register the clean up function */ void setup() { quit_if(system("./setup.sh")); quit_if(atexit(teardown)); errno = 0; } /* ---------- Suite 1 Tests --------------- */ /* test file_read() */ int test_file_read(int argc, const char **argv) { char b[255], dots[sizeof(b)]; int bytes_read, i; setup(); quit_if(IOERR_INVALID_ARGS != file_read(HELLO_FILE, 0, b, 0)); quit_if(IOERR_INVALID_ARGS != file_read(HELLO_FILE, 0, NULL, sizeof(b))); quit_if(IOERR_INVALID_ARGS != file_read(HELLO_FILE, -1, b, sizeof(b))); quit_if(IOERR_INVALID_ARGS != file_read(NULL, 0, b, sizeof(b))); quit_if(IOERR_INVALID_PATH != file_read(NO_SUCH_FILE, 0, b, sizeof(b))); bytes_read = file_read(HELLO_FILE, 0, b, sizeof(b)); quit_if(bytes_read != 5); quit_if(strncmp("Hello", b, 5)); bytes_read = file_read(HELLO_FILE, 1, b, sizeof(b)); quit_if(bytes_read != 4); quit_if(strncmp("ello", b, 4)); bytes_read = file_read(HELLO_FILE, -1, b, sizeof(b)); quit_if(bytes_read >= 0); for (i = 0; i < sizeof(dots); i++) {
  • 93. b[i] = dots[i] = i == sizeof(dots) - 1 ? '0' : '.'; } bytes_read = file_read(BIG_FILE, 1, b, sizeof(b)); quit_if(bytes_read != sizeof(b)); quit_if(!memcmp(b, dots, sizeof(b))); return 0; } /* Test file_info() */ int test_file_info(int argc, const char **argv) { char b[255], ftype[2]; int sz, params; long accessed, modified; char fmt[] = "Size:%d Accessed:%d Modified:%d Type %s"; setup(); // Test invalid arguments quit_if(IOERR_INVALID_ARGS != file_info(HELLO_FILE, b, 0)); quit_if(IOERR_INVALID_ARGS != file_info(HELLO_FILE, NULL, sizeof(b))); quit_if(IOERR_INVALID_ARGS != file_info(NULL, b, sizeof(b))); // Test stat on old file quit_if(file_info(OLD_FILE, b, sizeof(b))); params = sscanf(b, fmt, &sz, &accessed, &modified, &ftype); quit_if(params != 4); int one_day = 86400; int jan1_2005 = 1104534000; // seconds since epoch int jan3_2005 = jan1_2005 + one_day + one_day;
  • 94. quit_if(modified < jan1_2005 || modified > jan1_2005 + one_day); quit_if(accessed < jan3_2005 || accessed > jan3_2005 + one_day); return 0; } /* Test file_write() */ int test_file_write(int argc, const char **argv) { char b[] = "qwertyuiop", b2[255]; setup(); // Test invalid arguments quit_if(IOERR_INVALID_ARGS != file_write(NEW_FILE, 0, NULL, sizeof(b))); quit_if(IOERR_INVALID_ARGS != file_write(NULL, 0, b, sizeof(b))); // Test new file quit_if(sizeof(b) != file_write(NEW_FILE, 0, b, sizeof(b))); quit_if(strlen(b) + 1 != file_read(NEW_FILE, 0, b2, sizeof(b2))); quit_if(strncmp(b, b2, strlen(b))); return 0; } /* ---------- Suite 3 Tests --------------- */ /* Test the higher level function file_create. */ int test_file_create(int argc, const char **argv) { char pattern[] = "ab", b[255]; int repeat = 10; char expected[] = "abababababababababab"; setup(); quit_if(file_create(NEW_FILE, pattern, repeat));
  • 95. quit_if(strlen(expected) != file_read(NEW_FILE, 0, b, sizeof(b))); quit_if(strncmp(expected, b, strlen(expected))); return 0; } /* Test file_removal. */ int test_file_remove(int argc, const char **argv) { setup(); quit_if(IOERR_INVALID_ARGS != file_remove(NULL)); // Test correct removal quit_if(file_remove(OLD_FILE)); // Cant remove twice quit_if(IOERR_INVALID_PATH != file_remove(OLD_FILE)); return 0; } /* ---------- Suite 2 Tests --------------- */ /* Test dir_create (directory create)*/ int test_dir_create(int argc, const char **argv) { setup(); quit_if(IOERR_INVALID_ARGS != dir_create(NULL)); quit_if(IOERR_INVALID_PATH != dir_create(HELLO_FILE)); quit_if(dir_create(NEW_DIR)); struct stat s; quit_if(stat(NEW_DIR, &s) == -1); quit_if(!S_ISDIR(s.st_mode)) return 0; } /* Test dir_list (directory listing) */
  • 96. int test_dir_list(int argc, const char **argv) { char b[10000], *next_line, *last, names_found[10000]; int entries; setup(); quit_if(IOERR_INVALID_ARGS != dir_list(NULL, b, sizeof(b))); quit_if(IOERR_INVALID_ARGS != dir_list(HELLO_FILE, NULL, sizeof(b))); quit_if(IOERR_INVALID_ARGS != dir_list(HELLO_FILE, b, 0)); quit_if(IOERR_INVALID_PATH != dir_list(NO_SUCH_FILE, b, sizeof(b))); quit_if(IOERR_INVALID_PATH != dir_list(HELLO_FILE, b, sizeof(b))); quit_if(IOERR_BUFFER_TOO_SMALL != dir_list(TESTDATA_DIR, b, 1)); quit_if(dir_list(TESTDATA_DIR, b, sizeof(b))); quit_if(!memchr(b, 0, sizeof(b))); // check terminating nul byte entries = 0; names_found[0] = '|'; names_found[1] = '0'; next_line = strtok_r(b, "n", &last); while (next_line) { int args_read; char name[256]; entries++; args_read = sscanf(next_line, "%255s", name); quit_if(args_read != 1); quit_if(strlen(names_found) + strlen(name) + 2 >= sizeof(names_found));
  • 97. strcat(names_found, name); strcat(names_found, "|"); next_line = strtok_r(NULL, "n", &last); } quit_if(!strstr(names_found, "|1|")); quit_if(!strstr(names_found, "|.|")); quit_if(!strstr(names_found, "|..|")); quit_if(!strstr(names_found, "|hello.txt|")); quit_if(!strstr(names_found, "|oldfile.txt|")); quit_if(!strstr(names_found, "|bigfile|")); quit_if(entries != 6); return 0; } /* ---------- Suite 4 Tests --------------- */ /* Test file_checksum */ int test_file_checksum(int argc, const char **argv) { setup(); char hello[] = "Hello"; unsigned short cksum = checksum(hello, strlen(hello), 0); quit_if(IOERR_INVALID_ARGS != file_checksum(NULL)); quit_if(cksum != file_checksum(HELLO_FILE)); return 0; } /* in setup.sh() mkdir -p ./testdata/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20 cp ./testdata/hello.txt ./testdata/1/2/3/4/5/6/7/8/9/10/ cp ./testdata/oldfile.txt ./testdata/1/2/3/4/5/6/7/8/9/ This checksum algorithm commutes so we can calculate the the final checksum as follows... */
  • 98. /* Test dir_checksum */ int test_dir_checksum(int argc, const char **argv) { setup(); char dname[10]; int i; unsigned short cksum; int cksum2; quit_if(IOERR_INVALID_ARGS != dir_checksum(NULL)); cksum = checksum("OldFile", 7, checksum("Hello", 5, 0)); for (i = 2; i <= 20; i++) { sprintf(dname, "%d", i); cksum = checksum(dname, strlen(dname), cksum); } cksum2 = dir_checksum(SUBDIR1_DIR); quit_if(0 > cksum2); quit_if(cksum != cksum2); return 0; } /* * Main entry point for test harness */ int run_lmp1_tests(int argc, const char **argv) { /* Tests can be invoked by matching their name or their suite name or 'all' */ testentry_t tests[] = { {"read", "suite1", test_file_read}, {"info", "suite1", test_file_info}, {"write", "suite1", test_file_write},
  • 99. {"dirlist", "suite2", test_dir_list}, {"dircreate", "suite2", test_dir_create}, {"remove", "suite3", test_file_remove}, {"create", "suite3", test_file_create}, {"filechecksum", "suite4", test_file_checksum}, {"dirchecksum", "suite4", test_dir_checksum} }; return run_testrunner(argc, argv, tests, sizeof(tests) / sizeof(testentry_t)); } /* The real main function. */ int main(int argc, const char **argv) { if (argc > 1 && !strcmp(argv[1], "-test")) { return run_lmp1_tests(argc - 1, argv + 1); } else { return bonnie_main(argc, argv); } } assign4-2/assign4_part1/fileio.c #include <sys/types.h> #include <sys/stat.h> #include <sys/types.h> #include <dirent.h> #include <stdio.h> #include <unistd.h> #include <errno.h> #include "restart.h" #include "fileio.h"
  • 100. #if 1 #define VERBOSE(p) (p) #else #define VERBOSE(p) (0) #endif int file_read(char *path, int offset, void *buffer, size_t bufbytes) { return IOERR_NOT_YET_IMPLEMENTED; } int file_info(char *path, void *buffer, size_t bufbytes) { if (!path || !buffer || bufbytes < 1) return IOERR_INVALID_ARGS; return IOERR_NOT_YET_IMPLEMENTED; } int file_write(char *path, int offset, void *buffer, size_t bufbytes) { return IOERR_NOT_YET_IMPLEMENTED; } int file_create(char *path, char *pattern, int repeatcount) { return IOERR_NOT_YET_IMPLEMENTED; } int file_remove(char *path) { return IOERR_NOT_YET_IMPLEMENTED; } int dir_create(char *path)
  • 101. { return IOERR_NOT_YET_IMPLEMENTED; } int dir_list(char *path, void *buffer, size_t bufbytes) { return IOERR_NOT_YET_IMPLEMENTED; } int file_checksum(char *path) { return IOERR_NOT_YET_IMPLEMENTED; } int dir_checksum(char *path) { return IOERR_NOT_YET_IMPLEMENTED; } assign4-2/assign4_part1/util.c /*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/ /* execl*/ #include <unistd.h> /* errno */ #include <errno.h> /* waitpid,WEXITSTATUS*/ #include <sys/types.h> #include <sys/time.h> #include <sys/resource.h> #include <wait.h> /* fprintf*/ #include <stdio.h> #include <string.h>
  • 102. #include "util.h" /* Print a detailed error message to the given file descriptor. The pointers f,mesg,src can be null. */ void print_error(FILE * f, int errn, char *mesg, char *src, int line) { char errmesg[255]; *errmesg = '0'; if (strerror_r(errn, errmesg, sizeof(errmesg))) strcpy(errmesg, "Unknown"); fprintf(f ? f : stderr, "nFAILED AT %s(%d); %s%s. errno=%d(%s)n", src ? src : "notset", line, mesg ? "because " : "", mesg ? mesg : "", errn, errmesg); } /* Print a detailed error message and then exit with a status value of 1.*/ void quit_with_message(int errn, char *mesg, char *src, int line) { print_error(stderr, errn, mesg, src, line); exit(1); } /* Calculate a very simple checksum for a character buffer.*/ unsigned short checksum(char *buffer, size_t sz, unsigned short val) { if ((!buffer) || (!sz)) return val; while ((sz--) > 0) { val += *(buffer++); }
  • 103. return val; } assign4-2/assign4_part1/Makefile CC = gcc CCOPTS = -Wall -c -g LINKOPTS = -g -pthread -lrt EXEC = lmp1 OBJECTS = restart.o testrunner.o fileio.o lmp1_tests.o bonnie.o util.o all: $(EXEC) $(EXEC): $(OBJECTS) $(CC) $(LINKOPTS) -o [email protected] $^ %.o: %.c $(CC) $(CCOPTS) -o [email protected] $^ test: ./$(EXEC) -test -f0 all clean: - $(RM) $(EXEC) - $(RM) $(OBJECTS) - $(RM) *~ - $(RM) core.* - $(RM) -rf testdata pretty: indent *.c *.h -kr assign4-2/assign4_part1/bonnie.c
  • 104. /* * This is a file system benchmark which attempts to study bottlenecks - * it is named 'Bonnie' after Bonnie Raitt, who knows how to use one. * * Commentary on Bonnie's operations may be found at * http://www.textuality.com/bonnie/intro.html * * COPYRIGHT NOTICE: * Copyright (c) Tim Bray, 1990-1996. * */ #include <stdlib.h> #include <string.h> #include <unistd.h> #include <stdio.h> #include <errno.h> #include <fcntl.h> #include <time.h> #include <sys/time.h> #include <sys/types.h> #include <sys/wait.h> #if defined(SysV) #include <limits.h> #include <sys/times.h> #else #include <sys/resource.h> #endif #define IntSize (sizeof(int)) /* * N.B. in seeker_reports, CPU appears and Start/End time, but not Elapsed,
  • 105. * so position 1 is re-used; icky data coupling. */ #define CPU (0) #define Elapsed (1) #define StartTime (1) #define EndTime (2) #define Seeks (4000) #define UpdateSeek (10) #define SeekProcCount (3) #define Chunk (16384) /* labels for the tests, used as an array index */ typedef enum { Putc, ReWrite, FastWrite, Getc, FastRead, Lseek, TestCount } tests_t; static double cpu_so_far(); static void doseek(off_t where, int fd, int update); static void get_delta_t(tests_t test); static void io_error(char *message); static void newfile(char *name, int *fd, FILE * *stream, int create); static void fill_file_char(); static void fill_file_block(); static void file_read_rewrite_block(); static void file_read_getc(); static void file_read_chunk(); #if defined(SysV) /* System V wrappers for randomizers */ static long random(); static void srandom(int seed); #endif static void report(char *machine, off_t size);
  • 106. static double time_so_far(); static void timestamp(); static void usage(); /* * Housekeeping variables to build up timestamps for the tests; * global to make it easy to keep track of the progress of time. * all of this could have been done with non-global variables, * but the code is easier to read this way and I don't anticipate * much software engineering down the road */ static int basetime; /* when we started */ static double delta[(int) TestCount][2]; /* array of DeltaT values */ static double last_cpustamp = 0.0; /* for computing delta-t */ static double last_timestamp = 0.0; /* for computing delta-t */ char name[Chunk]; FILE *stream; int fd; off_t words; off_t size; int buf[Chunk / IntSize]; int bufindex; int chars[256]; int next; /* entry point for LMP1 */ int bonnie_main(int argc, char **argv) { int child; char *dir; double first_start; double last_stop; int lseek_count = 0; char *machine;
  • 107. int seek_control[2]; int seek_feedback[2]; char seek_tickets[Seeks + SeekProcCount]; double seeker_report[3]; fd = -1; basetime = (int) time((time_t *) NULL); size = 100; dir = "."; machine = ""; /* parse the argument sent from the command line */ for (next = 1; next < argc; next++) { if (strcmp(argv[next], "-s") == 0) size = atol(argv[++next]); else if (strcmp(argv[next], "-m") == 0) machine = argv[++next]; else usage(); } if (size < 1) { usage(); } /* CHECK SYSTEM CAPABILITY: We proceed to check the size of files because 32-bit machines has a limit */ if (sizeof(off_t) <= 4 && size > 2047) { fprintf(stderr, "File too large for 32-bit machine, sorryn"); exit(1); } sprintf(name, "%s/LMP1.%d", dir, getpid());
  • 108. /* The size is in Megabytes, and is rounded down to multiples of Chunk */ size *= (1024 * 1024); size = Chunk * (size / Chunk); fprintf(stderr, "File '%s', size: %ldn", name, size); fill_file_char(name, &fd, &stream); /* For specific details please go down to the body of this function */ file_read_rewrite_block(name, &fd, &stream); /* For specific details please go down to the body of this function */ fill_file_block(name, &fd, &stream); /* For specific details please go down to the body of this function */ file_read_getc(name, &fd, &stream); /* For specific details please go down to the body of this function */ /* use the frequency count */ for (words = 0; words < 256; words++) sprintf((char *) buf, "%d", chars[words]); file_read_chunk(name, &fd, &stream); /* For specific details please go down to the body of this function */ /* use the frequency count */ for (words = 0; words < 256; words++) sprintf((char *) buf, "%d", chars[words]); /* * Now test random seeks; first, set up for communicating with children. * The object of this e game is to do "Seeks" lseek() calls as quickly * as possible. So we'll farm them out among SeekProcCount processes. * We'll control them by writing 1-byte tickets down a pipe which * the children all read. We write "Seeks" bytes with val 1,
  • 109. whichever * child happens to get them does it and the right number of seeks get * done. * The idea is that since the write() of the tickets is probably * atomic, the parent process likely won't get scheduled while the * children are seeking away. If you draw a picture of the likely * timelines for three children, it seems likely that the seeks will * overlap very nicely with the process scheduling with the effect * that there will *always* be a seek() outstanding on the file. * Question: should the file be opened *before* the fork, so that * all the children are lseeking on the same underlying file object? */ if (pipe(seek_feedback) == -1 || pipe(seek_control) == -1) io_error("pipe"); for (next = 0; next < Seeks; next++) seek_tickets[next] = 1; for (; next < (Seeks + SeekProcCount); next++) seek_tickets[next] = 0; /* launch some parallel seek processes */ for (next = 0; next < SeekProcCount; next++) { /* for each seek proc */ if ((child = fork()) == -1) io_error("fork"); else if (child == 0) { /* child process */ /* set up and wait for the go-ahead */ close(seek_feedback[0]); close(seek_control[1]);
  • 110. newfile(name, &fd, &stream, 0); srandom(getpid()); fprintf(stderr, "Seeker %d...", next + 1); /* wait for the go-ahead */ if (read(seek_control[0], seek_tickets, 1) != 1) io_error("read ticket"); timestamp(); seeker_report[StartTime] = time_so_far(); /* loop until we read a 0 ticket back from our parent */ while (seek_tickets[0]) { /* until Mom says stop */ doseek((long) (random() % (size / Chunk)), fd, ((lseek_count++ % UpdateSeek) == 0)); if (read(seek_control[0], seek_tickets, 1) != 1) io_error("read ticket"); } /* until Mom says stop */ if (close(fd) == -1) io_error("close after seek"); /* report to parent */ get_delta_t(Lseek); seeker_report[EndTime] = time_so_far(); seeker_report[CPU] = delta[(int) Lseek][CPU]; if (write (seek_feedback[1], seeker_report, sizeof(seeker_report)) != sizeof(seeker_report)) io_error("pipe write"); exit(0); } /* child process */ } /* for each seek proc */ /* * Back in the parent; in an effort to ensure the children get an even * start, wait a few seconds for them to get scheduled, open
  • 111. their * files & so on. */ close(seek_feedback[1]); close(seek_control[0]); sleep(5); fprintf(stderr, "start 'em..."); if (write(seek_control[1], seek_tickets, sizeof(seek_tickets)) != sizeof(seek_tickets)) io_error("write tickets"); /* read back from children */ for (next = 0; next < SeekProcCount; next++) { /* for each child */ if (read (seek_feedback[0], (char *) seeker_report, sizeof(seeker_report)) != sizeof(seeker_report)) io_error("pipe read"); /* * each child writes back its CPU, start & end times. The elapsed time * to do all the seeks is the time the first child started until the * time the last child stopped */ delta[(int) Lseek][CPU] += seeker_report[CPU]; if (next == 0) {/* first time */ first_start = seeker_report[StartTime]; last_stop = seeker_report[EndTime]; } /* first time */ else { /* not first time */ first_start = (first_start < seeker_report[StartTime]) ? first_start : seeker_report[StartTime]; last_stop = (last_stop > seeker_report[EndTime]) ?
  • 112. last_stop : seeker_report[EndTime]; } /* not first time */ if (wait(&child) == -1) io_error("wait"); fprintf(stderr, "done..."); } /* for each child */ fprintf(stderr, "n"); delta[(int) Lseek][Elapsed] = last_stop - first_start; report(machine, size); unlink(name); return EXIT_SUCCESS; } /**************************************************** *****************/ /* FUNCTION report */ /**************************************************** *****************/ /* INPUT: Machine description and size of file */ /**************************************************** *****************/ /* PROCESS: */ /* 1. Print in the monitor the results from the */ /* operations the program supports. */ /**************************************************** *****************/ /* OUTPUT: doesn´t return any value because it is void */ /**************************************************** *****************/ static void report(char *machine, off_t size) { printf(" ");
  • 113. printf ("-------Sequential Output-------- ---Sequential Input-- -- Random--n"); printf(" "); printf ("-Per Char- --Block--- -Rewrite-- -Per Char- --Block--- -- Seeks---n"); printf("Machine MB "); printf("K/sec %%CPU K/sec %%CPU K/sec %%CPU K/sec %%CPU K/sec "); printf("%%CPU /sec %%CPUn"); printf("%-8.8s %4ld ", machine, size / (1024 * 1024)); printf("%5d %4.1f %5d %4.1f %5d %4.1f ", (int) (((double) size) / (delta[(int) Putc][Elapsed] * 1024.0)), delta[(int) Putc][CPU] / delta[(int) Putc][Elapsed] * 100.0, (int) (((double) size) / (delta[(int) FastWrite][Elapsed] * 1024.0)), delta[(int) FastWrite][CPU] / delta[(int) FastWrite][Elapsed] * 100.0, (int) (((double) size) / (delta[(int) ReWrite][Elapsed] * 1024.0)), delta[(int) ReWrite][CPU] / delta[(int) ReWrite][Elapsed] * 100.0); printf("%5d %4.1f %5d %4.1f ", (int) (((double) size) / (delta[(int) Getc][Elapsed] * 1024.0)), delta[(int) Getc][CPU] / delta[(int) Getc][Elapsed] * 100.0, (int) (((double) size) / (delta[(int) FastRead][Elapsed] * 1024.0)),
  • 114. delta[(int) FastRead][CPU] / delta[(int) FastRead][Elapsed] * 100.0); printf("%5.1f %4.1fn", ((double) Seeks) / delta[(int) Lseek][Elapsed], delta[(int) Lseek][CPU] / delta[(int) Lseek][Elapsed] * 100.0); } /**************************************************** *****************/ /* FUNCTION newfile */ /**************************************************** *****************/ /* INPUT: Name of the file, File Descriptor, Buffer, Create Flag */ /**************************************************** *****************/ /* PROCESS: */ /* 1. If Create Flag is one */ /* i) Checks if the file is unlinked */ /* a) If it is not returns error */ /* ii) Obatain File Descriptor with proper parameters */ /* and flags.NOTE: Use man pages to view the specific */ /* parameters open uses. Make sure you understand */ /* the return values, and see the errors the function */ /* returns) */ /* Else Create flag is not equal to zero */ /* Obtain file descriptor with proper parameters and */ /* flags.(NOTE: Use man pages to view the specific */
  • 115. /* parameters open uses. Make sure you understand */ /* the return values, and see the errors the function */ /* returns) */ /* 2. Fill buffer when calling fdopen with proper */ /* parameters and flags.(NOTE: Use man pages to view the */ /* specific parameters open uses. Make sure you understand */ /* the return values, and see the errors the function */ /* returns) */ /* 3. Check stream */ /**************************************************** *****************/ /* OUTPUT: doesn´t return any value because it is void */ /**************************************************** *****************/ static void newfile(char *name, int *fd, FILE ** stream, int create) { if (create) { if (unlink(name) == -1 && *fd != -1) io_error("unlink"); *fd = open(name, O_RDWR | O_CREAT | O_EXCL, 0777); } else *fd = open(name, O_RDWR, 0777); if (*fd == -1) io_error(name); *stream = fdopen(*fd, "r+"); if (*stream == NULL) io_error("fdopen"); }
  • 116. /**************************************************** *****************/ /* FUNCTION fill_file_char */ /**************************************************** *****************/ /* INPUT: does not receive any parameter */ /**************************************************** *****************/ /* PROCESS: */ /* 1. Open file */ /* 2. Record timestamp */ /* 3. For cycle to fill the file one character at a time*/ /* until it reaches the EndOfFile(EOF) */ /* 4. Close file */ /* 5. Call get_delta_t to find the performance of putc */ /**************************************************** *****************/ /* OUTPUT: doesn´t return any value because it is void */ /**************************************************** *****************/ static void fill_file_char() { fprintf(stderr, "FUNCTION fill_file_char() start..."); newfile(name, &fd, &stream, 1); timestamp(); for (words = 0; words < size; words++) if (putc(words & 0x7f, stream) == EOF) io_error("putc"); if (fclose(stream) == -1) io_error("fclose after putc"); get_delta_t(Putc); fprintf(stderr, "...done FUNCTION file_fill_char()n"); }
  • 117. /**************************************************** *****************/ /* FUNCTION fill_file_block */ /**************************************************** *****************/ /* INPUT: does not receive any parameter */ /**************************************************** *****************/ /* PROCESS: */ /* 1. Open file */ /* 2. Initialize every position of the buffer */ /* 3. Record timestamp */ /* 4. FOR cycle so for each word you need to: */ /* i) properly set the buffer index so that it points */ /* at the correct position. */ /* ii) Call write.(NOTE: Use man pages to view the */ /* specific parameters write uses. Make sure you */ /* understand the return values, and see the errors */ /* the function returns) */ /* 4. Close file */ /* 5. Call get_delta_t to find the performance of putc */ /**************************************************** *****************/ /* OUTPUT: doesn´t return any value because it is void */ /**************************************************** *****************/ static void fill_file_block() { fprintf(stderr, "FUNCTION fill_file_block() start..."); newfile(name, &fd, &stream, 1); for (words = 0; words < Chunk / IntSize; words++) buf[words] = 0; timestamp();
  • 118. for (words = bufindex = 0; words < (size / Chunk); words++) { if (bufindex == (Chunk / IntSize)) bufindex = 0; buf[bufindex++]++; if (write(fd, (char *) buf, Chunk) == -1) io_error("write(2)"); } if (close(fd) == -1) io_error("close after fast write"); get_delta_t(FastWrite); fprintf(stderr, "...done FUNCTION fill_file_block()n"); } /**************************************************** *****************/ /* FUNCTION file_read_rewrite_block */ /**************************************************** *****************/ /* INPUT: does not receive any parameter */ /**************************************************** *****************/ /* PROCESS: */ /* 1. Open file */ /* 2. Call lseek. (NOTE: Use man pages to view the */ /* specific parameters lseek uses. Make sure you */ /* understand the return values, and see the errors the */ /* function returns) */ /* 3. Record timestamp */ /* 4. Make sure the buffer index point to zero */ /* 5. Call read. (NOTE: Use man pages to view the */ /* specific parameters read uses. Make sure you
  • 119. */ /* understand the return values, and see the errors the */ /* function returns) */ /* 6. While we can read a block, increment the index to */ /* point to the the next position. Call lseek and call */ /* write.(NOTE: Use man pages to view the specific */ /* parameters write uses. Make sure you understand the */ /* return values,and see the errors the function */ /* returns) */ /* Call read until the while condition is false. */ /* 7. Close file */ /* 8. Call get_delta_t to find the performance of putc */ /**************************************************** *****************/ /* OUTPUT: doesn´t return any value because it is void */ /**************************************************** *****************/ static void file_read_rewrite_block() { fprintf(stderr, "FUNCTION file_read_rewrite() start..."); newfile(name, &fd, &stream, 0); if (lseek(fd, (off_t) 0, 0) == (off_t) - 1) io_error("lseek(2) before rewrite"); fprintf(stderr, "Rewriting"); timestamp(); bufindex = 0; if ((words = read(fd, (char *) buf, Chunk)) == -1) io_error("rewrite read"); while (words == Chunk) {
  • 120. if (bufindex == Chunk / IntSize) bufindex = 0; buf[bufindex++]++; if (lseek(fd, (off_t) - words, 1) == -1) io_error("relative lseek(2)"); if (write(fd, (char *) buf, words) == -1) io_error("re write(2)"); if ((words = read(fd, (char *) buf, Chunk)) == -1) io_error("rwrite read"); } if (close(fd) == -1) io_error("close after rewrite"); get_delta_t(ReWrite); fprintf(stderr, "...done FUNCTION file_read_rewrite_block()n"); } /**************************************************** *****************/ /* FUNCTION file_read_getc */ /**************************************************** *****************/ /* INPUT: does not receive any parameter */ /**************************************************** *****************/ /* PROCESS: */ /* 1. Open file */ /* 2. Initialize every position of the buffer words */ /* 3. Record timestamp */ /* 4. FOR cycle to fill the file 1 byte at a time until */ /* it reaches the EndOfFile(EOF).Make sure you notice */ /* the increment of the index pointing at chars */ /* 7. Close file */
  • 121. /* 8. Call get_delta_t to find the performance of getc */ /**************************************************** *****************/ /* OUTPUT: doesn´t return any value because it is void */ /**************************************************** *****************/ static void file_read_getc() { fprintf(stderr, "FUNCTION fill_read_getc() start..."); newfile(name, &fd, &stream, 0); for (words = 0; words < 256; words++) chars[words] = 0; timestamp(); for (words = 0; words < size; words++) { if ((next = getc(stream)) == EOF) io_error("getc(3)"); chars[next]++; } if (fclose(stream) == -1) io_error("fclose after getc"); get_delta_t(Getc); fprintf(stderr, "...done FUNCTION file_read_getc()n"); } /**************************************************** *****************/ /* FUNCTION file_read_chunk */ /**************************************************** *****************/ /* INPUT: does not receive any parameter */ /**************************************************** *****************/ /* PROCESS: */
  • 122. /* 1. Open file */ /* 2. Call lseek().(NOTE:Use man pages to view the */ /* specific */ /* parameters write uses. Make sure you understand the */ /* return values,and see the errors the function */ /* returns) */ /* 3. Record timestamp */ /* 6. DO cycle read a block.(NOTE: Use man pages to view*/ /* the specific parameters read uses. Make sure you */ /* understand the return values, and see the errors the */ /* function returns) Call read until the while condition is */ /* false. */ /* 7. Close file */ /* 8. Call get_delta_t to find the performance of getc */ /**************************************************** *****************/ /* OUTPUT: doesn´t return any value because it is void */ /**************************************************** *****************/ static void file_read_chunk() { fprintf(stderr, "FUNCTION file_read_chunk() start..."); newfile(name, &fd, &stream, 0); if (lseek(fd, (off_t) 0, 0) == -1) io_error("lseek before read"); timestamp(); do { if ((words = read(fd, (char *) buf, Chunk)) == -1)
  • 123. io_error("read(2)"); chars[buf[abs(buf[0]) % (Chunk / IntSize)] & 0x7f]++; } while (words); if (close(fd) == -1) io_error("close after read"); get_delta_t(FastRead); fprintf(stderr, "...done FUNCTION file_read_chunk()n"); } /**************************************************** *****************/ /* FUNCTION usage */ /**************************************************** *****************/ /* INPUT: does not receive any parameter */ /**************************************************** *****************/ /* PROCESS: */ /* 1. Presents all the options the program has */ /**************************************************** *****************/ /* OUTPUT: doesn´t return any value because it is void */ /**************************************************** *****************/ static void usage() { fprintf(stderr, "usage: ./lmp1 [-s size-in-Mb] [-m machine- label]n"); exit(1); } /**************************************************** *****************/ /* FUNCTION timestamp */
  • 124. /**************************************************** *****************/ /* INPUT: does not receive any parameter */ /**************************************************** *****************/ /* PROCESS: */ /* 1. Call time_so_far() and store it in last_timestamp */ /* 2. Call cpu_so_far() and store it in last_cpustamp */ /**************************************************** *****************/ /* OUTPUT: doesn´t return any value because it is void */ /**************************************************** *****************/ static void timestamp() { last_timestamp = time_so_far(); last_cpustamp = cpu_so_far(); } /**************************************************** *****************/ /* FUNCTION get_delta_t */ /**************************************************** *****************/ /* INPUT: Receives the structure tests_t */ /**************************************************** *****************/ /* PROCESS: */ /* 1. Identifies the procedure that was executed */ /* 2. Calls time_so_far() and deletes the value of */ /* of the global variable last_timestamp obtaining the time */ /* the procedure spent. */ /* 3. Calls cpu_so_far() and substracts the value of */
  • 125. /* of the global variable last_cpustamp obtaining the */ /* amount of CPU procedure spent. */ /**************************************************** *****************/ /* OUTPUT: doesn´t return any value because it is void */ /**************************************************** *****************/ static void get_delta_t(test) tests_t test; { int which = (int) test; delta[which][Elapsed] = time_so_far() - last_timestamp; delta[which][CPU] = cpu_so_far() - last_cpustamp; } /**************************************************** *****************/ /* FUNCTION cpu_so_far */ /**************************************************** *****************/ /* INPUT: does not receive any parameter */ /**************************************************** *****************/ /* PROCESS: */ /* 1. Identifies the System to check some variables */ /* if SysV */ /* i) Creates a structure tms. */ /* ii) returns the CPU time after adding over */ /* certain fields in the tms structure. */ /* Else */ /* i) Creates a structure rusage. */ /* ii) Calls getrusage().(NOTE: Use man pages */ /* to view the specific parameters write uses. */
  • 126. /* Make sure you understand the return values, */ /* and see the errors the function returns). */ /* iii) returns the CPU time after adding over */ /* certain fields in the rusage structure. */ /**************************************************** *****************/ /* OUTPUT: return the CPU usage until the time it has been called */ /**************************************************** *****************/ static double cpu_so_far() { #if defined(SysV) struct tms tms; if (times(&tms) == -1) io_error("times"); return ((double) tms.tms_utime) / ((double) sysconf(_SC_CLK_TCK)) + ((double) tms.tms_stime) / ((double) sysconf(_SC_CLK_TCK)); #else struct rusage rusage; getrusage(RUSAGE_SELF, &rusage); return ((double) rusage.ru_utime.tv_sec) + (((double) rusage.ru_utime.tv_usec) / 1000000.0) + ((double) rusage.ru_stime.tv_sec) + (((double) rusage.ru_stime.tv_usec) / 1000000.0); #endif } /**************************************************** *****************/ /* FUNCTION time_so_far */ /**************************************************** *****************/
  • 127. /* INPUT: does not receive any parameter */ /**************************************************** *****************/ /* PROCESS: */ /* 1. Identifies the System to check some variables */ /* if SysV */ /* i) Creates a structure tms. */ /* ii) Call the times function and assign the */ /* value it returns to the variable val */ /* iii) returns the CPU time after dividing val*/ /* by the returning value from sysconf() */ /* Else */ /* i) Creates a structure timeval tp. */ /* ii) Calls gettimeofday().(NOTE:Use man pages*/ /* to view the specific parameters */ /* gettimeofday uses. Make sure you understand */ /* the return values, and see the errors the */ /* function returns). */ /* iii) returns the CPU time after substractin */ /* certain fields in the tp structure. */ /**************************************************** *****************/ /* OUTPUT: return the time it has been used */ /**************************************************** *****************/ static double time_so_far() { #if defined(SysV) int val; struct tms tms; if ((val = times(&tms)) == -1) io_error("times");
  • 128. return ((double) val) / ((double) sysconf(_SC_CLK_TCK)); #else struct timeval tp; if (gettimeofday(&tp, (struct timezone *) NULL) == -1) io_error("gettimeofday"); return ((double) (tp.tv_sec - basetime)) + (((double) tp.tv_usec) / 1000000.0); #endif } /**************************************************** *****************/ /* FUNCTION io_error */ /**************************************************** *****************/ /* INPUT: Receives the error string */ /**************************************************** *****************/ /* PROCESS: */ /* 1. Call perror().(NOTE:Use man pages to view the */ /* specific parameters gettimeofday uses. Make sure you */ /* understand the return values, and see the errors the */ /* function returns). */ /* 2. Call exit().(NOTE:Use man pages to view the */ /* specific parameters gettimeofday uses. Make sure you */ /* understand the return values, and see the errors the */ /* function returns). */ /**************************************************** *****************/
  • 129. /* OUTPUT: return the time it has been used */ /**************************************************** *****************/ static void io_error(char *message) { char buf[Chunk]; sprintf(buf, "Program: drastic I/O error (%s)", message); perror(buf); exit(1); } /* * Do a typical-of-something random I/O. Any serious application that * has a random I/O bottleneck is going to be smart enough to operate * in a page mode. * The 'where' argument is used as a chunk number * To keep the cache from getting too clever, some pages must be updated. * However an application that updated each of many random pages that * it looked at is hard to imagine. * However, it would be wrong to put the update percentage in as a * parameter - the effect is too nonlinear. */ static void doseek(off_t where, int fd, int update) { int buf[Chunk / IntSize]; off_t probe; off_t size; probe = where * Chunk; if (lseek(fd, probe, 0) != probe)
  • 130. io_error("lseek in doseek"); if ((size = read(fd, (char *) buf, Chunk)) == -1) io_error("read in doseek"); /* every so often, update a block */ if (update) { /* update this block */ /* touch a word */ buf[((int) random() % (size / IntSize - 2)) + 1]--; if (lseek(fd, (long) probe, 0) != probe) io_error("lseek in doseek update"); if (write(fd, (char *) buf, size) == -1) io_error("write in doseek"); } /* update this block */ } #if defined(SysV) static char randseed[32]; static void srandom(int seed) { sprintf(randseed, "%06d", seed); } static long random() { return nrand48(randseed); } #endif assign4-2/assign4_part1/testrunner.h /*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/ typedef int (*test_fp) (int, const char **);
  • 131. typedef struct { const char *name; const char *suite; test_fp test_function; } testentry_t; int run_testrunner(int argc, const char **argv, testentry_t * entries, int entry_count); void set_testrunner_default_timeout(int s); void set_testrunner_timeout(int s); assign4-2/assign4_part1/teardown.sh #!/bin/sh #*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE *************** rm -rf ./testdata assign4-2/assign4_part1/restart.h /*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/ #include <fcntl.h> #include <unistd.h> #include <sys/time.h> #include <sys/types.h> #ifndef ETIME #define ETIME ETIMEDOUT #endif struct timeval add2currenttime(double seconds);
  • 132. int copyfile(int fromfd, int tofd); int r_close(int fildes); int r_dup2(int fildes, int fildes2); int r_open2(const char *path, int oflag); int r_open3(const char *path, int oflag, mode_t mode); ssize_t r_read(int fd, void *buf, size_t size); pid_t r_wait(int *stat_loc); pid_t r_waitpid(pid_t pid, int *stat_loc, int options); ssize_t r_write(int fd, void *buf, size_t size); ssize_t readblock(int fd, void *buf, size_t size); int readline(int fd, char *buf, int nbytes); ssize_t readtimed(int fd, void *buf, size_t nbyte, double seconds); int readwrite(int fromfd, int tofd); int readwriteblock(int fromfd, int tofd, char *buf, int size); int waitfdtimed(int fd, struct timeval end); assign4-2/assign4_part1/util.h /*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/ #include <stdlib.h> /* stdlib required for size_t */ #define quit_if_ne(p1,p2) {if((p1) != (p2)) quit_with_message((int)errno,"" #p1 "!=" #p2 ,__FILE__,__LINE__);} #define quit_if(mutley) {if(mutley) quit_with_message((int)errno, #mutley,__FILE__,__LINE__);} #define quit(mesg) {quit_with_message((int)errno,mesg,__FILE__,__LINE__);} void quit_with_message(int errn, char *mesg, char *src, int line);
  • 133. unsigned short checksum(char *buffer, size_t sz, unsigned short val); assign4-2/assign4_part1/fileio.h #include <stdlib.h> #define IOERR_INVALID_ARGS (-1) #define IOERR_INVALID_PATH (-2) #define IOERR_POSIX (-3) #define IOERR_BUFFER_TOO_SMALL (-4) #define IOERR_NOT_YET_IMPLEMENTED (-5) /* You will implement all of the following functions in fileio.c. */ /* ERROR HANDLING These functions will support basic error handling: If the arguments are bad (e.g., a pointer is NULL), then the function should immediately return IOERR_INVALID_ARGS. If a POSIX error occurs, the function should return IOERR_POSIX, unless the error is due to a bad path, in which case the return value is IOERR_INVALID_PATH. These functions do not return if a POSIX function is interrupted by a signal; only dirlist returns IOERR_BUFFER_TOO_SMALL (see below). You may find some of the library functions in restart.c useful.
  • 134. COMMON PARAMETERS path - file to be read offest - where to start reading/writing from buffer - buffer to write bytes into bufbytes - maximum number of bytes to read FUNCTION DESCRIPTIONS int file_read(char *path, int offset, void *buffer, size_t bufbytes); Reads bytes from a file into the buffer. Return value: >=0 number of bytes read, <0 ERROR (see above) int file_info(char *path, void *buffer, size_t bufbytes) Writes into buffer a string that describes meta information about the file. The string is in format: "Size:NNN Accessed:NNN Modified:NNN Type X" X can be 'f' or 'd' (file or directory, respectively) Size is in bytes Accessed and Modified - accessed and modified times (seconds since epoch) int file_write(char *path, int offset, void *buffer, size_t bufbytes); Writes bytes from 'buffer' into file 'path' at position 'offset'. Return value: >0 number of bytes written, <0 ERROR (see above) int file_create(char *path, char *pattern, int repeatcount); Creates a new file with the string 'pattern' repeated 'repeatcount' times. Return value:0 Success , <0 ERROR (see above)
  • 135. int file_remove(char *path); Removes an existing file if it exists. Return value: 0 file removed, <0 ERROR (see above) int dir_create(char *path); Creates a new directory. Return value: 0 directory created, <0 ERROR (see above) int dir_list(char *path, void *buffer, size_t bufbytes); Writes a list file and directory names inside path (including "." and ".." entries). Each entry is line terminated with the newline character 'n'. Return value: 0 success, <0 ERROR (see above) Returns IOERR_BUFFER_TOO_SMALL if the buffer is not large enough to write all entries. Hint: man opendir, readdir, closedir int file_checksum(char *path) Calculates a checksum value calculated by summing all the bytes of a file using an unsigned short. Return value: >=0 checksum value, <0 ERROR (see above) Hint: use the checksum function in util.c int dir_checksum(char *path); Recursively calculated a checksum: checksums of regular files are calculated using file_checksum; directory entries are traversed, also the subdirectory names are included in the checksum calculation See lmp1_tests.c for details of what we are looking for. Return value: >=0 checksum value, <0 ERROR (see above)