Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
debug
release
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.4.1)
include_directories(libstack/include)
add_subdirectory(libstack)

include_directories(libtimer/include)
add_subdirectory(libtimer)

include_directories(libthread/include)
add_subdirectory(libthread)
35 changes: 35 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
debug_dir = debug
debug_dir_target = $(debug_dir)-$(wildcard $(debug_dir))
debug_dir_present = $(debug_dir)-$(debug_dir)
debug_dir_absent = $(debug_dir)-
release_dir = release
release_dir_target = $(release_dir)-$(wildcard $(release_dir))
release_dir_present = $(release_dir)-$(release_dir)
release_dir_absent = $(release_dir)-

all: debug release

debug: | $(debug_dir_target) build_debug

release: | $(release_dir_target) build_release

$(release_dir_present):

$(release_dir_absent):
mkdir $(release_dir)

$(debug_dir_present):

$(debug_dir_absent):
mkdir $(debug_dir)

build_debug:
cd ${debug_dir} ; cmake -DCMAKE_BUILD_TYPE=Debug .. ; make || exit
build_release:
cd ${release_dir} ; cmake -DCMAKE_BUILD_TYPE=Release .. ; make || exit

.PHONY: all

clean:
rm -rf $(debug_dir)
rm -rf $(release_dir)
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# README #

Routines that will allow a program to run, with multiple threads, using NON-preemptive scheduling on most Unix/Linux operating systems. Contains implementation of custom semaphores, and sample programs to test threads and semaphores.
Routines that will allow a program to run, with multiple threads, using preemptive scheduling on most Unix/Linux operating systems. Contains implementation of custom semaphores, and sample programs to test threads and semaphores.

### Requirements ###

* Ubuntu 14.04
* gcc compiler
* g++ compiler
* gnu make
* cmake

### To test threads library ###

1. gcc thread_test.c
2. ./a.out | head -40
1. make
26 changes: 0 additions & 26 deletions TCB.h

This file was deleted.

5 changes: 5 additions & 0 deletions libstack/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.4.1)

include_directories(include)
add_library(stack SHARED direction.cpp new.cpp)
add_subdirectory(tests)
22 changes: 22 additions & 0 deletions libstack/direction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "include/stack.h"

int Stack::internal::getStackDirection(int *addr) {
int fun_local;
if (addr < &fun_local) {
printf("Stack grows upward\n");
return SDU;
}
printf("Stack grows downward\n");
return SDD;
}

int Stack::getStackDirection() {
int main_local;
return internal().getStackDirection(&main_local);
}

char * Stack::getStackDirectionAsString() {
if (direction == SDU) return "Stack grows upwards";
else if (direction == SDD) return "Stack grows downwards";
else return "Stack grows in an unknown direction";
}
12 changes: 12 additions & 0 deletions libstack/include/internal/direction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef STACK_DIRECTION
#define STACK_DIRECTION

// C program to check whether stack grows // downward or upward.
#include<stdio.h>

#define STACK_DIRECTION_UP 11
#define SDU STACK_DIRECTION_UP
#define STACK_DIRECTION_DOWN 12
#define SDD STACK_DIRECTION_DOWN

#endif
23 changes: 23 additions & 0 deletions libstack/include/stack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef STACK_STACK
#define STACK_STACK

#include "internal/direction.h"
#include <stdlib.h>

class Stack {
public:
char * stack = nullptr;
char * top = nullptr; // points to top of stack
size_t size = 0;
int direction = 0;
void alloc(size_t size);
void free();
class internal {
public:
int getStackDirection(int *addr);
};
int getStackDirection();
char * getStackDirectionAsString();
};

#endif
18 changes: 18 additions & 0 deletions libstack/new.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "include/stack.h"

void Stack::alloc(size_t size) {
stack = new char[size];
size = size;
direction = getStackDirection();
if (direction == SDU) top = stack;
else top = stack + (size*sizeof(char));;
}

void Stack::free() {
if (stack == nullptr) return;
delete[] stack;
stack = nullptr;
top = nullptr;
size = 0;
direction = 0;
}
5 changes: 5 additions & 0 deletions libstack/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.4.1)

add_executable(test_stack stack.cpp)
target_link_libraries(test_stack stack)
add_custom_command( TARGET test_stack POST_BUILD COMMAND test_stack)
8 changes: 8 additions & 0 deletions libstack/tests/stack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <stack.h>

int main(void) {
Stack s = Stack();
s.alloc(100);
s.free();
return 0;
}
5 changes: 5 additions & 0 deletions libthread/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.4.1)

add_library(thread SHARED TBC.cpp q.cpp thread.cpp)
target_link_libraries(thread stack timer)
add_subdirectory(tests)
9 changes: 9 additions & 0 deletions libthread/TBC.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "include/internal/TCB.h"

void init_TCB (TCB_t *tcb, void (* function)(void), void *stackP, int stack_size) {
memset(tcb, '\0', sizeof(TCB_t)); //wash rinse
getcontext(&tcb->context); //have to get parent context, else snow forms on hell
tcb->context.uc_stack.ss_sp = stackP;
tcb->context.uc_stack.ss_size = (size_t) stack_size;
makecontext(&tcb->context, function, 0); //context cooked
}
17 changes: 17 additions & 0 deletions libthread/include/internal/TCB.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*************************************************************
*
Author: Denny Abraham Cheriyan, Adrin Peter Fernandes
Contains TCB structure definition and code to initialize TCB

*/

#include <ucontext.h>
#include <string.h>

typedef struct TCB_t {
struct TCB_t *next;
ucontext_t context;
struct TCB_t *prev;
} TCB_t;

void init_TCB (TCB_t *tcb, void (* function)(void), void *stackP, int stack_size);
20 changes: 20 additions & 0 deletions libthread/include/internal/q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*************************************************************
*
Author: Denny Abraham Cheriyan, Adrin Peter Fernandes
Contains functions to initialize, add, delete and rotate
a doubly linked circular queue

*/

#include "TCB.h"
#include <stdio.h>
#include <stdlib.h>


void InitQ(TCB_t **head);

void AddQ(TCB_t **head, TCB_t *item);

TCB_t * DelQ(TCB_t **head);

void RotateQ(TCB_t **head);
12 changes: 12 additions & 0 deletions libthread/include/thread.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*************************************************************
*
Author: Denny Abraham Cheriyan, Adrin Peter Fernandes
Contains functions to Start, Run and Yield to other threads

*/

#include "internal/q.h"

void start_thread(void (* function)(void));
void run();
void yield();
41 changes: 41 additions & 0 deletions libthread/q.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "include/internal/q.h"

void InitQ(TCB_t **head) {
*head = 0;
}

void AddQ(TCB_t **head, TCB_t *item) {
if (*head == 0) {
//When the head pointer is null
*head = item;
(*head)->next = *head;
(*head)->prev = *head;
} else {
//When there is one or more nodes
(*head)->prev->next = item;
item->prev = (*head)->prev;
(*head)->prev = item;
item->next = *head;
}
}

TCB_t * DelQ(TCB_t **head) {
if ((*head) == 0)
return 0;
TCB_t *temp = *head;
if ((*head)->next == *head) {
//When there is one node
*head = 0;
} else {
//When there are two or more nodes
*head = (*head)->next;
temp->prev->next = *head;
(*head)->prev = temp->prev;
}
return temp;
}

void RotateQ(TCB_t **head) {
if (*head != 0)
(*head) = (*head)->next;
}
5 changes: 5 additions & 0 deletions libthread/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.4.1)

add_executable(test_thread thread.cpp)
target_link_libraries(test_thread thread)
add_custom_command( TARGET test_thread POST_BUILD COMMAND test_thread)
76 changes: 76 additions & 0 deletions libthread/tests/thread.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*************************************************************
*
Author: Denny Abraham Cheriyan, Adrin Peter Fernandes
Testing threads.h using infinite functions

*/

#include <thread.h>
#include <thread> // std::this_thread
#include <chrono> // std::chrono_literals

#include <stack.h>
#include <timer.h>

using namespace std::chrono_literals;

void thr1() {
while(1) {
printf("thr1 sleep for 2 seconds!\n");
// sleep(2) resumes on receiving a caught signal
std::this_thread::sleep_for(2s);
printf("slept!\n");
}
}

void thr2() {
while(1) {
printf("thr2 sleep for 2 seconds!\n");
// sleep(2) resumes on receiving a caught signal
std::this_thread::sleep_for(2s);
printf("slept!\n");
}
}

bool firstrun = false;

Timer timer = Timer();

// declare a custom timer handler

void Timer::timer_handler(int signum) {
static int count = 1;
if (!firstrun) {
fprintf (stderr, "> FIRST RUN timer ms = %d, count = %03d\n", timer.ms_, count++);
firstrun = true;
run();
} else {
fprintf (stderr, "> YIELDING timer ms = %d, count = %03d\n", timer.ms_, count++);
yield();
}
}

// declare a custom schedule yeilder

int Sched::yield(void * arg) {
// timer is per process, the process it is set in must exist in order to recieve a signal
timer.set_timer(timer.Types.ITIMER_REAL, Timer::timer_handler, 1000, false);
pause();
return 0;
}

int main(){
/* Flush each printf() as it happens. */
setvbuf(stdout, 0, _IOLBF, 0);
setvbuf(stderr, 0, _IOLBF, 0);

Sched foo = Sched(); // scoped initialization and de-initialization of the preemptive scheduler

start_thread(thr1);
start_thread(thr2);

// let threads to do something for 8 seconds
sleep(8);
puts("exiting");
return 0;
}
Loading