Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
U
uva
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Taddeüs Kroes
uva
Commits
1715f304
Commit
1715f304
authored
Nov 20, 2010
by
Sander Mathijs van Veen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Completed code for assignment 4 of Operating Systems.
parent
d3c10b1d
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
208 additions
and
94 deletions
+208
-94
os/ass4/main.c
os/ass4/main.c
+179
-94
os/ass4/main.h
os/ass4/main.h
+29
-0
No files found.
os/ass4/main.c
View file @
1715f304
#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"
/*
* Assignment 4 of Operating Systems: PThread simulation.
*
* Sander van Veen (6167969) and Taddeus Kroes (6054129).
* <sandervv@gmail.com> and <taddeuskroes@hotmail.com>.
*
* Submission date: 21 november 2010.
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
#include "main.h"
int
forks_len
;
pthread_mutex_t
*
forks
;
pthread_cond_t
wait_threshold
;
pthread_barrier_t
wait_barrier
;
typedef
struct
diner_stats
{
unsigned
int
meals
;
unsigned
int
forks
;
unsigned
int
id
;
unsigned
int
locked
;
}
diner_stats
;
int
diner_finished
=
0
;
#define TIME_LIMIT 2.f
/*
* Release fork taken by a philosopher.
*/
static
inline
void
release_fork
(
diner_stats
*
stats
,
int
f
)
{
if
(
diner_finished
)
return
;
stats
->
locked
^=
1
<<
f
;
pthread_mutex_unlock
(
&
forks
[
f
]);
// Unlock left or right fork.
stats
->
locked
^=
1
<<
(
f
%
2
);
pthread_mutex_unlock
(
forks
+
f
);
}
/*
* Try to claim a fork, but do not wait if the fork cannot be claimed.
* This call is therefore non-blocking.
*/
static
inline
int
try_take_fork
(
diner_stats
*
stats
,
int
f
)
{
// Try to lock left or right fork.
if
(
diner_finished
||
!
pthread_mutex_trylock
(
forks
+
f
))
return
1
;
stats
->
locked
|=
1
<<
(
f
%
2
);
stats
->
forks
++
;
return
0
;
}
/*
* Claim a fork, and wait (blocking) if the fork is already taken.
*/
static
inline
void
take_fork
(
diner_stats
*
stats
,
int
f
)
{
if
(
diner_finished
)
return
;
// Lock left or right fork.
pthread_mutex_lock
(
forks
+
f
);
stats
->
locked
|=
1
<<
f
;
stats
->
locked
|=
1
<<
(
f
%
2
)
;
stats
->
forks
++
;
}
#define PHILO_EATING \
if(diner_finished) \
break
; \
return 1
; \
\
stats->meals++;
void
philo_left
(
diner_stats
*
stats
,
int
id
)
{
while
(
!
diner_finished
)
{
// Let the philosopher take two forks.
static
const
char
*
philo_type_names
[]
=
{
"left"
,
"right"
,
"optimistic"
,
"shy"
,
"random"
};
static
const
philo_t
philo_types
[]
=
{
&
philo_left
,
&
philo_right
,
&
philo_shy
,
\
&
philo_optimistic
,
&
philo_random
};
static
const
int
philo_type_count
=
sizeof
(
philo_types
)
/
sizeof
(
philo_t
);
/*
* Philosopher favoring the left fork above the right fork. He will wait for
* both forks, and wouldn't release the first while he is waiting on the second.
*/
int
philo_left
(
diner_stats
*
stats
,
int
id
)
{
// Let the philosopher take two forks (first left, then right).
take_fork
(
stats
,
id
);
take_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
PHILO_EATING
;
// Release both forks.
release_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
release_fork
(
stats
,
id
);
}
return
0
;
}
void
philo_right
(
diner_stats
*
stats
,
int
id
)
{
while
(
!
diner_finished
)
{
// Let the philosopher take two forks.
/*
* Philosopher favoring the right fork above the left fork. He will wait for
* both forks, and wouldn't release the first while he is waiting on the second.
*/
int
philo_right
(
diner_stats
*
stats
,
int
id
)
{
// Let the philosopher take two forks (first right, then left).
take_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
take_fork
(
stats
,
id
);
PHILO_EATING
;
// Release both forks.
release_fork
(
stats
,
id
);
release_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
}
return
0
;
}
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
]))
{
/*
* Philosopher with optimistic behaviour: try to take the left or right fork,
* and if one fork is taken succesfully, wait till the second fork is released.
*/
int
philo_optimistic
(
diner_stats
*
stats
,
int
id
)
{
// Let the philosopher take the left fork of the two forks.
if
(
!
try_take_fork
(
stats
,
id
))
{
if
(
diner_finished
)
break
;
return
1
;
if
(
!
pthread_mutex_trylock
(
&
forks
[(
id
+
1
)
%
forks_len
]))
{
// Left fork is already taken, so try to take the right fork.
if
(
!
try_take_fork
(
stats
,
(
id
+
1
)
%
forks_len
))
{
if
(
diner_finished
)
break
;
// No fork
available, be faster next time!
return
1
;
// No forks
available, be faster next time!
sched_yield
();
}
else
{
stats
->
locked
|=
1
<<
((
id
+
1
)
%
forks_len
);
stats
->
forks
++
;
// Grabbed the right fork successfully.
if
(
diner_finished
)
break
;
return
1
;
take_fork
(
stats
,
id
);
PHILO_EATING
;
// Release both forks.
release_fork
(
stats
,
id
);
release_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
}
}
else
{
stats
->
locked
|=
1
<<
id
;
stats
->
forks
++
;
// Grabbed the left fork successfully.
take_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
PHILO_EATING
;
// Release both forks.
release_fork
(
stats
,
id
);
release_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
}
}
return
0
;
}
void
philo_shy
(
diner_stats
*
stats
,
int
id
)
{
/*
* Philosopher with shy behaviour: try again next time, when taking one of the
* forks fails.
*/
int
philo_shy
(
diner_stats
*
stats
,
int
id
)
{
// Try to take the right fork.
if
(
!
try_take_fork
(
stats
,
(
id
+
1
)
%
forks_len
))
{
if
(
diner_finished
)
return
1
;
}
// Failed to take fork, so try again next time.
sched_yield
();
}
// Let the philosopher try to take the left fork.
else
if
(
!
try_take_fork
(
stats
,
id
))
{
if
(
diner_finished
)
return
1
;
typedef
void
(
*
philo_t
)(
diner_stats
*
,
int
);
// Release the right fork and try again next time.
release_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
sched_yield
();
}
else
{
// Grabbed the left and right fork successfully.
PHILO_EATING
;
static
const
char
*
philo_type_names
[]
=
{
"left"
,
"right"
,
"optimistic"
};
//, "shy"};
static
const
philo_t
philo_types
[]
=
{
&
philo_left
,
&
philo_right
,
\
&
philo_optimistic
};
//, &philo_shy};
// Release both forks.
release_fork
(
stats
,
id
);
release_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
}
return
0
;
}
/*
* Philosopher with random behaviour: change each iteration to one of the other
* philosopher behaviours.
*/
int
philo_random
(
diner_stats
*
stats
,
int
id
)
{
// Pick a behaviour randomly (except for the "random" behaviour, since that
// would be recursive and thus useless to simulate).
return
(
*
philo_types
[
rand
()
%
(
philo_type_count
-
1
)])(
stats
,
id
);
}
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
))
;
type
=
rand
()
%
philo_type_count
;
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
);
while
(
!
diner_finished
&&
!
(
*
philo_types
[
type
])(
stats
,
id
));
printf
(
"P #%u: i'm leaving, after paying the bill.
\n
"
,
id
);
pthread_exit
(
NULL
);
}
...
...
@@ -189,25 +271,26 @@ void host_start(int philos) {
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.
// Duration of the diner party is 10 seconds
(see main.h). This loop will
// p
revent the p
hilosphers 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.
// Check each 10 ms for deadlock.
usleep
(
10000
);
// If an deadlock occured (all philosophers are waiting on their left or
// right fork), finish the diner party immidiately. It is unclear in the
// assignment, if the philosophers should leave the diner party, or if
// they only had to release their claimed forks. I choose the first
// assumption: leave the party. If they start arguing which fork is
// theirs, there's no party anymore.
int
p
;
for
(
p
=
0
;
p
<
philos
&&
stats
[
p
].
locked
&
(
1
<<
p
);
p
++
);
for
(
p
=
0
;
p
<
philos
&&
(
stats
[
p
].
locked
&
1
||
stats
[
p
].
locked
&
2
);
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
;
}
...
...
@@ -218,28 +301,22 @@ void host_start(int philos) {
puts
(
"Host: diner is finished."
);
// Wait on the other philosophers.
for
(
int
i
=
0
;
i
<
philos
;
i
++
)
{
// Reclaim all cutlery (mutexes). This is done twice, because some
// 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
++
)
// Reclaim all cutlery (mutexes) in reverse order.
for
(
int
p
=
philos
;
p
>=
i
;
p
--
)
pthread_mutex_unlock
(
&
forks
[
p
]);
// Wait on the other philosophers.
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 fork
s
.
\n
"
,
printf
(
"Philo #%d ate %d meal(s) and grabbed %d fork
(s)
.
\n
"
,
i
,
stats
[
i
].
meals
,
stats
[
i
].
forks
);
}
for
(
int
i
=
0
;
i
<
philos
;
i
++
)
pthread_mutex_destroy
(
&
forks
[
i
]);
}
puts
(
"Host: philosophers are done."
);
...
...
@@ -249,7 +326,15 @@ void host_start(int philos) {
pthread_exit
(
NULL
);
}
/*
* Start the philosopher diner problem simulation. By default two philosophers
* are simulated. The first commandline argument changes the total philosophers
* being simulated. If the argument is less than two, the philosopher count is
* set to the default count of two.
*/
int
main
(
int
argc
,
const
char
**
argv
)
{
// Get system clock's milliseconds and set it as seed to ensure a
// more "pseudo-random" simulation.
struct
timeval
wtc
;
gettimeofday
(
&
wtc
,
NULL
);
srand
(
wtc
.
tv_usec
);
...
...
os/ass4/main.h
0 → 100644
View file @
1715f304
/*
* Assignment 4 of Operating Systems: PThread simulation.
*
* Sander van Veen (6167969) and Taddeus Kroes (6054129).
* <sandervv@gmail.com> and <taddeuskroes@hotmail.com>.
*
* Submission date: 21 november 2010.
*/
typedef
struct
diner_stats
{
unsigned
int
meals
;
unsigned
int
forks
;
unsigned
int
id
;
unsigned
int
locked
;
}
diner_stats
;
/*
* Duration of the diner party (in seconds). When this time limit is reached,
* all philosophers are requested to pay their bill and leave the party.
*/
#define TIME_LIMIT 10.f
int
philo_left
(
diner_stats
*
stats
,
int
id
);
int
philo_right
(
diner_stats
*
stats
,
int
id
);
int
philo_optimistic
(
diner_stats
*
stats
,
int
id
);
int
philo_shy
(
diner_stats
*
stats
,
int
id
);
int
philo_random
(
diner_stats
*
stats
,
int
id
);
typedef
int
(
*
philo_t
)(
diner_stats
*
,
int
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment