feat: add script to fetch tests
This commit is contained in:
parent
a5964068b0
commit
22ca321fae
10
fetch_tests.sh
Executable file
10
fetch_tests.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
tst_dir=tst
|
||||||
|
filenames="01-main 02-switch 03-equity 11-join 12-join-main 21-create-many 22-create-many-recursive 23-create-many-once 31-switch-many 32-switch-many-join 33-switch-many-cascade 51-fibonacci 61-mutex 62-mutex 71-preemption 81-deadlock"
|
||||||
|
mkdir -p "${tst_dir}"
|
||||||
|
|
||||||
|
for filename in ${filenames}
|
||||||
|
do
|
||||||
|
curl -o "${tst_dir}/${filename}.c" "https://goglin.gitlabpages.inria.fr/enseirb-it202/tests/${filename}.c" &
|
||||||
|
done
|
28
tst/01-main.c
Normal file
28
tst/01-main.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test du thread_self et yield du main seul.
|
||||||
|
*
|
||||||
|
* le programme doit retourner correctement.
|
||||||
|
* valgrind doit être content.
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_yield() depuis et vers le main
|
||||||
|
* - thread_self() depuis le main
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int err, i;
|
||||||
|
|
||||||
|
for(i=0; i<10; i++) {
|
||||||
|
printf("le main yield tout seul\n");
|
||||||
|
err = thread_yield();
|
||||||
|
assert(!err);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("le main est %p\n", (void*) thread_self());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
62
tst/02-switch.c
Normal file
62
tst/02-switch.c
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test de switchs.
|
||||||
|
*
|
||||||
|
* les affichages doivent être dans le bon ordre (fifo)
|
||||||
|
* le programme doit retourner correctement.
|
||||||
|
* valgrind doit être content.
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - thread_yield() depuis ou vers le main
|
||||||
|
* - thread_exit()
|
||||||
|
* - thread_join() avec récupération de la valeur de retour, ou sans
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void * thfunc(void *id)
|
||||||
|
{
|
||||||
|
int err, i;
|
||||||
|
for(i=0; i<10; i++) {
|
||||||
|
printf("%s yield vers un autre thread\n", (char*) id);
|
||||||
|
err = thread_yield();
|
||||||
|
assert(!err);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s terminé\n", (char*) id);
|
||||||
|
thread_exit(NULL);
|
||||||
|
return (void*) 0xdeadbeef; /* unreachable, shut up the compiler */
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
thread_t th1,th2,th3;
|
||||||
|
void *res;
|
||||||
|
int err, i;
|
||||||
|
|
||||||
|
err = thread_create(&th1, thfunc, "fils1");
|
||||||
|
assert(!err);
|
||||||
|
err = thread_create(&th2, thfunc, "fils2");
|
||||||
|
assert(!err);
|
||||||
|
err = thread_create(&th3, thfunc, "fils3");
|
||||||
|
assert(!err);
|
||||||
|
/* des switchs avec l'autre thread */
|
||||||
|
for(i=0; i<20; i++) {
|
||||||
|
printf("le main yield vers un fils\n");
|
||||||
|
err = thread_yield();
|
||||||
|
assert(!err);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = thread_join(th3, &res);
|
||||||
|
assert(!err);
|
||||||
|
assert(res == NULL);
|
||||||
|
err = thread_join(th2, NULL); /* on ignore ce code de retour */
|
||||||
|
assert(!err);
|
||||||
|
err = thread_join(th1, &res);
|
||||||
|
assert(!err);
|
||||||
|
assert(res == NULL);
|
||||||
|
|
||||||
|
printf("main terminé\n");
|
||||||
|
return 0;
|
||||||
|
}
|
66
tst/03-equity.c
Normal file
66
tst/03-equity.c
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test de l'équité de la cooperation via des thread_yield().
|
||||||
|
*
|
||||||
|
* plus le score est proche de 1, plus
|
||||||
|
* l'ordonnancement cooperatif est equitable.
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - thread_yield() depuis ou vers le main
|
||||||
|
* - retour sans thread_exit()
|
||||||
|
* - thread_join()
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned v[3];
|
||||||
|
static int fini = 0;
|
||||||
|
static double score = 0;
|
||||||
|
|
||||||
|
static void * thfunc(void *arg)
|
||||||
|
{
|
||||||
|
unsigned long myid = (unsigned long) arg;
|
||||||
|
int err, i;
|
||||||
|
for(i=0; i<1000 && !fini; i++) {
|
||||||
|
err = thread_yield();
|
||||||
|
assert(!err);
|
||||||
|
v[myid]++;
|
||||||
|
if (v[myid] == 1000 && !fini) {
|
||||||
|
fini = 1;
|
||||||
|
printf("le thread %lu a terminé\n", myid);
|
||||||
|
printf("nombres de yield: %u %u %u\n", v[0], v[1], v[2]);
|
||||||
|
score = (v[0]+v[1]+v[2]) / 3000.;
|
||||||
|
printf("score: %lf\n", score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
thread_t th1, th2;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
v[0] = v[1] = v[2] = 0;
|
||||||
|
err = thread_create(&th1, thfunc, (void*)0UL);
|
||||||
|
assert(!err);
|
||||||
|
err = thread_create(&th2, thfunc, (void*)1UL);
|
||||||
|
assert(!err);
|
||||||
|
|
||||||
|
thfunc((void*)2UL);
|
||||||
|
|
||||||
|
err = thread_join(th2, NULL);
|
||||||
|
assert(!err);
|
||||||
|
err = thread_join(th1, NULL);
|
||||||
|
assert(!err);
|
||||||
|
|
||||||
|
if ( score < .8) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
49
tst/11-join.c
Normal file
49
tst/11-join.c
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test du join, avec ou sans thread_exit.
|
||||||
|
*
|
||||||
|
* le programme doit retourner correctement.
|
||||||
|
* valgrind doit être content.
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - thread_exit()
|
||||||
|
* - retour sans thread_exit()
|
||||||
|
* - thread_join() avec récupération valeur de retour, avec et sans thread_exit()
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void * thfunc(void *dummy __attribute__((unused)))
|
||||||
|
{
|
||||||
|
thread_exit((void*)0xdeadbeef);
|
||||||
|
return NULL; /* unreachable, shut up the compiler */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void * thfunc2(void *dummy __attribute__((unused)))
|
||||||
|
{
|
||||||
|
return (void*) 0xbeefdead;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
thread_t th, th2;
|
||||||
|
int err;
|
||||||
|
void *res = NULL;
|
||||||
|
|
||||||
|
err = thread_create(&th, thfunc, NULL);
|
||||||
|
assert(!err);
|
||||||
|
err = thread_create(&th2, thfunc2, NULL);
|
||||||
|
assert(!err);
|
||||||
|
|
||||||
|
err = thread_join(th, &res);
|
||||||
|
assert(!err);
|
||||||
|
assert(res == (void*) 0xdeadbeef);
|
||||||
|
|
||||||
|
err = thread_join(th2, &res);
|
||||||
|
assert(!err);
|
||||||
|
assert(res == (void*) 0xbeefdead);
|
||||||
|
|
||||||
|
printf("join OK\n");
|
||||||
|
return 0;
|
||||||
|
}
|
48
tst/12-join-main.c
Normal file
48
tst/12-join-main.c
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test du join du main par un fils.
|
||||||
|
*
|
||||||
|
* le programme doit terminer correctement (faire le printf et s'arreter entièrement).
|
||||||
|
* valgrind doit être content.
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - thread_self() dans le main
|
||||||
|
* - thread_exit() dans le main
|
||||||
|
* - retour sans thread_exit()
|
||||||
|
* - thread_join() du main par un autre thread
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_PTHREAD
|
||||||
|
thread_t thmain = 0;
|
||||||
|
#else
|
||||||
|
thread_t thmain = NULL; /* si votre thread_t est un pointeur */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void * thfunc(void *dummy __attribute__((unused)))
|
||||||
|
{
|
||||||
|
void *res;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = thread_join(thmain, &res);
|
||||||
|
assert(!err);
|
||||||
|
assert(res == (void*) 0xdeadbeef);
|
||||||
|
printf("main terminé OK\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
thread_t th;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
thmain = thread_self();
|
||||||
|
|
||||||
|
err = thread_create(&th, thfunc, NULL);
|
||||||
|
assert(!err);
|
||||||
|
|
||||||
|
thread_exit((void*) 0xdeadbeef);
|
||||||
|
return 0; /* unreachable, shut up the compiler */
|
||||||
|
}
|
52
tst/21-create-many.c
Normal file
52
tst/21-create-many.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test de plein de create-destroy consécutifs.
|
||||||
|
*
|
||||||
|
* valgrind doit etre content.
|
||||||
|
* la durée du programme doit etre proportionnelle au nombre de threads donnés en argument.
|
||||||
|
* jusqu'à combien de threads cela fonctionne-t-il ?
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - thread_exit()
|
||||||
|
* - thread_join() avec récupération de la valeur de retour
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void * thfunc(void *dummy __attribute__((unused)))
|
||||||
|
{
|
||||||
|
thread_exit(NULL);
|
||||||
|
return (void*) 0xdeadbeef; /* unreachable, shut up the compiler */
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
thread_t th;
|
||||||
|
struct timeval tv1, tv2;
|
||||||
|
unsigned long us;
|
||||||
|
int err, i, nb;
|
||||||
|
void *res;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("argument manquant: nombre de threads\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb = atoi(argv[1]);
|
||||||
|
|
||||||
|
gettimeofday(&tv1, NULL);
|
||||||
|
for(i=0; i<nb; i++) {
|
||||||
|
err = thread_create(&th, thfunc, NULL);
|
||||||
|
assert(!err);
|
||||||
|
err = thread_join(th, &res);
|
||||||
|
assert(!err);
|
||||||
|
assert(res == NULL);
|
||||||
|
}
|
||||||
|
gettimeofday(&tv2, NULL);
|
||||||
|
us = (tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec);
|
||||||
|
printf("%d threads créés et détruits séquentiellement en %lu us\n", nb, us);
|
||||||
|
return 0;
|
||||||
|
}
|
54
tst/22-create-many-recursive.c
Normal file
54
tst/22-create-many-recursive.c
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test de plein de create-destroy récursif.
|
||||||
|
*
|
||||||
|
* valgrind doit etre content.
|
||||||
|
* la durée du programme doit etre proportionnelle au nombre de threads donnés en argument.
|
||||||
|
* jusqu'à combien de threads cela fonctionne-t-il ?
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - retour sans thread_exit()
|
||||||
|
* - thread_join() avec récupération de la valeur de retour
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void * thfunc(void *_nb)
|
||||||
|
{
|
||||||
|
unsigned long nb = (unsigned long) _nb;
|
||||||
|
if ((unsigned long) nb > 0) {
|
||||||
|
thread_t th;
|
||||||
|
int err;
|
||||||
|
void *res;
|
||||||
|
err = thread_create(&th, thfunc, ((char*)_nb)-1);
|
||||||
|
assert(!err);
|
||||||
|
err = thread_join(th, &res);
|
||||||
|
assert(!err);
|
||||||
|
assert(res == ((char*)_nb-1));
|
||||||
|
}
|
||||||
|
return _nb;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
unsigned long nb;
|
||||||
|
struct timeval tv1, tv2;
|
||||||
|
unsigned long us;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("argument manquant: nombre de threads\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb = atoi(argv[1]);
|
||||||
|
|
||||||
|
gettimeofday(&tv1, NULL);
|
||||||
|
thfunc((void*) nb);
|
||||||
|
gettimeofday(&tv2, NULL);
|
||||||
|
us = (tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec);
|
||||||
|
printf("%ld threads créés et détruits récursivement en %lu us\n", nb, us);
|
||||||
|
return 0;
|
||||||
|
}
|
71
tst/23-create-many-once.c
Normal file
71
tst/23-create-many-once.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test de plein de create, puis plein de join quand ils ont tous fini
|
||||||
|
*
|
||||||
|
* valgrind doit etre content.
|
||||||
|
* la durée du programme doit etre proportionnelle au nombre de threads donnés en argument.
|
||||||
|
* jusqu'à combien de threads cela fonctionne-t-il ?
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - thread_exit()
|
||||||
|
* - thread_join() sans récupération de la valeur de retour
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void * thfunc(void *dummy __attribute__((unused)))
|
||||||
|
{
|
||||||
|
thread_exit(NULL);
|
||||||
|
return (void*) 0xdeadbeef; /* unreachable, shut up the compiler */
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
thread_t *th;
|
||||||
|
int err, i, nb;
|
||||||
|
struct timeval tv1, tv2;
|
||||||
|
unsigned long us;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("argument manquant: nombre de threads\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb = atoi(argv[1]);
|
||||||
|
|
||||||
|
th = malloc(nb*sizeof(*th));
|
||||||
|
if (!th) {
|
||||||
|
perror("malloc");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gettimeofday(&tv1, NULL);
|
||||||
|
|
||||||
|
/* on cree tous les threads */
|
||||||
|
for(i=0; i<nb; i++) {
|
||||||
|
err = thread_create(&th[i], thfunc, NULL);
|
||||||
|
assert(!err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* on leur passe la main, ils vont tous terminer */
|
||||||
|
for(i=0; i<nb; i++) {
|
||||||
|
thread_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* on les joine tous, maintenant qu'ils sont tous morts */
|
||||||
|
for(i=0; i<nb; i++) {
|
||||||
|
err = thread_join(th[i], NULL);
|
||||||
|
assert(!err);
|
||||||
|
}
|
||||||
|
|
||||||
|
gettimeofday(&tv2, NULL);
|
||||||
|
us = (tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec);
|
||||||
|
|
||||||
|
free(th);
|
||||||
|
|
||||||
|
printf("%d threads créés et détruits tous d'un coup en %lu us\n", nb, us);
|
||||||
|
return 0;
|
||||||
|
}
|
73
tst/31-switch-many.c
Normal file
73
tst/31-switch-many.c
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test de plein de switch par plein de threads
|
||||||
|
*
|
||||||
|
* la durée du programme doit etre proportionnelle au nombre de threads et de yields donnés en argument
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - thread_yield() depuis ou vers le main
|
||||||
|
* - retour sans thread_exit()
|
||||||
|
* - thread_join() avec récupération de la valeur de retour
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void * thfunc(void *_nbyield)
|
||||||
|
{
|
||||||
|
int nbyield = (intptr_t) _nbyield;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<nbyield; i++)
|
||||||
|
thread_yield();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int nbth, i, err;
|
||||||
|
int nbyield;
|
||||||
|
thread_t *ths;
|
||||||
|
struct timeval tv1, tv2;
|
||||||
|
unsigned long us;
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
printf("arguments manquants: nombre de threads, puis nombre de yield\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbth = atoi(argv[1]);
|
||||||
|
nbyield = atoi(argv[2]);
|
||||||
|
|
||||||
|
ths = malloc(nbth * sizeof(thread_t));
|
||||||
|
assert(ths);
|
||||||
|
|
||||||
|
gettimeofday(&tv1, NULL);
|
||||||
|
|
||||||
|
for(i=0; i<nbth; i++) {
|
||||||
|
err = thread_create(&ths[i], thfunc, (void*) (intptr_t) nbyield);
|
||||||
|
assert(!err);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<nbyield; i++)
|
||||||
|
thread_yield();
|
||||||
|
|
||||||
|
for(i=0; i<nbth; i++) {
|
||||||
|
void *res;
|
||||||
|
err = thread_join(ths[i], &res);
|
||||||
|
assert(!err);
|
||||||
|
assert(res == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
gettimeofday(&tv2, NULL);
|
||||||
|
us = (tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec);
|
||||||
|
printf("%d yield avec %d threads: %ld us\n",
|
||||||
|
nbyield, nbth, us);
|
||||||
|
|
||||||
|
free(ths);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
64
tst/32-switch-many-join.c
Normal file
64
tst/32-switch-many-join.c
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test de plein de switch pendant que N-1 threads sont bloqués dans join
|
||||||
|
*
|
||||||
|
* La durée du programme doit etre proportionnelle au nombre de threads et de yields donnés en argument
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - thread_yield() depuis ou vers le main
|
||||||
|
* - retour sans thread_exit()
|
||||||
|
* - thread_join() avec récupération de la valeur de retour
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int nbyield;
|
||||||
|
|
||||||
|
static void * thfunc(void *_nbth)
|
||||||
|
{
|
||||||
|
int nbth = (intptr_t) _nbth;
|
||||||
|
if ((unsigned long) nbth > 0) {
|
||||||
|
thread_t th;
|
||||||
|
int err;
|
||||||
|
void *res;
|
||||||
|
err = thread_create(&th, thfunc, ((char*)_nbth)-1);
|
||||||
|
assert(!err);
|
||||||
|
err = thread_join(th, &res);
|
||||||
|
assert(!err);
|
||||||
|
assert(res == ((char*)_nbth)-1);
|
||||||
|
} else {
|
||||||
|
int i;
|
||||||
|
struct timeval tv1, tv2;
|
||||||
|
unsigned long us;
|
||||||
|
gettimeofday(&tv1, NULL);
|
||||||
|
for(i=0; i<nbyield; i++)
|
||||||
|
thread_yield();
|
||||||
|
gettimeofday(&tv2, NULL);
|
||||||
|
us = (tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec);
|
||||||
|
printf("%d yield avec plein de threads dans join: %ld us\n",
|
||||||
|
nbyield, us);
|
||||||
|
}
|
||||||
|
return _nbth;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
unsigned long nbth;
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
printf("arguments manquants: nombre de threads, puis nombre de yield\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbth = atoi(argv[1]);
|
||||||
|
nbyield = atoi(argv[2]);
|
||||||
|
|
||||||
|
thfunc((void*) nbth);
|
||||||
|
|
||||||
|
printf("%ld threads créés et détruits\n", nbth);
|
||||||
|
return 0;
|
||||||
|
}
|
74
tst/33-switch-many-cascade.c
Normal file
74
tst/33-switch-many-cascade.c
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test une chaine de thread avec un nombre decroissants de switch quand on descend dans la chaine.
|
||||||
|
*
|
||||||
|
* La durée du programme doit etre proportionnelle au nombre de total de yields = ( nbyield * nbthread * (nbthread+1) / 2 ) donnés en argument
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - thread_yield() depuis ou vers le main
|
||||||
|
* - retour sans thread_exit()
|
||||||
|
* - thread_join() avec récupération de la valeur de retour
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int nbyield;
|
||||||
|
static int nbthread;
|
||||||
|
|
||||||
|
static void * thfunc(void *_nbth)
|
||||||
|
{
|
||||||
|
int nbth = (intptr_t) _nbth;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((unsigned long) nbth > 0) {
|
||||||
|
thread_t th;
|
||||||
|
int err;
|
||||||
|
void *res;
|
||||||
|
err = thread_create(&th, thfunc, ((char*)_nbth)-1);
|
||||||
|
assert(!err);
|
||||||
|
|
||||||
|
for(i=0; i<(nbyield*nbth); i++) {
|
||||||
|
thread_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
err = thread_join(th, &res);
|
||||||
|
assert(!err);
|
||||||
|
assert(res == ((char*)_nbth)-1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(i=0; i<(nbyield*nbthread); i++) {
|
||||||
|
thread_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _nbth;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct timeval tv1, tv2;
|
||||||
|
unsigned long us;
|
||||||
|
unsigned long nbth;
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
printf("arguments manquants: nombre de threads, puis nombre de yield\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbthread = atoi(argv[1]);
|
||||||
|
nbth = nbthread;
|
||||||
|
nbyield = atoi(argv[2]);
|
||||||
|
|
||||||
|
gettimeofday(&tv1, NULL);
|
||||||
|
thfunc((void*) nbth);
|
||||||
|
gettimeofday(&tv2, NULL);
|
||||||
|
|
||||||
|
us = (tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec);
|
||||||
|
printf("%d yield avec plein de threads dans join: %ld us\n", nbyield, us);
|
||||||
|
|
||||||
|
printf("%ld threads créés et détruits\n", nbth);
|
||||||
|
return 0;
|
||||||
|
}
|
88
tst/51-fibonacci.c
Normal file
88
tst/51-fibonacci.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* fibonacci.
|
||||||
|
*
|
||||||
|
* la durée doit être proportionnel à la valeur du résultat.
|
||||||
|
* valgrind doit être content.
|
||||||
|
* jusqu'à quelle valeur cela fonctionne-t-il ?
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - thread_join() avec récupération de la valeur de retour
|
||||||
|
* - retour sans thread_exit()
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void * fibo(void *_value)
|
||||||
|
{
|
||||||
|
thread_t th, th2;
|
||||||
|
int err;
|
||||||
|
void *res = NULL, *res2 = NULL;
|
||||||
|
unsigned long value = (unsigned long) _value;
|
||||||
|
|
||||||
|
/* on passe un peu la main aux autres pour eviter de faire uniquement la partie gauche de l'arbre */
|
||||||
|
thread_yield();
|
||||||
|
|
||||||
|
if (value < 3)
|
||||||
|
return (void*) 1;
|
||||||
|
|
||||||
|
err = thread_create(&th, fibo, (void*)(value-1));
|
||||||
|
assert(!err);
|
||||||
|
err = thread_create(&th2, fibo, (void*)(value-2));
|
||||||
|
assert(!err);
|
||||||
|
|
||||||
|
err = thread_join(th, &res);
|
||||||
|
assert(!err);
|
||||||
|
err = thread_join(th2, &res2);
|
||||||
|
assert(!err);
|
||||||
|
|
||||||
|
return (void*)((unsigned long) res + (unsigned long) res2);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long fibo_checker( unsigned long n )
|
||||||
|
{
|
||||||
|
unsigned long a = 1;
|
||||||
|
unsigned long b = 1;
|
||||||
|
unsigned long c, i;
|
||||||
|
|
||||||
|
if ( n <= 2 ) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i=2; i<n; i++ ) {
|
||||||
|
c = a + b;
|
||||||
|
a = b;
|
||||||
|
b = c;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
unsigned long value, res;
|
||||||
|
struct timeval tv1, tv2;
|
||||||
|
double s;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("argument manquant: entier x pour lequel calculer fibonacci(x)\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = atoi(argv[1]);
|
||||||
|
gettimeofday(&tv1, NULL);
|
||||||
|
res = (unsigned long) fibo((void *)value);
|
||||||
|
gettimeofday(&tv2, NULL);
|
||||||
|
s = (tv2.tv_sec-tv1.tv_sec) + (tv2.tv_usec-tv1.tv_usec) * 1e-6;
|
||||||
|
|
||||||
|
if (res != fibo_checker(value)) {
|
||||||
|
printf("fibo(%lu) != %lu (FAILED)\n", value, fibo_checker(value));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
} else {
|
||||||
|
printf("fibo(%lu) = %lu en %e s\n", value, res, s );
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
104
tst/61-mutex.c
Normal file
104
tst/61-mutex.c
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test de faire une somme avec plein de thread sur un compteur partagé
|
||||||
|
*
|
||||||
|
* valgrind doit etre content.
|
||||||
|
* Le résultat doit etre égal au nombre de threads * 1000.
|
||||||
|
* La durée du programme doit etre proportionnelle au nombre de threads donnés en argument.
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - retour sans thread_exit()
|
||||||
|
* - thread_join() sans récupération de la valeur de retour
|
||||||
|
* - thread_mutex_init()
|
||||||
|
* - thread_mutex_destroy()
|
||||||
|
* - thread_mutex_lock()
|
||||||
|
* - thread_mutex_unloc()
|
||||||
|
*/
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
thread_mutex_t lock;
|
||||||
|
|
||||||
|
static void * thfunc(void *dummy __attribute__((unused)))
|
||||||
|
{
|
||||||
|
unsigned long i = 0;
|
||||||
|
int tmp;
|
||||||
|
|
||||||
|
for(i=0; i<1000;i++) {
|
||||||
|
/* Verrouille la section critique accédant a counter */
|
||||||
|
thread_mutex_lock(&lock);
|
||||||
|
tmp = counter;
|
||||||
|
thread_yield();
|
||||||
|
tmp++;
|
||||||
|
thread_yield();
|
||||||
|
counter = tmp;
|
||||||
|
thread_mutex_unlock(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
thread_t *th;
|
||||||
|
int err, i, nb;
|
||||||
|
struct timeval tv1, tv2;
|
||||||
|
unsigned long us;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("argument manquant: nombre de threads\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb = atoi(argv[1]);
|
||||||
|
|
||||||
|
if (thread_mutex_init(&lock) != 0) {
|
||||||
|
fprintf(stderr, "thread_mutex_init failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
th = malloc(nb*sizeof(*th));
|
||||||
|
if (!th) {
|
||||||
|
perror("malloc");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gettimeofday(&tv1, NULL);
|
||||||
|
/* on cree tous les threads */
|
||||||
|
for(i=0; i<nb; i++) {
|
||||||
|
err = thread_create(&th[i], thfunc, NULL);
|
||||||
|
assert(!err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* on leur passe la main, ils vont tous terminer */
|
||||||
|
for(i=0; i<nb; i++) {
|
||||||
|
thread_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* on les joine tous, maintenant qu'ils sont tous morts */
|
||||||
|
for(i=0; i<nb; i++) {
|
||||||
|
err = thread_join(th[i], NULL);
|
||||||
|
assert(!err);
|
||||||
|
}
|
||||||
|
gettimeofday(&tv2, NULL);
|
||||||
|
|
||||||
|
free(th);
|
||||||
|
thread_mutex_destroy(&lock);
|
||||||
|
|
||||||
|
us = (tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec);
|
||||||
|
|
||||||
|
if ( counter == ( nb * 1000 ) ) {
|
||||||
|
printf("La somme a été correctement calculée (%d * 1000 = %d) en %ld us\n", nb, counter, us);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Le résultat est INCORRECT: %d * 1000 != %d\n", nb, counter);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
122
tst/62-mutex.c
Normal file
122
tst/62-mutex.c
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test de faire une somme avec plein de thread sur un compteur partagé
|
||||||
|
*
|
||||||
|
* valgrind doit etre content.
|
||||||
|
* Les résultats doivent etre égals au nombre de threads * 1000.
|
||||||
|
* La durée du programme doit etre proportionnelle au nombre de threads donnés en argument.
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - retour sans thread_exit()
|
||||||
|
* - thread_join() sans récupération de la valeur de retour
|
||||||
|
* - thread_mutex_init()
|
||||||
|
* - thread_mutex_destroy()
|
||||||
|
* - thread_mutex_lock()
|
||||||
|
* - thread_mutex_unloc()
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NB_MUTEX 10
|
||||||
|
|
||||||
|
int counter[NB_MUTEX] = { 0 };
|
||||||
|
thread_mutex_t lock[NB_MUTEX];
|
||||||
|
|
||||||
|
static void * thfunc(void *_nb)
|
||||||
|
{
|
||||||
|
unsigned long nb = (unsigned long) _nb;
|
||||||
|
unsigned long i = 0;
|
||||||
|
int tmp;
|
||||||
|
|
||||||
|
int m = nb % NB_MUTEX;
|
||||||
|
|
||||||
|
for(i=0; i<1000;i++) {
|
||||||
|
/* Verrouille la section critique accédant a counter */
|
||||||
|
thread_mutex_lock(&lock[m]);
|
||||||
|
tmp = counter[m];
|
||||||
|
thread_yield();
|
||||||
|
tmp++;
|
||||||
|
thread_yield();
|
||||||
|
counter[m] = tmp;
|
||||||
|
thread_mutex_unlock(&lock[m]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
thread_t *th;
|
||||||
|
int i, nbthrd;
|
||||||
|
int err, nb;
|
||||||
|
struct timeval tv1, tv2;
|
||||||
|
unsigned long us;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("argument manquant: nombre de threads\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb = atoi(argv[1]);
|
||||||
|
nbthrd = nb * NB_MUTEX;
|
||||||
|
|
||||||
|
for(i=0; i<NB_MUTEX; i++) {
|
||||||
|
if (thread_mutex_init(&lock[i]) != 0) {
|
||||||
|
fprintf(stderr, "thread_mutex_init(lock[%d]) failed\n", i);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
th = malloc(nbthrd*sizeof(*th));
|
||||||
|
if (!th) {
|
||||||
|
perror("malloc");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gettimeofday(&tv1, NULL);
|
||||||
|
/* on cree tous les threads */
|
||||||
|
for(i=0; i<nbthrd; i++) {
|
||||||
|
err = thread_create(&th[i], thfunc, (void*)((intptr_t)i));
|
||||||
|
assert(!err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* on leur passe la main, ils vont tous terminer */
|
||||||
|
for(i=0; i<nb; i++) {
|
||||||
|
thread_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* on les joine tous, maintenant qu'ils sont tous morts */
|
||||||
|
for(i=0; i<nbthrd; i++) {
|
||||||
|
err = thread_join(th[i], NULL);
|
||||||
|
assert(!err);
|
||||||
|
}
|
||||||
|
gettimeofday(&tv2, NULL);
|
||||||
|
|
||||||
|
free(th);
|
||||||
|
for(i=0; i<NB_MUTEX; i++) {
|
||||||
|
thread_mutex_destroy(&lock[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = EXIT_SUCCESS;
|
||||||
|
for(i=0; i<NB_MUTEX; i++) {
|
||||||
|
if ( counter[i] == ( nb * 1000 ) ) {
|
||||||
|
printf("La somme %d a été correctement calculée: %d * 1000 = %d\n", i, nb, counter[i]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Le résultat %d est INCORRECT: %d * 1000 != %d\n", i, nb, counter[i]);
|
||||||
|
err = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(err == EXIT_SUCCESS) {
|
||||||
|
us = (tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec);
|
||||||
|
printf("Programme exécuté en %ld us\n", us);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
110
tst/71-preemption.c
Normal file
110
tst/71-preemption.c
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test de validation de la pré-emption (et par effet de bord de certaines implémentation de priorités)
|
||||||
|
*
|
||||||
|
* valgrind doit etre content.
|
||||||
|
* La durée du programme doit etre proportionnelle au nombre de threads donnés en argument.
|
||||||
|
* L'affichage doit être une série d'id alternée dans un ordre plus ou
|
||||||
|
* moin aléatoire, et non une suite de 0, puis de 1, puis de 2, ...
|
||||||
|
*
|
||||||
|
* support nécessaire:
|
||||||
|
* - thread_create()
|
||||||
|
* - retour sans thread_exit()
|
||||||
|
* - thread_join() sans récupération de la valeur de retour
|
||||||
|
*/
|
||||||
|
#define NB_ITER 100
|
||||||
|
#define ITER_LENGTH 1000000
|
||||||
|
|
||||||
|
static int fini = 0;
|
||||||
|
static double score = 0;
|
||||||
|
static long *values = NULL;
|
||||||
|
|
||||||
|
static void * thfunc( void *arg )
|
||||||
|
{
|
||||||
|
unsigned long i, j = 0;
|
||||||
|
int me = (intptr_t)arg;
|
||||||
|
|
||||||
|
for(i=0; i<NB_ITER;i++) {
|
||||||
|
for(j=0; j<ITER_LENGTH;j++) {
|
||||||
|
if (fini) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
values[me]++;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "%ld ", (intptr_t)arg );
|
||||||
|
}
|
||||||
|
fini = 1;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
thread_t *th;
|
||||||
|
int i, err, nb;
|
||||||
|
struct timeval tv1, tv2;
|
||||||
|
unsigned long us;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("argument manquant: nombre de threads\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb = atoi(argv[1]);
|
||||||
|
th = malloc(nb * sizeof(*th));
|
||||||
|
if (!th) {
|
||||||
|
perror("malloc(th)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
values = calloc( nb+1, sizeof(long) );
|
||||||
|
if (!values) {
|
||||||
|
perror("malloc(values)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gettimeofday(&tv1, NULL);
|
||||||
|
/* on cree tous les threads */
|
||||||
|
for(i=0; i<nb; i++) {
|
||||||
|
err = thread_create(&th[i], thfunc, (void*)((intptr_t)i));
|
||||||
|
assert(!err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On participe au réchauffement climatique */
|
||||||
|
thfunc( (void*)((intptr_t)nb) );
|
||||||
|
|
||||||
|
/* on les join tous, maintenant qu'ils sont tous morts */
|
||||||
|
score = values[nb];
|
||||||
|
for(i=0; i<nb; i++) {
|
||||||
|
err = thread_join(th[i], NULL);
|
||||||
|
assert(!err);
|
||||||
|
|
||||||
|
score += values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
gettimeofday(&tv2, NULL);
|
||||||
|
us = (tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec);
|
||||||
|
|
||||||
|
score = score / ( (double)(nb+1) * NB_ITER * ITER_LENGTH );
|
||||||
|
printf("\nscore: %lf\n", score );
|
||||||
|
|
||||||
|
printf("Programme exécuté en %ld us\n", us);
|
||||||
|
|
||||||
|
free(th);
|
||||||
|
free(values);
|
||||||
|
|
||||||
|
if ( score < .5 ) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Temps attendu pour le programme complet: %e us\n", us / score );
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
57
tst/81-deadlock.c
Normal file
57
tst/81-deadlock.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
/* test de detection d'un deadlock lors d'un cycle de thread qui joignent tous le suivant.
|
||||||
|
* main(th0) joine th1 qui joine th2 qui joine main.
|
||||||
|
* il faut qu'un join renvoie EDEADLK quand il detecte le deadlock, et les autres renvoient 0 normalement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static thread_t th0, th1, th2;
|
||||||
|
int totalerr = 0;
|
||||||
|
|
||||||
|
static void * thfunc2(void *dummy __attribute__((unused)))
|
||||||
|
{
|
||||||
|
void *res;
|
||||||
|
int err = thread_join(th0, &res);
|
||||||
|
printf("join th2->th0 = %d\n", err);
|
||||||
|
totalerr += err;
|
||||||
|
thread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void * thfunc1(void *dummy __attribute__((unused)))
|
||||||
|
{
|
||||||
|
void *res;
|
||||||
|
int err = thread_create(&th2, thfunc2, NULL);
|
||||||
|
assert(!err);
|
||||||
|
err = thread_join(th2, &res);
|
||||||
|
printf("join th1->th2 = %d\n", err);
|
||||||
|
totalerr += err;
|
||||||
|
thread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
void *res;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
th0 = thread_self();
|
||||||
|
|
||||||
|
err = thread_create(&th1, thfunc1, NULL);
|
||||||
|
assert(!err);
|
||||||
|
err = thread_join(th1, &res);
|
||||||
|
printf("join th0->th1 = %d\n", err);
|
||||||
|
totalerr += err;
|
||||||
|
printf("somme des valeurs de retour = %d\n", totalerr);
|
||||||
|
assert(totalerr == EDEADLK);
|
||||||
|
|
||||||
|
if ( totalerr == EDEADLK ) {
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user