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
8b45567d
Commit
8b45567d
authored
Feb 07, 2011
by
Sander Mathijs van Veen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Synched local and repos
parent
89841f96
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
1195 additions
and
1122 deletions
+1195
-1122
os/ass1/interval.c
os/ass1/interval.c
+39
-39
os/ass1/interval.h
os/ass1/interval.h
+6
-6
os/ass1/main.c
os/ass1/main.c
+57
-57
os/ass1/meten.c
os/ass1/meten.c
+76
-76
os/ass1/testcache.c
os/ass1/testcache.c
+6
-6
os/ass2/mem_alloc.h
os/ass2/mem_alloc.h
+5
-5
os/ass2/mt19937.h
os/ass2/mt19937.h
+13
-13
os/ass2/mt19937ar.c
os/ass2/mt19937ar.c
+30
-30
os/ass2/scheduler.c
os/ass2/scheduler.c
+259
-259
os/ass2/scheduler.h
os/ass2/scheduler.h
+108
-108
os/ass3/fishbones.c
os/ass3/fishbones.c
+220
-220
os/ass4/main.c
os/ass4/main.c
+45
-45
os/ass5/index.c
os/ass5/index.c
+16
-16
os/ass5/index.h
os/ass5/index.h
+11
-11
os/ass5/isam.c
os/ass5/isam.c
+111
-111
os/ass5/isam.h
os/ass5/isam.h
+99
-99
os/ass5/isam_bench.c
os/ass5/isam_bench.c
+9
-9
os/ass5/isam_test.c
os/ass5/isam_test.c
+2
-2
portfolio/vcs/vcs.tex
portfolio/vcs/vcs.tex
+83
-10
No files found.
os/ass1/interval.c
View file @
8b45567d
/*
/*
Author: G.D. van Albada
Author: G.D. van Albada
Date: August 26, 2009
Date: August 26, 2009
(c) Universiteit van Amsterdam
(c) Universiteit van Amsterdam
In this file the data types and some of the functions declared
In this file the data types and some of the functions declared
in the file interval.h for the first assignment in the OS course
in the file interval.h for the first assignment in the OS course
for 2009 are defined.
for 2009 are defined.
*/
*/
/*
/*
...
@@ -26,9 +26,9 @@
...
@@ -26,9 +26,9 @@
#include "interval.h"
#include "interval.h"
#include <math.h>
#include <math.h>
/*
/*
* Over the years the number of clock ticks per second has been
* Over the years the number of clock ticks per second has been
* called by many names. The code give here appears to work on most
* called by many names. The code give here appears to work on most
* machines.
* machines.
* Use MY_CLK_TCK to convert the output of times() to seconds.
* Use MY_CLK_TCK to convert the output of times() to seconds.
*/
*/
...
@@ -53,56 +53,56 @@ interval newInterval(void)
...
@@ -53,56 +53,56 @@ interval newInterval(void)
{
{
return
NULL
;
return
NULL
;
}
}
gettimeofday
(
&
(
nw
->
last_wct
),
NULL
);
gettimeofday
(
&
(
nw
->
last_wct
),
NULL
);
times
(
&
(
nw
->
last_cput
));
times
(
&
(
nw
->
last_cput
));
if
(
!
MY_CLK_TCK
)
if
(
!
MY_CLK_TCK
)
{
{
MY_CLK_TCK
=
sysconf
(
_SC_CLK_TCK
);
MY_CLK_TCK
=
sysconf
(
_SC_CLK_TCK
);
}
}
return
nw
;
return
nw
;
}
}
/*
/*
* Free the memory used by the interval pointer and set the pointer to NULL. If
* Free the memory used by the interval pointer and set the pointer to NULL. If
* the pointer is valid, zero is returned, or 1 otherwise.
* the pointer is valid, zero is returned, or 1 otherwise.
*/
*/
int
delInterval
(
interval
*
intervalPtr
)
int
delInterval
(
interval
*
intervalPtr
)
{
{
if
(
intervalPtr
==
NULL
)
if
(
intervalPtr
==
NULL
)
return
1
;
return
1
;
free
(
*
intervalPtr
);
free
(
*
intervalPtr
);
*
intervalPtr
=
NULL
;
*
intervalPtr
=
NULL
;
return
0
;
return
0
;
}
}
/*
/*
* Returns the wall clock time, user CPU time and system CPU time for the
* Returns the wall clock time, user CPU time and system CPU time for the
* calling process and its children consumed since the previous call for the
* calling process and its children consumed since the previous call for the
* specified interval. Returns zero on success, -1 when an invalid pointer is
* specified interval. Returns zero on success, -1 when an invalid pointer is
* passed as argument.
* passed as argument.
*/
*/
int
timeInterval
(
interval
id
,
double
*
wct
,
double
*
ust
,
double
*
syt
)
int
timeInterval
(
interval
id
,
double
*
wct
,
double
*
ust
,
double
*
syt
)
{
{
if
(
!
id
||
wct
==
NULL
||
ust
==
NULL
||
syt
==
NULL
)
if
(
!
id
||
wct
==
NULL
||
ust
==
NULL
||
syt
==
NULL
)
return
-
1
;
return
-
1
;
struct
timeval
last_wct
=
id
->
last_wct
;
struct
timeval
last_wct
=
id
->
last_wct
;
struct
tms
last_cput
=
id
->
last_cput
;
struct
tms
last_cput
=
id
->
last_cput
;
if
(
delInterval
(
&
id
)
)
if
(
delInterval
(
&
id
)
)
return
-
1
;
return
-
1
;
id
=
newInterval
();
id
=
newInterval
();
*
wct
=
(
id
->
last_wct
.
tv_sec
+
id
->
last_wct
.
tv_usec
/
1e6
)
*
wct
=
(
id
->
last_wct
.
tv_sec
+
id
->
last_wct
.
tv_usec
/
1e6
)
-
(
last_wct
.
tv_sec
+
last_wct
.
tv_usec
/
1e6
);
-
(
last_wct
.
tv_sec
+
last_wct
.
tv_usec
/
1e6
);
*
ust
=
difftime
(
id
->
last_cput
.
tms_utime
,
last_cput
.
tms_utime
)
/
MY_CLK_TCK
;
*
ust
=
difftime
(
id
->
last_cput
.
tms_utime
,
last_cput
.
tms_utime
)
/
MY_CLK_TCK
;
*
syt
=
difftime
(
id
->
last_cput
.
tms_stime
,
last_cput
.
tms_stime
)
/
MY_CLK_TCK
;
*
syt
=
difftime
(
id
->
last_cput
.
tms_stime
,
last_cput
.
tms_stime
)
/
MY_CLK_TCK
;
return
0
;
return
0
;
}
}
os/ass1/interval.h
View file @
8b45567d
/*
/*
Author: G.D. van Albada
Author: G.D. van Albada
Date: August 26, 2009
Date: August 26, 2009
(c) Universiteit van Amsterdam
(c) Universiteit van Amsterdam
In this file the data types and functions exported by the file
In this file the data types and functions exported by the file
interval.c for the first assignment in the OS course for 2009
interval.c for the first assignment in the OS course for 2009
are defined.
are defined.
*/
*/
/* interval is a pointer to a struct used by the functions
/* interval is a pointer to a struct used by the functions
...
...
os/ass1/main.c
View file @
8b45567d
...
@@ -16,68 +16,68 @@
...
@@ -16,68 +16,68 @@
void
consume_time
()
void
consume_time
()
{
{
int
i
=
0
,
max
=
1e6
;
int
i
=
0
,
max
=
1e6
;
double
x
=
0
,
s
,
e
;
double
x
=
0
,
s
,
e
;
srand
(
0
);
srand
(
0
);
while
(
i
++
<
max
)
while
(
i
++
<
max
)
{
{
x
+=
rand
();
x
+=
rand
();
s
=
sqrt
(
x
);
s
=
sqrt
(
x
);
e
=
pow
(
10
,
log10
(
x
)
/
2
);
e
=
pow
(
10
,
log10
(
x
)
/
2
);
}
}
}
}
/*
/*
*
*
*/
*/
int
main
(
int
argc
,
char
**
argv
)
int
main
(
int
argc
,
char
**
argv
)
{
{
interval
id
=
newInterval
();
interval
id
=
newInterval
();
// Benchmark the duration of a few system calls using timeInterval.
// Benchmark the duration of a few system calls using timeInterval.
double
wct
=
0
,
double
wct
=
0
,
ust
=
0
,
ust
=
0
,
syt
=
0
;
syt
=
0
;
int
i
=
0
,
max
=
1e2
;
int
i
=
0
,
max
=
1e2
;
while
(
i
++
<
max
)
while
(
i
++
<
max
)
{
{
consume_time
();
consume_time
();
(
void
)
timeInterval
(
id
,
&
wct
,
&
ust
,
&
syt
);
(
void
)
timeInterval
(
id
,
&
wct
,
&
ust
,
&
syt
);
printf
(
"Task took %.3f sec (us: %.3f, sy: %.3f)
\n
"
,
wct
,
ust
,
syt
);
printf
(
"Task took %.3f sec (us: %.3f, sy: %.3f)
\n
"
,
wct
,
ust
,
syt
);
}
}
// Benchmark the duration of one million timeInterval calls.
// Benchmark the duration of one million timeInterval calls.
i
=
0
;
i
=
0
;
double
tmp_wc
=
0
,
double
tmp_wc
=
0
,
tmp_us
=
0
,
tmp_us
=
0
,
tmp_sy
=
0
;
tmp_sy
=
0
;
interval
max_id
=
newInterval
();
interval
max_id
=
newInterval
();
id
=
newInterval
();
id
=
newInterval
();
max
=
1e6
;
max
=
1e6
;
while
(
i
++
<
max
)
while
(
i
++
<
max
)
{
{
(
void
)
timeInterval
(
id
,
&
tmp_wc
,
&
tmp_us
,
&
tmp_sy
);
(
void
)
timeInterval
(
id
,
&
tmp_wc
,
&
tmp_us
,
&
tmp_sy
);
}
}
if
(
timeInterval
(
max_id
,
&
wct
,
&
ust
,
&
syt
)
)
if
(
timeInterval
(
max_id
,
&
wct
,
&
ust
,
&
syt
)
)
perror
(
"timeInterval() returned a non-zero error code."
);
perror
(
"timeInterval() returned a non-zero error code."
);
fprintf
(
stderr
,
"%dx timeInterval took %.3f sec (us: %.3f, sy: %.3f)
\n
"
,
fprintf
(
stderr
,
"%dx timeInterval took %.3f sec (us: %.3f, sy: %.3f)
\n
"
,
max
,
wct
,
ust
,
syt
);
max
,
wct
,
ust
,
syt
);
return
(
EXIT_SUCCESS
);
return
(
EXIT_SUCCESS
);
}
}
os/ass1/meten.c
View file @
8b45567d
...
@@ -11,12 +11,12 @@
...
@@ -11,12 +11,12 @@
#include "meten.h"
#include "meten.h"
#include "testcache.h"
#include "testcache.h"
/*
/*
* Afhankelijk van de machine, moet de maximale waarde van size tussen de 20 en
* Afhankelijk van de machine, moet de maximale waarde van size tussen de 20 en
* 80 miljoen liggen, en de minimale bij een paar miljoen. De maximale waarde
* 80 miljoen liggen, en de minimale bij een paar miljoen. De maximale waarde
* van stride moet ergens tussen de 100 000 en 200 000 liggen, en de minimale
* van stride moet ergens tussen de 100 000 en 200 000 liggen, en de minimale
* waarde moet 1 zijn. Zeker voor de kleinere waarden van size zullen de
* waarde moet 1 zijn. Zeker voor de kleinere waarden van size zullen de
* functies zo snel zijn dat je ze een flink aantal malen moet meten voordat je
* functies zo snel zijn dat je ze een flink aantal malen moet meten voordat je
* een betrouwbare meting van met name de CPU-tijd hebt.
* een betrouwbare meting van met name de CPU-tijd hebt.
*/
*/
static
long
cur_size
=
1e6
;
static
long
cur_size
=
1e6
;
...
@@ -28,104 +28,104 @@ static long max_stride = 2e5;
...
@@ -28,104 +28,104 @@ static long max_stride = 2e5;
static
long
*
data
;
static
long
*
data
;
/*
/*
* De invoerparameters omvatten in ieder geval een pointer naar een functie van
* De invoerparameters omvatten in ieder geval een pointer naar een functie van
* het type van fillArray en sumArray, size en stride. De uitvoerparameters
* het type van fillArray en sumArray, size en stride. De uitvoerparameters
* omvatten in ieder geval de gebruikte wall-clock tijd en de gebruikte CPU tijd
* omvatten in ieder geval de gebruikte wall-clock tijd en de gebruikte CPU tijd
* voor de aanroep. Of je het te gebruiken array als parameter meegeeft, of
* voor de aanroep. Of je het te gebruiken array als parameter meegeeft, of
* binnen de functie zelf aanmaakt staat je vrij.
* binnen de functie zelf aanmaakt staat je vrij.
*/
*/
void
time_single_fn
(
array_fn
*
fn
,
double
*
wct
,
double
*
ust
,
double
*
syt
)
void
time_single_fn
(
array_fn
*
fn
,
double
*
wct
,
double
*
ust
,
double
*
syt
)
{
{
interval
now
=
newInterval
();
interval
now
=
newInterval
();
double
t_w
=
0
,
t_u
=
0
,
t_s
=
0
;
double
t_w
=
0
,
t_u
=
0
,
t_s
=
0
;
int
i
=
0
;
int
i
=
0
;
do
do
{
{
(
*
fn
)(
data
,
cur_size
,
cur_stride
);
(
*
fn
)(
data
,
cur_size
,
cur_stride
);
timeInterval
(
now
,
&
t_w
,
&
t_u
,
&
t_s
);
timeInterval
(
now
,
&
t_w
,
&
t_u
,
&
t_s
);
*
wct
+=
t_w
;
*
wct
+=
t_w
;
*
ust
+=
t_u
;
*
ust
+=
t_u
;
*
syt
+=
t_s
;
*
syt
+=
t_s
;
i
++
;
i
++
;
}
}
while
(
*
wct
<
1
);
while
(
*
wct
<
1
);
if
(
i
>
1
)
if
(
i
>
1
)
{
{
*
wct
/=
i
;
*
wct
/=
i
;
*
ust
/=
i
;
*
ust
/=
i
;
*
syt
/=
i
;
*
syt
/=
i
;
}
}
}
}
/*
/*
* Deze functie gebruikt de bovengenoemde functie om achtereenvolgens de
* Deze functie gebruikt de bovengenoemde functie om achtereenvolgens de
* performance te meten van een gegeven functie voor een reeks van waarden voor
* performance te meten van een gegeven functie voor een reeks van waarden voor
* size en stride. Een beetje afhankelijk van de machine waarop je werkt, moet
* size en stride. Een beetje afhankelijk van de machine waarop je werkt, moet
* de maximale waarde van size tussen de 20 en 80 miljoen liggen, en de minimale
* de maximale waarde van size tussen de 20 en 80 miljoen liggen, en de minimale
* bij een paar miljoen. De maximale waarde van stride moet ergens tussen de
* bij een paar miljoen. De maximale waarde van stride moet ergens tussen de
* 100 000 en 200 000 liggen, en de minimale waarde moet 1 zijn. Zeker voor de
* 100 000 en 200 000 liggen, en de minimale waarde moet 1 zijn. Zeker voor de
* kleinere waarden van size zullen de functies zo snel zijn dat je ze een flink
* kleinere waarden van size zullen de functies zo snel zijn dat je ze een flink
* aantal malen moet meten voordat je een betrouwbare meting van met name de
* aantal malen moet meten voordat je een betrouwbare meting van met name de
* CPU-tijd hebt.
* CPU-tijd hebt.
*
*
* Druk voor iedere combinatie van size en stride een regel af met de diverse
* Druk voor iedere combinatie van size en stride een regel af met de diverse
* meetwaarden en de naam van de geteste functie. Om je resultaten met elkaar te
* meetwaarden en de naam van de geteste functie. Om je resultaten met elkaar te
* kunnen vergelijken kan je de waarde per geheugen-access berekenen.
* kunnen vergelijken kan je de waarde per geheugen-access berekenen.
*
*
* N.B.2 schrijf je routine zo dat de te meten routine herhaald wordt
* N.B.2 schrijf je routine zo dat de te meten routine herhaald wordt
* aangeroepen totdat een vooraf bepaalde hoeveelheid CPU tijd is gebruikt
* aangeroepen totdat een vooraf bepaalde hoeveelheid CPU tijd is gebruikt
* (b.v. 0.5 seconde). Tel het aantal aanroepen.
* (b.v. 0.5 seconde). Tel het aantal aanroepen.
*
*
* N.B.3 als je de velden in de regel met een tab scheidt, kan je die later
* N.B.3 als je de velden in de regel met een tab scheidt, kan je die later
* eenvoudig in een spreadsheet inlezen.
* eenvoudig in een spreadsheet inlezen.
*/
*/
void
time_fn
(
array_fn
*
fn
,
double
*
wct
,
double
*
ust
,
double
*
syt
)
void
time_fn
(
array_fn
*
fn
,
double
*
wct
,
double
*
ust
,
double
*
syt
)
{
{
for
(
cur_size
=
min_size
;
cur_size
<=
max_size
;
cur_size
+=
cur_size
)
for
(
cur_size
=
min_size
;
cur_size
<=
max_size
;
cur_size
+=
cur_size
)
{
{
for
(
cur_stride
=
min_stride
;
for
(
cur_stride
=
min_stride
;
cur_stride
<=
max_stride
;
cur_stride
<=
max_stride
;
cur_stride
*=
10
)
cur_stride
*=
10
)
{
{
*
wct
=
0
;
*
wct
=
0
;
*
ust
=
0
;
*
ust
=
0
;
*
syt
=
0
;
*
syt
=
0
;
time_single_fn
(
fn
,
wct
,
ust
,
syt
);
time_single_fn
(
fn
,
wct
,
ust
,
syt
);
printf
(
"%9.ld
\t
%6.ld
\t
%.3f
\t
%.3f
\t
%.3f
\n
"
,
printf
(
"%9.ld
\t
%6.ld
\t
%.3f
\t
%.3f
\t
%.3f
\n
"
,
cur_size
,
cur_stride
,
*
wct
,
*
ust
,
*
syt
);
cur_size
,
cur_stride
,
*
wct
,
*
ust
,
*
syt
);
}
}
}
}
}
}
/*
/*
* Deze functie doet de nodige initialisaties, drukt minimaal een kopregel voor
* Deze functie doet de nodige initialisaties, drukt minimaal een kopregel voor
* de tabel af, en roept timeAFunction aan voor de beide routines fillArray en
* de tabel af, en roept timeAFunction aan voor de beide routines fillArray en
* sumArray.
* sumArray.
*/
*/
int
main
(
int
argc
,
char
**
argv
)
int
main
(
int
argc
,
char
**
argv
)
{
{
data
=
malloc
(
max_size
*
sizeof
(
long
*
));
data
=
malloc
(
max_size
*
sizeof
(
long
*
));
double
wct
=
0
,
ust
=
0
,
syt
=
0
;
double
wct
=
0
,
ust
=
0
,
syt
=
0
;
puts
(
"### fillArray ###"
);
puts
(
"### fillArray ###"
);
puts
(
"size
\t
stride
\t
time
\t
user
\t
sys"
);
puts
(
"size
\t
stride
\t
time
\t
user
\t
sys"
);
time_fn
(
&
fillArray
,
&
wct
,
&
ust
,
&
syt
);
time_fn
(
&
fillArray
,
&
wct
,
&
ust
,
&
syt
);
puts
(
"### sumArray ###"
);
puts
(
"### sumArray ###"
);
puts
(
"size
\t
stride
\t
time
\t
user
\t
sys"
);
puts
(
"size
\t
stride
\t
time
\t
user
\t
sys"
);
time_fn
(
&
sumArray
,
&
wct
,
&
ust
,
&
syt
);
time_fn
(
&
sumArray
,
&
wct
,
&
ust
,
&
syt
);
return
(
EXIT_SUCCESS
);
return
(
EXIT_SUCCESS
);
}
}
os/ass1/testcache.c
View file @
8b45567d
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
/* This is a very very basic test of cache behaviour */
/* This is a very very basic test of cache behaviour */
/*
/*
* We'll use a big array, say NELEMENTS in size
* We'll use a big array, say NELEMENTS in size
* The goal is to add up the values in that array, but we'll
* The goal is to add up the values in that array, but we'll
* use a double loop and a STRIDE. The outer loop increments
* use a double loop and a STRIDE. The outer loop increments
* the start element, the inner loop strides through the array
* the start element, the inner loop strides through the array
...
@@ -12,14 +12,14 @@
...
@@ -12,14 +12,14 @@
/*
/*
* Fill the array with values, but in a possibly cache-unfriendly
* Fill the array with values, but in a possibly cache-unfriendly
* manner. The array should contain at least "size" elements.
* manner. The array should contain at least "size" elements.
* The function returns a long so as to ensure that it has the
* The function returns a long so as to ensure that it has the
* same type as the sumArray function below.
* same type as the sumArray function below.
*/
*/
long
fillArray
(
long
*
array
,
int
size
,
int
stride
)
long
fillArray
(
long
*
array
,
int
size
,
int
stride
)
{
{
int
start
;
int
start
;
int
i
=
0
;
int
i
=
0
;
for
(
start
=
0
;
start
<
stride
;
start
++
)
for
(
start
=
0
;
start
<
stride
;
start
++
)
{
{
for
(
i
=
start
;
i
<
size
;
i
+=
stride
)
for
(
i
=
start
;
i
<
size
;
i
+=
stride
)
...
@@ -27,7 +27,7 @@ long fillArray(long *array, int size, int stride)
...
@@ -27,7 +27,7 @@ long fillArray(long *array, int size, int stride)
array
[
i
]
=
i
;
array
[
i
]
=
i
;
}
}
}
}
return
(
long
)
i
;
return
(
long
)
i
;
}
}
...
@@ -43,7 +43,7 @@ long sumArray(long *array, int size, int stride)
...
@@ -43,7 +43,7 @@ long sumArray(long *array, int size, int stride)
int
start
;
int
start
;
int
i
;
int
i
;
long
sum
=
0
;
long
sum
=
0
;
for
(
start
=
0
;
start
<
stride
;
start
++
)
for
(
start
=
0
;
start
<
stride
;
start
++
)
{
{
for
(
i
=
start
;
i
<
size
;
i
+=
stride
)
for
(
i
=
start
;
i
<
size
;
i
+=
stride
)
...
@@ -51,6 +51,6 @@ long sumArray(long *array, int size, int stride)
...
@@ -51,6 +51,6 @@ long sumArray(long *array, int size, int stride)
sum
+=
array
[
i
];
sum
+=
array
[
i
];
}
}
}
}
return
sum
;
return
sum
;
}
}
os/ass2/mem_alloc.h
View file @
8b45567d
...
@@ -45,11 +45,11 @@ void mem_available(long *empty, long *large, long *n_holes);
...
@@ -45,11 +45,11 @@ void mem_available(long *empty, long *large, long *n_holes);
/* mem_available vertelt de gebruiker hoeveel geheugen er nog
/* mem_available vertelt de gebruiker hoeveel geheugen er nog
beschikbaar is
beschikbaar is
empty: totale hoeveelheid vrije ruimte
empty: totale hoeveelheid vrije ruimte
large: omvang van het grootste gat, gecorrigeerd voor
large: omvang van het grootste gat, gecorrigeerd voor
administratie
administratie
n_holes: het aantal gaten
n_holes: het aantal gaten
*/
*/
void
mem_exit
();
void
mem_exit
();
...
...
os/ass2/mt19937.h
View file @
8b45567d
/*
/*
Header file for mt19937ar.c
Header file for mt19937ar.c
A C-program for MT19937, with initialization improved 2002/1/26.
A C-program for MT19937, with initialization improved 2002/1/26.
Coded by Takuji Nishimura and Makoto Matsumoto.
Coded by Takuji Nishimura and Makoto Matsumoto.
Before using, initialize the state by using init_genrand(seed)
Before using, initialize the state by using init_genrand(seed)
or init_by_array(init_key, key_length).
or init_by_array(init_key, key_length).
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
All rights reserved.
Redistribution and use in source and binary forms, with or without
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
modification, are permitted provided that the following conditions
are met:
are met:
1. Redistributions of source code must retain the above copyright
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
products derived from this software without specific prior written
permission.
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
...
@@ -38,8 +38,8 @@
...
@@ -38,8 +38,8 @@
Any feedback is very welcome.
Any feedback is very welcome.
http://www.math.keio.ac.jp/matumoto/emt.html
http://www.math.keio.ac.jp/matumoto/emt.html
email: matumoto@math.keio.ac.jp
email: matumoto@math.keio.ac.jp
*/
*/
/* initializes mt[N] with a seed */
/* initializes mt[N] with a seed */
...
...
os/ass2/mt19937ar.c
View file @
8b45567d
/*
/*
A C-program for MT19937, with initialization improved 2002/1/26.
A C-program for MT19937, with initialization improved 2002/1/26.
Coded by Takuji Nishimura and Makoto Matsumoto.
Coded by Takuji Nishimura and Makoto Matsumoto.
Before using, initialize the state by using init_genrand(seed)
Before using, initialize the state by using init_genrand(seed)
or init_by_array(init_key, key_length).
or init_by_array(init_key, key_length).
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
All rights reserved.
Redistribution and use in source and binary forms, with or without
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
modification, are permitted provided that the following conditions
are met:
are met:
1. Redistributions of source code must retain the above copyright
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
products derived from this software without specific prior written
permission.
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
...
@@ -37,13 +37,13 @@
...
@@ -37,13 +37,13 @@
Any feedback is very welcome.
Any feedback is very welcome.
http://www.math.keio.ac.jp/matumoto/emt.html
http://www.math.keio.ac.jp/matumoto/emt.html
email: matumoto@math.keio.ac.jp
email: matumoto@math.keio.ac.jp
*/
*/
#include <stdio.h>
#include <stdio.h>
/* Period parameters */
/* Period parameters */
#define N 624
#define N 624
#define M 397
#define M 397
#define MATRIX_A 0x9908b0dfUL
/* constant vector a */
#define MATRIX_A 0x9908b0dfUL
/* constant vector a */
...
@@ -58,8 +58,8 @@ void init_genrand(unsigned long s)
...
@@ -58,8 +58,8 @@ void init_genrand(unsigned long s)
{
{
mt
[
0
]
=
s
&
0xffffffffUL
;
mt
[
0
]
=
s
&
0xffffffffUL
;
for
(
mti
=
1
;
mti
<
N
;
mti
++
)
{
for
(
mti
=
1
;
mti
<
N
;
mti
++
)
{
mt
[
mti
]
=
mt
[
mti
]
=
(
1812433253UL
*
(
mt
[
mti
-
1
]
^
(
mt
[
mti
-
1
]
>>
30
))
+
mti
);
(
1812433253UL
*
(
mt
[
mti
-
1
]
^
(
mt
[
mti
-
1
]
>>
30
))
+
mti
);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* only MSBs of the array mt[]. */
...
@@ -73,7 +73,7 @@ void init_genrand(unsigned long s)
...
@@ -73,7 +73,7 @@ void init_genrand(unsigned long s)
/* init_key is the array for initializing keys */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* key_length is its length */
void
init_by_array
(
init_key
,
key_length
)
void
init_by_array
(
init_key
,
key_length
)
unsigned
long
init_key
[],
key_length
;
unsigned
long
init_key
[],
key_length
;
{
{
int
i
,
j
,
k
;
int
i
,
j
,
k
;
init_genrand
(
19650218UL
);
init_genrand
(
19650218UL
);
...
@@ -81,7 +81,7 @@ unsigned long init_key[], key_length;
...
@@ -81,7 +81,7 @@ unsigned long init_key[], key_length;
k
=
(
N
>
key_length
?
N
:
key_length
);
k
=
(
N
>
key_length
?
N
:
key_length
);
for
(;
k
;
k
--
)
{
for
(;
k
;
k
--
)
{
mt
[
i
]
=
(
mt
[
i
]
^
((
mt
[
i
-
1
]
^
(
mt
[
i
-
1
]
>>
30
))
*
1664525UL
))
mt
[
i
]
=
(
mt
[
i
]
^
((
mt
[
i
-
1
]
^
(
mt
[
i
-
1
]
>>
30
))
*
1664525UL
))
+
init_key
[
j
]
+
j
;
/* non linear */
+
init_key
[
j
]
+
j
;
/* non linear */
mt
[
i
]
&=
0xffffffffUL
;
/* for WORDSIZE > 32 machines */
mt
[
i
]
&=
0xffffffffUL
;
/* for WORDSIZE > 32 machines */
i
++
;
j
++
;
i
++
;
j
++
;
if
(
i
>=
N
)
{
mt
[
0
]
=
mt
[
N
-
1
];
i
=
1
;
}
if
(
i
>=
N
)
{
mt
[
0
]
=
mt
[
N
-
1
];
i
=
1
;
}
...
@@ -89,13 +89,13 @@ unsigned long init_key[], key_length;
...
@@ -89,13 +89,13 @@ unsigned long init_key[], key_length;
}
}
for
(
k
=
N
-
1
;
k
;
k
--
)
{
for
(
k
=
N
-
1
;
k
;
k
--
)
{
mt
[
i
]
=
(
mt
[
i
]
^
((
mt
[
i
-
1
]
^
(
mt
[
i
-
1
]
>>
30
))
*
1566083941UL
))
mt
[
i
]
=
(
mt
[
i
]
^
((
mt
[
i
-
1
]
^
(
mt
[
i
-
1
]
>>
30
))
*
1566083941UL
))
-
i
;
/* non linear */
-
i
;
/* non linear */
mt
[
i
]
&=
0xffffffffUL
;
/* for WORDSIZE > 32 machines */
mt
[
i
]
&=
0xffffffffUL
;
/* for WORDSIZE > 32 machines */
i
++
;
i
++
;
if
(
i
>=
N
)
{
mt
[
0
]
=
mt
[
N
-
1
];
i
=
1
;
}
if
(
i
>=
N
)
{
mt
[
0
]
=
mt
[
N
-
1
];
i
=
1
;
}
}
}
mt
[
0
]
=
0x80000000UL
;
/* MSB is 1; assuring non-zero initial array */
mt
[
0
]
=
0x80000000UL
;
/* MSB is 1; assuring non-zero initial array */
}
}
/* generates a random number on [0,0xffffffff]-interval */
/* generates a random number on [0,0xffffffff]-interval */
...
@@ -124,7 +124,7 @@ unsigned long genrand_int32(void)
...
@@ -124,7 +124,7 @@ unsigned long genrand_int32(void)
mti
=
0
;
mti
=
0
;
}
}
y
=
mt
[
mti
++
];
y
=
mt
[
mti
++
];
/* Tempering */
/* Tempering */
...
@@ -145,29 +145,29 @@ long genrand_int31(void)
...
@@ -145,29 +145,29 @@ long genrand_int31(void)
/* generates a random number on [0,1]-real-interval */
/* generates a random number on [0,1]-real-interval */
double
genrand_real1
(
void
)
double
genrand_real1
(
void
)
{
{
return
genrand_int32
()
*
(
1
.
0
/
4294967295
.
0
);
return
genrand_int32
()
*
(
1
.
0
/
4294967295
.
0
);
/* divided by 2^32-1 */
/* divided by 2^32-1 */
}
}
/* generates a random number on [0,1)-real-interval */
/* generates a random number on [0,1)-real-interval */
double
genrand_real2
(
void
)
double
genrand_real2
(
void
)
{
{
return
genrand_int32
()
*
(
1
.
0
/
4294967296
.
0
);
return
genrand_int32
()
*
(
1
.
0
/
4294967296
.
0
);
/* divided by 2^32 */
/* divided by 2^32 */
}
}
/* generates a random number on (0,1)-real-interval */
/* generates a random number on (0,1)-real-interval */
double
genrand_real3
(
void
)
double
genrand_real3
(
void
)
{
{
return
(((
double
)
genrand_int32
())
+
0
.
5
)
*
(
1
.
0
/
4294967296
.
0
);
return
(((
double
)
genrand_int32
())
+
0
.
5
)
*
(
1
.
0
/
4294967296
.
0
);
/* divided by 2^32 */
/* divided by 2^32 */
}
}
/* generates a random number on [0,1) with 53-bit resolution*/
/* generates a random number on [0,1) with 53-bit resolution*/
double
genrand_res53
(
void
)
double
genrand_res53
(
void
)
{
{
unsigned
long
a
=
genrand_int32
()
>>
5
,
b
=
genrand_int32
()
>>
6
;
unsigned
long
a
=
genrand_int32
()
>>
5
,
b
=
genrand_int32
()
>>
6
;
return
(
a
*
67108864
.
0
+
b
)
*
(
1
.
0
/
9007199254740992
.
0
);
return
(
a
*
67108864
.
0
+
b
)
*
(
1
.
0
/
9007199254740992
.
0
);
}
}
/* These real versions are due to Isaku Wada, 2002/01/09 added */
/* These real versions are due to Isaku Wada, 2002/01/09 added */
os/ass2/scheduler.c
View file @
8b45567d
...
@@ -13,7 +13,7 @@
...
@@ -13,7 +13,7 @@
* Section Computational Science
* Section Computational Science
* Universiteit van Amsterdam
* Universiteit van Amsterdam
* September 29, 2005
* September 29, 2005
*
*
* Student name .... Sander van Veen & Taddeus Kroes
* Student name .... Sander van Veen & Taddeus Kroes
* Student email ... sandervv@gmail.com & taddeuskroes@hotmail.com
* Student email ... sandervv@gmail.com & taddeuskroes@hotmail.com
* Collegekaart .... 6167969 & 6054129
* Collegekaart .... 6167969 & 6054129
...
@@ -34,11 +34,11 @@ static long memory[MEM_SIZE];
...
@@ -34,11 +34,11 @@ static long memory[MEM_SIZE];
*/
*/
static
void
CPU_scheduler_RR
()
static
void
CPU_scheduler_RR
()
{
{
if
(
!
ready_proc
)
if
(
!
ready_proc
)
return
;
return
;
set_slice
(
timeslice
);
set_slice
(
timeslice
);
enqueue_back
(
&
ready_proc
,
dequeue
(
&
ready_proc
));
enqueue_back
(
&
ready_proc
,
dequeue
(
&
ready_proc
));
}
}
/*
/*
...
@@ -46,20 +46,20 @@ static void CPU_scheduler_RR()
...
@@ -46,20 +46,20 @@ static void CPU_scheduler_RR()
*/
*/
static
void
CPU_scheduler_LJF
()
static
void
CPU_scheduler_LJF
()
{
{
if
(
!
ready_proc
)
if
(
!
ready_proc
)
return
;
return
;
pcb
*
proc
,
*
proc_max
;
pcb
*
proc
,
*
proc_max
;
// Find the longest job and put it at the front of the queue
// Find the longest job and put it at the front of the queue
for
(
proc
=
proc_max
=
ready_proc
;
proc
;
proc
=
proc
->
next
)
for
(
proc
=
proc_max
=
ready_proc
;
proc
;
proc
=
proc
->
next
)
{
{
if
(
proc
->
MEM_need
>
proc_max
->
MEM_need
)
if
(
proc
->
MEM_need
>
proc_max
->
MEM_need
)
proc_max
=
proc
;
proc_max
=
proc
;
}
}
set_slice
(
timeslice
);
set_slice
(
timeslice
);
enqueue_front
(
&
ready_proc
,
remove_from_queue
(
&
ready_proc
,
proc_max
));
enqueue_front
(
&
ready_proc
,
remove_from_queue
(
&
ready_proc
,
proc_max
));
}
}
/*
/*
...
@@ -67,34 +67,34 @@ static void CPU_scheduler_LJF()
...
@@ -67,34 +67,34 @@ static void CPU_scheduler_LJF()
*/
*/
static
void
CPU_scheduler_FCFS
()
static
void
CPU_scheduler_FCFS
()
{
{
// This function is implemented by the simulator.
// This function is implemented by the simulator.
}
}
/*
/*
* The high-level memory allocation scheduler is implemented here
* The high-level memory allocation scheduler is implemented here
*/
*/
static
void
GiveMemory_FCFFS
()
static
void
GiveMemory_FCFFS
()
{
{
int
index
;
int
index
;
pcb
*
proc1
,
*
proc2
;
pcb
*
proc1
,
*
proc2
;
for
(
proc2
=
new_proc
;
proc2
;
proc2
=
proc2
->
next
)
for
(
proc2
=
new_proc
;
proc2
;
proc2
=
proc2
->
next
)
{
{
// Search for a new process that should be given memory.
// Search for a new process that should be given memory.
if
(
(
index
=
mem_get
(
proc2
->
MEM_need
))
>=
0
)
if
(
(
index
=
mem_get
(
proc2
->
MEM_need
))
>=
0
)
{
{
// Allocation succeeded, now put in administration
// Allocation succeeded, now put in administration
proc2
->
MEM_base
=
index
;
proc2
->
MEM_base
=
index
;
// You might want to move this process to the ready
// You might want to move this process to the ready
//queue now
//queue now
proc1
=
proc2
->
next
;
proc1
=
proc2
->
next
;
enqueue_back
(
&
ready_proc
,
remove_from_queue
(
&
new_proc
,
proc2
));
enqueue_back
(
&
ready_proc
,
remove_from_queue
(
&
new_proc
,
proc2
));
if
(
!
(
proc2
=
proc1
)
)
if
(
!
(
proc2
=
proc1
)
)
break
;
break
;
}
}
}
}
}
}
/*
/*
...
@@ -102,14 +102,14 @@ static void GiveMemory_FCFFS()
...
@@ -102,14 +102,14 @@ static void GiveMemory_FCFFS()
*/
*/
static
void
GiveMemory_FCFS
()
static
void
GiveMemory_FCFS
()
{
{
int
index
;
int
index
;
// Assign all available memory to the first processes in the queue
// Assign all available memory to the first processes in the queue
while
(
new_proc
&&
(
index
=
mem_get
(
new_proc
->
MEM_need
))
>=
0
)
while
(
new_proc
&&
(
index
=
mem_get
(
new_proc
->
MEM_need
))
>=
0
)
{
{
new_proc
->
MEM_base
=
index
;
new_proc
->
MEM_base
=
index
;
enqueue_back
(
&
ready_proc
,
dequeue
(
&
new_proc
));
enqueue_back
(
&
ready_proc
,
dequeue
(
&
new_proc
));
}
}
}
}
/*
/*
...
@@ -117,28 +117,28 @@ static void GiveMemory_FCFS()
...
@@ -117,28 +117,28 @@ static void GiveMemory_FCFS()
*/
*/
static
void
GiveMemory_SJF
()
static
void
GiveMemory_SJF
()
{
{
int
index
;
int
index
;
pcb
*
proc
,
*
proc_min
;
pcb
*
proc
,
*
proc_min
;
for
(
;;
)
for
(
;;
)
{
{
// Find the shortest process
// Find the shortest process
for
(
proc
=
proc_min
=
new_proc
;
proc
;
proc
=
proc
->
next
)
for
(
proc
=
proc_min
=
new_proc
;
proc
;
proc
=
proc
->
next
)
{
{
if
(
proc
->
MEM_need
<
proc_min
->
MEM_need
)
if
(
proc
->
MEM_need
<
proc_min
->
MEM_need
)
proc_min
=
proc
;
proc_min
=
proc
;
}
}
// Assign memory or if no memory is available, break loop
// Assign memory or if no memory is available, break loop
if
(
proc_min
&&
(
index
=
mem_get
(
proc_min
->
MEM_need
))
>=
0
)
if
(
proc_min
&&
(
index
=
mem_get
(
proc_min
->
MEM_need
))
>=
0
)
{
{
proc_min
->
MEM_base
=
index
;
proc_min
->
MEM_base
=
index
;
enqueue_back
(
&
ready_proc
,
remove_from_queue
(
&
new_proc
,
proc_min
));
enqueue_back
(
&
ready_proc
,
remove_from_queue
(
&
new_proc
,
proc_min
));
}
}
else
else
break
;
break
;
}
}
}
}
/*
/*
...
@@ -146,62 +146,62 @@ static void GiveMemory_SJF()
...
@@ -146,62 +146,62 @@ static void GiveMemory_SJF()
*/
*/
static
void
GiveMemory_SJF_fairness
()
static
void
GiveMemory_SJF_fairness
()
{
{
int
index
,
thres_max
=
0
;
int
index
,
thres_max
=
0
;
pcb
*
proc
,
*
proc_min
,
*
proc_long
;
pcb
*
proc
,
*
proc_min
,
*
proc_long
;
for
(
;;
)
for
(
;;
)
{
{
proc_long
=
NULL
;
proc_long
=
NULL
;
// Find the shortest process and the process with the
// Find the shortest process and the process with the
// highest fairness threshold value
// highest fairness threshold value
for
(
proc
=
proc_min
=
new_proc
;
proc
;
proc
=
proc
->
next
)
for
(
proc
=
proc_min
=
new_proc
;
proc
;
proc
=
proc
->
next
)
{
{
if
(
proc
->
MEM_need
<
proc_min
->
MEM_need
)
if
(
proc
->
MEM_need
<
proc_min
->
MEM_need
)
proc_min
=
proc
;
proc_min
=
proc
;
if
(
proc
->
your_admin
&&
*
((
int
*
)
proc
->
your_admin
)
>
thres_max
)
if
(
proc
->
your_admin
&&
*
((
int
*
)
proc
->
your_admin
)
>
thres_max
)
{
{
thres_max
=
*
((
int
*
)
proc
->
your_admin
);
thres_max
=
*
((
int
*
)
proc
->
your_admin
);
proc_long
=
proc
;
proc_long
=
proc
;
}
}
}
}
// Shortest process gives precedence to a process
// Shortest process gives precedence to a process
// which exceeds the fairness threshold
// which exceeds the fairness threshold
if
(
proc_long
&&
thres_max
>=
FAIRNESS_THRESHOLD
)
if
(
proc_long
&&
thres_max
>=
FAIRNESS_THRESHOLD
)
proc
=
proc_long
;
proc
=
proc_long
;
else
else
proc
=
proc_min
;
proc
=
proc_min
;
// The queue is empty
// The queue is empty
if
(
!
proc
)
if
(
!
proc
)
break
;
break
;
// If memory is available, assign it to the process.
// If memory is available, assign it to the process.
// Otherwise, increment its fairness value
// Otherwise, increment its fairness value
if
(
(
index
=
mem_get
(
proc
->
MEM_need
))
>=
0
)
if
(
(
index
=
mem_get
(
proc
->
MEM_need
))
>=
0
)
{
{
proc
->
MEM_base
=
index
;
proc
->
MEM_base
=
index
;
enqueue_back
(
&
ready_proc
,
remove_from_queue
(
&
new_proc
,
proc
));
enqueue_back
(
&
ready_proc
,
remove_from_queue
(
&
new_proc
,
proc
));
}
}
else
if
(
proc
->
your_admin
)
else
if
(
proc
->
your_admin
)
{
{
(
*
((
int
*
)
proc
->
your_admin
))
++
;
(
*
((
int
*
)
proc
->
your_admin
))
++
;
break
;
break
;
}
}
else
else
{
{
proc
->
your_admin
=
(
int
*
)
malloc
(
sizeof
(
int
));
proc
->
your_admin
=
(
int
*
)
malloc
(
sizeof
(
int
));
*
((
int
*
)
proc
->
your_admin
)
=
1
;
*
((
int
*
)
proc
->
your_admin
)
=
1
;
break
;
break
;
}
}
}
}
}
}
/*
/*
* Here we reclaim the memory of a process after it has finished
* Here we reclaim the memory of a process after it has finished
*/
*/
static
void
ReclaimMemory
()
static
void
ReclaimMemory
()
{
{
...
@@ -215,7 +215,7 @@ static void ReclaimMemory()
...
@@ -215,7 +215,7 @@ static void ReclaimMemory()
{
{
free
(
proc
->
your_admin
);
free
(
proc
->
your_admin
);
}
}
// Free the simulated allocated memory
// Free the simulated allocated memory
mem_free
(
proc
->
MEM_base
);
mem_free
(
proc
->
MEM_base
);
proc
->
MEM_base
=
-
1
;
proc
->
MEM_base
=
-
1
;
...
@@ -234,7 +234,7 @@ static void ReclaimMemory()
...
@@ -234,7 +234,7 @@ static void ReclaimMemory()
static
void
my_finale
()
static
void
my_finale
()
{
{
// Your very own code goes here
// Your very own code goes here
// Less is more :-)
// Less is more :-)
}
}
/*
/*
...
@@ -242,100 +242,100 @@ static void my_finale()
...
@@ -242,100 +242,100 @@ static void my_finale()
*/
*/
void
schedule
(
event_type
event
)
void
schedule
(
event_type
event
)
{
{
static
int
first
=
1
;
static
int
first
=
1
;
static
void
(
*
hl_handler
)(
void
)
;
static
void
(
*
hl_handler
)(
void
)
;
static
void
(
*
cpu_handler
)(
void
)
;
static
void
(
*
cpu_handler
)(
void
)
;
if
(
first
)
if
(
first
)
{
{
mem_init
(
memory
);
mem_init
(
memory
);
finale
=
my_finale
;
finale
=
my_finale
;
first
=
0
;
first
=
0
;
int
scheduler_type
=
0
;
int
scheduler_type
=
0
;
printf
(
"Kies een high-level scheduler:
\n
"
printf
(
"Kies een high-level scheduler:
\n
"
" 1. FCFS
\n
"
" 1. FCFS
\n
"
" 2. SJF
\n
"
" 2. SJF
\n
"
" 3. FCFFS
\n
"
" 3. FCFFS
\n
"
" 4. SJF (met fairness)
\n
"
" 4. SJF (met fairness)
\n
"
"Keuze: "
"Keuze: "
);
);
if
(
!
scanf
(
"%d"
,
&
scheduler_type
)
)
if
(
!
scanf
(
"%d"
,
&
scheduler_type
)
)
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
switch
(
scheduler_type
)
switch
(
scheduler_type
)
{
{
case
1
:
hl_handler
=
&
GiveMemory_FCFS
;
break
;
case
1
:
hl_handler
=
&
GiveMemory_FCFS
;
break
;
case
2
:
hl_handler
=
&
GiveMemory_SJF
;
break
;
case
2
:
hl_handler
=
&
GiveMemory_SJF
;
break
;
case
3
:
hl_handler
=
&
GiveMemory_FCFFS
;
break
;
case
3
:
hl_handler
=
&
GiveMemory_FCFFS
;
break
;
case
4
:
hl_handler
=
&
GiveMemory_SJF_fairness
;
break
;
case
4
:
hl_handler
=
&
GiveMemory_SJF_fairness
;
break
;
default:
default:
fprintf
(
stderr
,
fprintf
(
stderr
,
"Ongeldige invoer (alleen 1 t/m 4 toegestaan).
\n
"
);
"Ongeldige invoer (alleen 1 t/m 4 toegestaan).
\n
"
);
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
break
;
break
;
}
}
printf
(
"
\n
"
);
printf
(
"
\n
"
);
int
cpu_type
=
0
;
int
cpu_type
=
0
;
printf
(
"Kies een cpu scheduler:
\n
"
printf
(
"Kies een cpu scheduler:
\n
"
" 0. FCFS (standaard)
\n
"
" 0. FCFS (standaard)
\n
"
" 1. Round robin
\n
"
" 1. Round robin
\n
"
" 2. LJF
\n
"
" 2. LJF
\n
"
"Keuze: "
"Keuze: "
);
);
if
(
!
scanf
(
"%d"
,
&
cpu_type
)
)
if
(
!
scanf
(
"%d"
,
&
cpu_type
)
)
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
switch
(
cpu_type
)
switch
(
cpu_type
)
{
{
case
0
:
cpu_handler
=
&
CPU_scheduler_FCFS
;
break
;
case
0
:
cpu_handler
=
&
CPU_scheduler_FCFS
;
break
;
case
1
:
cpu_handler
=
&
CPU_scheduler_RR
;
break
;
case
1
:
cpu_handler
=
&
CPU_scheduler_RR
;
break
;
case
2
:
cpu_handler
=
&
CPU_scheduler_LJF
;
break
;
case
2
:
cpu_handler
=
&
CPU_scheduler_LJF
;
break
;
default:
default:
fprintf
(
stderr
,
fprintf
(
stderr
,
"Ongeldige invoer (alleen 0 t/m 2 toegestaan).
\n
"
);
"Ongeldige invoer (alleen 0 t/m 2 toegestaan).
\n
"
);
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
break
;
break
;
}
}
printf
(
"
\n
"
);
printf
(
"
\n
"
);
printf
(
"Geef lengte time-slice: "
);
printf
(
"Geef lengte time-slice: "
);
if
(
!
scanf
(
"%lf"
,
&
timeslice
)
||
timeslice
<
1
.
0
)
if
(
!
scanf
(
"%lf"
,
&
timeslice
)
||
timeslice
<
1
.
0
)
timeslice
=
1
.
0
;
timeslice
=
1
.
0
;
printf
(
"
\n
"
);
printf
(
"
\n
"
);
}
}
switch
(
event
)
switch
(
event
)
{
{
// You may want to do this differently
// You may want to do this differently
case
NewProcess_event
:
case
NewProcess_event
:
(
*
hl_handler
)();
(
*
hl_handler
)();
break
;
break
;
case
Time_event
:
case
Time_event
:
case
IO_event
:
case
IO_event
:
(
*
cpu_handler
)();
(
*
cpu_handler
)();
break
;
break
;
case
Ready_event
:
case
Ready_event
:
break
;
break
;
case
Finish_event
:
case
Finish_event
:
ReclaimMemory
();
ReclaimMemory
();
(
*
hl_handler
)();
(
*
hl_handler
)();
(
*
cpu_handler
)();
(
*
cpu_handler
)();
break
;
break
;
default:
default:
printf
(
"I cannot handle event nr. %d
\n
"
,
event
);
printf
(
"I cannot handle event nr. %d
\n
"
,
event
);
break
;
break
;
}
}
}
}
/*
/*
...
@@ -343,15 +343,15 @@ void schedule(event_type event)
...
@@ -343,15 +343,15 @@ void schedule(event_type event)
*/
*/
void
enqueue_front
(
pcb
**
queue
,
pcb
*
elem
)
void
enqueue_front
(
pcb
**
queue
,
pcb
*
elem
)
{
{
// Attach the (non-empty) queue to the new item
// Attach the (non-empty) queue to the new item
if
(
*
queue
)
if
(
*
queue
)
{
{
elem
->
next
=
*
queue
;
elem
->
next
=
*
queue
;
(
*
queue
)
->
prev
=
elem
;
(
*
queue
)
->
prev
=
elem
;
}
}
// Put the new element at the front of the queue
// Put the new element at the front of the queue
*
queue
=
elem
;
*
queue
=
elem
;
}
}
/*
/*
...
@@ -359,21 +359,21 @@ void enqueue_front(pcb **queue, pcb *elem)
...
@@ -359,21 +359,21 @@ void enqueue_front(pcb **queue, pcb *elem)
*/
*/
void
enqueue_back
(
pcb
**
queue
,
pcb
*
elem
)
void
enqueue_back
(
pcb
**
queue
,
pcb
*
elem
)
{
{
pcb
*
last
;
pcb
*
last
;
// Check if the queue is empty
// Check if the queue is empty
if
(
!
(
*
queue
)
)
if
(
!
(
*
queue
)
)
{
{
*
queue
=
elem
;
*
queue
=
elem
;
return
;
return
;
}
}
// Walk through the queue until the last queued item is reached
// Walk through the queue until the last queued item is reached
for
(
last
=
*
queue
;
last
->
next
;
last
=
last
->
next
);
for
(
last
=
*
queue
;
last
->
next
;
last
=
last
->
next
);
// Attach the element to the last item
// Attach the element to the last item
last
->
next
=
elem
;
last
->
next
=
elem
;
elem
->
prev
=
last
;
elem
->
prev
=
last
;
}
}
/*
/*
...
@@ -381,19 +381,19 @@ void enqueue_back(pcb **queue, pcb *elem)
...
@@ -381,19 +381,19 @@ void enqueue_back(pcb **queue, pcb *elem)
*/
*/
pcb
*
remove_from_queue
(
pcb
**
queue
,
pcb
*
elem
)
pcb
*
remove_from_queue
(
pcb
**
queue
,
pcb
*
elem
)
{
{
// Remove from front of queue.
// Remove from front of queue.
if
(
*
queue
==
elem
)
if
(
*
queue
==
elem
)
*
queue
=
elem
->
next
;
*
queue
=
elem
->
next
;
if
(
elem
->
next
)
if
(
elem
->
next
)
elem
->
next
->
prev
=
elem
->
prev
;
elem
->
next
->
prev
=
elem
->
prev
;
if
(
elem
->
prev
)
if
(
elem
->
prev
)
elem
->
prev
->
next
=
elem
->
next
;
elem
->
prev
->
next
=
elem
->
next
;
elem
->
next
=
elem
->
prev
=
NULL
;
elem
->
next
=
elem
->
prev
=
NULL
;
return
elem
;
return
elem
;
}
}
/*
/*
...
@@ -401,5 +401,5 @@ pcb *remove_from_queue(pcb **queue, pcb *elem)
...
@@ -401,5 +401,5 @@ pcb *remove_from_queue(pcb **queue, pcb *elem)
*/
*/
pcb
*
dequeue
(
pcb
**
queue
)
pcb
*
dequeue
(
pcb
**
queue
)
{
{
return
remove_from_queue
(
queue
,
*
queue
);
return
remove_from_queue
(
queue
,
*
queue
);
}
}
os/ass2/scheduler.h
View file @
8b45567d
/****************************************************************************
/****************************************************************************
Deze header file bevat de voor de opgave over high-level scheduling en
Deze header file bevat de voor de opgave over high-level scheduling en
geheugen-allocatie benodigde definities
geheugen-allocatie benodigde definities
Auteur: Dick van Albada
Auteur: Dick van Albada
Vakgroep Computersystemen
Vakgroep Computersystemen
Kruislaan 403
Kruislaan 403
Datum: 7 september 2003
Datum: 7 september 2003
Versie: 0.3
Versie: 0.3
Student name .... Sander van Veen & Taddeus Kroes
Student name .... Sander van Veen & Taddeus Kroes
Student email ... sandervv@gmail.com & taddeuskroes@hotmail.com
Student email ... sandervv@gmail.com & taddeuskroes@hotmail.com
Collegekaart .... 6167969 & 6054129
Collegekaart .... 6167969 & 6054129
Date ............ 10.10.2010
Date ............ 10.10.2010
****************************************************************************/
****************************************************************************/
/****************************************************************************
/****************************************************************************
De verschillende soorten events:
De verschillende soorten events:
NewProcess_event - er is een nieuw proces in de new_proc rij
NewProcess_event - er is een nieuw proces in de new_proc rij
bijgeplaatst.
bijgeplaatst.
Time_event - het lopende proces heeft zijn time-slice opgebruikt.
Time_event - het lopende proces heeft zijn time-slice opgebruikt.
Wordt niet gegenereerd, tenzij je zelf "set_slice" aanroept.
Wordt niet gegenereerd, tenzij je zelf "set_slice" aanroept.
Hoort b.v. in een Round-Robin schedule thuis.
Hoort b.v. in een Round-Robin schedule thuis.
Ready_event - een proces is klaar met I/O en is weer achteraan de
Ready_event - een proces is klaar met I/O en is weer achteraan de
ready_proc rij geplaatst. Voor sommige CPU-scheduling algoritmen
ready_proc rij geplaatst. Voor sommige CPU-scheduling algoritmen
een punt om weer een beslissing te nemen.
een punt om weer een beslissing te nemen.
IO_event - het lopende proces gaat I/O doen en is achteraan de
IO_event - het lopende proces gaat I/O doen en is achteraan de
io_proc rij geplaatst. Als je de volgorde van de processen in
io_proc rij geplaatst. Als je de volgorde van de processen in
de io_proc queue of in de ready queue wil aanpassen, kan dat nu.
de io_proc queue of in de ready queue wil aanpassen, kan dat nu.
Finish_event - het lopende proces is beeindigd en in de defunct_proc rij
Finish_event - het lopende proces is beeindigd en in de defunct_proc rij
geplaatst. Een goede gelegenheid om nieuwe processen toe te laten.
geplaatst. Een goede gelegenheid om nieuwe processen toe te laten.
****************************************************************************/
****************************************************************************/
typedef
enum
EVENT
{
NewProcess_event
,
Time_event
,
Ready_event
,
IO_event
,
typedef
enum
EVENT
{
NewProcess_event
,
Time_event
,
Ready_event
,
IO_event
,
Finish_event
}
event_type
;
Finish_event
}
event_type
;
/****************************************************************************
/****************************************************************************
de structuur "pcb" bevat alle informatie die voor de scheduler
de structuur "pcb" bevat alle informatie die voor de scheduler
beschikbaar is.
beschikbaar is.
SIM_pcb verwijst naar de voor de simulator benodigde informatie en mag
SIM_pcb verwijst naar de voor de simulator benodigde informatie en mag
niet worden gewijzigd.
niet worden gewijzigd.
your_admin wordt door de simulator niet gebruikt (aanvankelijk NULL).
your_admin wordt door de simulator niet gebruikt (aanvankelijk NULL).
Deze pointer is beschikbaar om desgewenst voor de scheduler een
Deze pointer is beschikbaar om desgewenst voor de scheduler een
eigen administratie aan de pcb te kunnen koppelen.
eigen administratie aan de pcb te kunnen koppelen.
prev en next worden gebruikt voor het construeren van dubbel verbonden
prev en next worden gebruikt voor het construeren van dubbel verbonden
lijsten. Ze kunnen zowel door de simulator als door de scheduler
lijsten. Ze kunnen zowel door de simulator als door de scheduler
worden gewijzigd.
worden gewijzigd.
MEM_need bevat het aantal voor dit proces benodigde longs geheugen.
MEM_need bevat het aantal voor dit proces benodigde longs geheugen.
MEM_need wordt door de simulator ingevuld en mag niet worden
MEM_need wordt door de simulator ingevuld en mag niet worden
gewijzigd.
gewijzigd.
MEM_base staat aanvankelijk op -1 en moet door de (hoog-niveau) scheduler
MEM_base staat aanvankelijk op -1 en moet door de (hoog-niveau) scheduler
een maal worden gevuld met de begin-locatie in het te gebruiken
een maal worden gevuld met de begin-locatie in het te gebruiken
geheugen-array. Door jouw scheduler een maal te veranderen.
geheugen-array. Door jouw scheduler een maal te veranderen.
proc_num is het volgnummer van het proces en wordt door de simulator
proc_num is het volgnummer van het proces en wordt door de simulator
gevuld. Niet veranderen.
gevuld. Niet veranderen.
****************************************************************************/
****************************************************************************/
typedef
struct
PCB
typedef
struct
PCB
{
{
void
*
SIM_pcb
;
void
*
SIM_pcb
;
void
*
your_admin
;
void
*
your_admin
;
struct
PCB
*
prev
,
struct
PCB
*
prev
,
*
next
;
*
next
;
long
MEM_need
,
long
MEM_need
,
MEM_base
,
MEM_base
,
proc_num
;
proc_num
;
}
pcb
;
}
pcb
;
/****************************************************************************
/****************************************************************************
De wachtrijen.
De wachtrijen.
Nieuwe processen worden achteraan in de rij new_proc bijgeplaatst.
Nieuwe processen worden achteraan in de rij new_proc bijgeplaatst.
(programma practicumleiding)
(programma practicumleiding)
Na toewijzing van geheugen dienen ze in de ready_proc rij te worden
Na toewijzing van geheugen dienen ze in de ready_proc rij te worden
geplaatst.
geplaatst.
(procedure schedule)
(procedure schedule)
Een proces wordt voor de CPU gescheduled door het voorin de ready_proc
Een proces wordt voor de CPU gescheduled door het voorin de ready_proc
rij te plaatsen. Zonder enige verdere voorzieningen werken de io_proc
rij te plaatsen. Zonder enige verdere voorzieningen werken de io_proc
en ready_proc rijen op FCFS basis hun klanten af.
en ready_proc rijen op FCFS basis hun klanten af.
(procedure schedule - een andere CPU scheduling dan FCFS vereist
(procedure schedule - een andere CPU scheduling dan FCFS vereist
dus aanpassingen in de volgorde van processen in deze queues.
dus aanpassingen in de volgorde van processen in deze queues.
Als een proces I/O wil doen (gesimuleerd), komt het in de io_proc rij.
Als een proces I/O wil doen (gesimuleerd), komt het in de io_proc rij.
Laat deze rij met rust.
Laat deze rij met rust.
Een beeindigd proces komt in de defunct_proc rij. Ruim deze op.
Een beeindigd proces komt in de defunct_proc rij. Ruim deze op.
*****************************************************************************/
*****************************************************************************/
pcb
*
new_proc
,
pcb
*
new_proc
,
...
@@ -89,72 +89,72 @@ pcb *new_proc,
...
@@ -89,72 +89,72 @@ pcb *new_proc,
*
defunct_proc
;
*
defunct_proc
;
/****************************************************************************
/****************************************************************************
De door de practicum-leiding aangeleverde fucties
De door de practicum-leiding aangeleverde fucties
*****************************************************************************/
*****************************************************************************/
double
sim_time
();
double
sim_time
();
/****************************************************************************
/****************************************************************************
sim_time geeft de gesimuleerde "wall-clock time" terug. Gebruik
sim_time geeft de gesimuleerde "wall-clock time" terug. Gebruik
naar het je goeddunkt
naar het je goeddunkt
*****************************************************************************/
*****************************************************************************/
extern
void
set_slice
(
double
slice
);
extern
void
set_slice
(
double
slice
);
/****************************************************************************
/****************************************************************************
set_slice zorgt dat over slice tijdseenheden een Time_event optreedt.
set_slice zorgt dat over slice tijdseenheden een Time_event optreedt.
Er kan maar een Time_event tegelijk in de pijp zitten, dus iedere
Er kan maar een Time_event tegelijk in de pijp zitten, dus iedere
set_slice aanroep "overschrijft" de vorige.
set_slice aanroep "overschrijft" de vorige.
set_slice zorgt er intern voor dat slice steeds minstens 1.0 is, om
set_slice zorgt er intern voor dat slice steeds minstens 1.0 is, om
voortgang te garanderen.
voortgang te garanderen.
Bij een Time_event wordt voordat de scheduler wordt aangeroepen steeds
Bij een Time_event wordt voordat de scheduler wordt aangeroepen steeds
een set_slice(9.9e12) gedaan om te voorkomen dat de simulator daarop kan
een set_slice(9.9e12) gedaan om te voorkomen dat de simulator daarop kan
blijven hangen.
blijven hangen.
Gebruik voor deze opgave is niet nodig.
Gebruik voor deze opgave is niet nodig.
*****************************************************************************/
*****************************************************************************/
long
rm_process
(
pcb
**
proces
);
long
rm_process
(
pcb
**
proces
);
/****************************************************************************
/****************************************************************************
rm_process heeft twee taken:
rm_process heeft twee taken:
1. het verzamelt de nodige statistische gegevens over de executie
1. het verzamelt de nodige statistische gegevens over de executie
van het proces voor het "eindrapport"
van het proces voor het "eindrapport"
2. het ruimt de pcb en de "SIM_pcb" op en werkt de defunct_proc rij bij.
2. het ruimt de pcb en de "SIM_pcb" op en werkt de defunct_proc rij bij.
rm_process ruimt de eventueel door "your_admin" gebruikte ruimte
rm_process ruimt de eventueel door "your_admin" gebruikte ruimte
niet op en geeft ook het gereserveerde geheugen niet vrij. Dat
niet op en geeft ook het gereserveerde geheugen niet vrij. Dat
moet je bij een "Finish_event" zelf doen.
moet je bij een "Finish_event" zelf doen.
****************************************************************************/
****************************************************************************/
/***************************************************************************
/***************************************************************************
De functie variabele finale wordt door het hoofdprogramma geinitialiseerd
De functie variabele finale wordt door het hoofdprogramma geinitialiseerd
met een vrijwel lege functie die alleen de tekst "Einde van het programma"
met een vrijwel lege functie die alleen de tekst "Einde van het programma"
afdrukt.
afdrukt.
Hij wordt aangeroepen vlak voor het eind van het programma, als de
Hij wordt aangeroepen vlak voor het eind van het programma, als de
door het hoofdprogramma verzamelde statistische gegevens zijn afgedrukt.
door het hoofdprogramma verzamelde statistische gegevens zijn afgedrukt.
Door finale naar een eigen functie van het juiste type te laten verwijzen,
Door finale naar een eigen functie van het juiste type te laten verwijzen,
kun je ervoor zorgen dat je eigen afsluitende routine wordt aangeroepen
kun je ervoor zorgen dat je eigen afsluitende routine wordt aangeroepen
om zo eventuele eigen statistieken af te drukken.
om zo eventuele eigen statistieken af te drukken.
Een interessante mogelijkheid is b.v. de samenhang tussen de wachttijd op
Een interessante mogelijkheid is b.v. de samenhang tussen de wachttijd op
geheugen en de grootte van het aangevraagde geheugen te onderzoeken.
geheugen en de grootte van het aangevraagde geheugen te onderzoeken.
Treedt er starvation op, en zo ja, voor welke processen?
Treedt er starvation op, en zo ja, voor welke processen?
****************************************************************************/
****************************************************************************/
typedef
void
function
();
typedef
void
function
();
function
*
finale
;
function
*
finale
;
/****************************************************************************
/****************************************************************************
Voor de eigenlijke meting worden 100 processen opgestart om de
Voor de eigenlijke meting worden 100 processen opgestart om de
queues te vullen. Daarna worden de statistieken weer op nul gezet.
queues te vullen. Daarna worden de statistieken weer op nul gezet.
Definieer zelf een functie waar je reset_stats naar laat wijzen
Definieer zelf een functie waar je reset_stats naar laat wijzen
om dat ook eventueel voor je eigen statistieken te doen.
om dat ook eventueel voor je eigen statistieken te doen.
****************************************************************************e */
****************************************************************************e */
function
*
reset_stats
;
function
*
reset_stats
;
/****************************************************************************
/****************************************************************************
De door de practicanten te schrijven routine
De door de practicanten te schrijven routine
****************************************************************************e */
****************************************************************************e */
void
schedule
(
event_type
event
);
void
schedule
(
event_type
event
);
...
...
os/ass3/fishbones.c
View file @
8b45567d
...
@@ -20,244 +20,244 @@ static pid_t parent_pid;
...
@@ -20,244 +20,244 @@ static pid_t parent_pid;
*/
*/
static
void
gup
(
FILE
*
log1
,
FILE
*
log2
,
int
pipe_id
[
2
],
int
myNumber
)
static
void
gup
(
FILE
*
log1
,
FILE
*
log2
,
int
pipe_id
[
2
],
int
myNumber
)
{
{
FILE
*
log3
;
FILE
*
log3
;
char
c
;
char
c
;
int
antidote
=
0
;
int
antidote
=
0
;
/* Put any required declarations and initialisations here */
/* Put any required declarations and initialisations here */
close
(
pipe_id
[
1
]);
/* Report your existence */
fprintf
(
log1
,
"This is child number %d
\n
"
,
myNumber
);
fprintf
(
log2
,
"This is child number %d
\n
"
,
myNumber
);
/* Open a line buffered log. */
log3
=
fopen
(
"child.log3"
,
"wt+"
);
setvbuf
(
log3
,
NULL
,
_IOLBF
,
BUFSIZ
);
fprintf
(
log3
,
"This is child number %d
\n
"
,
myNumber
);
close
(
pipe_id
[
1
]);
do
{
/* Read next character from pipe */
if
(
read
(
pipe_id
[
0
],
&
c
,
1
)
<=
0
)
{
/* Error while reading from the pipe, exit */
fprintf
(
log1
,
"Child %d read from pipe with error "
"and exited
\n
"
,
myNumber
);
fprintf
(
log2
,
"Child %d read from pipe with error "
"and exited
\n
"
,
myNumber
);
fprintf
(
log3
,
"Child %d read from pipe with error "
"and exited
\n
"
,
myNumber
);
fclose
(
log1
);
fclose
(
log2
);
fclose
(
log3
);
exit
(
1
);
}
/* Character read successfully, process it */
/* Report your existence */
fprintf
(
log1
,
"Child %d read character %x: '%c'
\n
"
,
myNumber
,
c
,
c
);
fprintf
(
log1
,
"This is child number %d
\n
"
,
myNumber
);
fprintf
(
log2
,
"Child %d read character %x: '%c'
\n
"
,
myNumber
,
c
,
c
);
fprintf
(
log2
,
"This is child number %d
\n
"
,
myNumber
);
fprintf
(
log3
,
"Child %d read character %x: '%c'
\n
"
,
myNumber
,
c
,
c
);
if
(
c
==
'P'
)
/* Open a line buffered log. */
{
log3
=
fopen
(
"child.log3"
,
"wt+"
);
/* Decrease antidote level or exit the process */
setvbuf
(
log3
,
NULL
,
_IOLBF
,
BUFSIZ
);
if
(
!
antidote
)
{
fprintf
(
log3
,
"This is child number %d
\n
"
,
myNumber
);
fprintf
(
log1
,
"Child %d has no antidote for poison "
"and will exit
\n
"
,
myNumber
);
do
fprintf
(
log2
,
"Child %d has no antidote for poison "
{
"and will exit
\n
"
,
myNumber
);
/* Read next character from pipe */
fprintf
(
log3
,
"Child %d has no antidote for poison "
if
(
read
(
pipe_id
[
0
],
&
c
,
1
)
<=
0
)
"and will exit
\n
"
,
myNumber
);
{
break
;
/* Error while reading from the pipe, exit */
}
fprintf
(
log1
,
"Child %d read from pipe with error "
else
"and exited
\n
"
,
myNumber
);
{
fprintf
(
log2
,
"Child %d read from pipe with error "
antidote
--
;
"and exited
\n
"
,
myNumber
);
fprintf
(
log1
,
"antidote used (%d left)
\n
"
,
antidote
);
fprintf
(
log3
,
"Child %d read from pipe with error "
fprintf
(
log2
,
"antidote used (%d left)
\n
"
,
antidote
);
"and exited
\n
"
,
myNumber
);
fprintf
(
log3
,
"antidote used (%d left)
\n
"
,
antidote
);
fclose
(
log1
);
}
fclose
(
log2
);
}
fclose
(
log3
);
else
if
(
c
==
'A'
)
exit
(
1
);
{
}
/* Increase antidote level */
antidote
++
;
/* Character read successfully, process it */
fprintf
(
log1
,
"Child %d finds antidote (now has %d)
\n
"
,
fprintf
(
log1
,
"Child %d read character %x: '%c'
\n
"
,
myNumber
,
c
,
c
);
myNumber
,
antidote
);
fprintf
(
log2
,
"Child %d read character %x: '%c'
\n
"
,
myNumber
,
c
,
c
);
fprintf
(
log2
,
"Child %d finds antidote (now has %d)
\n
"
,
fprintf
(
log3
,
"Child %d read character %x: '%c'
\n
"
,
myNumber
,
c
,
c
);
myNumber
,
antidote
);
fprintf
(
log3
,
"Child %d finds antidote (now has %d)
\n
"
,
if
(
c
==
'P'
)
myNumber
,
antidote
);
{
}
/* Decrease antidote level or exit the process */
}
while
(
c
);
if
(
!
antidote
)
{
/* Close logs and exit normally */
fprintf
(
log1
,
"Child %d has no antidote for poison "
fprintf
(
log1
,
"Child %d normal exit
\n
"
,
myNumber
);
"and will exit
\n
"
,
myNumber
);
fprintf
(
log2
,
"Child %d normal exit
\n
"
,
myNumber
);
fprintf
(
log2
,
"Child %d has no antidote for poison "
fprintf
(
log3
,
"Child %d normal exit
\n
"
,
myNumber
);
"and will exit
\n
"
,
myNumber
);
fclose
(
log1
);
fprintf
(
log3
,
"Child %d has no antidote for poison "
fclose
(
log2
);
"and will exit
\n
"
,
myNumber
);
fclose
(
log3
);
break
;
exit
(
0
);
}
else
{
antidote
--
;
fprintf
(
log1
,
"antidote used (%d left)
\n
"
,
antidote
);
fprintf
(
log2
,
"antidote used (%d left)
\n
"
,
antidote
);
fprintf
(
log3
,
"antidote used (%d left)
\n
"
,
antidote
);
}
}
else
if
(
c
==
'A'
)
{
/* Increase antidote level */
antidote
++
;
fprintf
(
log1
,
"Child %d finds antidote (now has %d)
\n
"
,
myNumber
,
antidote
);
fprintf
(
log2
,
"Child %d finds antidote (now has %d)
\n
"
,
myNumber
,
antidote
);
fprintf
(
log3
,
"Child %d finds antidote (now has %d)
\n
"
,
myNumber
,
antidote
);
}
}
while
(
c
);
/* Close logs and exit normally */
fprintf
(
log1
,
"Child %d normal exit
\n
"
,
myNumber
);
fprintf
(
log2
,
"Child %d normal exit
\n
"
,
myNumber
);
fprintf
(
log3
,
"Child %d normal exit
\n
"
,
myNumber
);
fclose
(
log1
);
fclose
(
log2
);
fclose
(
log3
);
exit
(
0
);
}
}
/*
/*
* Signal handler for SIGINT, SIGTERM and SIGCHLD.
* Signal handler for SIGINT, SIGTERM and SIGCHLD.
*/
*/
void
void
signal_handler
(
int
signum
)
signal_handler
(
int
signum
)
{
{
char
*
sig
=
"TERM"
;
char
*
sig
=
"TERM"
;
pid_t
pid
;
pid_t
pid
;
switch
(
signum
)
switch
(
signum
)
{
{
case
SIGINT
:
case
SIGINT
:
sig
=
"INT"
;
sig
=
"INT"
;
case
SIGTERM
:
case
SIGTERM
:
if
(
(
pid
=
getpid
())
==
parent_pid
)
if
(
(
pid
=
getpid
())
==
parent_pid
)
{
{
printf
(
"Parent process received SIG%s and will exit
\n
"
,
sig
);
printf
(
"Parent process received SIG%s and will exit
\n
"
,
sig
);
}
}
else
else
{
{
printf
(
"Process with id %d received SIG%s and will exit
\n
"
,
printf
(
"Process with id %d received SIG%s and will exit
\n
"
,
pid
,
sig
);
pid
,
sig
);
}
}
exit
(
1
);
exit
(
1
);
case
SIGCHLD
:
case
SIGCHLD
:
puts
(
"Parent process received SIGCHLD"
);
puts
(
"Parent process received SIGCHLD"
);
pid
=
wait
(
NULL
);
pid
=
wait
(
NULL
);
printf
(
"Child with id %d exited
\n
"
,
pid
);
printf
(
"Child with id %d exited
\n
"
,
pid
);
break
;
break
;
default:
default:
puts
(
"This handler is unapplicable for this type of signal"
);
puts
(
"This handler is unapplicable for this type of signal"
);
}
}
}
}
/*
/*
* Main funtion, initiates the program.
* Main funtion, initiates the program.
*/
*/
int
int
main
(
void
)
main
(
void
)
{
{
FILE
*
log1
;
FILE
*
log1
;
FILE
*
log2
;
FILE
*
log2
;
char
c
;
char
c
;
int
kiddoCount
=
0
,
pipe_id
[
2
];
int
kiddoCount
=
0
,
pipe_id
[
2
];
struct
sigaction
action
=
{.
sa_handler
=
signal_handler
};
struct
sigaction
action
=
{.
sa_handler
=
signal_handler
};
/* Save parent process id for signal handler */
/* Save parent process id for signal handler */
parent_pid
=
getpid
();
parent_pid
=
getpid
();
/* Create pipe, exit with error on failure */
if
(
pipe
(
pipe_id
)
)
{
fprintf
(
stderr
,
"Error %d occured while creating the pipe
\n
"
,
errno
);
exit
(
1
);
}
/* Bind signal handlers */
if
(
sigaction
(
SIGINT
,
&
action
,
NULL
)
||
sigaction
(
SIGTERM
,
&
action
,
NULL
)
||
sigaction
(
SIGCHLD
,
&
action
,
NULL
)
)
{
perror
(
"An error occured while binding the signal handlers
\n
"
);
exit
(
1
);
}
/* Open one buffered and one unbuffered log */
log1
=
fopen
(
"child.log1"
,
"wt+"
);
log2
=
fopen
(
"child.log2"
,
"wt+"
);
setvbuf
(
log2
,
NULL
,
_IONBF
,
BUFSIZ
);
/* Keep reading input */
while
(
(
c
=
getchar
())
)
{
if
(
c
==
EOF
)
{
if
(
errno
==
EINTR
)
{
/* Wait for signal handler to end */
continue
;
}
else
{
puts
(
"Error while reading input from stdin"
);
fclose
(
log1
);
fclose
(
log2
);
exit
(
1
);
}
}
/* Ignore newlines and spaces */
if
(
c
==
'\n'
||
c
==
32
)
{
continue
;
}
fprintf
(
log1
,
"Parent read character %x: '%c'
\n
"
,
c
,
c
);
fprintf
(
log2
,
"Parent read character %x: '%c'
\n
"
,
c
,
c
);
printf
(
"Character '%c' read
\n
"
,
c
);
if
(
c
==
'q'
)
{
/* Exit program */
break
;
}
else
if
(
c
!=
'f'
)
{
/* Write character to pipe for child processes */
if
(
write
(
pipe_id
[
1
],
&
c
,
1
)
<=
0
)
{
perror
(
"Cannot write to pipe
\n
"
);
exit
(
1
);
}
/* Wait for child process to 'eat the poison' */
//if( c == 'P' )
// wait(NULL);
}
else
{
pid_t
child_id
;
kiddoCount
++
;
/* When you fork, be sure to print the process id of the child
(if the fork succeeds) and an error message otherwise */
switch
(
(
child_id
=
fork
())
)
{
case
-
1
:
/* An error occured while forking */
perror
(
"Child could not be created
\n
"
);
exit
(
1
);
case
0
:
/* Child process after fork: Start reading from pipe */
gup
(
log1
,
log2
,
pipe_id
,
kiddoCount
);
break
;
default:
/* Parent proces after fork: Print child's process id */
fprintf
(
log1
,
"Started child process %d with id %d
\n
"
,
kiddoCount
,
child_id
);
fprintf
(
log2
,
"Started child process %d with id %d
\n
"
,
kiddoCount
,
child_id
);
printf
(
"Started child process %d with id %d
\n
"
,
kiddoCount
,
child_id
);
}
}
}
/* Create pipe, exit with error on failure */
/* Close logs and exit normally */
if
(
pipe
(
pipe_id
)
)
fprintf
(
log1
,
"Program exited normally
\n
"
);
{
fprintf
(
log2
,
"Program exited normally
\n
"
);
fprintf
(
stderr
,
"Error %d occured while creating the pipe
\n
"
,
fclose
(
log1
);
errno
);
fclose
(
log2
);
exit
(
1
);
}
/* Bind signal handlers */
if
(
sigaction
(
SIGINT
,
&
action
,
NULL
)
||
sigaction
(
SIGTERM
,
&
action
,
NULL
)
||
sigaction
(
SIGCHLD
,
&
action
,
NULL
)
)
{
perror
(
"An error occured while binding the signal handlers
\n
"
);
exit
(
1
);
}
/* Open one buffered and one unbuffered log */
log1
=
fopen
(
"child.log1"
,
"wt+"
);
log2
=
fopen
(
"child.log2"
,
"wt+"
);
setvbuf
(
log2
,
NULL
,
_IONBF
,
BUFSIZ
);
/* Keep reading input */
while
(
(
c
=
getchar
())
)
{
if
(
c
==
EOF
)
{
if
(
errno
==
EINTR
)
{
/* Wait for signal handler to end */
continue
;
}
else
{
puts
(
"Error while reading input from stdin"
);
fclose
(
log1
);
fclose
(
log2
);
exit
(
1
);
}
}
/* Ignore newlines and spaces */
return
0
;
if
(
c
==
'\n'
||
c
==
32
)
{
continue
;
}
fprintf
(
log1
,
"Parent read character %x: '%c'
\n
"
,
c
,
c
);
fprintf
(
log2
,
"Parent read character %x: '%c'
\n
"
,
c
,
c
);
printf
(
"Character '%c' read
\n
"
,
c
);
if
(
c
==
'q'
)
{
/* Exit program */
break
;
}
else
if
(
c
!=
'f'
)
{
/* Write character to pipe for child processes */
if
(
write
(
pipe_id
[
1
],
&
c
,
1
)
<=
0
)
{
perror
(
"Cannot write to pipe
\n
"
);
exit
(
1
);
}
/* Wait for child process to 'eat the poison' */
//if( c == 'P' )
// wait(NULL);
}
else
{
pid_t
child_id
;
kiddoCount
++
;
/* When you fork, be sure to print the process id of the child
(if the fork succeeds) and an error message otherwise */
switch
(
(
child_id
=
fork
())
)
{
case
-
1
:
/* An error occured while forking */
perror
(
"Child could not be created
\n
"
);
exit
(
1
);
case
0
:
/* Child process after fork: Start reading from pipe */
gup
(
log1
,
log2
,
pipe_id
,
kiddoCount
);
break
;
default:
/* Parent proces after fork: Print child's process id */
fprintf
(
log1
,
"Started child process %d with id %d
\n
"
,
kiddoCount
,
child_id
);
fprintf
(
log2
,
"Started child process %d with id %d
\n
"
,
kiddoCount
,
child_id
);
printf
(
"Started child process %d with id %d
\n
"
,
kiddoCount
,
child_id
);
}
}
}
/* Close logs and exit normally */
fprintf
(
log1
,
"Program exited normally
\n
"
);
fprintf
(
log2
,
"Program exited normally
\n
"
);
fclose
(
log1
);
fclose
(
log2
);
return
0
;
}
}
os/ass4/main.c
View file @
8b45567d
/*
/*
* Assignment 4 of Operating Systems: PThread simulation.
* Assignment 4 of Operating Systems: PThread simulation.
*
*
* Sander van Veen (6167969) and Taddeus Kroes (6054129).
* Sander van Veen (6167969) and Taddeus Kroes (6054129).
* <sandervv@gmail.com> and <taddeuskroes@hotmail.com>.
* <sandervv@gmail.com> and <taddeuskroes@hotmail.com>.
*
*
* Submission date: 21 november 2010.
* Submission date: 21 november 2010.
*/
*/
...
@@ -28,14 +28,14 @@ int diner_finished = 0;
...
@@ -28,14 +28,14 @@ int diner_finished = 0;
/*
/*
* Release fork taken by a philosopher.
* Release fork taken by a philosopher.
*/
*/
static
inline
void
release_fork
(
diner_stats
*
stats
,
int
f
)
{
static
inline
void
release_fork
(
diner_stats
*
stats
,
int
f
)
{
if
(
diner_finished
)
if
(
diner_finished
)
return
;
return
;
// Unlock left or right fork.
// Unlock left or right fork.
stats
->
locked
^=
1
<<
(
f
%
2
);
stats
->
locked
^=
1
<<
(
f
%
2
);
pthread_mutex_unlock
(
forks
+
f
);
pthread_mutex_unlock
(
forks
+
f
);
}
}
/*
/*
* Try to claim a fork, but do not wait if the fork cannot be claimed.
* Try to claim a fork, but do not wait if the fork cannot be claimed.
...
@@ -48,40 +48,40 @@ static inline int try_take_fork(diner_stats *stats, int f) {
...
@@ -48,40 +48,40 @@ static inline int try_take_fork(diner_stats *stats, int f) {
stats
->
locked
|=
1
<<
(
f
%
2
);
stats
->
locked
|=
1
<<
(
f
%
2
);
stats
->
forks
++
;
stats
->
forks
++
;
return
0
;
return
0
;
}
}
/*
/*
* Claim a fork, and wait (blocking) if the fork is already taken.
* Claim a fork, and wait (blocking) if the fork is already taken.
*/
*/
static
inline
void
take_fork
(
diner_stats
*
stats
,
int
f
)
{
static
inline
void
take_fork
(
diner_stats
*
stats
,
int
f
)
{
if
(
diner_finished
)
if
(
diner_finished
)
return
;
return
;
// Lock left or right fork.
// Lock left or right fork.
pthread_mutex_lock
(
forks
+
f
);
pthread_mutex_lock
(
forks
+
f
);
stats
->
locked
|=
1
<<
(
f
%
2
);
stats
->
locked
|=
1
<<
(
f
%
2
);
stats
->
forks
++
;
stats
->
forks
++
;
}
}
#define PHILO_EATING \
#define PHILO_EATING \
if(diner_finished) \
if(diner_finished) \
return 1; \
return 1; \
\
\
stats->meals++;
stats->meals++;
static
const
char
*
philo_type_names
[]
=
{
"left"
,
"right"
,
"optimistic"
,
"shy"
,
static
const
char
*
philo_type_names
[]
=
{
"left"
,
"right"
,
"optimistic"
,
"shy"
,
"random"
};
"random"
};
static
const
philo_t
philo_types
[]
=
{
&
philo_left
,
&
philo_right
,
&
philo_shy
,
\
static
const
philo_t
philo_types
[]
=
{
&
philo_left
,
&
philo_right
,
&
philo_shy
,
\
&
philo_optimistic
,
&
philo_random
};
&
philo_optimistic
,
&
philo_random
};
static
const
int
philo_type_count
=
sizeof
(
philo_types
)
/
sizeof
(
philo_t
);
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
* 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.
* both forks, and wouldn't release the first while he is waiting on the second.
*/
*/
int
philo_left
(
diner_stats
*
stats
,
int
id
)
{
int
philo_left
(
diner_stats
*
stats
,
int
id
)
{
// Let the philosopher take two forks (first left, then right).
// Let the philosopher take two forks (first left, then right).
take_fork
(
stats
,
id
);
take_fork
(
stats
,
id
);
...
@@ -99,14 +99,14 @@ int philo_left(diner_stats *stats, int id) {
...
@@ -99,14 +99,14 @@ int philo_left(diner_stats *stats, int id) {
/*
/*
* Philosopher favoring the right fork above the left fork. He will wait for
* 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.
* both forks, and wouldn't release the first while he is waiting on the second.
*/
*/
int
philo_right
(
diner_stats
*
stats
,
int
id
)
{
int
philo_right
(
diner_stats
*
stats
,
int
id
)
{
// Let the philosopher take two forks (first right, then left).
// Let the philosopher take two forks (first right, then left).
take_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
take_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
take_fork
(
stats
,
id
);
take_fork
(
stats
,
id
);
PHILO_EATING
;
PHILO_EATING
;
// Release both forks.
// Release both forks.
release_fork
(
stats
,
id
);
release_fork
(
stats
,
id
);
release_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
release_fork
(
stats
,
(
id
+
1
)
%
forks_len
);
...
@@ -115,7 +115,7 @@ int philo_right(diner_stats *stats, int id) {
...
@@ -115,7 +115,7 @@ int philo_right(diner_stats *stats, int id) {
}
}
/*
/*
* Philosopher with optimistic behaviour: try to take the left or right fork,
* 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.
* and if one fork is taken succesfully, wait till the second fork is released.
*/
*/
int
philo_optimistic
(
diner_stats
*
stats
,
int
id
)
{
int
philo_optimistic
(
diner_stats
*
stats
,
int
id
)
{
...
@@ -168,7 +168,7 @@ int philo_shy(diner_stats *stats, int id) {
...
@@ -168,7 +168,7 @@ int philo_shy(diner_stats *stats, int id) {
if
(
!
try_take_fork
(
stats
,
(
id
+
1
)
%
forks_len
))
{
if
(
!
try_take_fork
(
stats
,
(
id
+
1
)
%
forks_len
))
{
if
(
diner_finished
)
if
(
diner_finished
)
return
1
;
return
1
;
// Failed to take fork, so try again next time.
// Failed to take fork, so try again next time.
sched_yield
();
sched_yield
();
}
}
...
@@ -207,14 +207,14 @@ void *philo_start(void *raw_stats) {
...
@@ -207,14 +207,14 @@ void *philo_start(void *raw_stats) {
diner_stats
*
stats
=
(
diner_stats
*
)
raw_stats
;
diner_stats
*
stats
=
(
diner_stats
*
)
raw_stats
;
int
id
=
stats
->
id
,
int
id
=
stats
->
id
,
type
=
rand
()
%
philo_type_count
;
type
=
rand
()
%
philo_type_count
;
printf
(
"P #%u: hello everybody, i'm %s!
\n
"
,
id
,
philo_type_names
[
type
]);
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.
// Philosophers wait for each other, before they can start eating diner.
pthread_barrier_wait
(
&
wait_barrier
);
pthread_barrier_wait
(
&
wait_barrier
);
printf
(
"P #%u: let's eating!
\n
"
,
id
);
printf
(
"P #%u: let's eating!
\n
"
,
id
);
while
(
!
diner_finished
&&
!
(
*
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
);
printf
(
"P #%u: i'm leaving, after paying the bill.
\n
"
,
id
);
...
@@ -258,7 +258,7 @@ void host_start(int philos) {
...
@@ -258,7 +258,7 @@ void host_start(int philos) {
// Invite the philosophers.
// Invite the philosophers.
for
(
int
i
=
0
;
i
<
philos
;
i
++
)
{
for
(
int
i
=
0
;
i
<
philos
;
i
++
)
{
printf
(
"Host: inviting philo #%d
\n
"
,
i
);
printf
(
"Host: inviting philo #%d
\n
"
,
i
);
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
)
{
...
@@ -266,19 +266,19 @@ void host_start(int philos) {
...
@@ -266,19 +266,19 @@ void host_start(int philos) {
exit
(
-
1
);
exit
(
-
1
);
}
}
}
}
puts
(
"Host: invitations done."
);
puts
(
"Host: invitations done."
);
struct
timeval
wct
;
struct
timeval
wct
;
gettimeofday
(
&
wct
,
NULL
);
gettimeofday
(
&
wct
,
NULL
);
double
start_time
=
wct
.
tv_sec
+
wct
.
tv_usec
/
1e6
;
double
start_time
=
wct
.
tv_sec
+
wct
.
tv_usec
/
1e6
;
// Duration of the diner party is 10 seconds (see main.h). This loop will
// Duration of the diner party is 10 seconds (see main.h). This loop will
// prevent the philosphers from exceeding this time limit.
// prevent the philosphers from exceeding this time limit.
do
{
do
{
// Check each 10 ms for deadlock.
// Check each 10 ms for deadlock.
usleep
(
10000
);
usleep
(
10000
);
// If an deadlock occured (all philosophers are waiting on their left or
// If an deadlock occured (all philosophers are waiting on their left or
// right fork), finish the diner party immidiately. It is unclear in the
// right fork), finish the diner party immidiately. It is unclear in the
// assignment, if the philosophers should leave the diner party, or if
// assignment, if the philosophers should leave the diner party, or if
...
@@ -286,8 +286,8 @@ void host_start(int philos) {
...
@@ -286,8 +286,8 @@ void host_start(int philos) {
// assumption: leave the party. If they start arguing which fork is
// assumption: leave the party. If they start arguing which fork is
// theirs, there's no party anymore.
// theirs, there's no party anymore.
int
p
;
int
p
;
for
(
p
=
0
;
p
<
philos
&&
(
stats
[
p
].
locked
&
1
for
(
p
=
0
;
p
<
philos
&&
(
stats
[
p
].
locked
&
1
||
stats
[
p
].
locked
&
2
);
p
++
);
||
stats
[
p
].
locked
&
2
);
p
++
);
if
(
p
==
philos
)
{
if
(
p
==
philos
)
{
puts
(
"Host: deadlock occured."
);
puts
(
"Host: deadlock occured."
);
...
@@ -302,12 +302,12 @@ void host_start(int philos) {
...
@@ -302,12 +302,12 @@ void host_start(int philos) {
diner_finished
=
1
;
diner_finished
=
1
;
puts
(
"Host: diner is finished."
);
puts
(
"Host: diner is finished."
);
for
(
int
i
=
0
;
i
<
philos
;
i
++
)
{
for
(
int
i
=
0
;
i
<
philos
;
i
++
)
{
// Reclaim all cutlery (mutexes) in reverse order.
// Reclaim all cutlery (mutexes) in reverse order.
for
(
int
p
=
philos
;
p
>=
i
;
p
--
)
for
(
int
p
=
philos
;
p
>=
i
;
p
--
)
pthread_mutex_unlock
(
&
forks
[
p
]);
pthread_mutex_unlock
(
&
forks
[
p
]);
// Wait on the other philosophers.
// Wait on the other philosophers.
if
(
(
rc
=
pthread_join
(
threads
[
i
],
&
status
))
)
{
if
(
(
rc
=
pthread_join
(
threads
[
i
],
&
status
))
)
{
fprintf
(
stderr
,
"return code from pthread_join() is %d
\n
"
,
rc
);
fprintf
(
stderr
,
"return code from pthread_join() is %d
\n
"
,
rc
);
...
@@ -315,16 +315,16 @@ void host_start(int philos) {
...
@@ -315,16 +315,16 @@ void host_start(int philos) {
}
}
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
);
i
,
stats
[
i
].
meals
,
stats
[
i
].
forks
);
pthread_mutex_destroy
(
&
forks
[
i
]);
pthread_mutex_destroy
(
&
forks
[
i
]);
}
}
puts
(
"Host: philosophers are done."
);
puts
(
"Host: philosophers are done."
);
pthread_barrier_destroy
(
&
wait_barrier
);
pthread_barrier_destroy
(
&
wait_barrier
);
pthread_attr_destroy
(
&
attr
);
pthread_attr_destroy
(
&
attr
);
pthread_exit
(
NULL
);
pthread_exit
(
NULL
);
}
}
...
@@ -340,7 +340,7 @@ int main(int argc, const char **argv) {
...
@@ -340,7 +340,7 @@ int main(int argc, const char **argv) {
struct
timeval
wtc
;
struct
timeval
wtc
;
gettimeofday
(
&
wtc
,
NULL
);
gettimeofday
(
&
wtc
,
NULL
);
srand
(
wtc
.
tv_usec
);
srand
(
wtc
.
tv_usec
);
host_start
(
argc
>
1
?
atoi
(
argv
[
1
])
:
2
);
host_start
(
argc
>
1
?
atoi
(
argv
[
1
])
:
2
);
}
}
os/ass5/index.c
View file @
8b45567d
...
@@ -93,13 +93,13 @@ int index_error = 0;
...
@@ -93,13 +93,13 @@ int index_error = 0;
* characterised by Nblocks (the maximum number of entries in the index)
* characterised by Nblocks (the maximum number of entries in the index)
* and KeyLength (the length of the key strings).
* and KeyLength (the length of the key strings).
*/
*/
in_core
*
in_core
*
index_makeNew
(
unsigned
long
Nblocks
,
unsigned
long
KeyLength
)
index_makeNew
(
unsigned
long
Nblocks
,
unsigned
long
KeyLength
)
{
{
unsigned
long
iRecordLength
=
sizeof
(
indexRecord
)
-
sizeof
(
char
[
8
])
+
unsigned
long
iRecordLength
=
sizeof
(
indexRecord
)
-
sizeof
(
char
[
8
])
+
4
*
KeyLength
;
4
*
KeyLength
;
in_core
*
in
=
calloc
(
1
,
sizeof
(
in_core
)
-
sizeof
(
indexRecord
)
+
in_core
*
in
=
calloc
(
1
,
sizeof
(
in_core
)
-
sizeof
(
indexRecord
)
+
iRecordLength
);
iRecordLength
);
int
i
;
int
i
;
int
levs
;
int
levs
;
int
n
;
int
n
;
...
@@ -176,10 +176,10 @@ long index_writeToDisk(in_core * in, int fid)
...
@@ -176,10 +176,10 @@ long index_writeToDisk(in_core * in, int fid)
}
}
rv
=
write
(
fid
,
&
(
in
->
to_disk
),
rv
=
write
(
fid
,
&
(
in
->
to_disk
),
sizeof
(
indexheader
)
-
sizeof
(
indexRecord
)
+
in
->
to_disk
.
iRecordLength
);
sizeof
(
indexheader
)
-
sizeof
(
indexRecord
)
+
in
->
to_disk
.
iRecordLength
);
if
(
rv
!=
(
int
)(
sizeof
(
indexheader
)
-
sizeof
(
indexRecord
)
+
if
(
rv
!=
(
int
)(
sizeof
(
indexheader
)
-
sizeof
(
indexRecord
)
+
in
->
to_disk
.
iRecordLength
))
{
in
->
to_disk
.
iRecordLength
))
{
index_error
=
INDEX_WRITE_FAIL
;
index_error
=
INDEX_WRITE_FAIL
;
return
-
1
;
return
-
1
;
}
}
...
@@ -188,10 +188,10 @@ long index_writeToDisk(in_core * in, int fid)
...
@@ -188,10 +188,10 @@ long index_writeToDisk(in_core * in, int fid)
#endif
#endif
for
(
i
=
0
;
i
<
in
->
to_disk
.
Nlevels
;
i
++
)
{
for
(
i
=
0
;
i
<
in
->
to_disk
.
Nlevels
;
i
++
)
{
rv
=
write
(
fid
,
in
->
levels
[
i
],
in
->
to_disk
.
NperLevel
[
i
]
*
rv
=
write
(
fid
,
in
->
levels
[
i
],
in
->
to_disk
.
NperLevel
[
i
]
*
in
->
to_disk
.
iRecordLength
);
in
->
to_disk
.
iRecordLength
);
if
(
rv
!=
(
int
)(
in
->
to_disk
.
NperLevel
[
i
]
if
(
rv
!=
(
int
)(
in
->
to_disk
.
NperLevel
[
i
]
*
in
->
to_disk
.
iRecordLength
))
{
*
in
->
to_disk
.
iRecordLength
))
{
index_error
=
INDEX_WRITE_FAIL
;
index_error
=
INDEX_WRITE_FAIL
;
return
-
1
;
return
-
1
;
}
}
...
@@ -230,7 +230,7 @@ in_core *index_readFromDisk(int fid)
...
@@ -230,7 +230,7 @@ in_core *index_readFromDisk(int fid)
assert
(
head
.
iRecordLength
==
in
->
to_disk
.
iRecordLength
);
assert
(
head
.
iRecordLength
==
in
->
to_disk
.
iRecordLength
);
assert
(
head
.
Nlevels
==
in
->
to_disk
.
Nlevels
);
assert
(
head
.
Nlevels
==
in
->
to_disk
.
Nlevels
);
assert
(
head
.
NperLevel
[
head
.
Nlevels
-
1
]
==
assert
(
head
.
NperLevel
[
head
.
Nlevels
-
1
]
==
in
->
to_disk
.
NperLevel
[
head
.
Nlevels
-
1
]);
in
->
to_disk
.
NperLevel
[
head
.
Nlevels
-
1
]);
in
->
to_disk
=
head
;
in
->
to_disk
=
head
;
rv
=
read
(
fid
,
&
(
in
->
to_disk
.
root
),
head
.
iRecordLength
);
rv
=
read
(
fid
,
&
(
in
->
to_disk
.
root
),
head
.
iRecordLength
);
if
(
rv
!=
(
int
)
head
.
iRecordLength
)
{
if
(
rv
!=
(
int
)
head
.
iRecordLength
)
{
...
@@ -246,8 +246,8 @@ in_core *index_readFromDisk(int fid)
...
@@ -246,8 +246,8 @@ in_core *index_readFromDisk(int fid)
printf
(
"NperLevel[%d] = %d
\n
"
,
i
,
in
->
to_disk
.
NperLevel
[
i
]);
printf
(
"NperLevel[%d] = %d
\n
"
,
i
,
in
->
to_disk
.
NperLevel
[
i
]);
#endif
#endif
if
(
read
(
fid
,
in
->
levels
[
i
],
if
(
read
(
fid
,
in
->
levels
[
i
],
in
->
to_disk
.
NperLevel
[
i
]
*
in
->
to_disk
.
iRecordLength
)
in
->
to_disk
.
NperLevel
[
i
]
*
in
->
to_disk
.
iRecordLength
)
!=
(
int
)(
in
->
to_disk
.
NperLevel
[
i
]
*
in
->
to_disk
.
iRecordLength
))
!=
(
int
)(
in
->
to_disk
.
NperLevel
[
i
]
*
in
->
to_disk
.
iRecordLength
))
{
{
index_error
=
INDEX_READ_ERROR
;
index_error
=
INDEX_READ_ERROR
;
return
NULL
;
return
NULL
;
...
@@ -263,7 +263,7 @@ in_core *index_readFromDisk(int fid)
...
@@ -263,7 +263,7 @@ in_core *index_readFromDisk(int fid)
* it will return -1. (Zero is a valid index value) It needs as input: The
* it will return -1. (Zero is a valid index value) It needs as input: The
* sought key The index record The length of the keys.
* sought key The index record The length of the keys.
*/
*/
static
long
static
long
key_to_index
(
indexRecord
*
rec
,
const
char
*
key
,
unsigned
long
KeyLength
)
key_to_index
(
indexRecord
*
rec
,
const
char
*
key
,
unsigned
long
KeyLength
)
{
{
int
rv
;
int
rv
;
...
@@ -311,7 +311,7 @@ long index_keyToBlock(in_core * in, const char *key)
...
@@ -311,7 +311,7 @@ long index_keyToBlock(in_core * in, const char *key)
for
(
i
=
0
;
i
<
in
->
to_disk
.
Nlevels
;
i
++
)
{
for
(
i
=
0
;
i
<
in
->
to_disk
.
Nlevels
;
i
++
)
{
rec
=
(
indexRecord
*
)
(
index
*
in
->
to_disk
.
iRecordLength
+
rec
=
(
indexRecord
*
)
(
index
*
in
->
to_disk
.
iRecordLength
+
(
char
*
)
in
->
levels
[
i
]);
(
char
*
)
in
->
levels
[
i
]);
index
=
key_to_index
(
rec
,
key
,
KeyLength
);
index
=
key_to_index
(
rec
,
key
,
KeyLength
);
if
(
index
<
0
)
{
if
(
index
<
0
)
{
index_error
=
INDEX_INDEXING_ERROR
;
index_error
=
INDEX_INDEXING_ERROR
;
...
@@ -359,7 +359,7 @@ int index_addKey(in_core * in, const char *key, int index)
...
@@ -359,7 +359,7 @@ int index_addKey(in_core * in, const char *key, int index)
nrec
=
(
keyno
-
1
)
/
4
;
nrec
=
(
keyno
-
1
)
/
4
;
nkey
=
(
keyno
-
1
)
&
0x0003
;
nkey
=
(
keyno
-
1
)
&
0x0003
;
rec
=
(
indexRecord
*
)
(
nrec
*
in
->
to_disk
.
iRecordLength
+
rec
=
(
indexRecord
*
)
(
nrec
*
in
->
to_disk
.
iRecordLength
+
(
char
*
)
in
->
levels
[
lev
]);
(
char
*
)
in
->
levels
[
lev
]);
rv
=
strncmp
(
key
,
KeyInRec
(
nkey
,
*
rec
,
KeyLength
),
KeyLength
);
rv
=
strncmp
(
key
,
KeyInRec
(
nkey
,
*
rec
,
KeyLength
),
KeyLength
);
if
(
rv
<=
0
)
{
if
(
rv
<=
0
)
{
index_error
=
INDEX_KEY_NOT_LARGER
;
index_error
=
INDEX_KEY_NOT_LARGER
;
...
@@ -372,10 +372,10 @@ int index_addKey(in_core * in, const char *key, int index)
...
@@ -372,10 +372,10 @@ int index_addKey(in_core * in, const char *key, int index)
nrec
=
keyno
/
4
;
nrec
=
keyno
/
4
;
nkey
=
keyno
&
0x0003
;
nkey
=
keyno
&
0x0003
;
rec
=
(
indexRecord
*
)
(
nrec
*
in
->
to_disk
.
iRecordLength
+
rec
=
(
indexRecord
*
)
(
nrec
*
in
->
to_disk
.
iRecordLength
+
(
char
*
)
in
->
levels
[
lev
]);
(
char
*
)
in
->
levels
[
lev
]);
#ifdef DEBUG
#ifdef DEBUG
printf
(
"nrec = %d, nkey = %d, lev = %d, NperLevel = %d
\n
"
,
printf
(
"nrec = %d, nkey = %d, lev = %d, NperLevel = %d
\n
"
,
nrec
,
nkey
,
lev
,
in
->
to_disk
.
NperLevel
[
lev
]);
nrec
,
nkey
,
lev
,
in
->
to_disk
.
NperLevel
[
lev
]);
#endif
#endif
strncpy
(
KeyInRec
(
nkey
,
*
rec
,
KeyLength
),
key
,
KeyLength
);
strncpy
(
KeyInRec
(
nkey
,
*
rec
,
KeyLength
),
key
,
KeyLength
);
do_prev
=
!
nkey
;
do_prev
=
!
nkey
;
...
@@ -394,10 +394,10 @@ int index_addKey(in_core * in, const char *key, int index)
...
@@ -394,10 +394,10 @@ int index_addKey(in_core * in, const char *key, int index)
nkey
=
keyno
&
0x0003
;
nkey
=
keyno
&
0x0003
;
#ifdef DEBUG
#ifdef DEBUG
printf
(
"nrec = %d, nkey = %d, lev = %d, NperLevel = %d
\n
"
,
printf
(
"nrec = %d, nkey = %d, lev = %d, NperLevel = %d
\n
"
,
nrec
,
nkey
,
lev
,
in
->
to_disk
.
NperLevel
[
lev
]);
nrec
,
nkey
,
lev
,
in
->
to_disk
.
NperLevel
[
lev
]);
#endif
#endif
rec
=
(
indexRecord
*
)
(
nrec
*
in
->
to_disk
.
iRecordLength
+
rec
=
(
indexRecord
*
)
(
nrec
*
in
->
to_disk
.
iRecordLength
+
(
char
*
)
in
->
levels
[
lev
]);
(
char
*
)
in
->
levels
[
lev
]);
strncpy
(
KeyInRec
(
nkey
,
*
rec
,
KeyLength
),
key
,
KeyLength
);
strncpy
(
KeyInRec
(
nkey
,
*
rec
,
KeyLength
),
key
,
KeyLength
);
do_prev
=
!
nkey
;
do_prev
=
!
nkey
;
rec
->
index
[
nkey
]
=
keyno
;
rec
->
index
[
nkey
]
=
keyno
;
...
...
os/ass5/index.h
View file @
8b45567d
...
@@ -2,17 +2,17 @@
...
@@ -2,17 +2,17 @@
#define INDEX_H
#define INDEX_H
/* -------------------------------------------------------------------------
/* -------------------------------------------------------------------------
Author: G.D. van Albada
Author: G.D. van Albada
University of Amsterdam
University of Amsterdam
Faculty of Science
Faculty of Science
Informatics Institute
Informatics Institute
Copyright (C) Universiteit van Amsterdam
Copyright (C) Universiteit van Amsterdam
dick at science.uva.nl
dick at science.uva.nl
Version: 0.1
Version: 0.1
Date: December 2001 / January 2002 / November 2004
Date: December 2001 / January 2002 / November 2004
Goal: Part of an assignment on file system structure for the operating
Goal: Part of an assignment on file system structure for the operating
systems course. It demonstrates many of the administrative and
systems course. It demonstrates many of the administrative and
layering structures that are also used in normal file systems.
layering structures that are also used in normal file systems.
----------------------------------------------------------------------------*/
----------------------------------------------------------------------------*/
extern
int
index_error
;
extern
int
index_error
;
...
...
os/ass5/isam.c
View file @
8b45567d
...
@@ -69,25 +69,25 @@
...
@@ -69,25 +69,25 @@
* A case in point is the very first record in the file. In order to
* A case in point is the very first record in the file. In order to
* allow for the insertion of records with low key values, this record
* allow for the insertion of records with low key values, this record
* necessarily must have the minimum key value. Luckily, this is well
* necessarily must have the minimum key value. Luckily, this is well
* defined: it is the empty string "". This record will be created and
* defined: it is the empty string "". This record will be created and
* marked "reserved" right at the start.
* marked "reserved" right at the start.
*
*
* When creating the file, every Nth (N = NrecPB - 1) record's key will
* When creating the file, every Nth (N = NrecPB - 1) record's key will
* be inserted into the index.
* be inserted into the index.
*
*
* The index will be a tree where every node has up to four children.
* The index will be a tree where every node has up to four children.
* The leaf nodes point to the records. The reason for not using a more
* The leaf nodes point to the records. The reason for not using a more
* sophisticated tree structure are that not all keys searched for need
* sophisticated tree structure are that not all keys searched for need
* appear in the tree.
* appear in the tree.
*
*
* So the structure will be:
* So the structure will be:
* 1 17 33 49
* 1 17 33 49
* 1 5 9 13 17 ..
* 1 5 9 13 17 ..
* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ....
* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ....
*
*
* The depth of the tree will be determined by Nblocks
* The depth of the tree will be determined by Nblocks
* (D = ceil(log4(Nblocks)))
* (D = ceil(log4(Nblocks)))
*/
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
...
@@ -97,37 +97,37 @@
...
@@ -97,37 +97,37 @@
#include <fcntl.h>
#include <fcntl.h>
#include <string.h>
#include <string.h>
/*
/*
* Use assert to pinpoint fatal errors - should be removed later
* Use assert to pinpoint fatal errors - should be removed later
*/
*/
#include <assert.h>
#include <assert.h>
#include "isam.h"
#include "isam.h"
#include "index.h"
#include "index.h"
/*
/*
* Compile a static structure to store cache statistics
* Compile a static structure to store cache statistics
*/
*/
static
struct
ISAM_CACHE_STATS
cstat
;
static
struct
ISAM_CACHE_STATS
cstat
;
/*
/*
* Just one flag value describing the state of the file for now
* Just one flag value describing the state of the file for now
*/
*/
#define ISAM_STATE_UPDATING (1024)
#define ISAM_STATE_UPDATING (1024)
/*
/*
* Catch any calls to debugRecord, so we don't have any warnings :)
* Catch any calls to debugRecord, so we don't have any warnings :)
*/
*/
#ifndef DEBUG
#ifndef DEBUG
# define debugRecord(alpha, beta, gamma) __placeholder()
# define debugRecord(alpha, beta, gamma) __placeholder()
static
void
__placeholder
(
void
)
{
return
;}
static
void
__placeholder
(
void
)
{
return
;}
#endif
#endif
/*
/*
* An isam file will start with an information block that is described in
* An isam file will start with an information block that is described in
* the following typedef.
* the following typedef.
*/
*/
typedef
struct
typedef
struct
{
{
unsigned
long
magic
;
/* Make sure this is an isam file */
unsigned
long
magic
;
/* Make sure this is an isam file */
unsigned
long
version
;
/* Allow for later versions */
unsigned
long
version
;
/* Allow for later versions */
...
@@ -207,7 +207,7 @@ typedef struct ISAM
...
@@ -207,7 +207,7 @@ typedef struct ISAM
#define cur_head(isam) head((isam), (isam).cur_id, (isam).cur_recno)
#define cur_head(isam) head((isam), (isam).cur_id, (isam).cur_recno)
#define key(isam,id,Nrec) (((isam).cache[(id)])+\
#define key(isam,id,Nrec) (((isam).cache[(id)])+\
(Nrec)*((isam).fHead.RecordLen)+sizeof(recordHead))
(Nrec)*((isam).fHead.RecordLen)+sizeof(recordHead))
#define cur_key(isam) key((isam), (isam).cur_id, (isam).cur_recno)
#define cur_key(isam) key((isam), (isam).cur_id, (isam).cur_recno)
...
@@ -223,7 +223,7 @@ enum isam_error isam_error = ISAM_NO_ERROR;
...
@@ -223,7 +223,7 @@ enum isam_error isam_error = ISAM_NO_ERROR;
* makeIsamPtr creates an isamPtr given a file header, fills in some data
* makeIsamPtr creates an isamPtr given a file header, fills in some data
* and initialises the cache
* and initialises the cache
*/
*/
static
isamPtr
static
isamPtr
makeIsamPtr
(
fileHead
*
fHead
)
makeIsamPtr
(
fileHead
*
fHead
)
{
{
isamPtr
ipt
=
(
isamPtr
)
calloc
(
1
,
sizeof
(
isam
));
isamPtr
ipt
=
(
isamPtr
)
calloc
(
1
,
sizeof
(
isam
));
...
@@ -246,7 +246,7 @@ makeIsamPtr(fileHead * fHead)
...
@@ -246,7 +246,7 @@ makeIsamPtr(fileHead * fHead)
return
ipt
;
return
ipt
;
}
}
static
void
static
void
dumpMaxKey
(
isamPtr
f
)
dumpMaxKey
(
isamPtr
f
)
{
{
unsigned
int
i
;
unsigned
int
i
;
...
@@ -263,7 +263,7 @@ dumpMaxKey(isamPtr f)
...
@@ -263,7 +263,7 @@ dumpMaxKey(isamPtr f)
/*
/*
* Write the file header to disk (again)
* Write the file header to disk (again)
*/
*/
static
int
static
int
writeHead
(
isamPtr
f
)
writeHead
(
isamPtr
f
)
{
{
#ifdef DEBUG
#ifdef DEBUG
...
@@ -294,7 +294,7 @@ writeHead(isamPtr f)
...
@@ -294,7 +294,7 @@ writeHead(isamPtr f)
/*
/*
* You never can predict what junk you get as a file pointer...
* You never can predict what junk you get as a file pointer...
*/
*/
static
int
static
int
testPtr
(
isamPtr
f
)
testPtr
(
isamPtr
f
)
{
{
if
((
!
f
)
||
(
f
->
fHead
.
magic
!=
isamMagic
))
{
if
((
!
f
)
||
(
f
->
fHead
.
magic
!=
isamMagic
))
{
...
@@ -309,14 +309,14 @@ testPtr(isamPtr f)
...
@@ -309,14 +309,14 @@ testPtr(isamPtr f)
* In the remainder of the code, we should not need to worry about how and
* In the remainder of the code, we should not need to worry about how and
* where to write a given block from the cache
* where to write a given block from the cache
*/
*/
static
int
static
int
write_cache_block
(
isamPtr
isam_ident
,
int
iCache
)
write_cache_block
(
isamPtr
isam_ident
,
int
iCache
)
{
{
unsigned
long
block_no
=
isam_ident
->
blockInCache
[
iCache
];
unsigned
long
block_no
=
isam_ident
->
blockInCache
[
iCache
];
int
rv
;
int
rv
;
if
(
lseek
(
isam_ident
->
fileId
,
isam_ident
->
fHead
.
DataStart
+
if
(
lseek
(
isam_ident
->
fileId
,
isam_ident
->
fHead
.
DataStart
+
block_no
*
isam_ident
->
blockSize
,
SEEK_SET
)
==
(
off_t
)
-
1
)
{
block_no
*
isam_ident
->
blockSize
,
SEEK_SET
)
==
(
off_t
)
-
1
)
{
isam_error
=
ISAM_SEEK_ERROR
;
isam_error
=
ISAM_SEEK_ERROR
;
return
-
1
;
return
-
1
;
}
}
...
@@ -346,7 +346,7 @@ write_cache_block(isamPtr isam_ident, int iCache)
...
@@ -346,7 +346,7 @@ write_cache_block(isamPtr isam_ident, int iCache)
* in an EOF error anyway); we just zero the cache block (corresponding to
* in an EOF error anyway); we just zero the cache block (corresponding to
* an empty record).
* an empty record).
*/
*/
static
int
static
int
isam_cache_block
(
isamPtr
isam_ident
,
unsigned
long
block_no
)
isam_cache_block
(
isamPtr
isam_ident
,
unsigned
long
block_no
)
{
{
int
iCache
;
int
iCache
;
...
@@ -412,14 +412,14 @@ isam_cache_block(isamPtr isam_ident, unsigned long block_no)
...
@@ -412,14 +412,14 @@ isam_cache_block(isamPtr isam_ident, unsigned long block_no)
}
}
if
(
lseek
(
isam_ident
->
fileId
,
isam_ident
->
fHead
.
DataStart
+
if
(
lseek
(
isam_ident
->
fileId
,
isam_ident
->
fHead
.
DataStart
+
block_no
*
isam_ident
->
blockSize
,
block_no
*
isam_ident
->
blockSize
,
SEEK_SET
)
==
(
off_t
)
-
1
)
{
SEEK_SET
)
==
(
off_t
)
-
1
)
{
isam_error
=
ISAM_SEEK_ERROR
;
isam_error
=
ISAM_SEEK_ERROR
;
return
-
1
;
return
-
1
;
}
}
rv
=
read
(
isam_ident
->
fileId
,
isam_ident
->
cache
[
iCache
],
rv
=
read
(
isam_ident
->
fileId
,
isam_ident
->
cache
[
iCache
],
isam_ident
->
blockSize
);
isam_ident
->
blockSize
);
if
(
rv
!=
(
int
)
isam_ident
->
blockSize
)
{
if
(
rv
!=
(
int
)
isam_ident
->
blockSize
)
{
isam_error
=
ISAM_READ_ERROR
;
isam_error
=
ISAM_READ_ERROR
;
...
@@ -446,7 +446,7 @@ isam_cache_block(isamPtr isam_ident, unsigned long block_no)
...
@@ -446,7 +446,7 @@ isam_cache_block(isamPtr isam_ident, unsigned long block_no)
* function) We'll use the latter approach - it also has the advantage
* function) We'll use the latter approach - it also has the advantage
* that we only need to return a single value.
* that we only need to return a single value.
*/
*/
static
int
static
int
free_record_in_block
(
isamPtr
isam_ident
,
int
iCache
)
free_record_in_block
(
isamPtr
isam_ident
,
int
iCache
)
{
{
unsigned
int
iFree
;
unsigned
int
iFree
;
...
@@ -485,7 +485,7 @@ free_record_in_block(isamPtr isam_ident, int iCache)
...
@@ -485,7 +485,7 @@ free_record_in_block(isamPtr isam_ident, int iCache)
* Strictly for debugging - print some information about a record
* Strictly for debugging - print some information about a record
*/
*/
#ifdef DEBUG
#ifdef DEBUG
static
void
static
void
debugRecord
(
isamPtr
f
,
unsigned
long
n
,
char
*
from
)
debugRecord
(
isamPtr
f
,
unsigned
long
n
,
char
*
from
)
{
{
int
ib
=
n
/
f
->
fHead
.
NrecPB
;
int
ib
=
n
/
f
->
fHead
.
NrecPB
;
...
@@ -510,10 +510,10 @@ debugRecord(isamPtr f, unsigned long n, char *from)
...
@@ -510,10 +510,10 @@ debugRecord(isamPtr f, unsigned long n, char *from)
* yet.
* yet.
*/
*/
isamPtr
isamPtr
isam_create
(
const
char
*
name
,
unsigned
long
KeyLen
,
isam_create
(
const
char
*
name
,
unsigned
long
KeyLen
,
unsigned
long
DataLen
,
unsigned
long
NrecPB
,
unsigned
long
DataLen
,
unsigned
long
NrecPB
,
unsigned
long
Nblocks
)
unsigned
long
Nblocks
)
{
{
struct
stat
buf
;
struct
stat
buf
;
int
i
,
l
;
int
i
,
l
;
...
@@ -622,7 +622,7 @@ error_open:
...
@@ -622,7 +622,7 @@ error_open:
return
NULL
;
return
NULL
;
}
}
isamPtr
isamPtr
isam_open
(
const
char
*
name
,
int
update
)
isam_open
(
const
char
*
name
,
int
update
)
{
{
struct
stat
buf
;
struct
stat
buf
;
...
@@ -733,7 +733,7 @@ error_file:
...
@@ -733,7 +733,7 @@ error_file:
/*
/*
* Close an isam file and release the memory used
* Close an isam file and release the memory used
*/
*/
int
int
isam_close
(
isamPtr
f
)
isam_close
(
isamPtr
f
)
{
{
int
i
;
int
i
;
...
@@ -771,7 +771,7 @@ isam_close(isamPtr f)
...
@@ -771,7 +771,7 @@ isam_close(isamPtr f)
* record with that key (if it exists), or the next higher key (if that
* record with that key (if it exists), or the next higher key (if that
* exists)
* exists)
*/
*/
int
int
isam_setKey
(
isamPtr
isam_ident
,
const
char
*
key
)
isam_setKey
(
isamPtr
isam_ident
,
const
char
*
key
)
{
{
int
block_no
;
int
block_no
;
...
@@ -818,14 +818,14 @@ isam_setKey(isamPtr isam_ident, const char *key)
...
@@ -818,14 +818,14 @@ isam_setKey(isamPtr isam_ident, const char *key)
* Skip all records with smaller keys
* Skip all records with smaller keys
*/
*/
while
((
rv
=
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
while
((
rv
=
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
isam_ident
->
fHead
.
KeyLen
))
>
0
)
{
isam_ident
->
fHead
.
KeyLen
))
>
0
)
{
next
=
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
next
;
next
=
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
next
;
debugRecord
(
isam_ident
,
next
,
"setkey #1"
);
debugRecord
(
isam_ident
,
next
,
"setkey #1"
);
if
(
!
next
)
{
if
(
!
next
)
{
/*
/*
* There is no next record
* There is no next record
*/
*/
break
;
break
;
}
}
...
@@ -846,9 +846,9 @@ isam_setKey(isamPtr isam_ident, const char *key)
...
@@ -846,9 +846,9 @@ isam_setKey(isamPtr isam_ident, const char *key)
* record that has the valid flag set.
* record that has the valid flag set.
*/
*/
while
(((
rv
=
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
while
(((
rv
=
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
isam_ident
->
fHead
.
KeyLen
))
<=
0
)
||
isam_ident
->
fHead
.
KeyLen
))
<=
0
)
||
(
!
(
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
(
!
(
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
statusFlags
&
ISAM_VALID
)))
{
statusFlags
&
ISAM_VALID
)))
{
prev
=
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
previous
;
prev
=
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
previous
;
debugRecord
(
isam_ident
,
prev
,
"setkey #2"
);
debugRecord
(
isam_ident
,
prev
,
"setkey #2"
);
/* prev may be 0 - that is OK; we are then pointing to the dummy
/* prev may be 0 - that is OK; we are then pointing to the dummy
...
@@ -885,7 +885,7 @@ isam_setKey(isamPtr isam_ident, const char *key)
...
@@ -885,7 +885,7 @@ isam_setKey(isamPtr isam_ident, const char *key)
* isam_readNext will read the next valid record (from cur_recno and
* isam_readNext will read the next valid record (from cur_recno and
* cur_id), if such a record exists
* cur_id), if such a record exists
*/
*/
int
int
isam_readNext
(
isamPtr
isam_ident
,
char
*
key
,
void
*
data
)
isam_readNext
(
isamPtr
isam_ident
,
char
*
key
,
void
*
data
)
{
{
int
block_no
;
int
block_no
;
...
@@ -934,7 +934,7 @@ isam_readNext(isamPtr isam_ident, char *key, void *data)
...
@@ -934,7 +934,7 @@ isam_readNext(isamPtr isam_ident, char *key, void *data)
* isam_readPrev will read the current record, if it is valid, and then
* isam_readPrev will read the current record, if it is valid, and then
* reposition the file to the preceding valid record (if that exists).
* reposition the file to the preceding valid record (if that exists).
*/
*/
int
int
isam_readPrev
(
isamPtr
isam_ident
,
char
*
key
,
void
*
data
)
isam_readPrev
(
isamPtr
isam_ident
,
char
*
key
,
void
*
data
)
{
{
int
block_no
;
int
block_no
;
...
@@ -973,7 +973,7 @@ isam_readPrev(isamPtr isam_ident, char *key, void *data)
...
@@ -973,7 +973,7 @@ isam_readPrev(isamPtr isam_ident, char *key, void *data)
}
}
}
}
while
(
!
(
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
statusFlags
while
(
!
(
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
statusFlags
&
ISAM_VALID
));
&
ISAM_VALID
));
isam_ident
->
cur_id
=
iCache
;
isam_ident
->
cur_id
=
iCache
;
isam_ident
->
cur_recno
=
rec_no
;
isam_ident
->
cur_recno
=
rec_no
;
return
0
;
return
0
;
...
@@ -987,7 +987,7 @@ isam_readPrev(isamPtr isam_ident, char *key, void *data)
...
@@ -987,7 +987,7 @@ isam_readPrev(isamPtr isam_ident, char *key, void *data)
* isam_readByKey will attempt to read a record with the requested key
* isam_readByKey will attempt to read a record with the requested key
*/
*/
int
int
isam_readByKey
(
isamPtr
isam_ident
,
const
char
*
key
,
void
*
data
)
isam_readByKey
(
isamPtr
isam_ident
,
const
char
*
key
,
void
*
data
)
{
{
#ifdef OPTIMISED
#ifdef OPTIMISED
...
@@ -1020,7 +1020,7 @@ isam_readByKey(isamPtr isam_ident, const char *key, void *data)
...
@@ -1020,7 +1020,7 @@ isam_readByKey(isamPtr isam_ident, const char *key, void *data)
* Skip all records with smaller keys
* Skip all records with smaller keys
*/
*/
while
(
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
while
(
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
isam_ident
->
fHead
.
KeyLen
)
>
0
)
{
isam_ident
->
fHead
.
KeyLen
)
>
0
)
{
/*
/*
* There is no next record
* There is no next record
...
@@ -1039,7 +1039,7 @@ isam_readByKey(isamPtr isam_ident, const char *key, void *data)
...
@@ -1039,7 +1039,7 @@ isam_readByKey(isamPtr isam_ident, const char *key, void *data)
* Current key is not exact match
* Current key is not exact match
*/
*/
if
(
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
if
(
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
isam_ident
->
fHead
.
KeyLen
)
!=
0
)
{
isam_ident
->
fHead
.
KeyLen
)
!=
0
)
{
isam_error
=
ISAM_NO_SUCH_KEY
;
isam_error
=
ISAM_NO_SUCH_KEY
;
return
-
1
;
return
-
1
;
}
}
...
@@ -1060,13 +1060,13 @@ isam_readByKey(isamPtr isam_ident, const char *key, void *data)
...
@@ -1060,13 +1060,13 @@ isam_readByKey(isamPtr isam_ident, const char *key, void *data)
memcpy
(
data
,
data
((
*
isam_ident
),
iCache
,
rec_no
),
isam_ident
->
fHead
.
DataLen
);
memcpy
(
data
,
data
((
*
isam_ident
),
iCache
,
rec_no
),
isam_ident
->
fHead
.
DataLen
);
return
0
;
return
0
;
#else
#else
/*
/*
* STEP 5: This implementation is inefficient, and I have not verified
* STEP 5: This implementation is inefficient, and I have not verified
* that it really works according to its specification For one thing, it
* that it really works according to its specification For one thing, it
* does not test for a valid isam_ident before use. It is probably better
* does not test for a valid isam_ident before use. It is probably better
* to include tempData and tempKey as part of the structure pointed to by
* to include tempData and tempKey as part of the structure pointed to by
* isam_ident. That also saves some mallocs and frees
* isam_ident. That also saves some mallocs and frees
*/
*/
void
*
tempData
=
malloc
(
isam_ident
->
fHead
.
DataLen
);
void
*
tempData
=
malloc
(
isam_ident
->
fHead
.
DataLen
);
char
*
tempKey
=
malloc
(
isam_ident
->
fHead
.
KeyLen
);
char
*
tempKey
=
malloc
(
isam_ident
->
fHead
.
KeyLen
);
...
@@ -1111,7 +1111,7 @@ key_error:
...
@@ -1111,7 +1111,7 @@ key_error:
* overflow record position (last block in a record, or a free slot in an
* overflow record position (last block in a record, or a free slot in an
* overflow block)
* overflow block)
*/
*/
static
int
static
int
isam_append
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
data
)
isam_append
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
data
)
{
{
int
block_no
;
int
block_no
;
...
@@ -1153,11 +1153,11 @@ isam_append(isamPtr isam_ident, const char *key, const void *data)
...
@@ -1153,11 +1153,11 @@ isam_append(isamPtr isam_ident, const char *key, const void *data)
* case for append - let it be for now
* case for append - let it be for now
*/
*/
if
((
rv
=
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
if
((
rv
=
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
isam_ident
->
fHead
.
KeyLen
)))
{
isam_ident
->
fHead
.
KeyLen
)))
{
assert
(
rv
>
0
);
assert
(
rv
>
0
);
/*
/*
* This now implies an otherwise normal append
* This now implies an otherwise normal append
*/
*/
}
}
else
{
else
{
/*
/*
...
@@ -1171,17 +1171,17 @@ isam_append(isamPtr isam_ident, const char *key, const void *data)
...
@@ -1171,17 +1171,17 @@ isam_append(isamPtr isam_ident, const char *key, const void *data)
}
}
assert
(
0
==
strncmp
(
key
,
isam_ident
->
maxKey
,
assert
(
0
==
strncmp
(
key
,
isam_ident
->
maxKey
,
isam_ident
->
fHead
.
KeyLen
));
isam_ident
->
fHead
.
KeyLen
));
/*
/*
* Assert deleted state
* Assert deleted state
*/
*/
assert
(
ISAM_DELETED
==
assert
(
ISAM_DELETED
==
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
statusFlags
);
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
statusFlags
);
/*
/*
* We only need to copy the data and mark the record as valid
* We only need to copy the data and mark the record as valid
*/
*/
memcpy
(
data
(
*
isam_ident
,
iCache
,
rec_no
),
data
,
memcpy
(
data
(
*
isam_ident
,
iCache
,
rec_no
),
data
,
isam_ident
->
fHead
.
DataLen
);
isam_ident
->
fHead
.
DataLen
);
head
(
*
isam_ident
,
iCache
,
rec_no
)
->
statusFlags
=
ISAM_VALID
;
head
(
*
isam_ident
,
iCache
,
rec_no
)
->
statusFlags
=
ISAM_VALID
;
isam_ident
->
fHead
.
Nrecords
++
;
isam_ident
->
fHead
.
Nrecords
++
;
/*
/*
...
@@ -1218,7 +1218,7 @@ isam_append(isamPtr isam_ident, const char *key, const void *data)
...
@@ -1218,7 +1218,7 @@ isam_append(isamPtr isam_ident, const char *key, const void *data)
* Now we should have a record with a smaller key, equal to maxKey
* Now we should have a record with a smaller key, equal to maxKey
*/
*/
rv
=
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
rv
=
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
isam_ident
->
fHead
.
KeyLen
);
isam_ident
->
fHead
.
KeyLen
);
if
(
rv
<=
0
)
{
if
(
rv
<=
0
)
{
unsigned
int
i
;
unsigned
int
i
;
...
@@ -1244,11 +1244,11 @@ isam_append(isamPtr isam_ident, const char *key, const void *data)
...
@@ -1244,11 +1244,11 @@ isam_append(isamPtr isam_ident, const char *key, const void *data)
new_block_no
++
;
new_block_no
++
;
if
(
new_block_no
>=
(
int
)
isam_ident
->
fHead
.
Nblocks
)
{
if
(
new_block_no
>=
(
int
)
isam_ident
->
fHead
.
Nblocks
)
{
/*
/*
* Insertion in an overflow block obeys slightly different rules -
* Insertion in an overflow block obeys slightly different rules -
* e.g. we do not add to the index, and we do not leave a free
* e.g. we do not add to the index, and we do not leave a free
* slot
* slot
*/
*/
break
;
break
;
}
}
...
@@ -1332,7 +1332,7 @@ isam_append(isamPtr isam_ident, const char *key, const void *data)
...
@@ -1332,7 +1332,7 @@ isam_append(isamPtr isam_ident, const char *key, const void *data)
return
writeHead
(
isam_ident
);
return
writeHead
(
isam_ident
);
}
}
int
int
isam_writeNew
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
data
)
isam_writeNew
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
data
)
{
{
int
block_no
;
int
block_no
;
...
@@ -1379,7 +1379,7 @@ isam_writeNew(isamPtr isam_ident, const char *key, const void *data)
...
@@ -1379,7 +1379,7 @@ isam_writeNew(isamPtr isam_ident, const char *key, const void *data)
next
=
block_no
*
isam_ident
->
fHead
.
NrecPB
;
next
=
block_no
*
isam_ident
->
fHead
.
NrecPB
;
while
((
rv
=
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
while
((
rv
=
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
isam_ident
->
fHead
.
KeyLen
))
>
0
)
{
isam_ident
->
fHead
.
KeyLen
))
>
0
)
{
next
=
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
next
;
next
=
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
next
;
assert
(
next
);
assert
(
next
);
block_no
=
next
/
isam_ident
->
fHead
.
NrecPB
;
block_no
=
next
/
isam_ident
->
fHead
.
NrecPB
;
...
@@ -1399,13 +1399,13 @@ isam_writeNew(isamPtr isam_ident, const char *key, const void *data)
...
@@ -1399,13 +1399,13 @@ isam_writeNew(isamPtr isam_ident, const char *key, const void *data)
*/
*/
if
(
rv
==
0
)
{
if
(
rv
==
0
)
{
if
(
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
if
(
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
statusFlags
&
ISAM_DELETED
)
{
statusFlags
&
ISAM_DELETED
)
{
/*
/*
* Should be simple and OK.
* Should be simple and OK.
* We only need to copy the data and mark the record as valid
* We only need to copy the data and mark the record as valid
*/
*/
memcpy
(
data
(
*
isam_ident
,
iCache
,
rec_no
),
data
,
memcpy
(
data
(
*
isam_ident
,
iCache
,
rec_no
),
data
,
isam_ident
->
fHead
.
DataLen
);
isam_ident
->
fHead
.
DataLen
);
head
(
*
isam_ident
,
iCache
,
rec_no
)
->
statusFlags
=
ISAM_VALID
;
head
(
*
isam_ident
,
iCache
,
rec_no
)
->
statusFlags
=
ISAM_VALID
;
isam_ident
->
fHead
.
Nrecords
++
;
isam_ident
->
fHead
.
Nrecords
++
;
/*
/*
...
@@ -1669,7 +1669,7 @@ int isam_perror(const char *str)
...
@@ -1669,7 +1669,7 @@ int isam_perror(const char *str)
* isam_delete will delete a record if - it exists, - is valid - key and
* isam_delete will delete a record if - it exists, - is valid - key and
* data match
* data match
*/
*/
int
int
isam_delete
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
data
)
isam_delete
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
data
)
{
{
unsigned
long
block_no
;
unsigned
long
block_no
;
...
@@ -1707,7 +1707,7 @@ isam_delete(isamPtr isam_ident, const char *key, const void *data)
...
@@ -1707,7 +1707,7 @@ isam_delete(isamPtr isam_ident, const char *key, const void *data)
* Skip all records with smaller keys
* Skip all records with smaller keys
*/
*/
while
((
rv
=
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
while
((
rv
=
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
isam_ident
->
fHead
.
KeyLen
))
>
0
)
{
isam_ident
->
fHead
.
KeyLen
))
>
0
)
{
next
=
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
next
;
next
=
head
((
*
isam_ident
),
iCache
,
rec_no
)
->
next
;
debugRecord
(
isam_ident
,
next
,
"delete #1"
);
debugRecord
(
isam_ident
,
next
,
"delete #1"
);
...
@@ -1742,7 +1742,7 @@ isam_delete(isamPtr isam_ident, const char *key, const void *data)
...
@@ -1742,7 +1742,7 @@ isam_delete(isamPtr isam_ident, const char *key, const void *data)
* if it happens to be a string (isam_readByKey will take care of that)
* if it happens to be a string (isam_readByKey will take care of that)
*/
*/
if
(
memcmp
(
data
,
data
(
*
isam_ident
,
iCache
,
rec_no
),
if
(
memcmp
(
data
,
data
(
*
isam_ident
,
iCache
,
rec_no
),
isam_ident
->
fHead
.
DataLen
))
{
isam_ident
->
fHead
.
DataLen
))
{
isam_error
=
ISAM_DATA_MISMATCH
;
isam_error
=
ISAM_DATA_MISMATCH
;
return
-
1
;
return
-
1
;
}
}
...
@@ -1822,10 +1822,10 @@ isam_delete(isamPtr isam_ident, const char *key, const void *data)
...
@@ -1822,10 +1822,10 @@ isam_delete(isamPtr isam_ident, const char *key, const void *data)
* maxKey must be set to that of the preceding record.
* maxKey must be set to that of the preceding record.
*/
*/
if
(
!
strncmp
if
(
!
strncmp
(
key
,
isam_ident
->
maxKey
,
isam_ident
->
fHead
.
KeyLen
))
{
(
key
,
isam_ident
->
maxKey
,
isam_ident
->
fHead
.
KeyLen
))
{
memcpy
(
isam_ident
->
maxKey
,
memcpy
(
isam_ident
->
maxKey
,
key
(
*
isam_ident
,
pCache
,
prev_rec_no
),
key
(
*
isam_ident
,
pCache
,
prev_rec_no
),
isam_ident
->
fHead
.
KeyLen
);
isam_ident
->
fHead
.
KeyLen
);
isam_ident
->
fHead
.
MaxKeyRec
=
prev
;
isam_ident
->
fHead
.
MaxKeyRec
=
prev
;
}
}
}
}
...
@@ -1861,7 +1861,7 @@ isam_delete(isamPtr isam_ident, const char *key, const void *data)
...
@@ -1861,7 +1861,7 @@ isam_delete(isamPtr isam_ident, const char *key, const void *data)
return
-
1
;
return
-
1
;
}
}
while
(
prev_valid
while
(
prev_valid
&&
(
!
(
cur_head
(
*
isam_ident
)
->
statusFlags
&
ISAM_VALID
)))
{
&&
(
!
(
cur_head
(
*
isam_ident
)
->
statusFlags
&
ISAM_VALID
)))
{
prev_valid
=
cur_head
(
*
isam_ident
)
->
previous
;
prev_valid
=
cur_head
(
*
isam_ident
)
->
previous
;
prev_valid_block_no
=
prev_valid
/
isam_ident
->
fHead
.
NrecPB
;
prev_valid_block_no
=
prev_valid
/
isam_ident
->
fHead
.
NrecPB
;
prev_valid_rec_no
=
prev_valid
%
isam_ident
->
fHead
.
NrecPB
;
prev_valid_rec_no
=
prev_valid
%
isam_ident
->
fHead
.
NrecPB
;
...
@@ -1886,9 +1886,9 @@ isam_delete(isamPtr isam_ident, const char *key, const void *data)
...
@@ -1886,9 +1886,9 @@ isam_delete(isamPtr isam_ident, const char *key, const void *data)
* implementation, where far fewer records need to be written, is left as
* implementation, where far fewer records need to be written, is left as
* an exercise.
* an exercise.
*/
*/
int
int
isam_update
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
old_data
,
isam_update
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
old_data
,
const
void
*
new_data
)
const
void
*
new_data
)
{
{
#ifdef OPTIMISED
#ifdef OPTIMISED
int
block_no
;
int
block_no
;
...
@@ -1924,7 +1924,7 @@ isam_update(isamPtr isam_ident, const char *key, const void *old_data,
...
@@ -1924,7 +1924,7 @@ isam_update(isamPtr isam_ident, const char *key, const void *old_data,
* Skip all records with smaller keys
* Skip all records with smaller keys
*/
*/
while
(
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
while
(
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
isam_ident
->
fHead
.
KeyLen
)
>
0
)
{
isam_ident
->
fHead
.
KeyLen
)
>
0
)
{
/*
/*
* There is no next record
* There is no next record
...
@@ -1943,7 +1943,7 @@ isam_update(isamPtr isam_ident, const char *key, const void *old_data,
...
@@ -1943,7 +1943,7 @@ isam_update(isamPtr isam_ident, const char *key, const void *old_data,
* Current key is not exact match
* Current key is not exact match
*/
*/
if
(
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
if
(
strncmp
(
key
,
key
((
*
isam_ident
),
iCache
,
rec_no
),
isam_ident
->
fHead
.
KeyLen
)
!=
0
)
{
isam_ident
->
fHead
.
KeyLen
)
!=
0
)
{
isam_error
=
ISAM_NO_SUCH_KEY
;
isam_error
=
ISAM_NO_SUCH_KEY
;
return
-
1
;
return
-
1
;
}
}
...
@@ -1963,7 +1963,7 @@ isam_update(isamPtr isam_ident, const char *key, const void *old_data,
...
@@ -1963,7 +1963,7 @@ isam_update(isamPtr isam_ident, const char *key, const void *old_data,
* Verify that data matches
* Verify that data matches
*/
*/
if
(
memcmp
(
data
(
*
isam_ident
,
iCache
,
rec_no
),
old_data
,
if
(
memcmp
(
data
(
*
isam_ident
,
iCache
,
rec_no
),
old_data
,
isam_ident
->
fHead
.
DataLen
))
{
isam_ident
->
fHead
.
DataLen
))
{
isam_error
=
ISAM_DATA_MISMATCH
;
isam_error
=
ISAM_DATA_MISMATCH
;
return
-
1
;
return
-
1
;
}
}
...
@@ -1983,7 +1983,7 @@ isam_update(isamPtr isam_ident, const char *key, const void *old_data,
...
@@ -1983,7 +1983,7 @@ isam_update(isamPtr isam_ident, const char *key, const void *old_data,
isam_ident
->
fHead
.
FileState
|=
ISAM_STATE_UPDATING
;
isam_ident
->
fHead
.
FileState
|=
ISAM_STATE_UPDATING
;
if
(
writeHead
(
isam_ident
)
||
if
(
writeHead
(
isam_ident
)
||
write_cache_block
(
isam_ident
,
iCache
))
{
write_cache_block
(
isam_ident
,
iCache
))
{
return
-
1
;
return
-
1
;
}
}
...
@@ -2003,7 +2003,7 @@ isam_update(isamPtr isam_ident, const char *key, const void *old_data,
...
@@ -2003,7 +2003,7 @@ isam_update(isamPtr isam_ident, const char *key, const void *old_data,
* Like strlen, but with a maximum length allowed. There is "strnlen" in
* Like strlen, but with a maximum length allowed. There is "strnlen" in
* GNU libc, but it's non-standard, hence we provide our own version.
* GNU libc, but it's non-standard, hence we provide our own version.
*/
*/
static
long
static
long
my_strnlen
(
const
char
*
str
,
int
maxLen
)
my_strnlen
(
const
char
*
str
,
int
maxLen
)
{
{
const
char
*
s
=
str
;
const
char
*
s
=
str
;
...
@@ -2020,7 +2020,7 @@ my_strnlen(const char *str, int maxLen)
...
@@ -2020,7 +2020,7 @@ my_strnlen(const char *str, int maxLen)
* and complete blocks, separately for sequential part and for overflow
* and complete blocks, separately for sequential part and for overflow
* part. Also collect statistics on the key length used.
* part. Also collect statistics on the key length used.
*/
*/
int
int
isam_fileStats
(
isamPtr
isam_ident
,
struct
ISAM_FILE_STATS
*
stats
)
isam_fileStats
(
isamPtr
isam_ident
,
struct
ISAM_FILE_STATS
*
stats
)
{
{
int
iCache
;
int
iCache
;
...
@@ -2083,7 +2083,7 @@ isam_fileStats(isamPtr isam_ident, struct ISAM_FILE_STATS *stats)
...
@@ -2083,7 +2083,7 @@ isam_fileStats(isamPtr isam_ident, struct ISAM_FILE_STATS *stats)
* Record is used. Collect key length statistics.
* Record is used. Collect key length statistics.
*/
*/
int
keyLen
=
my_strnlen
(
key
(
*
isam_ident
,
iCache
,
rec_no
),
int
keyLen
=
my_strnlen
(
key
(
*
isam_ident
,
iCache
,
rec_no
),
isam_ident
->
fHead
.
KeyLen
);
isam_ident
->
fHead
.
KeyLen
);
used
++
;
used
++
;
if
(
stats
->
keyMin
==
-
1
||
keyLen
<
stats
->
keyMin
)
{
if
(
stats
->
keyMin
==
-
1
||
keyLen
<
stats
->
keyMin
)
{
...
...
os/ass5/isam.h
View file @
8b45567d
...
@@ -2,17 +2,17 @@
...
@@ -2,17 +2,17 @@
#define ISAM_H
#define ISAM_H
/* -------------------------------------------------------------------------
/* -------------------------------------------------------------------------
Author: G.D. van Albada
Author: G.D. van Albada
University of Amsterdam
University of Amsterdam
Faculty of Science
Faculty of Science
Informatics Institute
Informatics Institute
Copyright (C) Universiteit van Amsterdam
Copyright (C) Universiteit van Amsterdam
dick at science.uva.nl
dick at science.uva.nl
Version: 0.1
Version: 0.1
Date: December 2001 / January 2002 / November 2004
Date: December 2001 / January 2002 / November 2004
Goal: Part of an assignment on file system structure for the operating
Goal: Part of an assignment on file system structure for the operating
systems course. It demonstrates many of the administrative and layering
systems course. It demonstrates many of the administrative and layering
structures that are also used in normal file systems.
structures that are also used in normal file systems.
--------------------------------------------------------------------------*/
--------------------------------------------------------------------------*/
typedef
struct
ISAM
*
isamPtr
;
typedef
struct
ISAM
*
isamPtr
;
...
@@ -23,34 +23,34 @@ struct ISAM_CACHE_STATS;
...
@@ -23,34 +23,34 @@ struct ISAM_CACHE_STATS;
/* isam_create will create an isam_file, but only if a file of that name
/* isam_create will create an isam_file, but only if a file of that name
does not yet exist.
does not yet exist.
The parameters are:
The parameters are:
name: name of the file, possibly including directory information
name: name of the file, possibly including directory information
key_len: maximum length of the (character string) key.
key_len: maximum length of the (character string) key.
data_len: length of the data field
data_len: length of the data field
NrecPB: number of records that should be put into one block (including
NrecPB: number of records that should be put into one block (including
one overflow record per block).
one overflow record per block).
Nblocks: The number of regular data blocks = number of entries in the
Nblocks: The number of regular data blocks = number of entries in the
index
index
isam_create will return an isamPtr on success, NULL on failure
isam_create will return an isamPtr on success, NULL on failure
*/
*/
isamPtr
isam_create
(
const
char
*
name
,
unsigned
long
key_len
,
isamPtr
isam_create
(
const
char
*
name
,
unsigned
long
key_len
,
unsigned
long
data_len
,
unsigned
long
NrecPB
,
unsigned
long
Nblocks
);
unsigned
long
data_len
,
unsigned
long
NrecPB
,
unsigned
long
Nblocks
);
/* isam_open will open an existing isam file.
/* isam_open will open an existing isam file.
The parameters are:
The parameters are:
name: name of the file, possibly including directory information
name: name of the file, possibly including directory information
update: (not used) when != 0 the file is opened for reading and writing
update: (not used) when != 0 the file is opened for reading and writing
(it actually always is).
(it actually always is).
isam_open will return an isamPtr on success, NULL on failure
isam_open will return an isamPtr on success, NULL on failure
*/
*/
isamPtr
isam_open
(
const
char
*
name
,
int
update
);
isamPtr
isam_open
(
const
char
*
name
,
int
update
);
/* isam_close will close a previously opened/created isam_file
/* isam_close will close a previously opened/created isam_file
The parameters are:
The parameters are:
isam_ident: the isamPtr for the file.
isam_ident: the isamPtr for the file.
isam_close will return 0 on success, -1 on failure.
isam_close will return 0 on success, -1 on failure.
*/
*/
int
isam_close
(
isamPtr
isam_ident
);
int
isam_close
(
isamPtr
isam_ident
);
...
@@ -60,30 +60,30 @@ int isam_close(isamPtr isam_ident);
...
@@ -60,30 +60,30 @@ int isam_close(isamPtr isam_ident);
If no such record exists, the first record with a larger key will
If no such record exists, the first record with a larger key will
be returned, if that exists.
be returned, if that exists.
The parameters are:
The parameters are:
isam_ident: the isamPtr for the file.
isam_ident: the isamPtr for the file.
key: a string containing the requested key.
key: a string containing the requested key.
isam_setKey will return 0 on success, -1 on failure.
isam_setKey will return 0 on success, -1 on failure.
*/
*/
int
isam_setKey
(
isamPtr
isam_ident
,
const
char
*
key
);
int
isam_setKey
(
isamPtr
isam_ident
,
const
char
*
key
);
/* isam_readNext will read the next valid record, if that exists.
/* isam_readNext will read the next valid record, if that exists.
The parameters are:
The parameters are:
isam_ident: the isamPtr for the file.
isam_ident: the isamPtr for the file.
key: a character array where the key will be stored.
key: a character array where the key will be stored.
data: pointer to the location where the data are to be stored.
data: pointer to the location where the data are to be stored.
isam_readNext will return 0 on success, -1 on failure.
isam_readNext will return 0 on success, -1 on failure.
*/
*/
int
isam_readNext
(
isamPtr
isam_ident
,
char
*
key
,
void
*
data
);
int
isam_readNext
(
isamPtr
isam_ident
,
char
*
key
,
void
*
data
);
/* isam_readPrev will read the current record, if that exists and is valid and
/* isam_readPrev will read the current record, if that exists and is valid and
afterwards position the file at the preceding valid record, if that exists.
afterwards position the file at the preceding valid record, if that exists.
The parameters are:
The parameters are:
isam_ident: the isamPtr for the file.
isam_ident: the isamPtr for the file.
key: a character array where the key will be stored.
key: a character array where the key will be stored.
data: pointer to the location where the data are to be stored.
data: pointer to the location where the data are to be stored.
isam_readPrev will return 0 on success, -1 on failure.
isam_readPrev will return 0 on success, -1 on failure.
*/
*/
int
isam_readPrev
(
isamPtr
isam_ident
,
char
*
key
,
void
*
data
);
int
isam_readPrev
(
isamPtr
isam_ident
,
char
*
key
,
void
*
data
);
...
@@ -91,11 +91,11 @@ int isam_readPrev(isamPtr isam_ident, char *key, void *data);
...
@@ -91,11 +91,11 @@ int isam_readPrev(isamPtr isam_ident, char *key, void *data);
like an isam_setKey followed by an isam_readNext plus a check that the
like an isam_setKey followed by an isam_readNext plus a check that the
requested key and the retrieved key are the same.
requested key and the retrieved key are the same.
The parameters are:
The parameters are:
isam_ident: the isamPtr for the file.
isam_ident: the isamPtr for the file.
key: a string containing the requested key.
key: a string containing the requested key.
data: pointer to the location where the data are to be stored.
data: pointer to the location where the data are to be stored.
isam_readByKey will return 0 on success, -1 on failure.
isam_readByKey will return 0 on success, -1 on failure.
*/
*/
int
isam_readByKey
(
isamPtr
isam_ident
,
const
char
*
key
,
void
*
data
);
int
isam_readByKey
(
isamPtr
isam_ident
,
const
char
*
key
,
void
*
data
);
...
@@ -103,46 +103,46 @@ int isam_readByKey(isamPtr isam_ident, const char *key, void *data);
...
@@ -103,46 +103,46 @@ int isam_readByKey(isamPtr isam_ident, const char *key, void *data);
if such a record exists. As a security measure, it will verify that the
if such a record exists. As a security measure, it will verify that the
user has the correct original data.
user has the correct original data.
The parameters are:
The parameters are:
isam_ident: the isamPtr for the file.
isam_ident: the isamPtr for the file.
key: a string containing the requested key.
key: a string containing the requested key.
old_data: a pointer to a location containing a copy of the data that
old_data: a pointer to a location containing a copy of the data that
the record should contain before modification.
the record should contain before modification.
new_data: the new data to be stored in the record.
new_data: the new data to be stored in the record.
isam_update will return 0 on success, -1 on failure.
isam_update will return 0 on success, -1 on failure.
*/
*/
int
isam_update
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
old_data
,
int
isam_update
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
old_data
,
const
void
*
new_data
);
const
void
*
new_data
);
/* isam_writeNew will write a new record to the file, but only if the key is
/* isam_writeNew will write a new record to the file, but only if the key is
not yet in use.
not yet in use.
The parameters are:
The parameters are:
isam_ident: the isamPtr for the file.
isam_ident: the isamPtr for the file.
key: a string containing the new key.
key: a string containing the new key.
data: the data to be stored in the new record.
data: the data to be stored in the new record.
isam_writeNew will return 0 on success, -1 on failure.
isam_writeNew will return 0 on success, -1 on failure.
*/
*/
int
isam_writeNew
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
data
);
int
isam_writeNew
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
data
);
/* isam_delete will delete the record with the given key. As a security
/* isam_delete will delete the record with the given key. As a security
measure, it will verify that the user has the correct original data.
measure, it will verify that the user has the correct original data.
The parameters are:
The parameters are:
isam_ident: the isamPtr for the file.
isam_ident: the isamPtr for the file.
key: a string containing the key of the record to be deleted.
key: a string containing the key of the record to be deleted.
data: a pointer to a location containing a copy of the data that
data: a pointer to a location containing a copy of the data that
the record should contain before deletion.
the record should contain before deletion.
isam_delete will return 0 on success, -1 on failure.
isam_delete will return 0 on success, -1 on failure.
*/
*/
int
isam_delete
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
data
);
int
isam_delete
(
isamPtr
isam_ident
,
const
char
*
key
,
const
void
*
data
);
/* isam_fileStats will collect statistics about a given ISAM file.
/* isam_fileStats will collect statistics about a given ISAM file.
The parameters are:
The parameters are:
isam_ident: the isamPtr for the file.
isam_ident: the isamPtr for the file.
stats: the structure to fill in with statistics.
stats: the structure to fill in with statistics.
isam_fileStats will return 0 on success, -1 on failure.
isam_fileStats will return 0 on success, -1 on failure.
*/
*/
int
isam_fileStats
(
isamPtr
isam_ident
,
struct
ISAM_FILE_STATS
*
stats
);
int
isam_fileStats
(
isamPtr
isam_ident
,
struct
ISAM_FILE_STATS
*
stats
);
...
@@ -167,32 +167,32 @@ int isam_cacheStats(struct ISAM_CACHE_STATS *stats);
...
@@ -167,32 +167,32 @@ int isam_cacheStats(struct ISAM_CACHE_STATS *stats);
int
isam_perror
(
const
char
*
mess
);
int
isam_perror
(
const
char
*
mess
);
/*
/*
* Not all of the following errors are actually used ....
* Not all of the following errors are actually used ....
*/
*/
enum
isam_error
enum
isam_error
{
{
ISAM_NO_ERROR
=
(
0
),
ISAM_NO_ERROR
=
(
0
),
ISAM_WRITE_FAIL
,
ISAM_WRITE_FAIL
,
ISAM_KEY_LEN
,
ISAM_KEY_LEN
,
ISAM_FILE_EXISTS
,
ISAM_FILE_EXISTS
,
ISAM_LINK_EXISTS
,
ISAM_LINK_EXISTS
,
ISAM_OPEN_FAIL
,
ISAM_OPEN_FAIL
,
ISAM_NO_SUCH_FILE
,
ISAM_NO_SUCH_FILE
,
ISAM_OPEN_COUNT
,
ISAM_OPEN_COUNT
,
ISAM_INDEX_ERROR
,
ISAM_INDEX_ERROR
,
ISAM_READ_ERROR
,
ISAM_READ_ERROR
,
ISAM_BAD_MAGIC
,
ISAM_BAD_MAGIC
,
ISAM_BAD_VERSION
,
ISAM_BAD_VERSION
,
ISAM_HEADER_ERROR
,
ISAM_HEADER_ERROR
,
ISAM_OPEN_FOR_UPDATE
,
ISAM_OPEN_FOR_UPDATE
,
ISAM_IDENT_INVALID
,
ISAM_IDENT_INVALID
,
ISAM_NO_SUCH_KEY
,
ISAM_NO_SUCH_KEY
,
ISAM_NULL_KEY
,
ISAM_NULL_KEY
,
ISAM_DATA_MISMATCH
,
ISAM_DATA_MISMATCH
,
ISAM_RECORD_EXISTS
,
ISAM_RECORD_EXISTS
,
ISAM_SEEK_ERROR
,
ISAM_SEEK_ERROR
,
ISAM_SOF
,
ISAM_SOF
,
ISAM_EOF
ISAM_EOF
};
};
extern
enum
isam_error
isam_error
;
extern
enum
isam_error
isam_error
;
...
@@ -238,11 +238,11 @@ struct ISAM_FILE_STATS
...
@@ -238,11 +238,11 @@ struct ISAM_FILE_STATS
*/
*/
struct
ISAM_CACHE_STATS
struct
ISAM_CACHE_STATS
{
{
int
int
calls
,
/* Times the cache got called */
calls
,
/* Times the cache got called */
reads
,
/* Times we needed to read from disk */
reads
,
/* Times we needed to read from disk */
writes
,
/* Times we wrote to it */
writes
,
/* Times we wrote to it */
hwrites
;
/* Times we wrote a header */
hwrites
;
/* Times we wrote a header */
};
};
#endif
#endif
os/ass5/isam_bench.c
View file @
8b45567d
...
@@ -48,7 +48,7 @@ static int report = 0;
...
@@ -48,7 +48,7 @@ static int report = 0;
* Bereken dagnummer met 1/1/1900 == 1
* Bereken dagnummer met 1/1/1900 == 1
* Routine faalt op en na 1/3/2100
* Routine faalt op en na 1/3/2100
*/
*/
static
long
static
long
berekenDag
(
int
dag
,
int
maand
,
int
jaar
)
berekenDag
(
int
dag
,
int
maand
,
int
jaar
)
{
{
long
dagen
;
long
dagen
;
...
@@ -91,7 +91,7 @@ berekenDag(int dag, int maand, int jaar)
...
@@ -91,7 +91,7 @@ berekenDag(int dag, int maand, int jaar)
/*
/*
* Print klant-informatie
* Print klant-informatie
*/
*/
static
void
static
void
printKlant
(
FILE
*
log
,
char
*
kop
,
char
*
sleutel
,
klant
*
Klant
)
printKlant
(
FILE
*
log
,
char
*
kop
,
char
*
sleutel
,
klant
*
Klant
)
{
{
if
(
kop
)
{
if
(
kop
)
{
...
@@ -107,7 +107,7 @@ printKlant(FILE * log, char *kop, char *sleutel, klant * Klant)
...
@@ -107,7 +107,7 @@ printKlant(FILE * log, char *kop, char *sleutel, klant * Klant)
/*
/*
* Maak een random klant
* Maak een random klant
*/
*/
static
void
static
void
maakKlant
(
klant
*
nieuweKlant
)
maakKlant
(
klant
*
nieuweKlant
)
{
{
int
i
,
dag
,
maand
,
jaar
;
int
i
,
dag
,
maand
,
jaar
;
...
@@ -147,7 +147,7 @@ static int code = 1000;
...
@@ -147,7 +147,7 @@ static int code = 1000;
* Maak een random sleutel, dichtbij de postcode in "code". Verhoog code.
* Maak een random sleutel, dichtbij de postcode in "code". Verhoog code.
* Sleutel is een postcode plus huisnummer.
* Sleutel is een postcode plus huisnummer.
*/
*/
static
int
static
int
maakSleutel
(
char
*
sleutel
)
maakSleutel
(
char
*
sleutel
)
{
{
int
huisnummer
;
int
huisnummer
;
...
@@ -169,7 +169,7 @@ maakSleutel(char *sleutel)
...
@@ -169,7 +169,7 @@ maakSleutel(char *sleutel)
/*
/*
* Schrijf een nieuw record op een willekeurige plek in het bestand
* Schrijf een nieuw record op een willekeurige plek in het bestand
*/
*/
static
int
static
int
randomNieuwRecord
(
isamPtr
ip
)
randomNieuwRecord
(
isamPtr
ip
)
{
{
char
sleutel
[
20
];
char
sleutel
[
20
];
...
@@ -201,7 +201,7 @@ randomNieuwRecord(isamPtr ip)
...
@@ -201,7 +201,7 @@ randomNieuwRecord(isamPtr ip)
* Lees sequentieel alle records in bepaald sleutelbereik, en pleeg een
* Lees sequentieel alle records in bepaald sleutelbereik, en pleeg een
* bewerking
* bewerking
*/
*/
static
int
static
int
leesBereik
(
isamPtr
ip
,
char
*
minSleutel
,
char
*
maxSleutel
,
int
datum
)
leesBereik
(
isamPtr
ip
,
char
*
minSleutel
,
char
*
maxSleutel
,
int
datum
)
{
{
char
sleutel
[
20
];
char
sleutel
[
20
];
...
@@ -265,7 +265,7 @@ leesBereik(isamPtr ip, char *minSleutel, char *maxSleutel, int datum)
...
@@ -265,7 +265,7 @@ leesBereik(isamPtr ip, char *minSleutel, char *maxSleutel, int datum)
}
}
int
int
leesBestaandRecord
(
isamPtr
ip
,
int
sleutelNr
)
leesBestaandRecord
(
isamPtr
ip
,
int
sleutelNr
)
{
{
klant
klantRecord
;
klant
klantRecord
;
...
@@ -283,7 +283,7 @@ leesBestaandRecord(isamPtr ip, int sleutelNr)
...
@@ -283,7 +283,7 @@ leesBestaandRecord(isamPtr ip, int sleutelNr)
return
rv
;
return
rv
;
}
}
int
int
poetsBestaandRecord
(
isamPtr
ip
,
int
sleutelNr
)
poetsBestaandRecord
(
isamPtr
ip
,
int
sleutelNr
)
{
{
klant
klantRecord
;
klant
klantRecord
;
...
@@ -310,7 +310,7 @@ poetsBestaandRecord(isamPtr ip, int sleutelNr)
...
@@ -310,7 +310,7 @@ poetsBestaandRecord(isamPtr ip, int sleutelNr)
return
rv
;
return
rv
;
}
}
int
int
main
(
int
argc
,
char
*
argv
[])
main
(
int
argc
,
char
*
argv
[])
{
{
isamPtr
ip
;
isamPtr
ip
;
...
...
os/ass5/isam_test.c
View file @
8b45567d
...
@@ -24,7 +24,7 @@ code - it lacks comments, naming is ad-hoc, etc.
...
@@ -24,7 +24,7 @@ code - it lacks comments, naming is ad-hoc, etc.
#include <string.h>
#include <string.h>
#include "isam.h"
#include "isam.h"
void
void
instruct
(
void
)
instruct
(
void
)
{
{
char
str
[
256
];
char
str
[
256
];
...
@@ -65,7 +65,7 @@ instruct(void)
...
@@ -65,7 +65,7 @@ instruct(void)
printf
(
"
\n
"
);
printf
(
"
\n
"
);
}
}
int
int
main
(
int
argc
,
char
*
argv
[])
main
(
int
argc
,
char
*
argv
[])
{
{
int
rv
,
i
;
int
rv
,
i
;
...
...
portfolio/vcs/vcs.tex
View file @
8b45567d
...
@@ -360,8 +360,9 @@ fill in the names of files you expect to show up in the directory.
...
@@ -360,8 +360,9 @@ fill in the names of files you expect to show up in the directory.
In Git, it is not necessary to mention the renaming of files (since Git tracks
In Git, it is not necessary to mention the renaming of files (since Git tracks
content, not files). However, it is required to add the renamed file to Git's
content, not files). However, it is required to add the renamed file to Git's
index, otherwise the file is marked as ``deleted''. Git provides a command to
index, otherwise the file is marked as ``deleted''. Also, Git provides a command to
move (or rename) files and directories:
\texttt
{
git mv foo bar
}
.
move (or rename) files and directories:
\texttt
{
git mv foo bar
}
. This will save
you one command to type, compared to
\texttt
{
mv foo bar; git add bar
}
.
% }}}
% }}}
...
@@ -369,9 +370,10 @@ move (or rename) files and directories: \texttt{git mv foo bar}.
...
@@ -369,9 +370,10 @@ move (or rename) files and directories: \texttt{git mv foo bar}.
\label
{
sub:discarding-changes
}
\label
{
sub:discarding-changes
}
If you suddenly think your changes are not necessary or not the right solution,
If you suddenly think your changes are not necessary or not the right solution,
you can discard those changes in Git using
\texttt
{
git checkout -- baz.txt
}
. Or you
you can discard those changes in Git using
\texttt
{
git checkout -- baz.txt
}
for
could reset your source tree to the last commit (thus discarding all changes in
a single file or directory. Or you could reset your entire source tree to the
all tracked files made since the last commit) using
\texttt
{
git reset --hard HEAD
}
.
last commit (thus discarding all changes in all tracked files made since the
last commit) using
\texttt
{
git reset --hard HEAD
}
.
% }}}
% }}}
...
@@ -445,19 +447,19 @@ to your index in a row.
...
@@ -445,19 +447,19 @@ to your index in a row.
When you want to create an experimental feature, which will break functionality,
When you want to create an experimental feature, which will break functionality,
it is wise to create a branch. Creating a branch makes it possible to commit
it is wise to create a branch. Creating a branch makes it possible to commit
your changes, while other developers can continue their work.
If you do not
your changes, while other developers can continue their work. If you do not
create a branch, it is possible that the other developers cannot continue,
create a branch, it is possible that the other developers cannot continue,
because your commit broke some functionality they are depending on.
When your
because your commit broke some functionality they are depending on. When your
feature is stable, you can merge the two branches and your feature is included
feature is stable, you can merge the two branches and your feature is included
in the ``main'' source tree. Branches enable parallel development across the
in the ``main'' source tree. Branches enable parallel development across the
developers. Git is designed to handle large branches and merging those branches
developers. Git is designed to handle large branches and merging those branches
efficiently. Also notice when pulling from a Git repository, Git will
efficiently. Also notice when pulling from a Git repository, Git will
automatically merge two branches
(
your repository and the public repository
)
.
automatically merge two branches
(
your repository and the public repository
)
.
Consider
the situation where we need to create a branch. The following commands
Imagine
the situation where we need to create a branch. The following commands
will create a branch of the master branch, commit some changes in both branches
will create a branch of the master branch, commit some changes in both branches
and then merg
ing the two branches. In this after the merge, only master branch
and then merg
e the two branches. In this example after the merge, only the
is available.
``master'' branch
is available.
\begin
{
verbatim
}
\begin
{
verbatim
}
$
git branch
$
git branch
...
@@ -559,6 +561,77 @@ Finished one cherry-pick.
...
@@ -559,6 +561,77 @@ Finished one cherry-pick.
create mode 100644 def.txt
create mode 100644 def.txt
\end{verbatim}
\end{verbatim}
You can also pick multiple commits, for example, by using
\texttt
{
git
cherry-pick master
\~
{}
4 master
\~
{}
2
}
(two tildes). This will apply the changes
introduced by the fifth and third last commits pointed to by master and create 2
new commits with these changes. And it is possible to give a range:
\texttt
{
git
rev-list --reverse master -- README | git cherry-pick -n --stdin
}
. This will
apply the changes introduced by all commits on the master branch that touched
\texttt
{
README
}
to the working tree and index. Notice the
\texttt
{
-n
}
flag, so
the result can be inspected and made into a single new commit if suitable.
% }}}
\subsection
{
Hooks in Git
}
% {{{
\label
{
sub:hooks-in-git
}
All hooks are stored in your
\texttt
{
.git
}
-directory, and saved as
\texttt
{
.git/hooks/HOOKNAME
}
, where
\texttt
{
HOOKNAME
}
is in
$
\{
$
\texttt
{
applypatch-msg
}
,
\texttt
{
commit-msg
}
,
\texttt
{
post-commit
}
,
\texttt
{
post-receive
}
,
\texttt
{
post-update
}
,
\texttt
{
pre-applypatch
}
,
\texttt
{
pre-commit
}
,
\texttt
{
prepare-commit-msg
}
,
\texttt
{
pre-rebase
}
,
\texttt
{
update
}$
\}
$
. Example hooks (
\texttt
{
*.sample
}
) can be found in the
hooks-directory in your
\texttt
{
.git
}
-directory.
I'll demonstrate the use of a
\texttt
{
pre-commit
}
hook. This hook is invoked by
'git-commit', and can be bypassed with the
\texttt
{
--no-verify
}
option. It takes
no parameter, and is invoked before obtaining the proposed commit log message
and making a commit. Exiting with non-zero status from this script causes the
'git-commit' to abort. Aborting on a non-zero status enables a developer to run,
for example, a set of test cases before committing to the ``main'' Git server
(if you're working with a team of developers). In this example hook for
pre-commit, I'll check if the file
\texttt
{
conflict.txt
}
contains the
(sub)string
\texttt
{
abc
}
.
\begin{verbatim}
$
cat <<EOF >
/
tmp
/
uva
-
git
/
a
/
.git
/
hooks
/
pre
-
commit
#
!/
bin
/
bash
[
!
-
f Makefile
]
|| make
EOF
$
chmod +x /tmp/uva-git/a/.git/hooks/pre-commit
$
cat <<EOF >
/
tmp
/
uva
-
git
/
a
/
Makefile
all:
$
(printf '
\t
')grep abc conflict.txt
EOF
$
git add Makefile
&&
git commit
-
m "Added example Makefile."
[
master
78
f
6
e
33
]
Added example Makefile.
1
files changed,
2
insertions
(+)
,
0
deletions
(-)
create mode
100644
Makefile
$
git pull
&&
git push
$
echo "wrong" > conflict.txt
$
git commit -am "Added 'wrong' text to 'conflict.txt'"
grep abc conflict.txt
make: *** [all] Error 1
\end{verbatim}
\noindent
The pre-commit hook works as expected (since
\texttt
{
abc
}
is not found
in conflict.txt due to the commit). Now, I'll demonstrate forcing the commit,
which will bypass the pre-commit hook:
\begin{verbatim}
$
git commit
--
no
-
verify
-
am "Added 'wrong' text to 'conflict'
(
forced
)
"
[
master
9
fc
290
e
]
Added 'wrong' text to 'conflict'
(
forced
)
1
files changed,
1
insertions
(+)
,
1
deletions
(-)
\end
{
verbatim
}
\noindent
Although the used check
(
\texttt
{
grep abc conflict.txt
}
)
in the
example Makefile is pretty useless, the example clearly shows the possibilities
of a pre
-
commit hook. In this example, I also used here strings
(
\texttt
{
<<EOF
}
and
\texttt
{
EOF
}
)
to show what data is stored in which file. Here strings allows
a user to paste file content to a file without the need to escape all bash
-
related
built
-
in commands
(
since escaping is normally required to prevent bash from
performing shell expansion
)
.
% }}}
% }}}
% }}}
% }}}
...
...
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