Ogolne operacje na watkach
utworzenie nowego watkupthread_create
Deklaracja
#include <
pthread.h>int pthread_create(pthread_t * thread, pthread_attr_t *
attr, void * (*start_routine)(void *), void * arg);
Opis
Funkcja pthread_create tworzy nowy watek, ktory wykonuje sie wspolbieznie z watkiem wolajacym. Nowy watek zaczyna wykonywac podana funkcje start_routine podajac jej arg jako pierwaszy argument. Nowy watek konczy sie explicite przez wywolanie procedury pthread_exit lub przez powrot z start_routine.
Argument attr okresla atrybuty nowego watku, do ktorych ustalenia sluzy funkcja pthread_attr_init. Jesli jako attr przekazemy NULL, zostana okreslone domyslne atrybuty watku: mozliwosc dolaczenia, domyslny sposób kolejkowania (nie czasu rzeczywistego).
Po bezblednym wykonaniu pthread_create umieszcza identyfikator nowoutworzonego watku w miejscu wskazywanym przez argument thread i zwraca 0.
W razie bledu zwracane jest EAGAIN w przypadku, gdy brakuje zasobow systemowych zeby stworzyc proces dla nowego watku lub gdy wiecej niz PTHREAD_THREADS_MAX watkow juz dziala w systemie.
pthread_attr_init, pthread_attr_destroy,
pthread_attr_setdetachstate, pthread_attr_getdetachstate,
pthread_attr_setschedparam, pthread_attr_getschedparam,
pthread_attr_setschedpolicy, pthread_attr_getschedpolicy,
pthread_attr_setinheritsched,
pthread_attr_getinheritsched, pthread_attr_setscope,
pthread_attr_getscope
Deklaracja
#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
int pthread_attr_setdetachstate(pthread_attr_t *attr, int
detachstate);
int pthread_attr_getdetachstate(const pthread_attr_t
*attr, int *detachstate);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int
policy);
int pthread_attr_getschedpolicy(const pthread_attr_t
*attr, int *policy);
int pthread_attr_setschedparam(pthread_attr_t *attr, const
struct sched_param *param);
int pthread_attr_getschedparam(const pthread_attr_t *attr,
struct sched_param *param);
int pthread_attr_setinheritsched(pthread_attr_t *attr, int
inherit);
int pthread_attr_getinheritsched(const pthread_attr_t
*attr, int *inherit);
int pthread_attr_setscope(pthread_attr_t *attr, int
scope);
int pthread_attr_getscope(const pthread_attr_t *attr, int
*scope);
Opis
Ustawianie atrybutow watkow odbywa sie przez wypelnianie struktury
attr typu phread_attr_t (obiektu atrybutow) i nastepnie przekazanie jej jako drugi argument funkcji pthread_create. Przekazanie wartosci NULL odpowiada przypisaniu wszystkim atrybutom ich domyslnych wartosci (domyslne wartosci dla poszczegolnych atrybutow wypisane sa ponizej).pthread_attr_init
inicjalizuje obiekt attr i wypelnia wszystkie atrybuty ich domyslnymi wartosciami.Kazdy atrybut
attrname (ponizej lista dostepnych atrybutow) moze być idnywidualnie ustawiony za pomoca funkcji pthread_attr_setattrname i odczytany za pomoca pthread_attr_getattrname.pthread_attr_destroy
niszczy obiekt typu pthread_attr_t (w tej implementacji nie robi faktycznie nic).Obiekt atrybutow jest analizowany jedynie podczas tworzenia nowego watku. Ten sam obiekt atrybutow moze byc uzyty do stworzenia wielu watkow. Modyfikacja obiektu atrybutow po wywolaniu
pthread_create nie zmienia atrybutow watku wczesniej utworzonego.Dostepne sa nastepujace atrybuty:
detachstate
Okresla czy watek ma byc utworzony w stanie umozliwiajacym dolaczenie (wartosc
PTHREAD_CREATE_JOINABLE), czy odlaczonym (PTHREAD_CREATE_DETACHED).Wartoscia domyslna jest
PTHREAD_CREATE_JOINABLE.W stanie umozliwiajacym dolaczenie inny watek moze oczekiwac na zakonczenie i odczytac wartosc zakonczenia danego watku za pomoca
pthread_join, ale czesc zasobow przydzielonych do danego watku zostanie w pamieci nawet po jego zakonczeniu, do momentu az inny watek nie wywola na nim pthread_join.W stanie odlaczonym zasoby rezerwowane dla watku sa zwalniane zaraz po jego zakonczeniu, jednak
pthread_join nie moze byc uzyty do synchronizacji.Watek stworzony w stanie umozliwiajacym dolaczenie moze byc w kazdym momencie odlaczony przez wywolanie
pthread_detach.schedpolicy
Umozliwia wybor sposobu przelaczania dla watku. Mozna wybrac:
SCHED_OTHER
(normalne, przelaczanie nie w czasie rzeczywistym),SCHED_RR
(w czasie rzeczywistym, round-robin),SCHED_FIFO
(w czasie rzeczywistym, FIFO).
Wartoscia domyslna jest
SCHED_OTHER.Uwaga! Sposoby
SCHED_RR i SCHED_FIFO sa dostepne jedynie dla procesow z uprawnieniami superuzytkownika.Sposob kolejkowania moze byc zmieniony w czasie dzialania watku przez wywolanie
pthread_setschedparam.schedparam
Zawiera parametry do przelaczania (priorytet) watku.
Wartoscia domyslna jest priorytet 0.
Wartosc priorytetu nie ma znaczenia jesli sposob kolejkowania jest ustawiony na
SCHED_OTHER. Ustawienie ma sens jedynie przy sposobach czasu rzeczywistego SCHED_RR lub SCHED_FIFO.aPriorytet moze byc zmieniony w czasie dzialania watku przez wywolanie
pthread_setschedparam.inheritsched
Okresla kiedy sposob przelaczania i parametry z nim zwiazane dla nowo tworzonego watku sa explicite ustalone przez wartosci
schedpolicy i schedparam (PTHREAD_EXPLICIT_SCHED) lub sa dziedziczone z watku-ojca (PTHREAD_INHERIT_SCHED).Domyslna wartoscia jest
PTHREAD_EXPLICIT_SCHED.Zwracane wartosci:
Wszystkie funkcje zwracaja 0 w razie sukcesu i kod bledu przy niepowodzeniu.Po poprawnym zakonczeniu funkcje
pthread_attr_getattrname wkladaja aktualne wartosci atrybutow w miejsce okreslone przez drugi argument funkcji.W razie bledu funkcja
pthread_attr_setdetachstate zwraca EINVAL, co oznacza, ze podany parametr detachstate nie jest ani PTHREAD_CREATE_JOINABLE ani PTHREAD_CREATE_DETACHED.Funkcja
pthread_attr_setschedparam zwraca EINVAL, gdy podany priorytet jest poza zakresem dla sposobu przelaczania okreslonego w innym atrybucie (1 .. 99 dla SCHED_RR i SCHED_FIFO i 0 dla SCHED_OTHER).Funkcja
pthread_attr_setschedpolicy zwraca EINVAL jesli sposob przelaczania nie jest poprawny (SCHED_RR, SCHED_FIFO lub SCHED_OTHER) lub ENOTSUP jeśli sposob przelaczania jest ustawiony na SCHED_RR lub SCHED_FIFO i proces nie ma uprawnien superuzytkownika.Funkcja
pthread_attr_setinheritsched zwraca EINVAL, gdy podany argument nie jest PTHREAD_INHERIT_SCHED ani PTHREAD_EXPLICIT_SCHED.pthread_setschedparam, pthread_getschedparam
Deklaracja
#include <pthread.h>
int pthread_setschedparam(pthread_t target_thread, int policy,
const struct sched_param *param);
int pthread_getschedparam(pthread_t target_thread, int *policy,
struct sched_param *param);
Opis
Funkcja
pthread_setschedparam ustawia parametry przelaczania dla watku target_thread wg podanych wartosci policy i param. policy moze miec wartosc:SCHED_OTHER (normalne, przelaczanie nie w czasie rzeczywistym)
SCHED_RR (w czasie rzeczywistym, round-robin)
SCHED_FIFO (w czasie rzeczywistym, FIFO).
Param okresla priorytet przelaczania przy sposobie czasu rzeczywistego.
Uwaga! Sposoby SCHED_RR i SCHED_FIFO sa dostepne jedynie dla procesow z uprawnieniami superuzytkownika.
Funkcja
pthread_getschedparam pozwala sprawdzic sposob przelaczania i priorytet dla watku podanego jako target_thread. Wyniki umieszcza w miejscach wskazanych przez policy i param.Obie funkcje zwracaja 0 jesli zakonczyly dzialanie bez bledu lub nastepujace wartosci w razie bledow:
EINVAL - wartosc policy nie jest SCHED_OTHER, ani SCHED_RR, ani SCHED_FIFO
EINVAL - priorytet podany jako parametr nie pasuje do sposobu przelaczania
EPARM - wywolujacy funkcje proces nie ma uprawnien superuzytkowanika
ESRCH - watek target_thread nie istnieje lub zakonczyl dzialanie
EFAULT - wskaznik param lub policy wskazuje poza obszar pamieci dostepny dla procesu.
pthread_self
Deklaracja
#include <pthread.h>
pthread_t pthread_self(void);
Opis
pthread_self
zwraca identyfikator watku, ktory wywolal funkcje.pthread_equal
Deklaracja
#include <pthread.h>
int pthread_equal(pthread_t thread1, pthread_t thread2);
Opis
Funkcja
pthread_equal okresla, czy oba identyfikatory odnosza sie do tego samego watku.Zwraca niezerowa warosc jesli
thread1 i thread2 odnosza sie do tego samego watku. W przeciwnym przypadku 0 jest zwracane.pthread_exit
Deklaracja
#include <pthread.h>
void pthread_exit(void *retval);
Opis
Funkcja pthread_exit konczy dzialanie wolajacego watku. Wywolywane sa po kolei (LIFO) wszystkie funkcje czyszczace okreslone przez pthread_cleanup_push. Funkcje konczace dla wszystkich kluczy odnoszacych się do konkretnego watku i majacych wartosc inna niz NULL (patrz pthread_key_create) sa wykonywane. Dopiero po tym wszystkim dzialanie watku jest wstrzymywane. Argument retval okresla kod zakonczenia watku, ktory może byc odczytany przez inny watek za pomoca funkcji pthread_join.
pthread_join
Deklaracja
#include <pthread.h>
int pthread_join(pthread_t th, void **thread_return);
Opis
Funkcja
pthread_join zawiesza dzialanie wolajacego watku az do momentu, gdywatek identyfikowany przez th nie zakonczy dzialania. Jesli argument thread_return jest rozny od NULL to kod zakonczenia watku th zostanie wstawiony w miejsce wstazywane przez thread_return. Kodem zakonczenia może byc wartosc okreslona pzy wolaniu funkcji pthread_exit lub PTHREAD_CANCELLED jesli watek byl usuniety.Watek, do ktorego dolaczamy musi byc w stanie umozliwiajacym dolaczanie (nie moze byc odlaczony przez wywolanie
pthread_detach lub okreslenie atrybutu PTHREAD_CREATE_DETACHED przy jego tworzeniu przez pthread_create).W momencie, gdy watek w stanie umozliwiajacym dolaczenie konczy dzialanie jego zasoby (deskryptor watku i stos) nie sa zwalniane dopoki inny watek nie wykona na nim
pthread_join. Dlatego pthread_join powinien byc wykonany dla kazdego nie odlaczonego watku.Co najwyzej jeden watek moze czekac na zakonczenie danego watku. Wywolanie
pthread_join w momencie, gdy jakis inny watek juz oczekuje na jego zakonczenie spowoduje powrot z funkcji pthread_join z bledem.Oczekiwanie przez wywolanie funkcji
pthread_join jest tzw. cancellation-point, co oznacza, ze jesli watek zostanie odwolany (canceled) w czasie oczekiwania, to dzialanie watku zostanie zakonczone natychmiast bez czekania na synchronizacje z watkiem th.W przypadku sukcesu funkcja
pthread_join zwraca 0 i kod zakonczenia watku th jest umieszczany w miejscu wskazywanym przez thread_return. W przypadku bledu zwracana jest wartosc EINVAL jesli watek th juz zostal odlaczony (detached) lub inny watek juz oczekuje na jego zakonczenie albo wartosc EDEADLK jesli argument th odnosi sie do wolajacego watku.pthread_detach
Deklaracja
#include <pthread.h>
int pthread_detach(pthread_t th);
Opis
Funkcja pthread_detach odlacza wolajacy watek, co gwarantuje zwolnienie zasobow pamieci natychmiast po zakonczeniu dzialania watku, jednak do odlaczonego watku nie mozna dolaczyc po jego zakonczeniu (pthread_join).
Watek od razu prze tworzeniu moze byc okreslony jako odlaczony przez ustawienie odpowiedniego atrybutu przy wolaniu pthread_create.
Jesli funkcja pthread_detach zostanie wywolana w momencie, kiedy jakis watek juz czeka na zakonczenie wywolujacego watku, zostanie on w stanie umozliwiajacym dolaczenie (odlaczenie nie zostanie wykonane).
W razie powodzenia zwracane jest 0, EINVAL w przypadku bledu, co oznacza, ze watek th zostal juz wczesniej odlaczony.
pthread_once
Deklaracja
#include <pthread.h>
pthread_once_t once_control = PTHREAD_ONCE_INIT;
int pthread_once(pthread_once_t *once_control, void
(*init_routine) (void));
Opis
Wywolanie funkcji
pthread_once daje pewnosc, ze inicjalizacja będzie wykonana tylko co najwyzej raz. Argument once_control wskazuje na zewnetrzna zmienna statycznie zainicjalizowana do wartosi PTHREAD_ONCE_INIT.Pierwsze wywolanie
pthread_once z danym argumentem once_control powoduje wykonanie kodu bezargumentowej procedury init_routine i zmienia wartosc zmiennej once_control zeby zaznaczyc, ze inicjalizacja byla wykonana. Kolejne wywolania pthread_once z tym samym argumentem once_control będą pustymi wywolaniami.Funkcja
pthread_once zawsze zwraca 0.pthread_atfork
Deklaracja
#include <pthread.h>
int pthread_atfork(void (*prepare)(void), void (*parent)(void),
void (*child)(void));
Opis
Funkcja
pthread_atfork rejestruje funkcje obslugi do wywolania zaraz przed i zaraz po stworzeniu nowego procesu za pomoca funkcji fork. Funkcje przekazane jako prepare beda wykonane przez proces ojca zaraz przed wykonaniem fork, natomiast funkcje podane przez parameter parent zaraz po podziale procesu. Funkcje przekazane argumentem child wykonane zostana przez proces potomny tuz przed powrotem z funkcji fork.Kazdy z argumentow funkcji
pthread_atfork moze byc ustawiony na NULL, co oznacza puste wywolanie zamiast funkcjiFunkcja
pthread_atfork moze byc wywolywana wielokrotnie w celu zainstalowania wiecej niz jednego zbioru funkcji obslugi. W momencie wykonania fork funkcje prepare wykonywane sa w kolejnosci LIFO, zas parenti
child w kolejnosci FIFO.Zeby zrozumiec przyczyne istnienia funkcji
pthread_atfork warto przypomniec, ze w fork duplikuje cala pamiec procesu wlacznie z mutexami razem z ich stanem blokady, za to w procesie potomnym dziala jedynie jeden watek (wolajacy fork). Jesli wiec mutex byl zajety przez watek inny niz wolajacy fork, to zostanie zablokowany na zawsze (w procesie potomnym), co może spowodowac blokade calego procesu potomnego. Zeby tego uniknac należy instalowac funkcje obslugi jak nastepuje: funkcje prepare zajmuja globalne mutexy (w kolejnosci zajmowania), nastepnie funkcje parent i child zwalniaja je (w odwrotnej kolejnosci). Ewentualnie prepare i parent moga być ustawione na NULL podczas, gdy child powinien wywolac pthread_mutex_init na globalnych mutexach.Funkcja
pthread_atfork zwraca 0 w przypadku sukcesu lub blad ENOMEM, gdy nie ma wystarczajaco duzo pamieci dostepnej zeby zarejestrowac funkcje obslugi.