Threads et atomiques avec C11



Documents pareils
1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

Introduction à la programmation concurrente

Introduction au langage C

Les processus légers : threads. Système L3, /31

Bases de programmation. Cours 5. Structurer les données

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Mesure de performances. [Architecture des ordinateurs, Hennessy & Patterson, 1996]

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

4. Outils pour la synchronisation F. Boyer, Laboratoire Lig


Cours de C++ François Laroussinie. 2 novembre Dept. d Informatique, ENS de Cachan

Programmation système de commandes en C

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

Threads. Threads. USTL routier 1

Exclusion Mutuelle. Arnaud Labourel Courriel : arnaud.labourel@lif.univ-mrs.fr. Université de Provence. 9 février 2011

Le prototype de la fonction main()

OS Réseaux et Programmation Système - C5

Conventions d écriture et outils de mise au point

COMPARAISONDESLANGAGESC, C++, JAVA ET

as Architecture des Systèmes d Information

J2SE Threads, 1ère partie Principe Cycle de vie Création Synchronisation

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Le traitement du temps

Plan du cours. Historique du langage Nouveautés de Java 7

Algorithmique et Programmation, IMA

Suivant les langages de programmation, modules plus avancés : modules imbriqués modules paramétrés par des modules (foncteurs)

Cours de Systèmes d Exploitation

Cours de C. Petits secrets du C & programmation avancée. Sébastien Paumier

Programme Compte bancaire (code)

École Polytechnique de Montréal. Département de Génie Informatique et Génie Logiciel. Cours INF2610. Contrôle périodique.

UE Programmation Impérative Licence 2ème Année

UE C avancé cours 1: introduction et révisions

Programmer en JAVA. par Tama

INTRODUCTION À LA PROGRAMMATION CONCURRENTE

Arguments d un programme

Info0604 Programmation multi-threadée. Cours 5. Programmation multi-threadée en Java

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

1 Mesure de la performance d un système temps réel : la gigue

Langage C. Patrick Corde. 22 juin Patrick Corde ( Patrick.Corde@idris.fr ) Langage C 22 juin / 289

Cours d Algorithmique et de Langage C v 3.0

Programmation système en C/C++

Processus! programme. DIMA, Systèmes Centralisés (Ph. Mauran) " Processus = suite d'actions = suite d'états obtenus = trace

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Programmation en langage C

Architecture des ordinateurs

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

Programmation C. Apprendre à développer des programmes simples dans le langage C

Logiciel de base. Première année ENSIMAG

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

Cours 2: Exclusion Mutuelle entre processus (lourds, ou légers -- threads)

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski

MISE A NIVEAU INFORMATIQUE LANGAGE C - EXEMPLES DE PROGRAMMES. Université Paris Dauphine IUP Génie Mathématique et Informatique 2 ème année

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Projet gestion d'objets dupliqués

Cours 6 : Tubes anonymes et nommés

Compression de Données - Algorithme de Huffman Document de Conception

Une introduction à Java

Problèmes liés à la concurrence

Programmation en C/C++

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

Introduction : les processus. Introduction : les threads. Plan

Programmation C. J.-F. Lalande. 15 novembre 2012

Java Licence Professionnelle CISII,

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs

SUPPORT DE COURS. Langage C

Introduction à l algorithmique et à la programmation M1102 CM n 3

LOG4430 : Architecture et conception avancée

3IS - Système d'exploitation linux - Programmation système

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

Machines virtuelles. Brique ASC. Samuel Tardieu Samuel Tardieu (ENST) Machines virtuelles 1 / 40

Introduction aux systèmes temps réel. Iulian Ober IRIT

Programmation système I Les entrées/sorties

Chapitre 1 : La gestion dynamique de la mémoire

Playing with ptrace() for fun and profit

INF 104 (SELC) Introduction au langage C

Synchro et Threads Java TM

Principes des langages de programmation INF 321. Eric Goubault

Cours Programmation Système

Java Licence Professionnelle CISII,

Traduction des Langages : Le Compilateur Micro Java

Auto-évaluation Programmation en Java

Programmation en C. École Nationale Supérieure de Techniques Avancées. Pierre-Alain Fouque et David Pointcheval

Cours de programmation avancée. Le langage C. Université du Luxembourg

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

A.P.I. Kuka Manuel de l utilisateur Version 0.0.5

Les structures de données. Rajae El Ouazzani

Cours d initiation à la programmation en C++ Johann Cuenin

Cours de Programmation Impérative: Zones de mémoires et pointeurs

ACTIVITÉ DE PROGRAMMATION

Support de Cours de Langage C. Christian Bac

Cette application développée en C# va récupérer un certain nombre d informations en ligne fournies par la ville de Paris :

Algorithmique I. Algorithmique I p.1/??

TD3: tableaux avancées, première classe et chaînes

STS SE. FreeRTOS. Programmation réseau WIFI. Programmation réseau. Socket Tcp. FlyPort smart Wi-Fi module

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Transcription:

Threads et atomiques avec C11 Jens Gustedt INRIA ICube, Université de Strasbourg 2015 Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 1 / 41

Outline 1 Introduction 2 Threads 3 Atomic 4 L exclusion mutuelle 5 Threads, plus de détails Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 2 / 41

Table of Contents Introduction 1 Introduction 2 Threads 3 Atomic 4 L exclusion mutuelle 5 Threads, plus de détails Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 3 / 41

Introduction C et les standards ISO la normalisation garantie la portabilité mapper un language de haut niveau sur n importe quel architecture insistez que votre compilateur suit le dernier standard! C[ ]est une norme ISO annés 70, créé par Kernighan et Richie C89, première normalisation, le grand succès C95, bugfix C99, C moderne, difficilement accueillit C11 Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 4 / 41

Introduction C et les standards ISO C99 tableaux avec tailles dynamiques spécification formelle du préprocesseur objets temporaires (compound literals) arithmétique complexe <tgmath.h>, fonctions mathématiques génériques C11 threads et ses structures de contrôle types atomiques fonctions génériques plusieurs ajustements mineurs Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 5 / 41

Table of Contents Threads 1 Introduction 2 Threads 3 Atomic 4 L exclusion mutuelle 5 Threads, plus de détails Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 6 / 41

Threads, definitions Threads Définition d un thread processus léger : plusieurs threads se partagent un même espace mémoire API C11 : threads.h pas encore implanté par tous : p99_thread.h utiliser une lib C alternative, musl http://www.musl-libc.org/ Comparaison avec processus lourds pas de séparation d état entre threads plus rapide à lancer il n y a pas de hiérarchie entre threads, tous sont égaux (sauf un) exit et return de main termine tous les threads d un processus Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 7 / 41

Threads, interfaces Threads Gestion des threads C11 / Thread start and stop / typedef int (*thrd_start_t)(void*); int thrd_create(thrd_t *, thrd_start_t, void *); void thrd_exit (int); / Thread information / thrd_t thrd_current(void); int thrd_equal(thrd_t, thrd_t); / Thread coordination / int thrd_join(thrd_t, int*); int thrd_detach(thrd_t); Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 8 / 41

Threads, interfaces Threads Structures de contrôle threads C11 type aussi thrd_t identification de thread tss_t thread specific storage _Thread_local mtx_t exclusion mutuelle cnd_t variables de condition once_flag initialisation unique atomic_flag échange sans attente _Atomic Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 9 / 41

Threads Threads, exemple de base fonction exécutée par chaque thread / User type pour structuré les infos pass es aux threads / typedef struct thrd_info thrd_info; struct thrd_info { unsigned num; double val; }; int mythreadfunction(void* arg) { / Interprétation de arg en type voulu, no cast! / thrd_info* info = arg; printf("i am %u with value %g\n", info->num, info->val); / retour d un etat `a qqn qui s int eresse / return info->val > 1.0; } Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 10 / 41

Threads Threads, exemple de base int main(int argc, char *argv[ ]) { unsigned const n = argc-1; thrd_info info[n]; thrd_t id[n]; for (unsigned i = 0; i < n; ++i) { info[i] = (thrd_info){.num = i,.val = strtod(argv[i+1], 0) }; thrd_create(&id[i], mythreadfunction, &info[i]); } for (unsigned i = 0; i < n; ++i) { int ret = 0; thrd_join(id[i], &ret); printf("thread %u returned %d\n", i, ret); } return EXIT_SUCCESS; } Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 11 / 41

Threads Threads, exemple de threads détachés / cette version a une fuite, manque free(info) / static thrd_info * info = 0; int main(int argc, char *argv[ ]) { unsigned const n = argc-1; / doit être alloué sur le tas / info = malloc(sizeof(thrd_info[n])); for (unsigned i = 0; i < n; ++i) { thrd_t id; info[i] = (thrd_info){.num = i,.val = strtod(argv[i+1], 0) }; thrd_create(&id, mythreadfunction, &info[i]); thrd_detach(id); } / return de main ferait terminer tous le process / thrd_exit(exit_success); } Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 12 / 41

Threads Threads, exemple de threads détachés / sans fuite de mémoire / static thrd_info * info = 0; static void cleanup(void) { puts("terminating execution"); free(info); } int main(int argc, char *argv[ ]) { atexit(cleanup); unsigned const n = argc-1; / doit ^etre alloué sur le tas / info = malloc(sizeof(thrd_info[n]));... / return de main ferait terminer tous le process / thrd_exit(exit_success); } Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 13 / 41

Threads Threads, problèmes de cohérence Le problème de base : la variable critique ++a; / plusieurs instructions? / a += 1; / plusieurs instructions? / a = a + 1; / plusieurs instructions! / en amd64 avec une var locale, si chance : addl $1, -4(%rbp) pas de chance : movl a(%rip), %eax addl $1, %eax /* interruption? */ movl %eax, a(%rip) /* écrasement! */ Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 14 / 41

Threads Threads, problèmes de cohérence «thread safety» dangereux: variables globales variables locales static libc ctime, asctime : ne sont pas thread-safe car elles retournent un état statique printf et similaire sont thread-safe. read the manual! Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 15 / 41

Table of Contents Atomic 1 Introduction 2 Threads 3 Atomic 4 L exclusion mutuelle 5 Threads, plus de détails Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 16 / 41

problèmes de base Atomic Comment garantir la cohérence en cas de threads? Problèmes : multiples instructions assembler pour une instruction C multiples étapes pipeline pour une instruction assembler délais de visibilité de modifications d objets inter thread modification thread 1 mémoire visibilité thread 2 qqs centaines de cycles probabilité d interruption est non-nulle execution de parties d instructions dans un ordre quelconque Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 17 / 41

Atomic Atomic, le noveau API C11 comme qualificateur syntaxe : _Atomic toto = ATOMIC_VAR_INIT(007); implanté à partir : gcc v. 4.9, clang v. 3.5 chargement et écriture : évaluation (), affectation = arithmetique : opérateurs classiques ++, --, +=... comme spécificateur syntaxe : _Atomic(unsigned) toto = ATOMIC_VAR_INIT(007); support compilateur peut être émulé : p99.gforge.inria.fr chargement et écriture : atomic_load, atomic_store arithmétique : atomic_fetch_add échange conditionnel : atomic_compare_exchange_weak Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 18 / 41

Atomic ordonnoncement mémoire cohérence séquentielle Les atomics comme vues ici ont une cohérence sequentielle. «as-if» un ordre total entre threads sur les opérations atomics. sur la plupart des architectures synchronization des caches trés couteux en termes de cycles horloge (centaines) à utiliser avec modération autre modèles de cohérence memory_order peut être relâché pour chaque opération relaxed : seul garantie est l intégralité acquire/release : pour éviter la synchro complète Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 19 / 41

Atomic Atomic, le noveau API C11 utilisation dans la fonction des threads #include <stdatomic.h> unsigned volatile _Atomic count = ATOMIC_VAR_INIT(0); int mythreadfunction(void* arg) { / Interpr etation de arg en type voulu / thrd_info* info = arg; unsigned here = count++; printf("i am %u with counter %u, now %u\n", info->num, here, count); return info->num == here; } Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 20 / 41

Atomic Atomic, le noveau API C11 principales fonctions / macros C atomic_load(volatile A *obj); void atomic_store(volatile A *obj, C des); C atomic_exchange(volatile A *obj, C des); / échanges conditionels / _Bool atomic_compare_exchange_strong(volatile A *obj, C *attendu, C des); _Bool atomic_compare_exchange_weak(volatile A *obj, C *attendu, C des); / arithmetique / C atomic_fetch_add(volatile A *obj, M oper); C atomic_fetch_sub(volatile A *obj, M oper); / opération de bits / C atomic_fetch_and(volatile A *obj, M oper); C atomic_fetch_or(volatile A *obj, M oper); C atomic_fetch_xor(volatile A *obj, M oper); Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 21 / 41

Atomic Atomic, flags atomiques un type simple pour la gestion inter-threads : atomic_flag que deux interfaces de fonction, pas d opérateurs deux états : clear et set l état n est que observable en le modifiant / initialise à l état "clear" / atomic_flag flag = ATOMIC_FLAG_INIT; / assure l état "set" et retourne la valeur précédente / bool atomic_flag_test_and_set(volatile atomic_flag *); / inconditionnellement à l état "clear" / void atomic_flag_clear(volatile atomic_flag *); Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 22 / 41

L exclusion mutuelle Table of Contents 1 Introduction 2 Threads 3 Atomic 4 L exclusion mutuelle 5 Threads, plus de détails Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 23 / 41

L exclusion mutuelle Section critique variable critique une variable qui peut être modifiée par au moins un thread peut être lue par plusieurs threads Ce sont souvent des variables globales, ou passées en paramètre à la création du thread. section critique (SC) une partie d un programme parallèle qui ne doit pas être exécutée par plus qu un seul thread à la fois Ce sont souvent des parties de code qui accèdent aux variables critiques. Si congestion : attente imposée à l entrée dans la SC Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 24 / 41

L exclusion mutuelle SC avec peu de support matériel Algo de Peterson pour thread P id (limité à 2 thread, id = 0, 1) static bool volatile inside[2] = { false, false, }; static bool volatile prio = false; inside[id] = true; prio =!id; do { / busy wait / } while (inside[!id] && prio ==!id); / section critique / inside[id] = false; Attention: volatile, sinon les lectures au while peuvent être éliminés suppose une l écriture atomic de valeurs Booléens suppose une visibilité de l écriture "immédiate" sans utilisation d atomic, ce n est pas portable Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 25 / 41

L exclusion mutuelle SC re-écrit avec _Atomic static _Atomic(bool) volatile inside[2] = { ATOMIC_VAR_INIT(false), ATOMIC_VAR_INIT(false), }; static _Atomic(bool) volatile prio = ATOMIC_VAR_INIT(false); inside[id] = true; prio =!id; do { / busy wait / } while (inside[!id] && prio ==!id); / section critique / inside[id] = false; Remarque : volatile est toujours nécessaire Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 26 / 41

L exclusion mutuelle SC avec atomic_flag static atomic_flag flag = ATOMIC_FLAG_INIT; do { / busy wait / } while (atomic_flag_test_and_set(&flag)); / section critique / atomic_flag_clear(&flag); Avantages : facile à implanter (flag est local, initialisation statique) fonctionne pour plus que 2 threads rapide en situation de non-congestion adapté si la SC est quelques lignes / instructions Attention : c est une attente active Remarque : volatile n est pas nécessaire, ici, car appel à fonction. Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 27 / 41

L exclusion mutuelle Attente inactive attente inconditionnel : mutex int mtx_init(mtx_t *, int); int mtx_destroy(mtx_t *); int mtx_lock(mtx_t *); int mtx_trylock(mtx_t *); int mtx_unlock(mtx_t *); struct timespec { time_t tv_sec; long tv_nsec; }; int mtx_timedlock(mtx_t *, struct timespec *habs); Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 28 / 41

L exclusion mutuelle Attente inactive SC avec mtx_t / Hors fonction, visible a tous thread / mtx_t mutex; / interieur de main avant tous threads / mtx_init(&mutex, mtx_plain); / interieur des threads, attente inactive / mtx_lock(&mutex); / section critique / mtx_unlock(&mutex); Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 29 / 41

L exclusion mutuelle Attente inactive SC avec mtx_t Avantages: adapté si la SC est longue et/ou beaucoup de congestion c est une attente inactive Désavantages: initialization dynamique (mais v. POSIX) changement de contexte = noyau Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 30 / 41

L exclusion mutuelle Attente inactive Propriétés des mutex Le deuxième paramètre de mtx_init est une combinaison de enum { mtx_plain, mtx_recursive, mtx_timed, }; pour définir différents propriétés des mutex. Mutex "timed" mtx_timed : le mutex permet l appel de la fonction struct timespec { time_t tv_sec; long tv_nsec; }; int mtx_timedlock(mtx_t *, struct timespec *habs); Ceci permet de regagner contrôle après le temps demandé, même si le verrou n est pas acquit. Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 31 / 41

L exclusion mutuelle Attente inactive Mutex récursif mtx_recursive se combine avec mtx_plain ou mtx_timed : mtx_plain mtx_recursive mtx_timed mtx_recursive sans mtx_recursive : ne peuvent pas être verrouilles plusieurs fois par le même thread sans mtx_unlock mtx_recursive : autant d appels mtx_lock et mtx_unlock just à ce que le verrou est libéré par le thread Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 32 / 41

L exclusion mutuelle Attente inactive attente conditionnelle avec mutex mtx_lock(&mutex); while (blabla!= 42) { mtx_unlock(&mutex); / un autre thread assure la condition / mtx_lock(&mutex); } / section critique avec garantie sur la condition / mtx_unlock(&mutex); doublement mauvais c est encore une attente active plein de switch de contexte entre espace utilisateur et noyaud Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 33 / 41

L exclusion mutuelle Attente inactive attente conditionnelle : conditions int cnd_init(cnd_t *); void cnd_destroy(cnd_t *); int cnd_wait(cnd_t *, mtx_t *); int cnd_timedwait(cnd_t *, mtx_t *, struct timespec const *); int cnd_signal(cnd_t *cond); int cnd_broadcast(cnd_t *cond); Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 34 / 41

L exclusion mutuelle SC avec mtx_t et cnd_t Hors fonction, visible a tous thread mtx_t mutex; cnd_t cond; interieur de main avant tous threads mtx_init(&mutex, mtx_plain); cnd_init(&cond); Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 35 / 41

L exclusion mutuelle SC avec mtx_t et cnd_t attente inactive : cnd_wait liaison temporaire entre cond et mutex pendant l attente mutex est relaché en revenant le mutex est acquis de nouveau Attention : spurious wakeups cnd_wait doit toujours être dans une boucle qui teste la vrai condition Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 36 / 41

L exclusion mutuelle SC avec mtx_t et cnd_t interieur d un des threads, attente inactive mtx_lock(&mutex); / test de la condition et blocage possible / while (blabla!= 42) cnd_wait(&cond, &mutex); / section critique avec garantie sur la condition / mtx_unlock(&mutex); interieur d un autre thread, signalisation mtx_lock(&mutex); / assure la condition / blabla = 42; / reveille tous les threads en attente / cnd_broadcast(&cond); mtx_unlock(&mutex); Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 37 / 41

Threads, plus de détails Table of Contents 1 Introduction 2 Threads 3 Atomic 4 L exclusion mutuelle 5 Threads, plus de détails Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 38 / 41

Threads, plus de détails Threads, séparation des états variables local d un thread le plus important: garder les variables en local (auto) si ce n est pas possible _Thread_local (C11) thread (gcc) ou thread-specific storage, TSS typedef void (*tss_dtor_t)(void*); int tss_create(tss_t *key, tss_dtor_t dtor); void tss_delete(tss_t key); void *tss_get(tss_t key); int tss_set(tss_t key, void *val); Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 39 / 41

Threads, plus de détails Threads, séparation des états initialisation faire le plus possible de l initialisation dans le main si ce n est pas possible once_flag void call_once(once_flag *flag, void (*func)(void)); char* text = 0; void myinitfunc(void) { text = malloc(bignumber); } / intérieur aux fonctions de thread / static once_flag once = ONCE_FLAG_INIT; call_once(&once, myinitfunc); Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 40 / 41

Threads, plus de détails Threads, séparation des états finalisation char* text = 0; void myfinalfunc(void) { free(text); } void myinitfunc(void) { atexit(myfinalfunc); text = malloc(bignumber); } / intérieur aux fonctions de thread / static once_flag once = ONCE_FLAG_INIT; call_once(&once, myinitfunc); Jens Gustedt (INRIA) Threads et atomiques avec C11 2015 41 / 41