Almost finished assignment 4 of Operating Systems.

parent 61825fd6
PROG = ass4 PROG = ass4
CC = gcc CC = gcc
CFLAGS = -std=c99 -pedantic -Wall -Wextra # -D_POSIX_SOURCE CFLAGS = -std=c99 -pedantic -Wall -Wextra -D_GNU_SOURCE # -D_POSIX_SOURCE
LFLAGS = -lpthread LFLAGS = -lpthread
OFILES = main.o OFILES = main.o
RM = rm -f RM = rm -f
ifdef DEBUG ifdef DEBUG
CFLAGS += -ggdb CFLAGS +=-ggdb
else else
CFLAGS += -O3 CFLAGS +=-O3
endif endif
$(PROG): $(OFILES) $(PROG): $(OFILES)
......
...@@ -3,51 +3,147 @@ ...@@ -3,51 +3,147 @@
#include "pthread.h" #include "pthread.h"
#include <unistd.h> #include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
int forks_len; int forks_len;
pthread_mutex_t *forks; pthread_mutex_t *forks;
pthread_cond_t wait_threshold; pthread_cond_t wait_threshold;
pthread_barrier_t wait_barrier;
typedef struct diner_stats { typedef struct diner_stats {
int meals; unsigned int meals;
unsigned int forks;
unsigned int id;
unsigned int locked;
} diner_stats; } diner_stats;
int count = 0; int diner_finished = 0;
#define COUNT_LIMIT 12
void *philo_start() { #define TIME_LIMIT 2.f
int t_id = pthread_self();
printf("P #%d: hello everybody!\n", t_id);
for(int i = 0; i < 5; i++) { static inline void release_fork(diner_stats *stats, int f) {
// Let each philosopher take a random fork. if(diner_finished)
//int f = rand() % forks_len; return;
//pthread_mutex_lock(&forks[f]);
pthread_mutex_lock(&forks[t_id]);
pthread_mutex_lock(&forks[(t_id+1) % forks_len]);
//while( pthread_mutex_trylock(&forks[(t_id+1) % forks_len]) ) { stats->locked ^= 1 << f;
// pthread_mutex_unlock(&forks[t_id]); pthread_mutex_unlock(&forks[f]);
}
static inline void take_fork(diner_stats *stats, int f) {
if(diner_finished)
return;
pthread_mutex_lock(forks+f);
stats->locked |= 1 << f;
stats->forks++;
}
#define PHILO_EATING \
if(diner_finished) \
break; \
\
stats->meals++;
void philo_left(diner_stats *stats, int id) {
while(!diner_finished) {
// Let the philosopher take two forks.
take_fork(stats, id);
take_fork(stats, (id+1) % forks_len);
PHILO_EATING;
release_fork(stats, (id+1) % forks_len);
release_fork(stats, id);
}
}
void philo_right(diner_stats *stats, int id) {
while(!diner_finished) {
// Let the philosopher take two forks.
take_fork(stats, (id+1) % forks_len);
take_fork(stats, id);
PHILO_EATING;
// // Check the value of count and signal waiting thread when condition is release_fork(stats, id);
// // reached. Note that this occurs while mutex is locked. release_fork(stats, (id+1) % forks_len);
// //pthread_cond_signal(&wait_threshold); }
// sleep(1); }
void philo_optimistic(diner_stats *stats, int id) {
while(!diner_finished) {
// Let the philosopher take one of the two forks.
if(!pthread_mutex_trylock(&forks[id])) {
if(diner_finished)
break;
if(!pthread_mutex_trylock(&forks[(id+1) % forks_len])) {
if(diner_finished)
break;
// No fork available, be faster next time!
sched_yield();
}
else {
stats->locked |= 1 << ((id+1) % forks_len);
stats->forks++;
if(diner_finished)
break;
take_fork(stats, id);
PHILO_EATING;
// pthread_mutex_lock(&forks[t_id]); release_fork(stats, id);
//} release_fork(stats, (id+1) % forks_len);
}
}
else {
stats->locked |= 1 << id;
stats->forks++;
take_fork(stats, (id+1) % forks_len);
// Do something useless PHILO_EATING;
printf("P #%d: I'm eating.\n", t_id);
pthread_mutex_unlock(&forks[t_id]); release_fork(stats, id);
pthread_mutex_unlock(&forks[(t_id+1) % forks_len]); release_fork(stats, (id+1) % forks_len);
}
} }
}
void philo_shy(diner_stats *stats, int id) {
}
typedef void(*philo_t)(diner_stats *, int);
static const char *philo_type_names[] = {"left", "right", "optimistic"};//, "shy"};
static const philo_t philo_types[] = {&philo_left, &philo_right, \
&philo_optimistic};//, &philo_shy};
void *philo_start(void *raw_stats) {
diner_stats *stats = (diner_stats *) raw_stats;
int id = stats->id,
type = rand() % (sizeof(philo_types) / sizeof(philo_t));
printf("P #%u: hello everybody, i'm %s!\n", id, philo_type_names[type]);
// Philosophers wait for each other, before they can start eating diner.
pthread_barrier_wait(&wait_barrier);
(*philo_types[type])(stats, id);
pthread_exit(NULL); pthread_exit(NULL);
} }
void host_start(int philos) { void host_start(int philos) {
if( philos < 2 ) {
fprintf(stderr, "Invalid philosopher count.\n");
exit(EXIT_FAILURE);
}
pthread_attr_t attr; pthread_attr_t attr;
pthread_t *threads = malloc(philos * sizeof(pthread_t)); pthread_t *threads = malloc(philos * sizeof(pthread_t));
forks = malloc(philos * sizeof(pthread_mutex_t)); forks = malloc(philos * sizeof(pthread_mutex_t));
...@@ -63,12 +159,16 @@ void host_start(int philos) { ...@@ -63,12 +159,16 @@ void host_start(int philos) {
pthread_attr_init(&attr); pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_cond_init(&wait_threshold, NULL); // Let all philosophers wait before they can eat diner.
pthread_barrier_init(&wait_barrier, NULL, philos);
// Create the cutlery. // Create the cutlery (mutexes) and initialise the statistics.
for(int i = 0; i < philos; i++) { for(int i = 0; i < philos; i++) {
pthread_mutex_init(&forks[i], NULL); pthread_mutex_init(&forks[i], NULL);
stats[i].meals = 0 ; stats[i].meals = 0;
stats[i].forks = 0;
stats[i].id = i;
stats[i].locked = 0;
} }
// Invite the philosophers. // Invite the philosophers.
...@@ -77,28 +177,83 @@ void host_start(int philos) { ...@@ -77,28 +177,83 @@ void host_start(int philos) {
rc = pthread_create(threads+i, &attr, philo_start, (void*)&stats[i]); rc = pthread_create(threads+i, &attr, philo_start, (void*)&stats[i]);
if( rc ) { if(rc) {
fprintf(stderr, "pthread_create() returned: %d\n", rc); fprintf(stderr, "pthread_create() returned: %d\n", rc);
exit(-1); exit(-1);
} }
} }
printf("Host: invitations done.\n"); puts("Host: invitations done.");
struct timeval wct;
gettimeofday(&wct, NULL);
double start_time = wct.tv_sec + wct.tv_usec / 1e6;
// Duration of the diner party is 10 seconds. This loop will prevent the
// philosphers from exceeding this time limit.
do {
usleep(10);
// Check if deadlock occured. If an deadlock occured (all philosophers
// are waiting on their second fork), finish the diner immidiately.
int p;
for(p = 0; p < philos && stats[p].locked & (1 << p); p++);
if( p == philos ) {
puts("Host: deadlock occured.");
diner_finished = 1;
for(p = 0; p < philos; p++) {
pthread_mutex_unlock(&forks[p]);
stats[p].locked = 0;
}
break;
}
gettimeofday(&wct, NULL);
} while(wct.tv_sec + wct.tv_usec / 1e6 - start_time < TIME_LIMIT);
diner_finished = 1;
puts("Host: diner is finished.");
// Wait on the other philosophers. // Wait on the other philosophers.
for(int i = 0; i < philos; i++) { for(int i = 0; i < philos; i++) {
pthread_join(threads[i], &status); // Reclaim all cutlery (mutexes). This is done twice, because some
pthread_mutex_destroy(&forks[i]); // philosophers can continue take an fork while the host is still
// reclaiming the other forks.
for(int p = 0; p < philos; p++)
pthread_mutex_unlock(&forks[p]);
for(int p = 0; p < philos; p++)
pthread_mutex_unlock(&forks[p]);
if( (rc = pthread_join(threads[i], &status)) ) {
fprintf(stderr, "return code from pthread_join() is %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Philo #%d ate %d meal(s) and grabbed %d forks.\n",
i, stats[i].meals, stats[i].forks);
} }
for(int i = 0; i < philos; i++)
pthread_mutex_destroy(&forks[i]);
printf("Host: philosophers are done.\n"); puts("Host: philosophers are done.");
pthread_cond_destroy(&wait_threshold); pthread_barrier_destroy(&wait_barrier);
pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
pthread_exit(NULL); pthread_exit(NULL);
} }
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
struct timeval wtc;
gettimeofday(&wtc, NULL);
srand(wtc.tv_usec);
host_start( argc > 1 ? atoi(argv[1]) : 2 ); host_start( argc > 1 ? atoi(argv[1]) : 2 );
} }
...@@ -22,7 +22,7 @@ if version > 580 ...@@ -22,7 +22,7 @@ if version > 580
endif endif
let g:colors_name="darkspectrum" let g:colors_name="darkspectrum"
hi Normal guifg=#efefef guibg=#2A2A2A hi Normal guifg=#efefef guibg=#171717
" highlight groups " highlight groups
hi Cursor guibg=#ffffff guifg=#000000 hi Cursor guibg=#ffffff guifg=#000000
...@@ -123,8 +123,8 @@ hi link schemeFunc Statement ...@@ -123,8 +123,8 @@ hi link schemeFunc Statement
"hi link bashSpecialVariables Constant "hi link bashSpecialVariables Constant
" tabs (non gui) " tabs (non gui)
hi TabLine guifg=#A3A3A3 guibg=#202020 gui=none hi TabLine guifg=#A3A3A3 guibg=#171717 gui=none
hi TabLineFill guifg=#535353 guibg=#202020 gui=none hi TabLineFill guifg=#535353 guibg=#171717 gui=none
hi TabLineSel guifg=#FFFFFF gui=bold hi TabLineSel guifg=#FFFFFF gui=bold
"hi TabLineSel guifg=#FFFFFF guibg=#000000 gui=bold "hi TabLineSel guifg=#FFFFFF guibg=#000000 gui=bold
" vim: sw=4 ts=4 " vim: sw=4 ts=4
...@@ -22,7 +22,7 @@ endif ...@@ -22,7 +22,7 @@ endif
map ,rl :!pdflatex -src -shell-escape -interaction=nonstopmode % map ,rl :!pdflatex -src -shell-escape -interaction=nonstopmode %
" trigger pdflatex (above) on FileWritePost event " trigger pdflatex (above) on FileWritePost event
:autocmd BufWritePost *.tex :!pdflatex -src -shell-escape -interaction=nonstopmode % | grep -A 4 -i "error" :autocmd BufWritePost *.tex :!pdflatex -src -shell-escape -interaction=nonstopmode % | grep -A 4 -i "error"
set textwidth=80 set textwidth=80
...@@ -31,6 +31,34 @@ augroup vimrc_autocmds ...@@ -31,6 +31,34 @@ augroup vimrc_autocmds
autocmd BufEnter * match OverLength /\%81v.*/ autocmd BufEnter * match OverLength /\%81v.*/
augroup END augroup END
" configure tags - add additional tags here or comment out not-used ones
" cd /usr/include
" ctags -R --sort=yes --fields=+iaS -f ~/.vim/tags/stdc stdio.h stdlib.h \
" pthread.h math.h assert.h errno.h malloc.h strings.h fcntl.h unistd.h
" ctags -R --sort=yes --fields=+iaS -f ~/.vim/tags/gl GL/
set tags+=~/.vim/tags/stdc
set tags+=~/.vim/tags/gl
" build tags of your own project with CTRL+F12
map <C-F12> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<CR>
"noremap <F12> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<cr>
"inoremap <F12> <Esc>:!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<cr>
" OmniCppComplete
let OmniCpp_NamespaceSearch = 1
let OmniCpp_GlobalScopeSearch = 1
let OmniCpp_ShowAccess = 1
let OmniCpp_MayCompleteDot = 1
let OmniCpp_MayCompleteArrow = 1
let OmniCpp_MayCompleteScope = 1
let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD"]
" automatically open and close the popup menu / preview window
au CursorMovedI,InsertLeave * if pumvisible() == 0|silent! pclose|endif
"set completeopt=menuone,menu,longest,preview
set completeopt=menuone,menu " ,longest,preview
set nocp set nocp
filetype plugin on filetype plugin on
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment