Ε-85: Ειδικά Θέµατα Λογισµικού

Σχετικά έγγραφα
Ειδικά Θέµατα. Αντικείµενα Ιδιοτήτων. Ε-85: Ειδικά Θέµατα Λογισµικού. Αντικείµενα ιδιοτήτων (attributes objects)

Προγραµµατισµός Νηµάτων. Αρχικοποίηση µιας Φοράς pthread_once_t once_block = PTHREAD_ONCE_INIT; pthread_mutex_t mutex;

Ε-85: Ειδικά Θέµατα Λογισµικού

Νήµατα. Πολύ σηµαντικό

Ε-85: Ειδικά Θέµατα Λογισµικού

Παράλληλη Επεξεργασία

Προγραμματισμός συστημάτων UNIX/POSIX. Σήματα (signals)

Εργαστήριο 14. Συγχρονισμός Νημάτων (χρήση pthread_mutex_t, pthread_cond_t)

Προγραμματισμός Ι (ΗΥ120)

Παράλληλη Επεξεργασία

Ανάπτυξη και Σχεδίαση Λογισμικού

ΝΗΜΑΤΑ - ΕΡΓΑΣΤΗΡΙΟ 1 - ΣΗΜΕΙΩΣΕΙΣ

26/3/2012 Προγραμματισμός συστημάτων κοινόχρηστης μνήμης (Ι) Β. Δημακόπουλος

Εισαγωγή εκτελέσιμου κώδικα σε διεργασίες

Θέτοντας και επιστρέφοντας την τιµή της προτεραιότητας διεργασίας

Λειτουργικά Συστήματα

Κατηγορίες Νηµάτων. Νήµατα Επιπέδου Πυρήνα. Νήµατα Επιπέδου Χρήστη. «Νήµατα Επιπέδου Χρήστη» Ε-85: Ειδικά Θέµατα Λογισµικού

NIKOΛΑΟΣ ΝΤΙΡΛΗΣ 5ο ΦΡΟΝΤΙΣΤΗΡΙΟ ΑΙΘΟΥΣΑ Β4

Προγραμματισμός με Κοινόχρηστο Χώρο Διευθύνσεων 4

Νήµαταστην Java. Συγχρονισµός νηµάτων Επικοινωνία νηµάτων Εκτελέσιµα αντικείµενα Νήµατα δαίµονες Οµάδες νηµάτων. Κατανεµηµένα Συστήµατα 11-1

Εισαγωγή στον Προγραμματισμό (με. τη C)

Εισαγωγή στον Προγραµµατισµό. Διάλεξη 3 η : Επίλυση Προβληµάτων Χειµερινό Εξάµηνο 2011

Συστήματα Παράλληλης και Κατανεμημένης Επεξεργασίας

Δομημένος Προγραμματισμός

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ. Διεργασίες και Νήματα Εργαστηριακές Ασκήσεις

Παρουσίαση 5 ης Άσκησης:

Παρουσίαση 5 ης Άσκησης:

#include <stdlib.h> Α. [-128,127] Β. [-127,128] Γ. [-128,128]

Περιεχόμενα. Πρόλογος... 21

Εργαστήριο ΔΙΕΡΓΑΣΙΕΣ - ΔΙΑΧΕΙΡΙΣΗ

Ιδιοκτησία Αντικειµένου

Διάλεξη 13η: Δυναμική Διαχείρηση Μνήμης, μέρος 1

Λειτουργικά Συστήματα

Λύβας Χρήστος Αρχική επιµέλεια Πιτροπάκης Νικόλαος και Υφαντόπουλος Νικόλαος

Προγραμματισμός Ι. Δυναμική Διαχείριση Μνήμης. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Εθνικό Μετσόβιο Πολυτεχνείο Σχολή Ηλεκτρολόγων Μηχ. και Μηχανικών Υπολογιστών Εργαστήριο Υπολογιστικών Συστημάτων. Συγχρονισμός

Εθνικό Μετσόβιο Πολυτεχνείο Σχολή Ηλεκτρολόγων Μηχ. και Μηχανικών Υπολογιστών Εργαστήριο Υπολογιστικών Συστημάτων. Συγχρονισμός

ΠΑΝΕΠΙΣΤΗΜΙΟ ΘΕΣΣΑΛΙΑΣ ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ

Ανάπτυξη και Σχεδίαση Λογισμικού

ΕΘΝΙΚΟ ΚΑΙ ΚΑΠΟΔΙΣΤΡΙΑΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ & ΤΗΛΕΠΙΚΟΙΝΩΝΙΩΝ ΧΕΙΜΕΡΙΝΟ ΕΞΑΜΗΝΟ ΜΑΘΗΜΑ: ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ

Προγραμματισμός Υπολογιστών & Υπολογιστική Φυσική

Προγραμματισμός συστημάτων UNIX/POSIX

Δίκτυα Επικοινωνιών ΙΙ: Network Programming UDP Sockets, Signals

Δημιουργία & Τερματισμός Διεργασιών. Προγραμματισμός II 1

Εισαγωγή στον Προγραμματισμό

Λειτουργικά Συστήματα. Ενότητα # 10: Προγραμματισμός UNIX Διδάσκων: Γεώργιος Ξυλωμένος Τμήμα: Πληροφορικής

Δείκτες (Pointers) Ένας δείκτης είναι μια μεταβλητή με τιμή μια διεύθυνση μνήμης. 9.8

Κλάσεις και Αντικείµενα

Πληροφορική & Τηλεπικοινωνίες K18 - Υλοποίηση Συστηµάτων Βάσεων εδοµένων Εαρινό Εξάµηνο

είκτες και Πίνακες (2)

Δυναμική δέσμευση και αποδέσμευση μνήμης. Προγραμματισμός II 1

Διάλεξη 3η: Τύποι Μεταβλητών, Τελεστές, Είσοδος/Έξοδος

Κατανεμημένα Συστήματα

Προγραμματισμός Ι. Εγγραφές. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Α. unsigned int Β. double. Γ. int. unsigned char x = 1; x = x + x ; x = x * x ; x = x ^ x ; printf("%u\n", x); Β. unsigned char

Καρακασίδης Αλέξανδρος Καστίδου Γεωργία Παπαφώτη Μαρία Πέτσιος Κων/νος Στέφανος Σαλτέας Καλογεράς Παναγιώτης. Threads in Java ΝΗΜΑΤΑ ΣΤΗ JAVA

Η γλώσσα προγραμματισμού C

Προγραμματισμός Η/Υ (ΤΛ2007 )

Σχεδίαση Γλωσσών Προγραμματισμού. Εαρινό Εξάμηνο Lec03 18/02/2019

Εισαγωγή στην C. Μορφή Προγράµµατος σε γλώσσα C

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #4

2η Προγραµµατιστική Εργασία

Ανάπτυξη Μεγάλων Εφαρµογών στη Γλώσσα C (2)

Κεφάλαιο , 3.2: Συναρτήσεις II. ( ιάλεξη 12) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

Περίληψη. Υπερυπολογιστές. Υπολογιστικά προβλήµατα. TOP 500 (Ιούνιος 2007) TOP 500 (Ιούνιος 2009) Ε-85: Ειδικά Θέµατα Λογισµικού

Εισαγωγή στον Προγραµµατισµό. Διάλεξη 2 η : Βασικές Έννοιες της γλώσσας προγραµµατισµού C Χειµερινό Εξάµηνο 2011

Ορισµός Νήµα (thread) είναι µια ακολουθιακή ροή ελέγχου (δηλ. κάτι που έχει αρχή, ακολουθία εντολών και τέλος) σ ένα

Ανάπτυξη Μεγάλων Εφαρµογών στη Γλώσσα C (Programming in the large)

Παράλληλη Επεξεργασία

Περιεχόμενα. Πρόλογος... 17

Χρήση των POSIX Threads

Μεθόδων Επίλυσης Προβλημάτων

Προγραμματισμός συστημάτων UNIX/POSIX

ΕΠΛ232 Προγραμματιστικές Τεχνικές και Εργαλεία Δυναμική Δέσμευση Μνήμης και Δομές Δεδομένων (Φροντιστήριο)

Κεφάλαιο , 3.2: Συναρτήσεις II. (Διάλεξη 12)

Σε γενικές γραμμές, είναι καλή πρακτική να γράϕουμε προγράμματα C που αποτελούνται από πολλές και μικρές συναρτήσεις, παρά από λίγες και μεγάλες.

Εικονική Μνήμη (Virtual Memory) Προγραμματισμός II 1

Η γλώσσα προγραμματισμού C

Εισαγωγή στον Προγραμματισμό

Chapter 2. Εντολές : Η γλώσσα του υπολογιστή. (συνέχεια) Η διασύνδεση Υλικού και λογισμικού David A. Patterson και John L.

ΙΩΑΝΝΗΣ ΚΩΝΣΤΑΝΤΙΝΟΥ 2ο ΦΡΟΝΤΙΣΤΗΡΙΟ ΠΑΡΑΣΚΕΥΗ 26 ΟΚΤΩΒΡΙΟΥ 2012 ΑΙΘΟΥΣΑ Β4

Δημιουργία & Τερματισμός Διεργασιών. Προγραμματισμός II 1

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΜΑΘΗΜΑ 6 Ο. Συναρτήσεις Τοπικές, καθολικές, στατικές μεταβλητές Μεταβλητές τύπου extern και register Αναδρομή

Η βασική συνάρτηση προγράμματος main()

Λειτουργικά Συστήματα

ιεργασίες και νήµατα Προγραµµατισµός ΙΙΙ 1 lalis@inf.uth.gr

lab13grades Άσκηση 2 -Σωστά απελευθερώνετε ολόκληρη τη λίστα και την κεφαλή

Προγραμματισμός Ι. Είσοδος/Έξοδος. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Ε-85: Ειδικά Θέµατα Λογισµικού

Ε-85: Ειδικά Θέµατα Λογισµικού

Υ07 Παράλληλα Συστήματα & 29/3/2016 Προγραμματισμός συστημάτων κοινόχρηστης μνήμης (Ι)

Εικονική Μνήμη (Virtual Memory) Προγραμματισμός II 1

Δομημένος Προγραμματισμός (ΤΛ1006)

Διάλεξη 13: Δομές Δεδομένων ΙΙ (Ταξινομημένες Λίστες)

Διαδικαστικός Προγραμματισμός

Α Β Γ static; printf("%c\n", putchar( A +1)+2); B DB BD. int i = 0; while (++i); printf("*");

Κεφάλαιο VΙΙ (λίγο διαφορετικό)

B. Ενσωμάτωση Ιθαγενών Μεθόδων

Συναρτήσεις-Διαδικασίες

Ανάπτυξη και Σχεδίαση Λογισμικού

Transcript:

Ε-85: Ειδικά Θέµατα Λογισµικού Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων Χειµερινό Εξάµηνο 2009-10 «Ειδικά Θέµατα Προγραµµατισµού Νηµάτων» Παναγιώτης Χατζηδούκας (Π.Δ. 407/80) E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 1

ΕιδικάΘέµατα Αντικείµενα ιδιοτήτων (attributes objects) Ιδιότητες νηµάτων Ιδιότητες των mutexes Ιδιότητες µεταβλητών συνθήκης Αρχικοποίηση µιας φοράς (one-time initialization) Ιδιωτικά δεδοµένα νήµατος Ακύρωση νηµάτων (cancellation) Χειριστές καθαρισµού Σήµατα Σηµαφόροι E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 2

ΑντικείµεναΙδιοτήτων ηµιουργίανηµάτων και δυναµική αρχικοποίηση mutexesκαι µεταβλητών συνθήκης µε το δεύτερο όρισµα στην αντίστοιχη ρουτίνα ίσο µε NULL Το όρισµα είναι δείκτης σε ένα αντικείµενο ιδιοτήτων Τιµή NULL σηµαίνει την εξ ορισµού τιµή των ιδιοτήτων (όπως στην στατική αρχικοποίηση) Ένα αντικείµενο ιδιοτήτων µπορεί να θεωρηθεί ως µια ιδιωτική δοµή δεδοµένων. Η προσπέλαση των πεδίων της (για ανάγνωση και εγγραφή) δεν πραγµατοποιείται άµεσα αλλά πάντα µέσω κατάλληλων ρουτινών pthread_attr_getstacksize, pthread_attr_setstacksize E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 3

pthread_attr_t attr; ΙδιότητεςΝηµάτων int pthread_attr_init(&attr); int pthread_attr_destroy(&attr); ήλωση, αρχικοποίηση και καταστροφή ενός αντικειµένου ιδιοτήτων νηµάτων int pthread_attr_getdetachstate(&attr, (int *) &ds); int pthread_attr_setdetachstate(&attr, (int) ds); Καθορισµός αν ένα νήµα είναι αποδεσµευµένο ή όχι PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_DETACHED E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 4

ΙδιότητεςΝηµάτων int pthread_attr_getstacksize(&attr, (size_t *) &ss); int pthread_attr_setstacksize(&attr, (size_t) ss); Καθορισµός του µεγέθους της στοίβας ενός νήµατος Ελάχιστο µέγεθος στοίβας: PTHREAD_STACK_MIN int pthread_attr_getstackaddr(&attr, (void **) &sa); int pthread_attr_setstacksize(&attr, (void *) sa); Καθορισµός της στοίβας ενός νήµατος Η µνήµη για τη στοίβα δεσµεύεται ρητά (π.χ. malloc) Πρέπει να είναι τουλάχιστον PTHREAD_STACK_MIN εν παρέχει πλήρη µεταφερσιµότητα E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 5

ΙδιότητεςΝηµάτων int pthread_attr_getscope(&attr, (int *) &cs); int pthread_attr_setscope(&attr, (int_t) cs); Καθορισµός του χώρου όπου δροµολογείται ένα νήµα (διεργασία ή λειτουργικό σύστηµα) υνατές επιλογές: PTHREAD_SCOPE_PROCESS, PTHREAD_SCOPE_SYSTEM int pthread_attr_getschedpolicy(&attr, (int *) &sp); int pthread_attr_setschedpolicy(&attr, (int) sp); Καθορισµός της πολιτικής δροµολόγησης µε την οποία θα εκτελεστούν τα νήµατα υνατές επιλογές: SCHED_FIFO,SCHED_RR,SCHED_OTHER Η προκαθορισµένη πολιτική εξαρτάται από την υλοποίηση E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 6

ΙδιότητεςΜutexes pthread_mutexattr_t attr; int pthread_mutexattr_init(&attr); int pthread_mutexattr_destroy(&attr); ήλωση, αρχικοποίηση και καταστροφή ενός αντικειµένου ιδιοτήτων mutexes #ifdef _POSIX_THREAD_PROCESS_SHARED int pthread_mutexattr_getpshared(&attr, (int *) &ps); int pthread_mutexattr_setpshared(&attr, (int) ps); #endif ιαµοίραση ή µη ενός mutex µεταξύ διαφορετικών διεργασίων ps: PTHREAD_PROCESS_{PRIVATE, SHARED} To mutexπρέπει να έχει δεσµευτεί σε περιοχή µνήµης που είναι κοινή µεταξύ των διεργασιών E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 7

Ιδιότητες Mutexes int pthread_mutexattr_gettype(&attr, (int *) &type); int pthread_mutexattr_settype(&attr, (int ) type); Καθορισµός ορισµός του τύπου ενός mutexπου δηµιουργείται µε το αντικείµενο ιδιοτήτων attr υνατές επιλογές PTHREAD_MUTEX_NORMAL: ταχύτερη υλοποίηση χωρίς έλεγχο σφαλµάτων PTHREAD_MUTEX_RECURSIVE: ένα mutexµπορεί να κλειδωθεί πολλές φορές από το ίδιο νήµα PTHREAD_MUTEX_ERRORCHECK: για debugging κατά την ανάπτυξη εφαρµογών PTHREAD_MUTEX_DEFAULT: αντιστοιχίζεται από την εκάστοτε πλατφόρµα σε κάποια από τις παραπάνω επιλογές (συνήθως στην πρώτη) E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 8

ΙδιότητεςΜεταβλητών Συνθήκης pthread_condattr_t attr; int pthread_condattr_init(&attr); int pthread_condattr_destroy(&attr); ήλωση, αρχικοποίηση και καταστροφή ενός αντικειµένου ιδιοτήτων mutexes #ifdef _POSIX_THREAD_PROCESS_SHARED int pthread_condattr_getpshared(&attr, (int *) &ps); int pthread_condattr_setpshared(&attr, (int) ps); #endif ιαµοίραση ή µη µιας µεταβλητής συνθήκηςµεταξύ διαφορετικών διεργασίων ps: PTHREAD_PROCESS_{PRIVATE, SHARED} Η µεταβλητή συνθήκηςπρέπει να έχει δεσµευτεί σε περιοχή µνήµης που είναι κοινή µεταξύ των διεργασιών E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 9

Αρχικοποίησηµιας Φοράς Αρχικοποίηση δεδοµένων (π.χ. mutexes) από την main Στην ανάπτυξη βιβλιοθηκών δεν υπάρχει αυτή η πολυτέλεια Σε εφαρµογές µε ένα νήµα µια κατάλληλη booleanµεταβλητή αρκεί για να δηλώσει ότι έγινε η αρχικοποίηση Ένα στατικά αρχικοποιηµένο mutexαρκεί µα αν απαιτείται δυναµική αρχικοποίηση τότε χρησιµοποιείται η pthread_once pthread_once_t once_control = PTHREAD_ONCE_INIT; int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)); Οποιοδήποτε νήµα µπορεί να καλέσει την συνάρτηση Ελέγχεται αυτόµατα η αντίστοιχη µεταβλητή και καλείται η ρουτίνα αρχικοποίησης Αν ένα άλλο νήµα καλέσει την συνάρτηση, θα µπλοκάρει µέχρι να ολοκληρωθεί η αρχικοποίηση E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 10

Αρχικοποίησηµιας Φοράς pthread_once_t once_block = PTHREAD_ONCE_INIT; pthread_mutex_t mutex; /* Initialization routine */ void once_init_routine(void) { pthread_mutex_init(&mutex, NULL); } /* Thread start routine that calls pthread_once */ void *thread_routine(void *arg) { pthread_once(&once_block, once_init_routine);... } int main() { pthread_create(&t, NULL, thread_routine, NULL); pthread_once(&once_block, once_init_routine);... } E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 11

Ιδιωτικά εδοµένα Νηµάτων ιατήρησητης τιµής µιας µεταβλητής µεταξύ κλήσεων διαφορετικών ρουτινών σε ένα συγκεκριµένο νήµα Μεταβλητές που ορίζονται ως static σε µια ρουτίνα / αρχείο µπορούν να προσπελαστούν από όλα τα νήµατα Μόνο το περιεχόµενο των καταχωρητών είναι πραγµατικό ιδιωτικό σεένα νήµα. Ακόµα και η στοίβα που θα µπορούσε να προσπελαστεί από έναάλλο νήµα pthread_key_t key; int pthread_key_create(pthread_key_t *key, void (*destructor)(void *)); int pthread_key_delete(pthread_key_t key); ηµιουργία και διαγραφή κλειδιού για αποθήκευση ιδιωτικών δεδοµένων int pthread_setspecific(pthread_key_t key, const void *value); void *pthread_getspecific(pthread_key_t key); Ανάθεση και ανάκτηση τιµής κλειδιού E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 12

Ιδιωτικά εδοµένα Νηµάτων pthread_key_t key; pthread_once_t key_once = PTHREAD_ONCE_INIT; void once_routine(void) { pthread_key_create(&key, NULL); } void routine() { long *value; value = pthread_setspecific(key); } void *thread_routine(void *) { long *value; pthread_once(&key_once, once_routine); } value = malloc(sizeof(long)); *value = (long)pthread_self(); pthread_setspecific(key, value); routine(); E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 13

Χειρισµόςσφαλµάτων Στιςπαραδοσιακές διεργασίες η errnoείναι µια καθολική µεταβλητή ακέραιου (int) τύπου Μια τέτοια µεταβλητή θα ήταν άχρηστη σε ένα πολυνηµατικό πρόγραµµα Στην πραγµατικότητα, η errnoείναι ένα macroπου ορίζεται στο αρχείο <errno.h> και επιστρέφει πληροφορία ανά νήµα Κάθε νήµα έχει ένα ιδιωτικό αντίγραφο της errno #if (defined(_reentrant) extern int * errno(); #define errno (*( errno())) #else extern int errno; #endif E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 14

ΑκύρωσηΝηµάτων int pthread_cancel(pthread_t thread); Ακυρώνει την εκτέλεση ενός νήµατος int pthread_setcancelstate(int state, int *ostate); Ένα νήµα επιτρέπει την ακύρωση του ή όχι PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_DISABLE int pthread_setcanceltype(int type, int *otype); Καθορισµός του τύπου ακύρωσης Με αναβολή (deferred): PTHREAD_CANCEL_DEFERRED Ασύγχρονος (asynchronous): PTHREAD_CANCEL_ASYNCHRONOUS int pthread_testcanceltype(); Ένα νήµα ελέγχει αν έχει πάρει εντολή για να ακυρωθεί E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 15

ΠεριπτώσειςΑκύρωσης Νήµατος Πρώτη περίπτωση Κατάσταση: απενεργοποιηµένη Είδος ακύρωσης: Και τα δύο (µε αναβολή ή ασύγχρονη) Η ακύρωση παραµένει σε εκκρεµότητα µέχρι να ενεργοποιηθεί εύτερη περίπτωση Κατάσταση: ενεργοποιηµένη Είδος ακύρωσης: Με αναβολή Η ακύρωση θα πραγµατοποιηθεί όταν το νήµα φτάσει σε ένα σηµείο ακύρωσης (π.χ. pthread_testcancel) Τρίτη περίπτωση Κατάσταση: ενεργοποιηµένη Είδος ακύρωσης: Ασύγχρονη Η ακύρωση θα πραγµατοποιηθεί οποιαδήποτε χρονική στιγµή E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 16

ΑκύρωσηΝηµάτων pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; void *test_wait(void *arg){ pthread_setcancelstate(pthread_cancel_enable, NULL); pthread_setcanceltype(pthread_cancel_asynchronous, NULL); } pthread_mutex_lock(&mut); /* already locked */ return NULL; int main() { }... pthread_mutex_lock(&mut); pthread_create(&pth, NULL, test_wait, NULL); sleep(5); pthread_cancel(pth); /* cancel blocked thread */ pthread_mutex_unlock(&mut); pthread_join(pth, NULL); /* join cancelled thread */ E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 17

#include <pthread.h> Χειριστέςκαθαρισµού void pthread_cleanup_push(void (*routine) (void *), void *arg); void pthread_cleanup_pop(int execute); Οι χειριστές καθαρισµού είναι ρουτίνες που καλούνται όταν ένα νήµα τερµατίζει, είτε καλώντας pthread_exit είτε λόγω ακύρωσης. Εγκαθίστανται και αφαιρούνται ακολουθώντας µια µορφή στοίβας Σκοπός τους είναι η απελευθέρωση πόρων που ένα νήµα µπορεί να κρατά ενώ τερµατίζει Παράδειγµα: Ένα νήµα τερµατίζει ή ακυρώνεται ενώ κρατά κλειδωµένο ένα mutex. Η καλύτερη λύση είναι η χρήση ενός χειριστή καθαρισµού που θα ξεκλειδώνει το mutex Παρόµοιες χρήσεις: απελευθέρωση δυναµικής µνήµης (malloc/free), κλείσιµο περιγραφέων αρχείων E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 18

#include <pthread.h> Χειριστέςκαθαρισµού void pthread_cleanup_push(void (*routine) (void *), void *arg); void pthread_cleanup_pop(int execute); Η pthread_cleanup_pushεγκαθιστά έναν χειριστή καθαρισµού. Από το σηµείο αυτό µέχρι την αντίστοιχη pthread_cleanup_pop, η ρουτίνα καθαρισµού routine θα κληθεί µε όρισµα arg όταν το νήµα τερµατίσει ή ακυρωθεί Αν αρκετοί χειριστές καθαρισµού είναι ενεργοί, θα κληθούν όλοι µε σειρά LIFO: ο πιο πρόσφατα εγκαταστηµένος χειριστής θα κληθεί πρώτος Η pthread_cleanup_pop αφαιρεί τον πιο πρόσφατα εγκαταστηµένο χειριστή Αν το όρισµα execute δεν είναι 0, εκτελεί επίσης τον χειριστή Αν το όρισµα execute είναι 0, ο χειριστής αφαιρείται µα δεν εκτελείται Τα ζευγάρια pthread_cleanup_pushκαι pthread_cleanup_popπρέπει να εµφανίζονται µέσα στην ίδια ρουτίνα, στο ίδιο επίπεδο κώδικα. Στην πραγµατικότητα είναι macros που εισάγουν ένα ζευγάρι αγκυλών στο κώδικα του χρήστη, δηλαδή { και } αντίστοιχα E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 19

Παράδειγµα pthread_cleanup_push(pthread_mutex_unlock, (void *)&mut); pthread_mutex_lock(&mut); /* do some work */ pthread_mutex_unlock(&mut); pthread_cleanup_pop(0); Οι τελευταίες δύο γραµµές µπορούν να αντικατασταθούν µε: pthread_cleanup_pop(1); Ο παραπάνω κώδικας δεν είναι ασφαλής στην περίπτωση ασύγχρονης ακύρωσης: το νήµα µπορεί να προσπαθήσει να ξεκλειδώσει ένα mutex που δεν έχει κλειδώσει E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 20

Παράδειγµα Οπαρακάτω κώδικας επιλύει το προηγούµενο πρόβληµα της ασύγχρονης ακύρωσης pthread_setcanceltype(pthread_cancel_deferred, &oldtype); pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut); pthread_mutex_lock(&mut); /* do some work */ pthread_cleanup_pop(1); pthread_setcanceltype(oldtype, NULL); E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 21

Παράδειγµα void cleaner (void *data) { printf ("Clean %d\n", *(int *)data); } void *thread (void *param) { int data1 = 1, data2 = 2; pthread_cleanup_push (cleaner, &data1); pthread_cleanup_push (cleaner, &data2); pthread_cleanup_pop (1); pthread_exit (param); pthread_cleanup_pop (0); /* not reached */ } return NULL; E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 22

Σήµατα #include <pthread.h> #include <signal.h> int pthread kill(pthread t thread, int signo); Επιστρέφει 0 για επιτυχία, µη µηδενική τιµή σε περίπτωση σφάλµατος Τιµές σφαλµάτων ESRCH: εν αντιστοιχεί νήµα στο συγκεκριµένο αναγνωριστικό EINVAL: µη αποδεκτός αριθµός σήµατος E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 23

Αποστολήσήµατος σε νήµα Τα νήµατα δεν χρησιµοποιούνται για τερµατισµό νηµάτων Η pthread_kill χρησιµοποιείται όπως η kill Το σήµα αποστέλλεται σε ένα συγκεκριµένο νήµα µα ο χειρισµός του µπορεί να επηρεάσει όλη τη διεργασία Το SIGKILL θα τερµατίσει όλη τη διεργασία Το SIGSTOP θα µπλοκάρει όλη τη διεργασία (νήµατα) Ένα νήµα µπορεί να στείλει ένα σήµα στον εαυτό του (παρόµοια µε την κλήση raise): pthread_kill(pthread_self(), signo); E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 24

Χειρισµόςσηµάτων και νήµατα Όλατα νήµατα µοιράζονται τους χειριστές σηµάτων της διεργασίας Κάθε νήµα έχει την δική του µάσκα σηµάτων που αυτό µπλοκάρει Υπάρχουν τρεις τύποι σηµάτων µε διαφορετικές µεθόδους παράδοσης Ασύγχρονα:Σήµατα που δεν παραδίδονται κάποια καθορισµένη χρονική στιγµή ούτε σχετίζονται µε κάποιο συγκεκριµένο νήµα (π.χ. SIGINT). Παραδίδονται σε κάποιο νήµα που δεν έχει µπλοκάρει το σήµα Σύγχρονα: Σήµατα που παράγονται στο ίδιο σηµείο κατά την εκτέλεση ενός νήµατος (π.χ. SIGFPE, για αριθµητικό σφάλµα όπως διαίρεση µε το µηδέν). Παραδίδονται στο νήµα που προκάλεσε το σήµα. Κατευθυνόµενα: Σήµατα που αποστέλλονται σε ένα συγκεκριµένο νήµα µε την κλήση pthread_kill. Παραδίδονται στο νήµα που καθορίζεται. E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 25

Χειρισµόςσηµάτων και νήµατα Όλατα νήµατα υιοθετούν τη µάσκα σηµάτων (ποια σήµατα είναι µπλοκαρισµένα) από το νήµα που τα δηµιουργεί Η µάσκα σηµάτων µπορεί να τεθεί µε την κλήση pthread_sigmask Οι ενέργειες σηµάτων έχουν εµβέλεια διεργασίας. εν µπορεί να υπάρχει για το ίδιο σήµα ένα χειριστής σε κάποιο νήµα και ένας διαφορετικός χειριστής σε κάποιο άλλο νήµα Ένα σήµα παραδίδεται σε ένα νήµα. Αν ένα δεύτερο σήµα φτάσει ενώ το πρώτο σήµα βρίσκεται υπό επεξεργασία, το σήµα παραδίδεται σε κάποιο άλλο νήµα, εφόσον υπάρχει κάποιο που δεν το έχει µπλοκαρισµένο (ισχύει για ασύγχρονα σήµατα µόνο) Πρακτικά, η µάσκα σηµάτων και οι χειριστές σηµάτων τίθενται στο κύριο νήµα, µια φορά E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 26

Χειρισµόςσηµάτων και νήµατα Τασήµατα πάντα παραδίδονται αρκεί να υπάρχουν νήµατα που δεν τα µπλοκάρουν, ακόµα κι αν ένα άλλο νήµα εκτελεί έναν χειριστή σήµατος Συνηθισµένη τακτική είναι ένα συγκεκριµένο νήµα να χειρίζεται όλα τα ασύγχρονα σήµατα Το κύριο νήµα µπλοκάρει όλα τα εισερχόµενα σήµα. Αφού τα νήµα που δηµιουργούνται υιοθετούν τη µάσκα σηµάτων, όλα τα νήµατα θα έχουν τα σήµατα µπλοκαρισµένα ηµιουργείται ένα ξεχωριστό νήµα για χειρισµό σηµάτων, το οποίο καλεί την sigwait. Τα σήµατα για τα οποία έχουν οριστεί χειριστές ξεµπλοκάρονται για το συγκεκριµένο νήµα. Το νήµα καλεί την sigwaitµέσα σε ένα βρόχο, αφού η συνάρτηση επιστρέφει όταν ο χειριστής σήµατος καλείται E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 27

Χειρισµόςσηµάτων και νήµατα Μιασυνάρτηση των νηµάτων POSIX δεν πρέπει να καλείται µέσα από έναν χειριστή σήµατος Μια συνάρτηση είναι async-signal safe εφόσον µπορεί να διακοπεί µε ασφάλεια από ένα σήµα και να ξεκινήσει αφού ο χειριστής σήµατος επιστρέψει, ακόµα κι αν ο χειριστής σήµατος καλέσει την ίδια την ρουτίνα Συναρτήσεις που χρησιµοποιούν εσωτερικά στατικές δοµές δεν είναι async-safeεκτός κι αν µπλοκάρουν τα σήµατα ώστε να µη διακοπεί η εκτέλεσή τους Καµία συνάρτηση των νηµάτων POSIX δεν είναι ασφαλής. Το µπλοκάρισµα των σηµάτων έχει υψηλό κόστος αφού πρόκειται για κλήση συστήµατος Οι συναρτήσεις των νηµάτων POSIX έχουν σχεδιαστεί για ταχύτητα παρά για ασφάλεια E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 28

Σηµαφόροι Πρέπει να αρχικοποιούνται δυναµικά sem_t sem; sem_init( &sem, 0, 5 ); sem_destroy( &sem ); Βασικές λειτουργίες sem_post( &sem ); // + sem_wait( &sem ); // - (block if <= 0) sem_trywait( &sem ); sem_getvalue( &sem ); Μπορούν να χρησιµοποιηθούν µε ασφάλεια µέσα από χειριστές σηµάτων Η κλήση sem_wait() µπορεί να διακοπεί: do { err = sem_wait(&sem); } while ( err=eintr ); E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 29

Σηµαφόροι sem_t mutex; sem_init(&mutex, 0, 1); THREAD 1 sem_wait (&mutex); a = data; a++; data = a; sem_post (&mutex); THREAD 2 sem_wait (&mutex); /* blocked */ /* blocked */ /* blocked */ /* blocked */ b = data; b--; data = b; sem_post (&mutex); E-85: Ε.Θ.Λ: Προγραµµατισµός Συστηµάτων Υψηλών Επιδόσεων 30