Synched local and repos

parent 89841f96
/* /*
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;
} }
/* /*
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
......
...@@ -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);
} }
...@@ -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 \tstride\ttime\tuser\tsys"); puts("size \tstride\ttime\tuser\tsys");
time_fn(&fillArray, &wct, &ust, &syt); time_fn(&fillArray, &wct, &ust, &syt);
puts("### sumArray ###"); puts("### sumArray ###");
puts("size \tstride\ttime\tuser\tsys"); puts("size \tstride\ttime\tuser\tsys");
time_fn(&sumArray, &wct, &ust, &syt); time_fn(&sumArray, &wct, &ust, &syt);
return (EXIT_SUCCESS); return (EXIT_SUCCESS);
} }
...@@ -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;
} }
...@@ -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();
......
/* /*
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 */
......
/* /*
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 */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* /*
* 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 );
} }
...@@ -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;
......
...@@ -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;
......
This diff is collapsed.
This diff is collapsed.
...@@ -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;
......
...@@ -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;
......
...@@ -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 merging the two branches. In this after the merge, only master branch and then merge 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 78f6e33] 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 9fc290e] 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).
% }}} % }}}
% }}} % }}}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment