Commit 24c0c966 authored by cdf009's avatar cdf009

Lab8 done

parent b4422677
This diff is collapsed.
CC = gcc -I ./include
CFLAGS = -std=gnu99 -Wall -g #-DDEBUG
INC = ./include
SRC = ./src
OBJ = ./obj
DOC = ./doc
BIN = ./bin
vpath %.h ./include
vpath %.c ./src
EXECS = mem_test
all: $(EXECS)
doc:
doxygen return -1;
$(OBJ)/dnode.o: dnode.h dnode.c
$(CC) $(CFLAGS) -c $(SRC)/dnode.c -o $(OBJ)/dnode.o
$(OBJ)/dlist.o: dlist.h dlist.c dnode.h
$(CC) $(CFLAGS) -c $(SRC)/dlist.c -o $(OBJ)/dlist.o
frag-eval: $(SRC)/frag-eval.c $(SRC)/allocator.c allocator.h $(OBJ)/dnode.o $(OBJ)/dlist.o
$(CC) $(CFLAGS) $(SRC)/allocator.c $(OBJ)/dnode.o $(OBJ)/dlist.o $(SRC)/frag-eval.c -o $(BIN)/frag-eval
.PHONY: clean
clean:
/bin/rm -rf $(BIN)/* $(OBJ)/* core* *~
1.1) The types of fragmentation found in our custom memory allocator are both internal and external fragmentation. The
external fragmentation happens when there is free memory in the free list. Meaning that there are spaces of unallocated memory
in between other nodes of allocated memory. The internal fregmentation happens in my allocator when we allocate memory on a node but
the amount allocted is smalled than the cpacity of that node.
1.2) One of the metrics you could use is to see how many nodes in the list were able to be used during allocation. The more nodes that
were able to be used means the more memory that is able to be allocated onto the list. The second mentric that I would use is the average size
of the memory being allocated onto the allocated list. Yeah, its great if we use a lot of nodes but that may lead to a lot of fragemntation.
If we look at the average size of the meory allocated, we will see if we are able to allocate large sizes of memory.
1.3) In the function "double average_frag()", I will first create an iter that will be a dnode struct that will initialize the free list. I will then
create variables to store the sum and the count of nodes visited. Then I enter the do while and basically just go from node to node while adding each frag
to the sum and incremting/store the amount of nodes. I will do this while the initilizaed list isnt NULL or empty. Then I will just divide the sum by the amount
of node and return it.
2.1) The best allocation policy for my custom memory allocator is the Best Fit method. This is because the point estimate for Best Fit is much lower than
the point estimate for the First Fit. The confidence intervals are about the same. The clear worst method is worst fit. This has the highest point estimate and the
largest margin of error. I believe that the Best Fit worked better than the rest because it places the process in the block that has the smallest size that it will fit in.
Policy: Point Estimate: Margin of Error: Confidence Interval:
First Fit 62.629 0.843 (62.786, 64.4714)
Best Fit 56.864 0.849 (56.0149, 57.713)
Worst Fit 76.215 1.02 (75.1947. 77.2345)
#ifdef _DLIST_H_
#define _DLIST_H_
#include <stdint.h>
#include <stdbool.h>
#include "dlist.h"
#include "dnode.h"
//Casey Friend
//Lab 7
//allocator.h
int allocator_init(int size);
//this is where we will create and initialize 2 doubly linked lists
//one is called free_list and one is allocated_list
struct dnode* allocate(int size, int param);
//this is basically malloc
//will allocate a chunk of memory of a size on the free list
int deallocate(void *ptr);
//this will free memory on the allocated list
struct dnode* first_fit(int size);
struct dnode* best_fit(int size);
struct dnode* worst_fit(int size);
void allocator_print();
double average_frag();
//computes the average fragmentation
#endif /* _DLIST_H_ */
/*
* Copyright (c) 2012 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: L. Felipe Perrone (perrone@bucknell.edu)
*/
#ifndef _DLIST_H_
#define _DLIST_H_
#include <stdint.h>
#include <stdbool.h>
#include "dnode.h"
/**
* Doubly-linked list.
*/
struct dlist {
struct dnode *front;
struct dnode *back;
struct dnode *iter;
uint32_t counter;
};
/**
* Allocates new dlist dynamically.
*
* @return pointer to the list.
*/
struct dlist *dlist_create();
struct dnode* dlist_find(struct dlist *l, void *ptr);
/**
* Deallocates all nodes in a dlist and the data they point to, but
* preserve the list.
*
* @param l pointer to the list (non-NULL)
*/
void dlist_destroy(struct dlist *l);
/**
* Deallocates all nodes in a dlist and the data they point to; deallocate
* the list itself as well. This is the inverse of dlist_create.
* @param l pointer to the list (non-NULL)
*/
void dlist_obliterate(struct dlist *l);
/**
* Inserts new node in dlist before the first node.
*
* @param l pointer to the list (non_NULL)
* @param ptr pointer to generic data to store in new list node
*/
void dlist_add_front(struct dlist *l, void *ptr, int size);
/**
* Inserts new node in dlist after the last node.
*
* @param l pointer to the list (non-NULL)
* @param ptr pointer to generic data to store in new list node
*/
struct dnode* dlist_add_back(struct dlist *l, void *ptr, int size);
/**
* Remove the first node and return pointer to the data. It is the
* responsibility of the caller to free the memory pointed by the return
* value.
*
* @param l pointer to the list (non-NULL)
* @return pointer to data stored in front node
*/
struct dnode *dlist_remove_front(struct dlist *l);
/**
* Remove the last node and return pointer to the data. It is the
* responsibility of the caller to free the memory pointed by the return
* value.
*
* @param l pointer to the list (non-NULL)
* @return pointer to data stored in back node
*/
struct dnode *dlist_remove_back(struct dlist *l);
/**
* Seek out the node that contains a pointer and remove from list returning
* the pointer to the data. It is the
* responsibility of the caller to free the memory pointed by the return
* value.
*
* @param l pointer to the list (non-NULL)
* @param ptr pointer to the data item been sought
* @return pointer to data stored in the node that was found node
*/
struct dnode *dlist_find_remove(struct dlist *l, void *ptr);
/**
* Returns the number of elements in the list (nodes).
*
* @param l pointer to the list (non-NULL)
*/
uint32_t dlist_num_elems(struct dlist *l);
/**
* Initialize iterator for traversing a dlist forwards.
*/
void *dlist_iter_begin(struct dlist *l);
/**
* Returns current item and advances iterator to next item in list.
*/
void *dlist_iter_next(struct dlist *l);
/**
* Check if iterator has reached the end of the list.
*/
bool dlist_iter_has_next(struct dlist *l);
/**
* Initialize iterator for traversing a dlist backwards.
*/
void *dlist_iter_end(struct dlist *l);
/**
* Returns current item and advances iterator to previous item in list.
*/
void *dlist_iter_prev(struct dlist *l);
/**
* Check if iterator has reached the start of the list.
*/
bool dlist_iter_has_prev(struct dlist *l);
#endif /* _DLIST_H_ */
/*
* Copyright (c) 2012 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: L. Felipe Perrone (perrone@bucknell.edu)
*/
#ifndef _DNODE_H_
#define _DNODE_H_
/**
* Node in a doubly-linked list.
*/
struct dnode {
struct dnode *prev;
struct dnode *next;
void *data;
int size;
};
/**
* Allocates a new dnode leaving the pointer to data as null.
*
* @return pointer to a new dnode
*/
struct dnode *dnode_create();
/**
* Sets the pointer to data with the value passed in.
*
* @param n pointer to the dnone
* @param ptr pointer to a generic data type to store in dnode
*/
void dnode_setdata(struct dnode *n, void *ptr, int size);
/**
* Deallocates a dnode but not the data it points to. The caller must take
* the responsibility of deallocating the data later on.
*
* @param n pointer to the dnode
* @return pointer to the generic data type associated with node
*/
void *dnode_destroy(struct dnode *n);
/**
* Deallocates a dnode and also the data it points to.
*
* @param ptr pointer to the dnode
*/
void dnode_obliterate(struct dnode *n);
void print_node(struct dnode *node);
#endif /* _DNODE_H_ */
/*
* Copyright (c) 2012 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: L. Felipe Perrone (perrone@bucknell.edu)
*/
#ifndef _READLINE_H_
#define _READLINE_H_
/**
* This function implements a safer way to read strings from a C stream
* (that is, safer than scanf and gets).
*
* The function causes characters to be read one at a time and placed into
* an input buffer that is automatically enlarged to fit the entire string.
* The returned value is a pointer to a dynamically allocated area of
* memory. Note that the caller of this function becomes responsible for
* disposing of the memory allocated for the string read in.
*
* @parm stream Pointer to an open C stream (such as stdin)
* @return A pointer to the line read from source on success or NULL on failure.
*/
extern char*
readline(FILE* stream);
#endif /* _READLINE_H_ */
#include "allocator.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include "dnode.h"
#include "dlist.h"
//struct dnode *dnode_curr;
struct dlist* free_list;
struct dlist* allocated_list;
void* data1;
void* datafirst;
void* databest;
void* dataworst;
int allocator_init(int size){
//void *data;
//struct dnode *node;
allocated_list = dlist_create();
free_list = dlist_create();
data1 = malloc(size);
if (data1 == NULL){
return -1;
}
//free_list dlist_create();
dlist_add_front(free_list, data1, size);
//allocated_list = dlist_create();
return 0;
}
double average_frag(){
struct dnode* iter = dlist_iter_begin(free_list);
double sum = 0;
double count = 0;
do{
sum += iter->size;
count++;
iter = dlist_iter_next(free_list);
}while(iter != NULL);
return (sum/count);
}
int deallocate(void *ptr){
struct dnode* dealloc;
dealloc = dlist_find_remove(allocated_list, ptr);
// printf("%x deallocating node %x, %d", ptr, dealloc->data, dealloc->size);
dlist_add_back(free_list, dealloc->data, dealloc->size);
return 0;
}
void allocator_print() {
// Create iterator to traverse list
struct dnode* iter = dlist_iter_begin(free_list);
printf("\n------------------------\n");
/* Print free list */
printf("Free List: |\n");
do{
printf("Pointer: %p, Size: %d ", iter->data, iter->size);
iter = dlist_iter_next(free_list);
printf("count: %d\n", allocated_list->counter);
}
while(iter);
if (dlist_num_elems(allocated_list) > 0) {
iter = dlist_iter_begin(allocated_list);
/* Print allocated list */
printf("\nAllocated List:\n");
do{
//int* demo = (int*) iter;
printf("Pointer: %p, Size: %d\n", iter->data, iter->size);
iter = dlist_iter_next(allocated_list);
}
while(iter);
}
printf(" |\n");
printf("------------------------\n");
return;
}
struct dnode* first_fit(int size){
//this is where it will check and see if it fits
struct dnode* current = dlist_iter_begin(free_list);
do{
if (size <= current->size){
datafirst = dlist_add_back(allocated_list, current->data, size);
current->size -= size;
current->data += size;
if (0 == current->size){
if (dlist_num_elems(free_list) > 1){
dlist_find_remove(free_list, current);
}
}
break;
}
if (free_list->back == current){
return NULL;
}
current = dlist_iter_next(free_list);
}
while(current);
return datafirst;
}
struct dnode* best_fit(int size){
struct dnode* iter = dlist_iter_begin(free_list);
struct dnode* minimum;
int min_size = 0;
do{
if (size <= iter->size){
if (iter->size <= min_size || min_size == 0){
min_size = iter->size;
minimum = iter;
}
}
iter = dlist_iter_next(free_list);
}
while(iter);
if (min_size == 0){
return NULL;
}
databest = dlist_add_back(allocated_list, minimum->data, size);
minimum->size -= size;
minimum->data += size;
if (0 == minimum->size){
if (dlist_num_elems(free_list) > 1){
dlist_find_remove(free_list, minimum);
}
}
return databest;
}
struct dnode* worst_fit(int size){
struct dnode* iter = dlist_iter_begin(free_list);
struct dnode* maximum;
int max_size = 0;
do{
if (size <= iter->size){
if (iter->size >= max_size || max_size == 0){
max_size = iter->size;
maximum = iter;
}
}
iter = dlist_iter_next(free_list);
}
while (iter);
if (max_size == 0){
return NULL;printf("Casey4\n");
}
dataworst = dlist_add_back(allocated_list, maximum->data, size);
maximum->size -= size;
maximum->data += size;
if (0 == maximum->size){
if (dlist_num_elems(free_list) > 1){
dlist_find_remove(free_list, maximum);
}
}
return dataworst;
}
struct dnode* allocate(int size, int param){
struct dnode* x = NULL;
if (param == 0){
x = first_fit(size);
return x;
}
if (param == 1){
x = best_fit(size);
return x;
}
if (param == 2){
x = worst_fit(size);
return x;
}
return 0;
}
/*
* Copyright (c) 2012 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: L. Felipe Perrone (perrone@bucknell.edu)
*/
#include <stdlib.h>
#include <stdio.h>
#include "dnode.h"
#include "dlist.h"
struct dlist *
dlist_create() {
return calloc(1, sizeof(struct dlist));
}
void
dlist_destroy(struct dlist *l) {
struct dnode *p = l->front;
do {
l->front = l->front->next;
free(p->data);
free(p);
p = l->front;
} while (l->front != NULL);
l->front = l->back = NULL;
l->counter = 0;
}
void
dlist_obliterate(struct dlist *l) {
dlist_destroy(l);
free(l);
}
void
dlist_add_front(struct dlist *l, void *ptr, int size) {
struct dnode *n = dnode_create();
n->data = ptr;
n->size = size;
if (0 == l->counter) {
l->front = l->back = n;
l->counter = 1;
} else {
n->next = l->front;
l->front->prev = n;
l->front = n;
(l->counter)++;
}
#ifdef DEBUG
printf("counter= %d, %s\n", l->counter, (char *) ptr);
printf("front= %s\n", (char *) l->front->data);
printf("back= %s\n\n", (char *) l->back->data);
#endif /* DEBUG */
}
struct dnode*
dlist_add_back(struct dlist *l, void *ptr, int size) {
struct dnode *n = dnode_create();
n->data = ptr;
n->size = size;
if (0 == l->counter) {
l->front = l->back = n;
l->counter = 1;
} else {
n->prev = l->back;
l->back->next = n;
l->back = n;
(l->counter)++;
}
#ifdef DEBUG
printf("counter= %d, %s\n", l->counter, (char *) ptr);
printf("front= %s\n", (char *) l->front->data);
printf("back= %s\n\n", (char *) l->back->data);
#endif /* DEBUG */
return n;
}
struct dnode* dlist_remove_front(struct dlist *l) {
struct dnode *n = l->front;
void* ptr = dnode_create();
dnode_setdata(ptr, n->data, n->size);
if (1 == l->counter) {
l->front = l->back = NULL;
} else {
l->front = l->front->next;
l->front->prev = NULL;
}
(l->counter)--;
free(n);
return ptr;
}
struct dnode*
dlist_remove_back(struct dlist *l) {
struct dnode *n = l->back;
void *ptr = dnode_create();
dnode_setdata(ptr, n->data, n->size);
if (1 == l->counter) {
l->front = l->back = NULL;
} else {
l->back = l->back->prev;
l->back->next = NULL;
}
(l->counter)--;
free(n);
return ptr;
}
struct dnode*
dlist_find_remove(struct dlist *l, void *ptr) {
struct dnode *n = l->front;
struct dnode *ret_ptr = dnode_create();
while ((n != NULL) && (n->data != ptr)) {
n = n->next;
}
if (n != NULL) {
dnode_setdata(ret_ptr, n->data, n->size);
if (l->front == n) {
return dlist_remove_front(l);
} else if (l->back == n) {
return dlist_remove_back(l);
} else {
if (1 == l->counter) {
l->front = l->back = NULL;
} else {
n->prev->next = n->next;
n->next->prev = n->prev;
}
(l->counter)--;
}
//ret_ptr = n->data;
free(n);
}
return ret_ptr;
}
uint32_t
dlist_num_elems(struct dlist *l) {
return l->counter;
}
void *
dlist_iter_begin(struct dlist *l) {
void *ret_val = NULL;
l->iter = l->front;
if (l->iter != NULL) {
ret_val = l->iter;
}
return ret_val;
}
void *
dlist_iter_next