feat: update structure

This commit is contained in:
2024-01-22 14:27:40 +08:00
parent 7836c9185c
commit 3544a28a2e
559 changed files with 120846 additions and 4102 deletions

View File

@@ -0,0 +1,17 @@
#include <stdio.h>
#include "queue.h"
int main() {
double v;
for(int i = 0; i<= MAX_Q_SIZE; i++) {
v = ((double) i / 10.0);
printf("Adding %3.2f\n", v);
enq(v);
}
for(int i = 0; i<= MAX_Q_SIZE; i++) {
v = deq();
printf("Element %d is %3.2f\n", i, v);
}
}

View File

@@ -0,0 +1,31 @@
#include <stdio.h>
int (*fptr)(int);
int func(int x) {
return 2 * x;
}
int y = 10;
int *(*pfptr)();
int *func2() {
return &y;
}
int main() {
printf("Calling func with value 6: %d\n", func(6));
printf("Now setting fptr to point to func.\n");
fptr = func;
printf("Caling fptr with value 6: %d\n", fptr(6));
printf("\nNow caling func2 which returns the address of global variable y: %p\n", func2());
printf("Pointing pfptr to func2.\n");
pfptr = func2;
printf("Now calling fpfptr: %p\n", pfptr());
}

View File

@@ -0,0 +1,83 @@
#include "queue.h"
#include <stdio.h>
static double _queue[MAX_Q_SIZE];
static int _front = 0, _rear = 0;
void enq(double data) {
if ((_front + 1) % MAX_Q_SIZE == _rear){
printf("Error: Queue is full. Item value %3.2f is not added.\n", data);
}
else {
_queue[_front] = data;
_front = (_front + 1) % MAX_Q_SIZE;
}
}
double deq() {
double val = -1;
if (_rear == _front){
printf("Error: Queue is empty. Nothing to return\n");
}
else {
val = _queue[_rear];
_rear = (_rear + 1) % MAX_Q_SIZE;
}
return val;
}
/* This section is for the function pointers exercise */
static double _res;
void sum(double x) {
_res += x;
}
void prod(double x) {
_res *= x;
}
void clear_sum() {
_res = 0;
}
void clear_prod() {
_res = 1.0;
}
double reduce() {
int ndx = _rear;
clear_sum();
while(ndx != _front) {
sum(_queue[ndx]);
ndx = (ndx + 1) % MAX_Q_SIZE;
}
return _res;
}
/* Implement flex_reduce here:
double flex_reduce(clear, op){
// clear(); // Clear _res to either 0 or 1
// for every element in queue:
//Call op with element.
return _res;
}
*/
double flex_reduce(void (*clear)(), void (*op)(double)) {
int ndx = _rear;
clear();
while(ndx != _front) {
op(_queue[ndx]);
ndx = (ndx + 1) % MAX_Q_SIZE;
}
return _res;
}

View File

@@ -0,0 +1,17 @@
// Maximum number of elements in a queue
//
#define MAX_Q_SIZE 10
// Place function prototypes here.
void enq(double);
double deq();
void sum(double);
void prod(double);
void clear_sum();
void clear_prod();
double reduce();
double flex_reduce(void (*)(), void (*)(double));

View File

@@ -0,0 +1,20 @@
#include <stdio.h>
#include "queue.h"
int main() {
int i;
for(i=1; i<=9; i++)
{
printf("Enqueing %d\n", i);
enq((double) i);
}
printf("\nCalling reduce result is %3.2f\n", reduce());
/* Uncomment the following two statements to test flex_reduce */
printf("Calling flex reduce with sum. Result is %3.2f\n", flex_reduce(clear_sum, sum));
printf("Calling flex reduce with prod. Result is %3.2f\n", flex_reduce(clear_prod, prod));
}

View File

@@ -0,0 +1,42 @@
#include <stdio.h>
int *p1, *p2, *p3, *p4;
void fun1(int x, int y) {
static int w;
int z;
w = x * y;
z = x + y;
printf("Inside fun1\n");
p1 = &w;
p2 = &x;
p3 = &y;
p4 = &z;
printf("Address of p1 = %p, address of p2 = %p, address of p3 = %p, address of p4 = %p\n", &p1, &p2, &p3, &p4);
printf("Address of w = %p, address of x = %p, address of y = %p, address of z = %p\n", p1, p2, p3, p4);
printf("w = %d, x = %d, y = %d, z = %d\n", w, x, y, z);
}
int fun2(int f, int g, int h) {
printf("\nInside fun2\n");
printf("w = %d, x = %d, y = %d, z = %d\n", *p1, *p2, *p3, *p4);
return f + g + h;
}
int main() {
int a = 5, b = 6, c;
fun1(a, b);
printf("\nOutside fun1\n");
printf("w = %d, x = %d, y = %d, z = %d\n", *p1, *p2, *p3, *p4);
fun2(1, 2, 3);
printf("\nOutside fun2\n");
printf("w = %d, x = %d, y = %d, z = %d\n", *p1, *p2, *p3, *p4);
}

View File

@@ -0,0 +1,21 @@
#include <stdio.h>
int accumulate(int x) {
// Modify this function so that it accumulates values passed to it to
// a value called "acc".
static int acc = 0;
acc = acc + x;
printf("acc is now %d\n", acc);
}
int main() {
// Call fun2 to accumulate from 1 to 10
for(int i=1; i<=10; i++)
accumulate(i);
}

View File

@@ -0,0 +1,210 @@
#include <stdlib.h>
#include <stdio.h>
#include "bintree.h"
/* ------------------------- DO NOT IMPLEMENT THESE ----------------------
These are provided "free" to you, and you do not need to implement them,
though you MAY need to understand what they do. Some give you hints
on how to work with pointers to pointers. You MAY find some of these
functions useful.
------------------------------------------------------------------------- */
// Searches for the node containing "name" in the tree whose root is at "root",
// returning both the node ifself in "node", and its parent in "prevnode"
// (useful for deleting node). Both "node" and "prevnode" are set to NULL
// if name is not found in the tree.
void findNode(char *name, TTreeNode *root, TTreeNode **node, TTreeNode **prevnode)
{
TTreeNode *trav = root;
TTreeNode *prev = NULL;
while (trav != NULL)
{
int cmp = strcmp(trav->name, name);
if (cmp == 0)
{
*node = trav;
*prevnode = prev;
return;
}
prev = trav;
if (cmp < 0)
trav = trav->right;
else
trav = trav->left;
}
*node = NULL;
*prevnode = NULL;
}
// Searches for the node with the smallest value ("smallest node") in the tree originating at "node".
// Returns the smallest node and its parent in "smallest_node" and "parent"
// respectively.
void findSmallest(TTreeNode *node, TTreeNode **smallest_node, TTreeNode **parent)
{
TTreeNode *trav = node;
TTreeNode *prev = NULL;
if (trav == NULL)
return;
while (trav->left != NULL)
{
prev = trav;
trav = trav->left;
}
*smallest_node = trav;
*parent = prev;
}
// Delete a node at "node" with parent node "prevnode"
void delNode(TTreeNode *node, TTreeNode *prevnode)
{
// This is a leaf node
if (node->left == NULL && node->right == NULL)
{
// See whether node is on parent's left or right, and NULL the
// corresponding pointer
int cmp = strcmp(prevnode->name, node->name);
// Previous node is smaller than this one. This
// node is on the right
if (cmp < 0)
prevnode->right = NULL;
else
prevnode->left = NULL;
freenode(node);
return;
}
// This has a child on the left only
if (node->right == NULL)
{
// Copy the right child over
node = node->left;
freenode(node->left);
return;
}
// This has a child on the right only
if (node->left == NULL)
{
node = node->right;
freenode(node->right);
return;
}
// This has children on both nodes
TTreeNode *smallest, *smallest_parent;
findSmallest(node->right, &smallest, &smallest_parent);
node = smallest;
smallest_parent->left = NULL;
freenode(smallest);
}
/* ---------------------------- IMPLEMENT THESE --------------------------- */
// Create a new node with name set to "name" and
// phoneNum set to "phoneNum".
void delTree(TTreeNode *root)
{
// Implement deleting the entire tree, whose
// root is at "root".
if (root == NULL)
return;
if (root->left != NULL)
delTree(root->left);
if (root->right != NULL)
delTree(root->right);
freenode(root);
}
TTreeNode *makeNewNode(char *name, char *phoneNum)
{
TTreeNode *node = malloc(sizeof(TTreeNode));
node->name = malloc(strlen(name) + 1);
strcpy(node->name, name);
strcpy(node->phoneNum, phoneNum);
node->left = NULL;
node->right = NULL;
return node;
// Implement makeNewNode to create a new
// TTreeNode containing name and phoneNum
}
// Add a new node to the tree.
// Note that "root" is a POINTER to the tree's root,
// not the root itself.
void addNode(TTreeNode **root, TTreeNode *node)
{
if (*root == NULL)
{
*root = node;
}
TTreeNode **trav = root;
while (1)
{
int cmp = strcmp((*trav)->name, node->name);
if (cmp == 0)
return;
if (cmp > 0)
{
if ((*trav)->left == NULL)
(*trav)->left = node;
else
{
trav = &((*trav)->left);
continue;
}
}
else if (cmp < 0)
{
if ((*trav)->right == NULL)
(*trav)->right = node;
else
{
trav = &((*trav)->right);
continue;
}
}
}
// Add a new node to the tree, where root is
// the POINTER to the tree's root.
}
void freenode(TTreeNode *node)
{
free(node->name);
free(node);
// Frees the memory used by node.
}
void print_inorder(TTreeNode *node)
{
// Implement in-order printing of the tree
// Recursion is probably best here.
if (node == NULL)
return;
if (node->left != NULL)
print_inorder(node->left);
printf("Name is %s Number is %s\n", node->name, node->phoneNum);
if (node->right != NULL)
print_inorder(node->right);
}

View File

@@ -0,0 +1,17 @@
#include <string.h>
#include <stdlib.h>
typedef struct tn {
char *name;
char phoneNum[9];
struct tn *left, *right;
} TTreeNode;
void findNode(char *, TTreeNode *, TTreeNode **, TTreeNode **);
void findSmallest(TTreeNode *, TTreeNode **, TTreeNode **);
void delNode(TTreeNode *, TTreeNode *);
void delTree(TTreeNode *);
TTreeNode *makeNewNode(char *, char *);
void addNode(TTreeNode **, TTreeNode *);
void freenode(TTreeNode *);
void print_inorder(TTreeNode *);

Binary file not shown.

View File

@@ -0,0 +1,30 @@
#include <stdio.h>
#include <stdlib.h>
int *p;
void dfun1(int x, int y)
{
int *z;
z = (int *) malloc(sizeof(int));
p = z;
*z = x + y;
printf("Inside dfun1: &x = %p, &y = %p, &z = %p, &p = %p\n", &x, &y, &z, &p);
printf("Address stored in z: %p\n", z);
}
void dfun2() {
printf("Inside dfun2: The value p is pointing to is: %d\n", *p);
}
int main() {
printf("Address stored in p before calling dfun1: %p\n", p);
dfun1(10, 20);
printf("Address stored in p after calling dfun1: %p\n", p);
printf("Value pointed to by p: %d\n", *p);
dfun2();
free(p);
}

View File

@@ -0,0 +1,9 @@
#include <stdlib.h>
#include <stdio.h>
int main() {
int *p = (int *) malloc(sizeof(int));
*p = 5;
printf("p is %p and *p is %d\n", p, *p);
free(p);
}

View File

@@ -0,0 +1,44 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
char *name;
int age;
} TPerson;
TPerson *makeNewNode(char *name, int age) {
TPerson *p = (TPerson *) malloc(sizeof(TPerson));
strcpy(p->name, name);
p->age = age;
return p;
}
void freeNode(TPerson *node) {
free(node);
}
#define NUM_PERSONS 3
int main() {
TPerson persons[NUM_PERSONS] = {{"Tan Ah Kow", 65}, {"Sio Bak Pau", 23},
{"Aiken Dueet", 21}};
TPerson *list[NUM_PERSONS];
int i;
printf("ADDING PERSONS\n");
for(i=0; i<NUM_PERSONS; i++) {
printf("Adding %s aged %d\n", persons[i].name, persons[i].age);
list[i] = makeNewNode(persons[i].name, persons[i].age);
}
printf("\nDELETING PERSONS\n");
for(i=0; i<NUM_PERSONS; i++) {
printf("Deleting %s aged %d\n", list[i]->name, list[i]->age);
freeNode(list[i]);
}
}

View File

@@ -0,0 +1,51 @@
#include <stdio.h>
#include "phonebook.h"
#include "bintree.h"
static TTreeNode *_root = NULL;
char *findPerson(char *name)
{
TTreeNode *node, *prev;
findNode(name, _root, &node, &prev);
if (node != NULL)
return node->phoneNum;
else
return NULL;
}
void print_phonebook()
{
print_inorder(_root);
}
void addPerson(char *name, char *phoneNum)
{
if (findPerson(name) == NULL)
{
TTreeNode *node = makeNewNode(name, phoneNum);
addNode(&_root, node);
}
else
printf("%s is already in phonebook.\n", name);
}
void delPerson(char *name)
{
TTreeNode *node, *prevnode;
findNode(name, _root, &node, &prevnode);
if (node == NULL)
{
printf("Unable to find %s\n", name);
return;
}
delNode(node, prevnode);
}
void delPhonebook()
{
delTree(_root);
_root = NULL;
}

View File

@@ -0,0 +1,5 @@
char *findPerson(char *);
void addPerson(char *, char *);
void delPerson(char *);
void print_phonebook();
void delPhonebook();

View File

@@ -0,0 +1,60 @@
#include <stdio.h>
#include "phonebook.h"
#define ITEMS 5
typedef struct d
{
char *name, *tel;
} TData;
void printResult(char *name)
{
char *result;
printf("Looking for %s ", name);
result = findPerson(name);
if (result == NULL)
printf("NOT FOUND\n");
else
printf(" Number is %s\n", result);
}
int main()
{
TData data[ITEMS] = {{"Fred Astaire", "95551234"}, {"Jean Valjean", "95558764"}, {"Gal Gadot", "95551123"}, {"Aiken Dueet", "95558876"}, {"Victor Hugo", "95524601"}};
int i;
for (i = 0; i < ITEMS; i++)
{
printf("Adding %s, phone number %s\n", data[i].name, data[i].tel);
addPerson(data[i].name, data[i].tel);
}
printf("\nNow retrieiving stored data.\n");
char *result;
for (i = 0; i < ITEMS; i++)
{
printResult(data[i].name);
}
printf("\nRetrieving unknown person.\n");
printResult("Wee Tu Loh");
printf("\nPrinting entire phonebook.\n");
print_phonebook();
printf("\nDeleting Aiken Dueet.\n");
delPerson("Aiken Dueet");
print_phonebook();
printf("\nDeleting Victor Hugo.\n");
delPerson("Victor Hugo");
print_phonebook();
printf("\nDeleting entire phone book.\n");
delPhonebook();
print_phonebook();
}

View File

@@ -0,0 +1,24 @@
#!/bin/bash
# Check if we have enough arguments
# Delete temporary files
# Compile the reference program
# Generate reference output files
# Now mark submissions
#
# Note: See Lab02Qn.pdf for format of output file. Marks will be deducted for missing elements.
#
# Iterate over every submission directory
# Compile C code
# Print compile error message to output file
# Generate output from C code using *.in files in ref
# Compare with reference output files and award 1 mark if they are identical
# print score for student
# print total files marked.

View File

@@ -0,0 +1,5 @@
1
3
5
3
4

View File

@@ -0,0 +1,7 @@
382
44
112
95
hello
world
12

View File

@@ -0,0 +1,4 @@
3.4
5.4
1
2.3

View File

@@ -0,0 +1,42 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "utils.h"
#define MAX_STR_LEN 128
void strip(char *str) {
while(*str) {
if(*str == '\n')
*str = '\0';
str++;
}
}
int main() {
char str[MAX_STR_LEN];
int nums[128];
int count=0;
int res = 0;
while(!feof(stdin)) {
char *res = fgets(str, MAX_STR_LEN, stdin);
if(res){
strip(str);
int val = atoi(str);
if(val){
nums[count++] = val;
}
else
printf("%s is not a non-zero integer.\n", str);
}
}
res = sum(nums, count);
printf("Item count is %d\n", count);
printf("The sum is %d\n", res);
exit(res);
}

View File

@@ -0,0 +1,10 @@
#include "utils.h"
int sum(int sum_array[], int n) {
int i, res = 0;
for(i=0; i<n; i++)
res += sum_array[i];
return res;
}

View File

@@ -0,0 +1,2 @@
int sum(int [], int);

View File

@@ -0,0 +1,42 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "utils.h"
#define MAX_STR_LEN 128
void strip(char *str) {
while(*str) {
if(*str == '\n')
*str = '\0';
str++;
}
}
int main() {
char str[MAX_STR_LEN];
int nums[128];
int count=0;
int res = 0;
while(!feof(stdin)) {
char *res = fgets(str, MAX_STR_LEN, stdin);
if(res){
strip(str);
int val = atoi(str);
if(val){
nums[count++] = val;
}
else
printf("%s is not a non-zero integer.\n", str);
}
}
res = sum(nums, count);
printf("Item count is %d\n", count);
printf("The sum is %d\n", res);
exit(res);
}

View File

@@ -0,0 +1,10 @@
#include "utils.h"
int sum(int sum_array[], int n) {
int i, res = 0;
for(i=0; i<n; i++)
res += sum_array[i];
return res;
}

View File

@@ -0,0 +1,2 @@
int sum(int [], int);

View File

@@ -0,0 +1,40 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "utils.h"
#define MAX_STR_LEN 128
void strip(char *str) {
while(*str) {
if(*str == '\n')
*str = '\0';
str++;
}
}
int main() {
char str[MAX_STR_LEN];
int nums[128];
int count=0;
int res = 0;
while(!feof(stdin)) {
char *res = fgets(str, MAX_STR_LEN, stdin);
if(res){
strip(str);
int val = atoi(str);
if(val){
nums[count++] = val;
}
}
}
res = sum(nums, count);
printf("Item count is %d\n", count);
printf("The sum is %d\n", res);
exit(res);
}

View File

@@ -0,0 +1,10 @@
#include "utils.h"
int sum(int sum_array[], int n) {
int i, res = 0;
for(i=0; i<n; i++)
res += sum_array[i];
return res;
}

View File

@@ -0,0 +1,2 @@
int sum(int [], int);

View File

@@ -0,0 +1,42 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "utils.h"
#define MAX_STR_LEN 128
void strip(char *str) {
while(*str) {
if(*str == '\n')
*str = '\0';
str++;
}
}
int main() {
char str[MAX_STR_LEN];
int nums[128];
int count=0;
int res = 0;
while(!feof(stdin)) {
char *res = fgets(str, MAX_STR_LEN, stdin);
if(res){
strip(str);
int val = atoi(str);
if(val){
nums[count++] = val;
}
else
printf("%s is not a non-zero integer.\n", str);
}
}
res = sum(nums, count);
printf("Item count is %d\n", count);
printf("The sum is %d\n", res);
exit(res);
}

View File

@@ -0,0 +1,10 @@
#include "utils.h"
int sum(int sum_array[], int n) {
int i, res = 0;
for(i=0; i<n; i++)
res += sum_array[i];
return res;
}

View File

@@ -0,0 +1,2 @@
double sum(int [], int);

5
cs2106/labs/lab2/part1/diff.sh Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/bash
x=15
y=20
z=$(($x-$y))
echo "$x - $y = $z"

View File

@@ -0,0 +1,2 @@
This is a text file.
CS2106 Introduction to Operating Systems is a cool module!

View File

@@ -0,0 +1,3 @@
#!/bin/bash
echo "Hello $(whoami), today is $(date)"

View File

@@ -0,0 +1,2 @@
#!/bin/bash
echo "Hello World"

View File

@@ -0,0 +1,29 @@
#include <stdio.h>
// For the sleep functiopn
#include <unistd.h>
// For the atoi function that converts
// strings to integers
#include <stdlib.h>
int main(int ac, char **av) {
if(ac != 2) {
printf("\nCounts from specified integer n to n + 5\n");
printf("Usage: %s <integer>\n\n", av[0]);
exit(-1);
}
int n = atoi(av[1]);
int i;
for(i=n; i<=n+5; i++) {
printf("%d\n", i);
sleep(1);
}
printf("\nFinal value of i is %d\n\n", i);
exit(i);
}

View File

@@ -0,0 +1,13 @@
#include <stdio.h>
#define BUF_SIZE 128
int main() {
char input[128];
char *ret;
while(!feof(stdin)) {
ret = fgets(input, BUF_SIZE - 1, stdin);
if(ret != NULL)
printf("This is what I read: %s\n", input);
}
}

View File

@@ -0,0 +1,2 @@
This is a text file.
CS2106 Introduction to Operating Systems is a cool module!

View File

@@ -0,0 +1,47 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int slow(char *name, int time, int n) {
for(int i=n; i<=n+4; i++) {
printf("%s: i = %d\n", name, i);
sleep(time);
}
}
sdf
asdf
as
dfas
f
int main() {
int id;
if((id = fork()) != 0) {
int stat;
int my_id = getpid();
int parent_id = getppid();
printf("\nI am the parent.\n");
printf("My ID is %d\n", my_id);
printf("My parent's ID is %d\n", parent_id);
printf("My child's ID is %d\n\n", id);
slow("Parent", 1, 5);
printf("\nWaiting for child to exit.\n");
wait(&stat);
printf("CHILD HAS EXITED WITH STATUS %d\n", WEXITSTATUS(stat));
}
else
{
id = getpid();
int parent_id = getppid();
printf("\nI am the child.\n");
printf("My ID is %d\n", id);
printf("My parent's ID is %d\n\n", parent_id);
slow("Child", 2, 10);
exit(25);
}
}

View File

@@ -0,0 +1,17 @@
#include <stdio.h>
int main(int ac, char **av, char **vp) {
printf("ac = %d\n", ac);
printf("Arguments:\n");
int i;
for(i=0; i<ac; i++)
printf("Arg %d is %s\n", i, av[i]);
i=0;
while(vp[i] != NULL) {
printf("Env %d is %s\n", i, vp[i]);
i++;
}
}

View File

@@ -0,0 +1,12 @@
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
int main() {
if(fork() == 0) {
execlp("cat", "cat", "file.txt", NULL);
}
else
wait(NULL);
}

View File

@@ -0,0 +1,24 @@
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
int fp_in = open("./file.txt", O_RDONLY);
int fp_out = open("./talk.out", O_CREAT | O_WRONLY);
if(fork() == 0) {
dup2(fp_in, STDIN_FILENO);
dup2(fp_out, STDOUT_FILENO);
execlp("./talk", "talk", (char *) 0);
close(fp_in);
close(fp_out);
}
else
wait(NULL);
}

View File

@@ -0,0 +1,34 @@
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
int main() {
int p[2];
char str[] = "Hello this is the parent.";
// This creates a pipe. p[0] is the reading end,
// p[1] is the writing end.
if(pipe(p) < 0)
perror("lab2p2e: ");
// We will send a message from father to child
if(fork() != 0) {
close(p[0]); // The the end we are not using.
write(p[1], str, strlen(str));
close(p[1]);
wait(NULL);
}
else
{
char buffer[128];
close(p[1]); // Close the writing end
read(p[0], buffer, 127);
printf("Child got the message \"%s\"\n", buffer);
close(p[0]);
}
}

View File

@@ -0,0 +1,20 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <fcntl.h>
int main() {
printf("Be patient, the program will take around 7 seconds to run.\n");
printf("At the end you can do \"cat results.out\" to see the result.\n");
//
// Add code here to pipe from ./slow 5 to ./talk and redirect
// output of ./talk to results.out
// I.e. your program should do the equivalent of ./slow 5 | talk > results.out
// WITHOUT using | and > from the shell.
//
}

View File

@@ -0,0 +1,29 @@
#include <stdio.h>
// For the sleep functiopn
#include <unistd.h>
// For the atoi function that converts
// strings to integers
#include <stdlib.h>
int main(int ac, char **av) {
if(ac != 2) {
printf("\nCounts from specified integer n to n + 5\n");
printf("Usage: %s <integer>\n\n", av[0]);
exit(-1);
}
int n = atoi(av[1]);
int i;
for(i=n; i<=n+5; i++) {
printf("%d\n", i);
sleep(1);
}
printf("\nFinal value of i is %d\n\n", i);
exit(i);
}

View File

@@ -0,0 +1,13 @@
#include <stdio.h>
#define BUF_SIZE 128
int main() {
char input[128];
char *ret;
while(!feof(stdin)) {
ret = fgets(input, BUF_SIZE - 1, stdin);
if(ret != NULL)
printf("This is what I read: %s\n", input);
}
}

View File

@@ -0,0 +1,56 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#define NUM_PROCESSES 5
int main() {
int i, j, pid;
// We create a new shared variable for our lock
int *lock;
int shmid;
shmid = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0600);
lock = shmat(shmid, NULL, 0);
// If lock is 1, we get to run our code.
lock[0] = 1;
for (i = 0; i < NUM_PROCESSES; i++) {
if ((pid = fork()) == 0) {
break;
}
}
if (pid == 0) {
// Spin lock until lock is 1
while (lock[0] == 0)
;
// Claim to lock
lock[0] = 0;
printf("I am child %d\n", i);
for (j = i * 10; j < i * 10 + 10; j++) {
printf("%d ", j);
fflush(stdout);
usleep(250000);
}
printf("\n\n");
// Release the lock
lock[0] = 1;
} else {
for (i = 0; i < NUM_PROCESSES; i++)
wait(NULL);
shmdt(lock);
shmctl(shmid, IPC_RMID, 0);
}
}

View File

@@ -0,0 +1,47 @@
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#define NUM_PROCESSES 5
int main() {
int shmid;
int i, j, pid;
sem_t* sems[NUM_PROCESSES];
for (int i = 0; i < NUM_PROCESSES; i++) {
shmid = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT | 0600);
sems[i] = (sem_t*)shmat(shmid, NULL, 0);
}
sem_post(sems[0]);
for (int i = 0; i < NUM_PROCESSES; i++) sem_init(sems[i], 1, 0);
// allow the first process to run
sem_post(sems[0]);
for (i = 0; i < NUM_PROCESSES; i++) {
if ((pid = fork()) == 0) {
break;
}
}
if (pid == 0) {
sem_wait(sems[i]);
printf("I am child %d\n", i);
for (j = i * 10; j < i * 10 + 10; j++) {
printf("%d ", j);
fflush(stdout);
usleep(250000);
}
printf("\n\n");
sem_post(sems[i + 1]);
} else {
for (i = 0; i < NUM_PROCESSES; i++) wait(NULL);
}
}

View File

@@ -0,0 +1,43 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#define NUM_PROCESSES 5
int main() {
int i, j, pid;
int *turn;
int shmid;
shmid = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0600);
turn = shmat(shmid, NULL, 0);
turn[0] = 0;
for (i = 0; i < NUM_PROCESSES; i++) {
if ((pid = fork()) == 0) {
break;
}
}
if (pid == 0) {
while (turn[0] != i)
;
printf("I am child %d\n", i);
for (j = i * 10; j < i * 10 + 10; j++) {
printf("%d ", j);
fflush(stdout);
usleep(250000);
}
printf("\n\n");
turn[0] = i + 1;
} else {
for (i = 0; i < NUM_PROCESSES; i++)
wait(NULL);
}
}

View File

@@ -0,0 +1,33 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#define NUM_PROCESSES 5
int main() {
int i, j, pid;
for (i = 0; i < NUM_PROCESSES; i++) {
if ((pid = fork()) == 0) {
break;
}
}
if (pid == 0) {
printf("I am child %d\n", i);
for (j = i * 10; j < i * 10 + 10; j++) {
printf("%d ", j);
fflush(stdout);
usleep(250000);
}
printf("\n\n");
} else {
for (i = 0; i < NUM_PROCESSES; i++)
wait(NULL);
}
}

View File

@@ -0,0 +1,32 @@
//
// Program to create shared semaphores
//
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
int shmid, pid;
sem_t *sem;
shmid = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT | 0600);
sem = (sem_t *)shmat(shmid, NULL, 0);
sem_init(sem, 1, 0);
if ((pid = fork()) != 0) {
printf("Parent!. Making my child wait for 1 second.\n");
sleep(1);
sem_post(sem);
wait(NULL);
sem_destroy(sem);
shmctl(shmid, IPC_RMID, 0);
} else {
sem_wait(sem);
printf("Child! Waited 1 second for parent.\n");
}
}

View File

@@ -0,0 +1,30 @@
//
// Program to create shared semaphores
//
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
sem_t sem;
int pid;
sem_init(&sem, 1, 0);
if ((pid = fork()) != 0) {
printf("Parent! Making my child wait for 1 second.\n");
sleep(1);
sem_post(&sem);
} else {
sem_wait(&sem);
printf("Child! Waited 1 second for parent.\n");
}
if (pid != 0) {
wait(NULL);
sem_destroy(&sem);
}
}

View File

@@ -0,0 +1,55 @@
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
int nproc = 0;
// count must be a semaphore
int *count;
sem_t *barrier;
sem_t *countMut;
int barrierShmId, countShmId, countMutShmId;
void init_barrier(int numproc) {
nproc = numproc;
barrierShmId = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT | 0600);
countMutShmId = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT | 0600);
countShmId = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0600);
barrier = (sem_t *)shmat(barrierShmId, NULL, 0);
countMut = (sem_t *)shmat(countMutShmId, NULL, 0);
count = (int *)shmat(countShmId, NULL, 0);
sem_init(barrier, 1, 0);
sem_init(countMut, 1, 1);
}
void reach_barrier() {
sem_wait(countMut);
*count += 1;
sem_post(countMut);
if (*count == nproc) {
sem_post(barrier);
} else {
sem_wait(barrier);
sem_post(barrier);
}
}
void destroy_barrier(int my_pid) {
if (my_pid != 0) {
sem_destroy(barrier);
sem_destroy(countMut);
shmdt(count);
shmdt(barrier);
shmdt(countMut);
shmctl(countShmId, IPC_RMID, 0);
shmctl(barrierShmId, IPC_RMID, 0);
shmctl(countMutShmId, IPC_RMID, 0);
// Destroy the semaphores and detach
// and free any shared memory. Notice
// that we explicity check that it is
// the parent doing it.
}
}

View File

@@ -0,0 +1,3 @@
void init_barrier(int);
void reach_barrier();
void destroy_barrier(int);

View File

@@ -0,0 +1,48 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/wait.h>
#include "barrier.h"
#define NUM_PROCESSES 6
#define MAX_SLEEP 1000000 // Maximum sleep period in microseconds
int main() {
int i, pid;
int sleep_time[NUM_PROCESSES];
init_barrier(NUM_PROCESSES+1);
srand(time(NULL));
for(i=0; i<NUM_PROCESSES; i++) {
// The children will all slip at different amounts of time
sleep_time[i] = (int) (((float) rand() / RAND_MAX) * MAX_SLEEP);
if((pid = fork()) == 0) {
srand(time(NULL));
break;
}
}
if(pid == 0) {
usleep(sleep_time[i]);
// Reach the barrier.
printf("\tChild %d slept for %3.2f seconds and has now reached the barrier\n", i, sleep_time[i]/1000000.0);
reach_barrier();
}
else {
// Parent will just wait at barrier for all children to return
printf("**Parent waiting for children**\n\n");
reach_barrier();
printf("\n**All the children have returned**\n");
// Clean up the process table
for(i=0; i<NUM_PROCESSES; i++)
wait(NULL);
destroy_barrier(pid);
}
}

View File

@@ -0,0 +1,55 @@
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
int nproc = 0;
// count must be a semaphore
int *count;
sem_t *barrier;
sem_t *countMut;
int barrierShmId, countShmId, countMutShmId;
void init_barrier(int numproc) {
nproc = numproc;
barrierShmId = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT | 0600);
countMutShmId = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT | 0600);
countShmId = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0600);
barrier = (sem_t *)shmat(barrierShmId, NULL, 0);
countMut = (sem_t *)shmat(countMutShmId, NULL, 0);
count = (int *)shmat(countShmId, NULL, 0);
sem_init(barrier, 1, 0);
sem_init(countMut, 1, 1);
}
void reach_barrier() {
sem_wait(countMut);
*count += 1;
sem_post(countMut);
if (*count == nproc) {
sem_post(barrier);
} else {
sem_wait(barrier);
sem_post(barrier);
}
}
void destroy_barrier(int my_pid) {
if (my_pid != 0) {
sem_destroy(barrier);
sem_destroy(countMut);
shmdt(count);
shmdt(barrier);
shmdt(countMut);
shmctl(countShmId, IPC_RMID, 0);
shmctl(barrierShmId, IPC_RMID, 0);
shmctl(countMutShmId, IPC_RMID, 0);
// Destroy the semaphores and detach
// and free any shared memory. Notice
// that we explicity check that it is
// the parent doing it.
}
}

View File

@@ -0,0 +1,3 @@
void init_barrier(int);
void reach_barrier();
void destroy_barrier(int);

View File

@@ -0,0 +1,101 @@
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include "barrier.h"
#include "config.h"
#define NUM_PROCESSES 8
int main() {
int vect[VECT_SIZE];
int pid;
int largestShmId, smallestShmId;
int *largest, *smallest;
init_barrier(NUM_PROCESSES + 1);
largestShmId =
shmget(IPC_PRIVATE, sizeof(int) * NUM_PROCESSES, IPC_CREAT | 0600);
largest = (int *)shmat(largestShmId, NULL, 0);
smallestShmId =
shmget(IPC_PRIVATE, sizeof(int) * NUM_PROCESSES, IPC_CREAT | 0600);
smallest = (int *)shmat(smallestShmId, NULL, 0);
float per_process_raw = (float)VECT_SIZE / NUM_PROCESSES;
int per_process = (int)per_process_raw;
clock_t start, end;
double time_taken;
if (per_process_raw != (float)per_process) {
printf("Vector size of %d is not divisible by %d processes.\n", VECT_SIZE,
NUM_PROCESSES);
exit(-1);
}
srand(24601);
int i;
for (i = 0; i < VECT_SIZE; i++) {
vect[i] = rand();
}
for (i = 0; i < NUM_PROCESSES; i++) {
pid = fork();
if (pid == 0)
break;
}
int j;
int big = -INT_MAX;
int small = INT_MAX;
if (pid == 0) {
int start = i * per_process;
int end = i * per_process + per_process;
for (j = start; j < end; j++) {
if (vect[j] > big)
big = vect[j];
if (vect[j] < small)
small = vect[j];
}
largest[i] = big;
smallest[i] = small;
reach_barrier();
} else {
reach_barrier();
start = clock();
for (j = 0; j < NUM_PROCESSES; j++) {
if (largest[j] > big)
big = largest[j];
if (smallest[j] < small)
small = smallest[j];
}
end = clock();
time_taken = ((double)end - start) / CLOCKS_PER_SEC;
printf("\nNumber of items: %d\n", VECT_SIZE);
printf("Smallest element is %d\n", small);
printf("Largest element is %d\n", big);
printf("Time taken is %3.2fs\n\n", time_taken);
// Clean up process table
for (j = 0; j < NUM_PROCESSES; j++)
wait(NULL);
destroy_barrier(pid);
shmdt(largest);
shmdt(smallest);
shmctl(largestShmId, IPC_RMID, 0);
shmctl(smallestShmId, IPC_RMID, 0);
}
}

View File

@@ -0,0 +1,41 @@
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#include "config.h"
// Sort through an array of VECT_SIZE integers
int main() {
int vect[VECT_SIZE], i;
clock_t start, end;
double time_taken;
srand(24601);
for(i=0; i<VECT_SIZE; i++) {
vect[i] = rand();
}
// Now find smallest and largest
int smallest = INT_MAX;
int largest = -INT_MAX;
start = clock();
for(i=0; i<VECT_SIZE; i++) {
if(vect[i] < smallest) {
smallest = vect[i];
}
if(vect[i] > largest) {
largest = vect[i];
}
}
end = clock();
time_taken = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("\nNumber of items: %d\n", VECT_SIZE);
printf("Smallest element is %d\n", smallest);
printf("Largest element is %d\n", largest);
printf("Time taken is %3.2f seconds\n\n", time_taken);
}

View File

@@ -0,0 +1,3 @@
#define VECT_SIZE 2000000
#define VECT_NAME "vector.dat"

View File

@@ -0,0 +1,19 @@
.PHONY: run
bitmap: bitmap.c testmap.c
gcc $^ -o $@
run-bitmap: bitmap
./bitmap
mymalloc: mymalloc.c testmalloc.c bitmap.c
gcc $^ -o $@
run-mymalloc: mymalloc
./mymalloc
harness: harness.c mymalloc.c bitmap.c
gcc $^ -o $@
run-harness: harness
./harness

BIN
cs2106/labs/lab4/bitmap/bitmap Executable file

Binary file not shown.

View File

@@ -0,0 +1,115 @@
#include "bitmap.h"
#include <stdio.h>
// IMPLEMENTED FOR YOU
// Utility function to print out an array of char as bits
// Print the entire bitmap. Arguments: The bitmap itself, and the length of the
// bitmap Each bit of the bitmap represents 1 byte of memory. 0 = free, 1 =
// allocated. map: The bitmap itself, an array of unsigned char.
// Each bit of the bitmap represents one byte of memory
// len: The length of the bitmap array in characters
//
// Returns: Nothing
void print_map(unsigned char *map, int len) {
int i, j;
for (i = 0; i < len; i++) {
unsigned char mask = 0b10000000;
for (j = 0; j < 8; j++) {
if (map[i] & mask)
printf("1");
else
printf("0");
mask = mask >> 1;
}
printf(" ");
}
printf("\n");
}
// Search the bitmap for the required number of zeroes (representing
// free bytes of memory). Returns index of first stretch of 0s
// that meet the criteria. You can use this as an index into
// an array of char that represents the process heap
// bitmap = Bitmap declared as an array of unsigned char
// len = Length of bitmap in characters
// num_zeroes = Length of string of 0's required
// Returns: Index to stretch of 0's of required length, -1 if no such stretch
// can be found
long search_map(unsigned char *bitmap, int len, long num_zeroes) {
int count = 0;
for (int i = 0; i < len; i++) {
unsigned char mask = 0b10000000;
for (int j = 0; j < 8; j++) {
if ((bitmap[i] & mask) == 0) {
count++;
if (count == num_zeroes) {
return i * 8 + j - num_zeroes + 1;
}
} else {
count = 0;
}
mask >>= 1;
}
}
return -1;
} // main
// Set map bits to 0 or 1 depending on whether value is non-zero
// map = Bitmap, declared as an array of unsigned char
// start = Starting index to mark as 1 or 0
// length = Number of bits to mark
// value = Value to mark the bits as. value = 0 marks the bits
// as 0, non-zero marks the bits as 1
// Returns: Nothing
// start: 7
// length: 4
// value: 1
void set_map(unsigned char *map, long start, long length, int value) {
// printf("set_map with start=%ld, length=%ld val=%d\n", start, length,
// value);
int starting_index = start / 8;
for (int i = 0; i < length; i++) {
int currIdx = (start + i) / 8;
int currOffset = (start + i) % 8;
int mask = 0b10000000;
if (value == 0) {
map[currIdx] &= ~(mask >> currOffset);
} else {
map[currIdx] |= (mask >> currOffset);
}
}
// the ~(1<< offset) is a nice trick to create, for example
// ~(1 << 2) = 1111 1011
// By anding this, you can set the value to 0 for that bit
// map[char_index + length_index] &= ~(1 << length_offset);
// the (1<< offset) is a nice trick to create, for example
// (1 << 2) = 0000 0100
// likewise, set the given bit to 1
// map[char_index + length_index] |= (1 << length_offset);
}
// IMPLEMENTED FOR YOU
// Marks a stretch of bits as "1", representing allocated memory
// map = Bitmap declared as array of unsigned char
// start = Starting index to mark
// length = Number of bits to mark as "1"
void allocate_map(unsigned char *map, long start, long length) {
set_map(map, start, length, 1);
}
// IMPLEMENTED FOR YOU
// Marks a stretch of bits as "0", representing allocated memory
// map = Bitmap declared as array of unsigned char
// start = Starting index to mark
// length = Number of bits to mark as "0"
void free_map(unsigned char *map, long start, long length) {
set_map(map, start, length, 0);
}

View File

@@ -0,0 +1,40 @@
/* Bitmap management
The bitmap should be an array of unsigned char.
*/
// Used by test harness
long get_index(void *ptr);
// Utility function to print out an array of char as bits
// Print the entire bitmap. Arguments: The bitmap itself, and the length of the
// bitmap Each bit of the bitmap represents 1 byte of memory. 0 = free, 1 =
// allocated. map: The bitmap itself, an array of unsigned char.
// Each bit of the bitmap represents one byte of memory
// len: The length of the bitmap array in characters
//
// Returns: Nothing
void print_map(unsigned char *map, int len);
// Search the bitmap for the required number of zeroes (representing
// free bytes of memory). Returns index of first stretch of 0s
// that meet the criteria. You can use this as an index into
// an array of char that represents the process heap
// bitmap = Bitmap declared as an array of unsigned char
// len = Length of bitmap in characters
// num_zeroes = Length of string of 0's required
// Returns: Index to stretch of 0's of required length
long search_map(unsigned char *bitmap, int len, long num_zeroes);
// Marks a stretch of bits as "1", representing allocated memory
// map = Bitmap declared as array of unsigned char
// start = Starting index to mark
// length = Number of bits to mark as "1"
void allocate_map(unsigned char *map, long start, long length);
// Marks a stretch of bits as "0", representing allocated memory
// map = Bitmap declared as array of unsigned char
// start = Starting index to mark
// length = Number of bits to mark as "0"
void free_map(unsigned char *, long, long);

BIN
cs2106/labs/lab4/bitmap/harness Executable file

Binary file not shown.

View File

@@ -0,0 +1,52 @@
#include <stdio.h>
#include <assert.h>
#include "mymalloc.h"
void *runmalloc(size_t len, long expected_ndx) {
long ndx;
void *ptr;
printf("Allocate %ld bytes.\n", len);
printf("Before: ");
print_memlist();
ptr = mymalloc(len);
printf("After: ");
print_memlist();
ndx = get_index((void *) ptr);
printf("\n");
assert(ndx == expected_ndx);
return ptr;
}
void runfree(void *ptr) {
printf("Free\n");
printf("Before: ");
print_memlist();
myfree(ptr);
printf("After: ");
print_memlist();
printf("\n");
}
int main() {
void *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
ptr1 = runmalloc(4, 0);
ptr2 = runmalloc(32, 4);
ptr3 = runmalloc(2, 36);
runfree(ptr2);
ptr2 = runmalloc(12, 4);
ptr4 = runmalloc(24, 38);
ptr5 = runmalloc(18, 16);
runfree(ptr1);
ptr1 = runmalloc(2, 0);
runfree(ptr1);
runfree(ptr2);
runfree(ptr3);
runfree(ptr4);
runfree(ptr5);
}

View File

@@ -0,0 +1,239 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "llist.h"
//#define DEBUG // Enable debug printing
// Debug printer
void dbprintf(char *format, ...) {
#ifdef DEBUG
va_list args;
va_start(args, format);
vprintf(format, args);
#endif
}
// Implements a double linked list.
// Create a new node. You need to
// Create your own TData node, populate
// it, then create a new node with a suitable
// key. Insertion into the link list is
// by ascending order of the key. An example key
// might be the starting address of a memory segment.
TNode *make_node(unsigned int key, TData *data) {
TNode *node = malloc(sizeof(TNode));
node->key = key;
node->pdata = data;
node->prev = NULL;
node->next = NULL;
return node;
}
// Inserts a node into the correct point of the
// double linked list. The list is sorted
// in ascending order of the key. Duplicate keys
// are permitted, though not recommended.
// llist = Pointer to link list
// node = Pointer to node created by make_node
// dir = 0: Insert in ascending order
// dir = 1: Insert in descending order
void insert_node(TNode **llist, TNode *node, int dir) {
if(*llist == NULL) {
*llist = node;
(*llist)->trav = *llist;
(*llist)->tail = *llist;
}
else
if(((*llist)->key >= node->key && dir == 0) || (((*llist)->key <= node->key) && dir == 1)) {
node->next = *llist;
(*llist)->prev = node;
*llist = node;
(*llist)->trav = *llist;
}
else
{
TNode *trav = *llist;
if(dir == 0)
while(trav->next != NULL && trav->key < node->key)
trav = trav->next;
else if(dir == 1)
while(trav->next != NULL && trav->key > node->key)
trav = trav->next;
if(trav->next == NULL && ((trav->key < node->key && dir == 0) ||
(trav->key > node->key && dir == 1))) {
trav->next = node;
node->prev = trav;
// Set the tail
(*llist)->tail = node;
} else {
// Insert into the previous space
node->next = trav;
if(trav->prev != NULL) {
trav->prev->next = node;
node->prev = trav->prev;
}
if(trav->next != NULL) {
}
trav->prev = node;
}
}
}
// Remove a given node from the linked list
void delete_node(TNode **llist, TNode *node) {
if(*llist == NULL || node == NULL)
return;
if((*llist)->key == node->key) {
// Node to be deleted is at the front of the list.
*llist = (*llist)->next;
// Ensure that we don't point to it anymore.
if(*llist != NULL)
(*llist)->prev = NULL;
}
else
{
TNode *trav = *llist;
while(trav != NULL && trav->key != node->key)
trav = trav->next;
// We've found the deletion point
if(trav != NULL) {
trav->prev->next = trav->next;
if(trav->next != NULL)
trav->next->prev = trav->prev;
else
(*llist)->tail = trav->prev;
}
}
free(node);
}
// Find a node that has the value of key
// If there are duplicate keys, the first one encountered
// will be returned.
TNode *find_node(TNode *llist, unsigned int key) {
if(llist == NULL)
return NULL;
TNode *trav = llist;
while(trav != NULL && trav->key != key)
trav = trav->next;
return trav;
}
// Merge the node provided with either the node after or the node before.
// You need to manage merging the data in node->pdata yourself. This code just
// deletes the larger of the two nodes.
// dir = 0: Merge with node before
// dir = 1: Merge with node after
void merge_node(TNode *llist, TNode *node, int dir) {
if(dir == 0) {
if(node->prev == NULL)
return;
delete_node(&llist, node);
}
else
if(dir == 1) {
if(node->next == NULL)
return;
delete_node(&llist, node->next);
}
}
// Go over every element of llist, and call func
// func prototype is void func(TNode *);
void process_list(TNode *llist, void (*func)(TNode *)) {
TNode *trav = llist;
while(trav) {
func(trav);
trav = trav->next;
}
}
// Purge the entire list. You must
// free any dynamic data in the TData
// struct yourself.
void purge_list(TNode **llist) {
TNode *trav = *llist, *tmp;
while(trav) {
tmp = trav->next;
free(trav);
trav = tmp;
}
*llist = NULL;
}
// Reset traverser
// where=0 START: Resets traverser to start of list
// where=1 END: Rsets
void reset_traverser(TNode *llist, int where)
{
if(llist == NULL)
return;
if(where == FRONT)
llist->trav = llist;
else
if(where == REAR)
llist->trav = llist->tail;
}
// Get the next node
TNode *succ(TNode *llist)
{
if(llist == NULL)
return NULL;
TNode *ret = llist->trav;
if(llist->trav != NULL)
llist->trav = llist->trav->next;
return ret;
}
// Get the previous node
TNode *pred(TNode *llist)
{
if(llist == NULL)
return NULL;
TNode *ret = llist->trav;
if(llist->trav != NULL)
llist->trav = llist->trav->prev;
return ret;
}

View File

@@ -0,0 +1,113 @@
// Uncomment the next line to enable debug printing
#define DEBUG // Enable debug printing
// The debug printer; used like a normal printf, except
// that printing can be turned off by commenting out the
// #define DEBUG above.
void dbprintf(char *format, ...);
// You should modify this structure to hold
// whatever you need to implement your
// memory manager
typedef struct td {
size_t len;
} TData;
/* -----------------------------------------
BASIC ROUTINES
Basic linked list routines
---------------------------------------- */
// Basic double linked list node.
typedef struct tn {
unsigned int key;
TData *pdata; // Pointer to the data you want to store
struct tn *trav; // Only used in the root for traversal
struct tn *tail; // Only used in the root for finding the end of the list
struct tn *prev;
struct tn *next;
} TNode;
// Insert Direction
#define ASCENDING 0
#define DESCENDING 1
// Merge direction
#define PRECEDING 0
#define SUCCEEDING 1
// Traverser position
#define FRONT 0
#define REAR 1
// Create a new node. You need to
// Create your own TData node, populate
// it, then create a new node with a suitable
// key. Insertion into the link list is
// by ascending order of the key. An example key
// might be the starting address of a memory segment.
TNode *make_node(unsigned int key, TData *data);
// Inserts a node into the correct point of the
// double linked list. The list is sorted
// in ascending order of the key. Duplicate keys
// are permitted, though not recommended.
// llist = Pointer to link list
// node = Pointer to node created by make_node
// dir = 0: Insert in ascending order
// dir = 1: Insert in descending order
void insert_node(TNode **llist, TNode *node, int dir);
// Remove a given node from the linked list
void delete_node(TNode **llist, TNode *node);
// Find a node that has the value of key
// If there are duplicate keys, the first one encountered
// will be returned.
TNode *find_node(TNode *llist, unsigned int key);
// Merge the node provided with either the node after or the node before.
// You need to manage merging the data in node->pdata yourself. This code just
// deletes the larger of the two nodes.
// dir = 0: Merge with node before
// dir = 1: Merge with node after
void merge_node(TNode *llist, TNode *node, int dir);
// Purge the entire list. You must
// free any dynamic data in the TData
// struct yourself.
void purge_list(TNode **llist);
/* -----------------------------------------
TRAVERSAL ROUTINES
Lets you traverse the linked list
---------------------------------------- */
// Go over every element of llist, and call func
// func prototype is void func(TNode *);
void process_list(TNode *llist, void (*func)(TNode *));
// Reset traverser
// where=0 START: Resets traverser to start of list
// where=1 END: Rsets
void reset_traverser(TNode *llist, int where);
// Get the next node
TNode *succ(TNode *llist);
// Get the previous node
TNode *pred(TNode *llist);

BIN
cs2106/labs/lab4/bitmap/mymalloc Executable file

Binary file not shown.

View File

@@ -0,0 +1,40 @@
#include "mymalloc.h"
#include "bitmap.h"
#include <stdio.h>
#include <stdlib.h>
char _heap[MEMSIZE] = {0};
unsigned char _bitmap[BITMAP_SIZE] = {};
char lens[MEMSIZE] = {0};
// Do not change this. Used by the test harness.
// You may however use this function in your code if necessary.
long get_index(void *ptr) {
if (ptr == NULL)
return -1;
else
return (long)((char *)ptr - &_heap[0]);
}
void print_memlist() { print_map(_bitmap, BITMAP_SIZE); }
// Allocates size bytes of memory and returns a pointer
// to the first byte.
void *mymalloc(size_t size) {
long start = search_map(_bitmap, BITMAP_SIZE, size);
if (start == -1)
return NULL;
allocate_map(_bitmap, start, size);
lens[start] = size;
return (void *)(&_heap[start]);
}
// Frees memory pointer to by ptr.
void myfree(void *ptr) {
if (ptr == NULL)
return;
long ptrIdx = get_index(ptr);
long size = lens[ptrIdx];
free_map(_bitmap, ptrIdx, size);
lens[ptrIdx] = 0;
}

View File

@@ -0,0 +1,12 @@
#include "stdio.h"
#define MEMSIZE 64 // Size of memory in bytes
#define BITMAP_SIZE 8 // Size of Bitmap
// Used by the test harness
long get_index(void *ptr);
// Debugging routine
void print_memlist();
void *mymalloc(size_t);
void myfree(void *);

View File

@@ -0,0 +1,35 @@
#include "mymalloc.h"
#include <stdio.h>
void testalloc(long size, char *ptrname, char **ptr) {
printf("\nAllocating %ld bytes to %s\n", size, ptrname);
*ptr = mymalloc(size);
if (*ptr == NULL)
printf("Allocation failed.\n");
print_memlist();
}
void testfree(char *ptr, char *ptrname) {
printf("\nFreeing %s\n", ptrname);
myfree(ptr);
print_memlist();
}
int main() {
char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
testalloc(4, "ptr1", &ptr1);
testalloc(32, "ptr2", &ptr2);
testalloc(4, "ptr3", &ptr3);
testfree(ptr2, "ptr2");
testalloc(24, "ptr2", &ptr2);
testalloc(6, "ptr4", &ptr4);
testfree(ptr2, "ptr2");
testalloc(32, "ptr5", &ptr5);
testfree(ptr1, "ptr1");
testfree(ptr2, "ptr2");
testfree(ptr3, "ptr3");
testfree(ptr4, "ptr4");
testfree(ptr5, "ptr5");
}

View File

@@ -0,0 +1,54 @@
#include <stdio.h>
#include <assert.h>
#include "bitmap.h"
#define LEN 5
void print_result(unsigned char *map, int len, long length, long expected) {
long ndx = search_map(map, len, length);
printf("Length: %ld, Expected: %ld, Actual: %ld\n", length, expected, ndx);
// This will cause a crash if the index returned does not match what is expected
assert(ndx == expected);
}
int main() {
unsigned char map[LEN] = {0b11001000, 0b00011111, 0b00001100, 0b11000000, 0b00000001};
int ndx;
printf("\n");
print_result(map, LEN, 2, 2);
print_result(map, LEN, 4, 5);
print_result(map, LEN, 6, 5);
print_result(map, LEN, 12, 26);
print_result(map, LEN, 128, -1);
// Allocate map
printf("\nAllocating 2 bytes\n");
printf("BEFORE: ");
print_map(map, LEN);
ndx = search_map(map, LEN, 2);
allocate_map(map, ndx, 2);
printf("AFTER: ");
print_map(map, LEN);
printf("\n");
printf("Allocating 12 bytes\n");
printf("BEFORE: ");
print_map(map, LEN);
ndx = search_map(map, LEN, 12);
allocate_map(map, ndx, 12);
printf("AFTER: ");
print_map(map, LEN);
printf("\n");
print_result(map, LEN, 12, -1);
printf("Freeing 12 bytes\n");
printf("BEFORE: ");
print_map(map, LEN);
free_map(map, ndx, 12);
printf("AFTER: ");
print_map(map, LEN);
printf("\n");
print_result(map, LEN, 12, 26);
}

View File

@@ -0,0 +1,13 @@
.PHONY: run test
run: harness-bf
./harness-bf
test: testmalloc
./testmalloc
harness-bf: harness-bf.c llist.c mymalloc.c
gcc $^ -o $@
testmalloc: testmalloc.c mymalloc.c llist.c
gcc $^ -o $@

View File

@@ -0,0 +1,55 @@
#include <stdio.h>
#include <assert.h>
#include "mymalloc.h"
void *runmalloc(size_t len, long expected_ndx) {
long ndx;
void *ptr;
printf("Allocate %ld bytes.\n", len);
printf("Before: ");
print_memlist();
printf("\n");
ptr = mymalloc(len);
ndx = get_index((void *) ptr);
printf("EXPECTED: %ld ACTUAL: %ld\n", expected_ndx, ndx);
printf("After: ");
print_memlist();
printf("\n");
assert(ndx == expected_ndx);
return ptr;
}
void runfree(void *ptr) {
printf("Free\n");
printf("Before: ");
print_memlist();
printf("\n");
myfree(ptr);
printf("After: ");
print_memlist();
printf("\n");
}
int main() {
void *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
ptr1 = runmalloc(4, 0);
ptr2 = runmalloc(32, 4);
ptr3 = runmalloc(2, 36);
runfree(ptr2);
ptr2 = runmalloc(12, 4);
ptr4 = runmalloc(24, 38);
ptr5 = runmalloc(18, 16);
runfree(ptr1);
ptr1 = runmalloc(2, 34);
runfree(ptr1);
runfree(ptr2);
runfree(ptr3);
runfree(ptr4);
runfree(ptr5);
}

View File

@@ -0,0 +1,239 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "llist.h"
//#define DEBUG // Enable debug printing
// Debug printer
void dbprintf(char *format, ...) {
#ifdef DEBUG
va_list args;
va_start(args, format);
vprintf(format, args);
#endif
}
// Implements a double linked list.
// Create a new node. You need to
// Create your own TData node, populate
// it, then create a new node with a suitable
// key. Insertion into the link list is
// by ascending order of the key. An example key
// might be the starting address of a memory segment.
TNode *make_node(unsigned int key, TData *data) {
TNode *node = malloc(sizeof(TNode));
node->key = key;
node->pdata = data;
node->prev = NULL;
node->next = NULL;
return node;
}
// Inserts a node into the correct point of the
// double linked list. The list is sorted
// in ascending order of the key. Duplicate keys
// are permitted, though not recommended.
// llist = Pointer to link list
// node = Pointer to node created by make_node
// dir = 0: Insert in ascending order
// dir = 1: Insert in descending order
void insert_node(TNode **llist, TNode *node, int dir) {
if(*llist == NULL) {
*llist = node;
(*llist)->trav = *llist;
(*llist)->tail = *llist;
}
else
if(((*llist)->key >= node->key && dir == 0) || (((*llist)->key <= node->key) && dir == 1)) {
node->next = *llist;
(*llist)->prev = node;
*llist = node;
(*llist)->trav = *llist;
}
else
{
TNode *trav = *llist;
if(dir == 0)
while(trav->next != NULL && trav->key < node->key)
trav = trav->next;
else if(dir == 1)
while(trav->next != NULL && trav->key > node->key)
trav = trav->next;
if(trav->next == NULL && ((trav->key < node->key && dir == 0) ||
(trav->key > node->key && dir == 1))) {
trav->next = node;
node->prev = trav;
// Set the tail
(*llist)->tail = node;
} else {
// Insert into the previous space
node->next = trav;
if(trav->prev != NULL) {
trav->prev->next = node;
node->prev = trav->prev;
}
if(trav->next != NULL) {
}
trav->prev = node;
}
}
}
// Remove a given node from the linked list
void delete_node(TNode **llist, TNode *node) {
if(*llist == NULL || node == NULL)
return;
if((*llist)->key == node->key) {
// Node to be deleted is at the front of the list.
*llist = (*llist)->next;
// Ensure that we don't point to it anymore.
if(*llist != NULL)
(*llist)->prev = NULL;
}
else
{
TNode *trav = *llist;
while(trav != NULL && trav->key != node->key)
trav = trav->next;
// We've found the deletion point
if(trav != NULL) {
trav->prev->next = trav->next;
if(trav->next != NULL)
trav->next->prev = trav->prev;
else
(*llist)->tail = trav->prev;
}
}
free(node);
}
// Find a node that has the value of key
// If there are duplicate keys, the first one encountered
// will be returned.
TNode *find_node(TNode *llist, unsigned int key) {
if(llist == NULL)
return NULL;
TNode *trav = llist;
while(trav != NULL && trav->key != key)
trav = trav->next;
return trav;
}
// Merge the node provided with either the node after or the node before.
// You need to manage merging the data in node->pdata yourself. This code just
// deletes the larger of the two nodes.
// dir = 0: Merge with node before
// dir = 1: Merge with node after
void merge_node(TNode *llist, TNode *node, int dir) {
if(dir == 0) {
if(node->prev == NULL)
return;
delete_node(&llist, node);
}
else
if(dir == 1) {
if(node->next == NULL)
return;
delete_node(&llist, node->next);
}
}
// Go over every element of llist, and call func
// func prototype is void func(TNode *);
void process_list(TNode *llist, void (*func)(TNode *)) {
TNode *trav = llist;
while(trav) {
func(trav);
trav = trav->next;
}
}
// Purge the entire list. You must
// free any dynamic data in the TData
// struct yourself.
void purge_list(TNode **llist) {
TNode *trav = *llist, *tmp;
while(trav) {
tmp = trav->next;
free(trav);
trav = tmp;
}
*llist = NULL;
}
// Reset traverser
// where=0 START: Resets traverser to start of list
// where=1 END: Rsets
void reset_traverser(TNode *llist, int where)
{
if(llist == NULL)
return;
if(where == FRONT)
llist->trav = llist;
else
if(where == REAR)
llist->trav = llist->tail;
}
// Get the next node
TNode *succ(TNode *llist)
{
if(llist == NULL)
return NULL;
TNode *ret = llist->trav;
if(llist->trav != NULL)
llist->trav = llist->trav->next;
return ret;
}
// Get the previous node
TNode *pred(TNode *llist)
{
if(llist == NULL)
return NULL;
TNode *ret = llist->trav;
if(llist->trav != NULL)
llist->trav = llist->trav->prev;
return ret;
}

View File

@@ -0,0 +1,115 @@
#include <stdbool.h>
#include <stdio.h>
// Uncomment the next line to enable debug printing
#define DEBUG // Enable debug printing
// The debug printer; used like a normal printf, except
// that printing can be turned off by commenting out the
// #define DEBUG above.
void dbprintf(char *format, ...);
// You should modify this structure to hold
// whatever you need to implement your
// memory manager. You can delete the
// val field. It is only used for testlist.c
typedef struct td {
bool occupied;
size_t size;
} TData;
/* -----------------------------------------
BASIC ROUTINES
Basic linked list routines
---------------------------------------- */
// Basic double linked list node.
typedef struct tn {
unsigned int key;
TData *pdata; // Pointer to the data you want to store
struct tn *trav; // Only used in the root for traversal
struct tn *tail; // Only used in the root for finding the end of the list
struct tn *prev;
struct tn *next;
} TNode;
// Insert Direction
#define ASCENDING 0
#define DESCENDING 1
// Merge direction
#define PRECEDING 0
#define SUCCEEDING 1
// Traverser position
#define FRONT 0
#define REAR 1
// Create a new node. You need to
// Create your own TData node, populate
// it, then create a new node with a suitable
// key. Insertion into the link list is
// by ascending order of the key. An example key
// might be the starting address of a memory segment.
TNode *make_node(unsigned int key, TData *data);
// Inserts a node into the correct point of the
// double linked list. The list is sorted
// in ascending order of the key. Duplicate keys
// are permitted, though not recommended.
// llist = Pointer to link list
// node = Pointer to node created by make_node
// dir = 0: Insert in ascending order
// dir = 1: Insert in descending order
void insert_node(TNode **llist, TNode *node, int dir);
// Remove a given node from the linked list
void delete_node(TNode **llist, TNode *node);
// Find a node that has the value of key
// If there are duplicate keys, the first one encountered
// will be returned.
TNode *find_node(TNode *llist, unsigned int key);
// Merge the node provided with either the node after or the node before.
// You need to manage merging the data in node->pdata yourself. This code just
// deletes the larger of the two nodes.
// dir = 0: Merge with node before
// dir = 1: Merge with node after
void merge_node(TNode *llist, TNode *node, int dir);
// Purge the entire list. You must
// free any dynamic data in the TData
// struct yourself.
void purge_list(TNode **llist);
/* -----------------------------------------
TRAVERSAL ROUTINES
Lets you traverse the linked list
---------------------------------------- */
// Go over every element of llist, and call func
// func prototype is void func(TNode *);
void process_list(TNode *llist, void (*func)(TNode *));
// Reset traverser
// where=0 START: Resets traverser to start of list
// where=1 END: Rsets
void reset_traverser(TNode *llist, int where);
// Get the next node
TNode *succ(TNode *llist);
// Get the previous node
TNode *pred(TNode *llist);

View File

@@ -0,0 +1,103 @@
#include "mymalloc.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/_types/_null.h>
#include "llist.h"
char _heap[MEMSIZE] = {0};
TNode *_memlist = NULL; // To maintain information about length
// Do not change this. Used by the test harness.
// You may however use this function in your code if necessary.
long get_index(void *ptr) {
if (ptr == NULL)
return -1;
else
return (long)((char *)ptr - &_heap[0]);
}
// Allocates size bytes of memory and returns a pointer
// to the first byte.
void *mymalloc(size_t size) {
if (_memlist == NULL) {
TData *data = malloc(sizeof(TData));
data->occupied = false;
data->size = MEMSIZE;
_memlist = make_node(0, data);
}
// loop through the list to find a free block
// if found, split the block and return the pointer
// if not found, return NULL
TNode *curr = _memlist;
TNode *best = NULL;
while (curr != NULL) {
if (curr->pdata->occupied == true) {
curr = curr->next;
continue;
}
if (curr->pdata->size < size) {
curr = curr->next;
continue;
}
if (best == NULL) {
best = curr;
curr = curr->next;
continue;
}
if (best->pdata->size > curr->pdata->size) {
best = curr;
curr = curr->next;
continue;
}
curr = curr->next;
}
if (best == NULL)
return NULL;
best->pdata->occupied = true;
if (best->pdata->size > size) {
// Create a new node with the leftover space
TData *newData = malloc(sizeof(TData));
newData->occupied = false;
newData->size = best->pdata->size - size;
TNode *newNode = make_node(best->key + size, newData);
// insert new node after the current one in the list.
insert_node(&_memlist, newNode, 0);
// change the size of the current node.
best->pdata->size = size;
}
return &_heap[best->key];
}
// Frees memory pointer to by ptr.
void myfree(void *ptr) {
if (ptr == NULL)
return;
long index = get_index(ptr);
TNode *node = find_node(_memlist, index);
if (node == NULL)
return;
node->pdata->occupied = false;
// merge with the next node if it is free
while (node->next != NULL && node->next->pdata->occupied == false) {
node->pdata->size += node->next->pdata->size;
merge_node(_memlist, node, 1);
}
while (node->prev != NULL && node->prev->pdata->occupied == false) {
TNode *prev = node->prev;
prev->pdata->size += node->pdata->size;
merge_node(_memlist, node, 0);
}
}
void print_node(TNode *node) {
printf("Status: %s Start index: %d Length: %zu\n",
node->pdata->occupied ? "ALLOCATED" : "FREE", node->key,
node->pdata->size);
}
void print_memlist() { process_list(_memlist, print_node); }

View File

@@ -0,0 +1,7 @@
#include <stdio.h>
#define MEMSIZE 64 * 1024 // Size of memory in bytes
long get_index(void *ptr);
void print_memlist();
void *mymalloc(size_t);
void myfree(void *);

Binary file not shown.

View File

@@ -0,0 +1,36 @@
#include <stdio.h>
#include "mymalloc.h"
void testalloc(long size, char *ptrname, char **ptr) {
printf("\nAllocating %ld bytes to %s\n", size, ptrname);
*ptr = mymalloc(size);
if(*ptr == NULL)
printf("Allocation failed.\n");
print_memlist();
}
void testfree(char *ptr, char *ptrname) {
printf("\nFreeing %s\n", ptrname);
myfree(ptr);
print_memlist();
}
int main() {
char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
testalloc(2048, "ptr1", &ptr1);
testalloc(6144, "ptr2", &ptr2);
testalloc(1024, "ptr3", &ptr3);
testfree(ptr2, "ptr2");
testalloc(2048, "ptr2", &ptr2);
testalloc(4096, "ptr4", &ptr4);
testfree(ptr2, "ptr2");
testalloc(3072, "ptr5", &ptr5);
testfree(ptr1, "ptr1");
testfree(ptr2, "ptr2");
testfree(ptr3, "ptr3");
testfree(ptr4, "ptr4");
testfree(ptr5, "ptr5");
}

View File

@@ -0,0 +1,14 @@
.PHONY: run test
run: harness-ff
./harness-ff
test: testmalloc
./testmalloc
harness-ff: harness-ff.c llist.c mymalloc.c
gcc $^ -o $@
testmalloc: testmalloc.c mymalloc.c llist.c
gcc $^ -o $@

View File

@@ -0,0 +1,54 @@
#include "llist.h"
#include "mymalloc.h"
#include <assert.h>
#include <stdio.h>
void *runmalloc(size_t len, long expected_ndx) {
long ndx;
void *ptr;
printf("Allocate %ld bytes.\n", len);
printf("Before: ");
print_memlist();
printf("\n");
ptr = mymalloc(len);
ndx = get_index((void *)ptr);
printf("EXPECTED: %ld ACTUAL: %ld\n", expected_ndx, ndx);
printf("After: ");
print_memlist();
printf("\n");
assert(ndx == expected_ndx);
return ptr;
}
void runfree(void *ptr) {
printf("Free\n");
printf("Before: ");
print_memlist();
printf("\n");
myfree(ptr);
printf("After: ");
print_memlist();
printf("\n");
}
int main() {
void *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
ptr1 = runmalloc(4, 0);
ptr2 = runmalloc(32, 4);
ptr3 = runmalloc(2, 36);
runfree(ptr2);
ptr2 = runmalloc(12, 4);
ptr4 = runmalloc(24, 38);
ptr5 = runmalloc(18, 16);
runfree(ptr1);
ptr1 = runmalloc(2, 0);
runfree(ptr1);
runfree(ptr2);
runfree(ptr3);
runfree(ptr4);
runfree(ptr5);
}

View File

@@ -0,0 +1,239 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "llist.h"
//#define DEBUG // Enable debug printing
// Debug printer
void dbprintf(char *format, ...) {
#ifdef DEBUG
va_list args;
va_start(args, format);
vprintf(format, args);
#endif
}
// Implements a double linked list.
// Create a new node. You need to
// Create your own TData node, populate
// it, then create a new node with a suitable
// key. Insertion into the link list is
// by ascending order of the key. An example key
// might be the starting address of a memory segment.
TNode *make_node(unsigned int key, TData *data) {
TNode *node = malloc(sizeof(TNode));
node->key = key;
node->pdata = data;
node->prev = NULL;
node->next = NULL;
return node;
}
// Inserts a node into the correct point of the
// double linked list. The list is sorted
// in ascending order of the key. Duplicate keys
// are permitted, though not recommended.
// llist = Pointer to link list
// node = Pointer to node created by make_node
// dir = 0: Insert in ascending order
// dir = 1: Insert in descending order
void insert_node(TNode **llist, TNode *node, int dir) {
if(*llist == NULL) {
*llist = node;
(*llist)->trav = *llist;
(*llist)->tail = *llist;
}
else
if(((*llist)->key >= node->key && dir == 0) || (((*llist)->key <= node->key) && dir == 1)) {
node->next = *llist;
(*llist)->prev = node;
*llist = node;
(*llist)->trav = *llist;
}
else
{
TNode *trav = *llist;
if(dir == 0)
while(trav->next != NULL && trav->key < node->key)
trav = trav->next;
else if(dir == 1)
while(trav->next != NULL && trav->key > node->key)
trav = trav->next;
if(trav->next == NULL && ((trav->key < node->key && dir == 0) ||
(trav->key > node->key && dir == 1))) {
trav->next = node;
node->prev = trav;
// Set the tail
(*llist)->tail = node;
} else {
// Insert into the previous space
node->next = trav;
if(trav->prev != NULL) {
trav->prev->next = node;
node->prev = trav->prev;
}
if(trav->next != NULL) {
}
trav->prev = node;
}
}
}
// Remove a given node from the linked list
void delete_node(TNode **llist, TNode *node) {
if(*llist == NULL || node == NULL)
return;
if((*llist)->key == node->key) {
// Node to be deleted is at the front of the list.
*llist = (*llist)->next;
// Ensure that we don't point to it anymore.
if(*llist != NULL)
(*llist)->prev = NULL;
}
else
{
TNode *trav = *llist;
while(trav != NULL && trav->key != node->key)
trav = trav->next;
// We've found the deletion point
if(trav != NULL) {
trav->prev->next = trav->next;
if(trav->next != NULL)
trav->next->prev = trav->prev;
else
(*llist)->tail = trav->prev;
}
}
free(node);
}
// Find a node that has the value of key
// If there are duplicate keys, the first one encountered
// will be returned.
TNode *find_node(TNode *llist, unsigned int key) {
if(llist == NULL)
return NULL;
TNode *trav = llist;
while(trav != NULL && trav->key != key)
trav = trav->next;
return trav;
}
// Merge the node provided with either the node after or the node before.
// You need to manage merging the data in node->pdata yourself. This code just
// deletes the larger of the two nodes.
// dir = 0: Merge with node before
// dir = 1: Merge with node after
void merge_node(TNode *llist, TNode *node, int dir) {
if(dir == 0) {
if(node->prev == NULL)
return;
delete_node(&llist, node);
}
else
if(dir == 1) {
if(node->next == NULL)
return;
delete_node(&llist, node->next);
}
}
// Go over every element of llist, and call func
// func prototype is void func(TNode *);
void process_list(TNode *llist, void (*func)(TNode *)) {
TNode *trav = llist;
while(trav) {
func(trav);
trav = trav->next;
}
}
// Purge the entire list. You must
// free any dynamic data in the TData
// struct yourself.
void purge_list(TNode **llist) {
TNode *trav = *llist, *tmp;
while(trav) {
tmp = trav->next;
free(trav);
trav = tmp;
}
*llist = NULL;
}
// Reset traverser
// where=0 START: Resets traverser to start of list
// where=1 END: Rsets
void reset_traverser(TNode *llist, int where)
{
if(llist == NULL)
return;
if(where == FRONT)
llist->trav = llist;
else
if(where == REAR)
llist->trav = llist->tail;
}
// Get the next node
TNode *succ(TNode *llist)
{
if(llist == NULL)
return NULL;
TNode *ret = llist->trav;
if(llist->trav != NULL)
llist->trav = llist->trav->next;
return ret;
}
// Get the previous node
TNode *pred(TNode *llist)
{
if(llist == NULL)
return NULL;
TNode *ret = llist->trav;
if(llist->trav != NULL)
llist->trav = llist->trav->prev;
return ret;
}

View File

@@ -0,0 +1,115 @@
#include <stdbool.h>
#include <stdio.h>
// Uncomment the next line to enable debug printing
#define DEBUG // Enable debug printing
// The debug printer; used like a normal printf, except
// that printing can be turned off by commenting out the
// #define DEBUG above.
void dbprintf(char *format, ...);
// You should modify this structure to hold
// whatever you need to implement your
// memory manager. You can delete the
// val field. It is only used for testlist.c
typedef struct td {
bool occupied;
size_t size;
} TData;
/* -----------------------------------------
BASIC ROUTINES
Basic linked list routines
---------------------------------------- */
// Basic double linked list node.
typedef struct tn {
unsigned int key;
TData *pdata; // Pointer to the data you want to store
struct tn *trav; // Only used in the root for traversal
struct tn *tail; // Only used in the root for finding the end of the list
struct tn *prev;
struct tn *next;
} TNode;
// Insert Direction
#define ASCENDING 0
#define DESCENDING 1
// Merge direction
#define PRECEDING 0
#define SUCCEEDING 1
// Traverser position
#define FRONT 0
#define REAR 1
// Create a new node. You need to
// Create your own TData node, populate
// it, then create a new node with a suitable
// key. Insertion into the link list is
// by ascending order of the key. An example key
// might be the starting address of a memory segment.
TNode *make_node(unsigned int key, TData *data);
// Inserts a node into the correct point of the
// double linked list. The list is sorted
// in ascending order of the key. Duplicate keys
// are permitted, though not recommended.
// llist = Pointer to link list
// node = Pointer to node created by make_node
// dir = 0: Insert in ascending order
// dir = 1: Insert in descending order
void insert_node(TNode **llist, TNode *node, int dir);
// Remove a given node from the linked list
void delete_node(TNode **llist, TNode *node);
// Find a node that has the value of key
// If there are duplicate keys, the first one encountered
// will be returned.
TNode *find_node(TNode *llist, unsigned int key);
// Merge the node provided with either the node after or the node before.
// You need to manage merging the data in node->pdata yourself. This code just
// deletes the larger of the two nodes.
// dir = 0: Merge with node before
// dir = 1: Merge with node after
void merge_node(TNode *llist, TNode *node, int dir);
// Purge the entire list. You must
// free any dynamic data in the TData
// struct yourself.
void purge_list(TNode **llist);
/* -----------------------------------------
TRAVERSAL ROUTINES
Lets you traverse the linked list
---------------------------------------- */
// Go over every element of llist, and call func
// func prototype is void func(TNode *);
void process_list(TNode *llist, void (*func)(TNode *));
// Reset traverser
// where=0 START: Resets traverser to start of list
// where=1 END: Rsets
void reset_traverser(TNode *llist, int where);
// Get the next node
TNode *succ(TNode *llist);
// Get the previous node
TNode *pred(TNode *llist);

View File

@@ -0,0 +1,87 @@
#include "mymalloc.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/_types/_null.h>
#include "llist.h"
char _heap[MEMSIZE] = {0};
TNode *_memlist = NULL; // To maintain information about length
// Do not change this. Used by the test harness.
// You may however use this function in your code if necessary.
long get_index(void *ptr) {
if (ptr == NULL)
return -1;
else
return (long)((char *)ptr - &_heap[0]);
}
// Allocates size bytes of memory and returns a pointer
// to the first byte.
void *mymalloc(size_t size) {
if (_memlist == NULL) {
TData *data = malloc(sizeof(TData));
data->occupied = false;
data->size = MEMSIZE;
_memlist = make_node(0, data);
}
// loop through the list to find a free block
// if found, split the block and return the pointer
// if not found, return NULL
TNode *curr = _memlist;
while (curr != NULL) {
TData *data = curr->pdata;
if (data->occupied == false && data->size >= size) {
data->occupied = true;
if (data->size > size) {
// Create a new node with the leftover space
TData *newData = malloc(sizeof(TData));
newData->occupied = false;
newData->size = data->size - size;
TNode *newNode = make_node(curr->key + size, newData);
// insert new node after the current one in the list.
insert_node(&_memlist, newNode, 0);
// change the size of the current node.
data->size = size;
}
return &_heap[curr->key];
}
curr = curr->next;
}
return NULL;
}
// Frees memory pointer to by ptr.
void myfree(void *ptr) {
if (ptr == NULL)
return;
long index = get_index(ptr);
TNode *node = find_node(_memlist, index);
if (node == NULL)
return;
node->pdata->occupied = false;
// merge with the next node if it is free
while (node->next != NULL && node->next->pdata->occupied == false) {
node->pdata->size += node->next->pdata->size;
merge_node(_memlist, node, 1);
}
while (node->prev != NULL && node->prev->pdata->occupied == false) {
TNode *prev = node->prev;
prev->pdata->size += node->pdata->size;
merge_node(_memlist, node, 0);
}
}
void print_node(TNode *node) {
printf("Status: %s Start index: %d Length: %zu\n",
node->pdata->occupied ? "ALLOCATED" : "FREE", node->key,
node->pdata->size);
}
void print_memlist() { process_list(_memlist, print_node); }

View File

@@ -0,0 +1,7 @@
#include <stdio.h>
#define MEMSIZE 64 * 1024 // Size of memory in bytes
long get_index(void *ptr);
void print_memlist();
void *mymalloc(size_t);
void myfree(void *);

Binary file not shown.

View File

@@ -0,0 +1,35 @@
#include "mymalloc.h"
#include <stdio.h>
void testalloc(long size, char *ptrname, char **ptr) {
printf("\nAllocating %ld bytes to %s\n", size, ptrname);
*ptr = mymalloc(size);
if (*ptr == NULL)
printf("Allocation failed.\n");
print_memlist();
}
void testfree(char *ptr, char *ptrname) {
printf("\nFreeing %s\n", ptrname);
myfree(ptr);
print_memlist();
}
int main() {
char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
testalloc(2048, "ptr1", &ptr1);
testalloc(6144, "ptr2", &ptr2);
testalloc(1024, "ptr3", &ptr3);
testfree(ptr2, "ptr2");
testalloc(2048, "ptr2", &ptr2);
testalloc(4096, "ptr4", &ptr4);
testfree(ptr2, "ptr2");
testalloc(3072, "ptr5", &ptr5);
testfree(ptr1, "ptr1");
testfree(ptr2, "ptr2");
testfree(ptr3, "ptr3");
testfree(ptr4, "ptr4");
testfree(ptr5, "ptr5");
}

View File

@@ -0,0 +1,239 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "llist.h"
//#define DEBUG // Enable debug printing
// Debug printer
void dbprintf(char *format, ...) {
#ifdef DEBUG
va_list args;
va_start(args, format);
vprintf(format, args);
#endif
}
// Implements a double linked list.
// Create a new node. You need to
// Create your own TData node, populate
// it, then create a new node with a suitable
// key. Insertion into the link list is
// by ascending order of the key. An example key
// might be the starting address of a memory segment.
TNode *make_node(unsigned int key, TData *data) {
TNode *node = malloc(sizeof(TNode));
node->key = key;
node->pdata = data;
node->prev = NULL;
node->next = NULL;
return node;
}
// Inserts a node into the correct point of the
// double linked list. The list is sorted
// in ascending order of the key. Duplicate keys
// are permitted, though not recommended.
// llist = Pointer to link list
// node = Pointer to node created by make_node
// dir = 0: Insert in ascending order
// dir = 1: Insert in descending order
void insert_node(TNode **llist, TNode *node, int dir) {
if(*llist == NULL) {
*llist = node;
(*llist)->trav = *llist;
(*llist)->tail = *llist;
}
else
if(((*llist)->key >= node->key && dir == 0) || (((*llist)->key <= node->key) && dir == 1)) {
node->next = *llist;
(*llist)->prev = node;
*llist = node;
(*llist)->trav = *llist;
}
else
{
TNode *trav = *llist;
if(dir == 0)
while(trav->next != NULL && trav->key < node->key)
trav = trav->next;
else if(dir == 1)
while(trav->next != NULL && trav->key > node->key)
trav = trav->next;
if(trav->next == NULL && ((trav->key < node->key && dir == 0) ||
(trav->key > node->key && dir == 1))) {
trav->next = node;
node->prev = trav;
// Set the tail
(*llist)->tail = node;
} else {
// Insert into the previous space
node->next = trav;
if(trav->prev != NULL) {
trav->prev->next = node;
node->prev = trav->prev;
}
if(trav->next != NULL) {
}
trav->prev = node;
}
}
}
// Remove a given node from the linked list
void delete_node(TNode **llist, TNode *node) {
if(*llist == NULL || node == NULL)
return;
if((*llist)->key == node->key) {
// Node to be deleted is at the front of the list.
*llist = (*llist)->next;
// Ensure that we don't point to it anymore.
if(*llist != NULL)
(*llist)->prev = NULL;
}
else
{
TNode *trav = *llist;
while(trav != NULL && trav->key != node->key)
trav = trav->next;
// We've found the deletion point
if(trav != NULL) {
trav->prev->next = trav->next;
if(trav->next != NULL)
trav->next->prev = trav->prev;
else
(*llist)->tail = trav->prev;
}
}
free(node);
}
// Find a node that has the value of key
// If there are duplicate keys, the first one encountered
// will be returned.
TNode *find_node(TNode *llist, unsigned int key) {
if(llist == NULL)
return NULL;
TNode *trav = llist;
while(trav != NULL && trav->key != key)
trav = trav->next;
return trav;
}
// Merge the node provided with either the node after or the node before.
// You need to manage merging the data in node->pdata yourself. This code just
// deletes the larger of the two nodes.
// dir = 0: Merge with node before
// dir = 1: Merge with node after
void merge_node(TNode *llist, TNode *node, int dir) {
if(dir == 0) {
if(node->prev == NULL)
return;
delete_node(&llist, node);
}
else
if(dir == 1) {
if(node->next == NULL)
return;
delete_node(&llist, node->next);
}
}
// Go over every element of llist, and call func
// func prototype is void func(TNode *);
void process_list(TNode *llist, void (*func)(TNode *)) {
TNode *trav = llist;
while(trav) {
func(trav);
trav = trav->next;
}
}
// Purge the entire list. You must
// free any dynamic data in the TData
// struct yourself.
void purge_list(TNode **llist) {
TNode *trav = *llist, *tmp;
while(trav) {
tmp = trav->next;
free(trav);
trav = tmp;
}
*llist = NULL;
}
// Reset traverser
// where=0 START: Resets traverser to start of list
// where=1 END: Rsets
void reset_traverser(TNode *llist, int where)
{
if(llist == NULL)
return;
if(where == FRONT)
llist->trav = llist;
else
if(where == REAR)
llist->trav = llist->tail;
}
// Get the next node
TNode *succ(TNode *llist)
{
if(llist == NULL)
return NULL;
TNode *ret = llist->trav;
if(llist->trav != NULL)
llist->trav = llist->trav->next;
return ret;
}
// Get the previous node
TNode *pred(TNode *llist)
{
if(llist == NULL)
return NULL;
TNode *ret = llist->trav;
if(llist->trav != NULL)
llist->trav = llist->trav->prev;
return ret;
}

View File

@@ -0,0 +1,114 @@
// Uncomment the next line to enable debug printing
#define DEBUG // Enable debug printing
// The debug printer; used like a normal printf, except
// that printing can be turned off by commenting out the
// #define DEBUG above.
void dbprintf(char *format, ...);
// You should modify this structure to hold
// whatever you need to implement your
// memory manager. You can delete the
// val field. It is only used for testlist.c
typedef struct td {
int val;
} TData;
/* -----------------------------------------
BASIC ROUTINES
Basic linked list routines
---------------------------------------- */
// Basic double linked list node.
typedef struct tn {
unsigned int key;
TData *pdata; // Pointer to the data you want to store
struct tn *trav; // Only used in the root for traversal
struct tn *tail; // Only used in the root for finding the end of the list
struct tn *prev;
struct tn *next;
} TNode;
// Insert Direction
#define ASCENDING 0
#define DESCENDING 1
// Merge direction
#define PRECEDING 0
#define SUCCEEDING 1
// Traverser position
#define FRONT 0
#define REAR 1
// Create a new node. You need to
// Create your own TData node, populate
// it, then create a new node with a suitable
// key. Insertion into the link list is
// by ascending order of the key. An example key
// might be the starting address of a memory segment.
TNode *make_node(unsigned int key, TData *data);
// Inserts a node into the correct point of the
// double linked list. The list is sorted
// in ascending order of the key. Duplicate keys
// are permitted, though not recommended.
// llist = Pointer to link list
// node = Pointer to node created by make_node
// dir = 0: Insert in ascending order
// dir = 1: Insert in descending order
void insert_node(TNode **llist, TNode *node, int dir);
// Remove a given node from the linked list
void delete_node(TNode **llist, TNode *node);
// Find a node that has the value of key
// If there are duplicate keys, the first one encountered
// will be returned.
TNode *find_node(TNode *llist, unsigned int key);
// Merge the node provided with either the node after or the node before.
// You need to manage merging the data in node->pdata yourself. This code just
// deletes the larger of the two nodes.
// dir = 0: Merge with node before
// dir = 1: Merge with node after
void merge_node(TNode *llist, TNode *node, int dir);
// Purge the entire list. You must
// free any dynamic data in the TData
// struct yourself.
void purge_list(TNode **llist);
/* -----------------------------------------
TRAVERSAL ROUTINES
Lets you traverse the linked list
---------------------------------------- */
// Go over every element of llist, and call func
// func prototype is void func(TNode *);
void process_list(TNode *llist, void (*func)(TNode *));
// Reset traverser
// where=0 START: Resets traverser to start of list
// where=1 END: Rsets
void reset_traverser(TNode *llist, int where);
// Get the next node
TNode *succ(TNode *llist);
// Get the previous node
TNode *pred(TNode *llist);

View File

@@ -0,0 +1,25 @@
#include <stdio.h>
#include <stdlib.h>
#include "mymalloc.h"
char _heap[MEMSIZE] = {0};
TNode *_memlist = NULL; // To maintain information about length
// Do not change this. Used by the test harness.
// You may however use this function in your code if necessary.
long get_index(void *ptr) {
if(ptr == NULL)
return -1;
else
return (long) ((char *) ptr - &_heap[0]);
}
// Allocates size bytes of memory and returns a pointer
// to the first byte.
void *mymalloc(size_t size) {
}
// Frees memory pointer to by ptr.
void myfree(void *ptr) {
}

View File

@@ -0,0 +1,5 @@
#define MEMSIZE 64 * 1024 // Size of memory in bytes
long get_index(void *ptr);
void *mymalloc(size_t);
void myfree(void *);

View File

@@ -0,0 +1,192 @@
#include "bintree.h"
#include "mymalloc.h"
#include <stdio.h>
#include <stdlib.h>
/* ------------------------- DO NOT IMPLEMENT THESE ----------------------
These are provided "free" to you, and you do not need to implement them,
though you MAY need to understand what they do. Some give you hints
on how to work with pointers to pointers. You MAY find some of these
functions useful.
------------------------------------------------------------------------- */
// Searches for the node containing "name" in the tree whose root is at "root",
// returning both the node ifself in "node", and its parent in "prevnode"
// (useful for deleting node). Both "node" and "prevnode" are set to NULL
// if name is not found in the tree.
void findNode(char *name, TTreeNode *root, TTreeNode **node,
TTreeNode **prevnode) {
TTreeNode *trav = root;
TTreeNode *prev = NULL;
while (trav != NULL) {
int cmp = strcmp(trav->name, name);
if (cmp == 0) {
*node = trav;
*prevnode = prev;
return;
}
prev = trav;
if (cmp < 0)
trav = trav->right;
else
trav = trav->left;
}
*node = NULL;
*prevnode = NULL;
}
// Searches for the node with the smallest value ("smallest node") in the tree
// originating at "node". Returns the smallest node and its parent in
// "smallest_node" and "parent" respectively.
void findSmallest(TTreeNode *node, TTreeNode **smallest_node,
TTreeNode **parent) {
TTreeNode *trav = node;
TTreeNode *prev = NULL;
if (trav == NULL)
return;
while (trav->left != NULL) {
prev = trav;
trav = trav->left;
}
*smallest_node = trav;
*parent = prev;
}
// Delete a node at "node" with parent node "prevnode"
void delNode(TTreeNode *node, TTreeNode *prevnode) {
// This is a leaf node
if (node->left == NULL && node->right == NULL) {
// See whether node is on parent's left or right, and NULL the
// corresponding pointer
int cmp = strcmp(prevnode->name, node->name);
// Previous node is smaller than this one. This
// node is on the right
if (cmp < 0)
prevnode->right = NULL;
else
prevnode->left = NULL;
freenode(node);
return;
}
// This has a child on the left only
if (node->right == NULL) {
// Copy the right child over
node = node->left;
freenode(node->left);
return;
}
// This has a child on the right only
if (node->left == NULL) {
node = node->right;
freenode(node->right);
return;
}
// This has children on both nodes
TTreeNode *smallest, *smallest_parent;
findSmallest(node->right, &smallest, &smallest_parent);
node = smallest;
smallest_parent->left = NULL;
freenode(smallest);
}
/* ---------------------------- IMPLEMENT THESE --------------------------- */
// Create a new node with name set to "name" and
// phoneNum set to "phoneNum".
void delTree(TTreeNode *root) {
// Implement deleting the entire tree, whose
// root is at "root".
if (root == NULL)
return;
if (root->left != NULL)
delTree(root->left);
if (root->right != NULL)
delTree(root->right);
freenode(root);
}
TTreeNode *makeNewNode(char *name, char *phoneNum) {
TTreeNode *node = mymalloc(sizeof(TTreeNode));
node->name = mymalloc(strlen(name) + 1);
strcpy(node->name, name);
strcpy(node->phoneNum, phoneNum);
node->left = NULL;
node->right = NULL;
return node;
// Implement makeNewNode to create a new
// TTreeNode containing name and phoneNum
}
// Add a new node to the tree.
// Note that "root" is a POINTER to the tree's root,
// not the root itself.
void addNode(TTreeNode **root, TTreeNode *node) {
if (*root == NULL) {
*root = node;
}
TTreeNode **trav = root;
while (1) {
int cmp = strcmp((*trav)->name, node->name);
if (cmp == 0)
return;
if (cmp > 0) {
if ((*trav)->left == NULL)
(*trav)->left = node;
else {
trav = &((*trav)->left);
continue;
}
} else if (cmp < 0) {
if ((*trav)->right == NULL)
(*trav)->right = node;
else {
trav = &((*trav)->right);
continue;
}
}
}
// Add a new node to the tree, where root is
// the POINTER to the tree's root.
}
void freenode(TTreeNode *node) {
myfree(node->name);
myfree(node);
// Frees the memory used by node.
}
void print_inorder(TTreeNode *node) {
// Implement in-order printing of the tree
// Recursion is probably best here.
if (node == NULL)
return;
if (node->left != NULL)
print_inorder(node->left);
printf("Name is %s Number is %s\n", node->name, node->phoneNum);
if (node->right != NULL)
print_inorder(node->right);
}

View File

@@ -0,0 +1,17 @@
#include <string.h>
#include <stdlib.h>
typedef struct tn {
char *name;
char phoneNum[9];
struct tn *left, *right;
} TTreeNode;
void findNode(char *, TTreeNode *, TTreeNode **, TTreeNode **);
void findSmallest(TTreeNode *, TTreeNode **, TTreeNode **);
void delNode(TTreeNode *, TTreeNode *);
void delTree(TTreeNode *);
TTreeNode *makeNewNode(char *, char *);
void addNode(TTreeNode **, TTreeNode *);
void freenode(TTreeNode *);
void print_inorder(TTreeNode *);

View File

@@ -0,0 +1,239 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "llist.h"
//#define DEBUG // Enable debug printing
// Debug printer
void dbprintf(char *format, ...) {
#ifdef DEBUG
va_list args;
va_start(args, format);
vprintf(format, args);
#endif
}
// Implements a double linked list.
// Create a new node. You need to
// Create your own TData node, populate
// it, then create a new node with a suitable
// key. Insertion into the link list is
// by ascending order of the key. An example key
// might be the starting address of a memory segment.
TNode *make_node(unsigned int key, TData *data) {
TNode *node = malloc(sizeof(TNode));
node->key = key;
node->pdata = data;
node->prev = NULL;
node->next = NULL;
return node;
}
// Inserts a node into the correct point of the
// double linked list. The list is sorted
// in ascending order of the key. Duplicate keys
// are permitted, though not recommended.
// llist = Pointer to link list
// node = Pointer to node created by make_node
// dir = 0: Insert in ascending order
// dir = 1: Insert in descending order
void insert_node(TNode **llist, TNode *node, int dir) {
if(*llist == NULL) {
*llist = node;
(*llist)->trav = *llist;
(*llist)->tail = *llist;
}
else
if(((*llist)->key >= node->key && dir == 0) || (((*llist)->key <= node->key) && dir == 1)) {
node->next = *llist;
(*llist)->prev = node;
*llist = node;
(*llist)->trav = *llist;
}
else
{
TNode *trav = *llist;
if(dir == 0)
while(trav->next != NULL && trav->key < node->key)
trav = trav->next;
else if(dir == 1)
while(trav->next != NULL && trav->key > node->key)
trav = trav->next;
if(trav->next == NULL && ((trav->key < node->key && dir == 0) ||
(trav->key > node->key && dir == 1))) {
trav->next = node;
node->prev = trav;
// Set the tail
(*llist)->tail = node;
} else {
// Insert into the previous space
node->next = trav;
if(trav->prev != NULL) {
trav->prev->next = node;
node->prev = trav->prev;
}
if(trav->next != NULL) {
}
trav->prev = node;
}
}
}
// Remove a given node from the linked list
void delete_node(TNode **llist, TNode *node) {
if(*llist == NULL || node == NULL)
return;
if((*llist)->key == node->key) {
// Node to be deleted is at the front of the list.
*llist = (*llist)->next;
// Ensure that we don't point to it anymore.
if(*llist != NULL)
(*llist)->prev = NULL;
}
else
{
TNode *trav = *llist;
while(trav != NULL && trav->key != node->key)
trav = trav->next;
// We've found the deletion point
if(trav != NULL) {
trav->prev->next = trav->next;
if(trav->next != NULL)
trav->next->prev = trav->prev;
else
(*llist)->tail = trav->prev;
}
}
free(node);
}
// Find a node that has the value of key
// If there are duplicate keys, the first one encountered
// will be returned.
TNode *find_node(TNode *llist, unsigned int key) {
if(llist == NULL)
return NULL;
TNode *trav = llist;
while(trav != NULL && trav->key != key)
trav = trav->next;
return trav;
}
// Merge the node provided with either the node after or the node before.
// You need to manage merging the data in node->pdata yourself. This code just
// deletes the larger of the two nodes.
// dir = 0: Merge with node before
// dir = 1: Merge with node after
void merge_node(TNode *llist, TNode *node, int dir) {
if(dir == 0) {
if(node->prev == NULL)
return;
delete_node(&llist, node);
}
else
if(dir == 1) {
if(node->next == NULL)
return;
delete_node(&llist, node->next);
}
}
// Go over every element of llist, and call func
// func prototype is void func(TNode *);
void process_list(TNode *llist, void (*func)(TNode *)) {
TNode *trav = llist;
while(trav) {
func(trav);
trav = trav->next;
}
}
// Purge the entire list. You must
// free any dynamic data in the TData
// struct yourself.
void purge_list(TNode **llist) {
TNode *trav = *llist, *tmp;
while(trav) {
tmp = trav->next;
free(trav);
trav = tmp;
}
*llist = NULL;
}
// Reset traverser
// where=0 START: Resets traverser to start of list
// where=1 END: Rsets
void reset_traverser(TNode *llist, int where)
{
if(llist == NULL)
return;
if(where == FRONT)
llist->trav = llist;
else
if(where == REAR)
llist->trav = llist->tail;
}
// Get the next node
TNode *succ(TNode *llist)
{
if(llist == NULL)
return NULL;
TNode *ret = llist->trav;
if(llist->trav != NULL)
llist->trav = llist->trav->next;
return ret;
}
// Get the previous node
TNode *pred(TNode *llist)
{
if(llist == NULL)
return NULL;
TNode *ret = llist->trav;
if(llist->trav != NULL)
llist->trav = llist->trav->prev;
return ret;
}

View File

@@ -0,0 +1,115 @@
#include <stdbool.h>
#include <stdio.h>
// Uncomment the next line to enable debug printing
#define DEBUG // Enable debug printing
// The debug printer; used like a normal printf, except
// that printing can be turned off by commenting out the
// #define DEBUG above.
void dbprintf(char *format, ...);
// You should modify this structure to hold
// whatever you need to implement your
// memory manager. You can delete the
// val field. It is only used for testlist.c
typedef struct td {
bool occupied;
size_t size;
} TData;
/* -----------------------------------------
BASIC ROUTINES
Basic linked list routines
---------------------------------------- */
// Basic double linked list node.
typedef struct tn {
unsigned int key;
TData *pdata; // Pointer to the data you want to store
struct tn *trav; // Only used in the root for traversal
struct tn *tail; // Only used in the root for finding the end of the list
struct tn *prev;
struct tn *next;
} TNode;
// Insert Direction
#define ASCENDING 0
#define DESCENDING 1
// Merge direction
#define PRECEDING 0
#define SUCCEEDING 1
// Traverser position
#define FRONT 0
#define REAR 1
// Create a new node. You need to
// Create your own TData node, populate
// it, then create a new node with a suitable
// key. Insertion into the link list is
// by ascending order of the key. An example key
// might be the starting address of a memory segment.
TNode *make_node(unsigned int key, TData *data);
// Inserts a node into the correct point of the
// double linked list. The list is sorted
// in ascending order of the key. Duplicate keys
// are permitted, though not recommended.
// llist = Pointer to link list
// node = Pointer to node created by make_node
// dir = 0: Insert in ascending order
// dir = 1: Insert in descending order
void insert_node(TNode **llist, TNode *node, int dir);
// Remove a given node from the linked list
void delete_node(TNode **llist, TNode *node);
// Find a node that has the value of key
// If there are duplicate keys, the first one encountered
// will be returned.
TNode *find_node(TNode *llist, unsigned int key);
// Merge the node provided with either the node after or the node before.
// You need to manage merging the data in node->pdata yourself. This code just
// deletes the larger of the two nodes.
// dir = 0: Merge with node before
// dir = 1: Merge with node after
void merge_node(TNode *llist, TNode *node, int dir);
// Purge the entire list. You must
// free any dynamic data in the TData
// struct yourself.
void purge_list(TNode **llist);
/* -----------------------------------------
TRAVERSAL ROUTINES
Lets you traverse the linked list
---------------------------------------- */
// Go over every element of llist, and call func
// func prototype is void func(TNode *);
void process_list(TNode *llist, void (*func)(TNode *));
// Reset traverser
// where=0 START: Resets traverser to start of list
// where=1 END: Rsets
void reset_traverser(TNode *llist, int where);
// Get the next node
TNode *succ(TNode *llist);
// Get the previous node
TNode *pred(TNode *llist);

View File

@@ -0,0 +1,103 @@
#include "mymalloc.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/_types/_null.h>
#include "llist.h"
char _heap[MEMSIZE] = {0};
TNode *_memlist = NULL; // To maintain information about length
// Do not change this. Used by the test harness.
// You may however use this function in your code if necessary.
long get_index(void *ptr) {
if (ptr == NULL)
return -1;
else
return (long)((char *)ptr - &_heap[0]);
}
// Allocates size bytes of memory and returns a pointer
// to the first byte.
void *mymalloc(size_t size) {
if (_memlist == NULL) {
TData *data = malloc(sizeof(TData));
data->occupied = false;
data->size = MEMSIZE;
_memlist = make_node(0, data);
}
// loop through the list to find a free block
// if found, split the block and return the pointer
// if not found, return NULL
TNode *curr = _memlist;
TNode *best = NULL;
while (curr != NULL) {
if (curr->pdata->occupied == true) {
curr = curr->next;
continue;
}
if (curr->pdata->size < size) {
curr = curr->next;
continue;
}
if (best == NULL) {
best = curr;
curr = curr->next;
continue;
}
if (best->pdata->size > curr->pdata->size) {
best = curr;
curr = curr->next;
continue;
}
curr = curr->next;
}
if (best == NULL)
return NULL;
best->pdata->occupied = true;
if (best->pdata->size > size) {
// Create a new node with the leftover space
TData *newData = malloc(sizeof(TData));
newData->occupied = false;
newData->size = best->pdata->size - size;
TNode *newNode = make_node(best->key + size, newData);
// insert new node after the current one in the list.
insert_node(&_memlist, newNode, 0);
// change the size of the current node.
best->pdata->size = size;
}
return &_heap[best->key];
}
// Frees memory pointer to by ptr.
void myfree(void *ptr) {
if (ptr == NULL)
return;
long index = get_index(ptr);
TNode *node = find_node(_memlist, index);
if (node == NULL)
return;
node->pdata->occupied = false;
// merge with the next node if it is free
while (node->next != NULL && node->next->pdata->occupied == false) {
node->pdata->size += node->next->pdata->size;
merge_node(_memlist, node, 1);
}
while (node->prev != NULL && node->prev->pdata->occupied == false) {
TNode *prev = node->prev;
prev->pdata->size += node->pdata->size;
merge_node(_memlist, node, 0);
}
}
void print_node(TNode *node) {
printf("Status: %s Start index: %d Length: %zu\n",
node->pdata->occupied ? "ALLOCATED" : "FREE", node->key,
node->pdata->size);
}
void print_memlist() { process_list(_memlist, print_node); }

View File

@@ -0,0 +1,7 @@
#include <stdio.h>
#define MEMSIZE 64 * 1024 // Size of memory in bytes
long get_index(void *ptr);
void print_memlist();
void *mymalloc(size_t);
void myfree(void *);

Some files were not shown because too many files have changed in this diff Show More