Programming with POSIX threads [annotated edition] 0201633922, 9780201633924

This book offers an in-depth description of the IEEE operating system interface standard, POSIX (Portable Operating Syst

274 96 3MB

English Pages 398 [399] Year 1997

Report DMCA / Copyright

DOWNLOAD PDF FILE

Recommend Papers

Programming with POSIX threads [annotated edition]
 0201633922, 9780201633924

  • 0 0 0
  • Like this paper and download? You can publish your own PDF file online for free in a few minutes! Sign Up
File loading please wait...
Citation preview

A d d is o n -W e s le y P ro fe s s io n a l C o m p u tin g S e rie s B r ia n W . K e r n ig h a n , C o n s u l t in g E d ito r

K e n A r n o l d / J o h n P e y t o n , A C U s e r's G u id e to A N S I C D a v i d R . B u t e n h o f , P ro g ra m m in g w ith P O S I X

Thre ad s

T o m C a r g i l l , C + + P ro g ra m m in g S ty le W i l l i a m R . C h e s w i c k / S t e v e n M . B e l l o v i n , F ire w a lls and In te rn e t S e cu rity : R e p e llin g the W ily H a cke r D a v i d A . C u r r y , U N IX ® S y s te m S e cu rity : A G u id e f o r U s e rs and S y s te m A d m in is tra to rs E r i c h G a m m a / R i c h a r d H e l m / R a l p h J o h n s o n / J o h n V l i s s i d e s , D e s ig n P a tte rn s : E le m e n ts o f

R e us ab le O b je c t- O rie n te d S oftw a re E r i c h G a m m a / R i c h a r d H e l m / R a l p h J o h n s o n / J o h n V l i s s i d e s , D e s ig n P a tte rn s C D : E le m e n ts o f

R e us ab le O b je ct- O rie n te d S oftw a re D a v i d R . H a n s o n , C In te rfa ce s and Im p le m e n ta tio n s : Te chnique s f o r C re a tin g R e us ab le S oftw a re S . K e s h a v , A n E n g in e e rin g A p p ro a ch to C o m p u te r N e tw o rk in g : A T M

N e tw o rk s , Th e In te rn e t, and

the Te le phon e N e tw o rk J o h n L a k o s , L a rg e - S ca le C + + S oftw a re D e s ig n S c o t t M e y e r s , E ffe ctiv e C + + , S e con d E d itio n : 50 S p e cific W ay s to Im p ro v e Y o u r P ro g ra m s and D e s ig n s S c o t t M e y e r s , M o re E ffe ctiv e C + + : 35 N e w W ay s to Im p ro v e Y o u r P ro g ra m s a n d D e s ig n s R o b e r t B . M u r r a y , C + + S tra te gie s and Tactics D a v i d R . M u s s e r / A t u l S a i n i , S T L T u to ria l and R e fe re n ce G u id e : C + + P ro g ra m m in g w ith the

S tan d a rd Te m p late L ib ra ry J o h n K . O u s t e r h o u t , Te l and the T k Too lk it C r a i g P a r t r i d g e , G ig a b it N e tw o rk in g J . S t e p h e n P e n d e r g r a s t J r ., D e s ktop K o rn S h e ll G ra p hica l P ro g ra m m in g R a d i a P e r l m a n , In te rco n n e ctio n s : B rid ge s and R o u te rs D a v i d M . P i s c i t e l l o / A . L y m a n C h a p i n , O p e n S y s te m s N e tw o rk in g : T C P / IP and O S I S t e p h e n A . R a g o , U N IX ® S y s te m V N e tw o rk P ro g ra m m in g C u r t S c h i m m e l , U N IX ® S y s te m s f o r M o d e rn A rch ite c tu re s : S y m m e tric M u ltip ro c e s s in g .v !d

C a ch in g f o r K e rn e l P ro g ra m m e rs W . R i c h a r d S t e v e n s , A d v a n ce d P ro g ra m m in g in the U N IX ® E n v iro n m e n t W . R i c h a r d S t e v e n s , T C P / IP Illu s tra te d , V o lu m e 1: Th e P ro to c o ls W . R i c h a r d S t e v e n s , T C P / IP Illu s tra te d , V o lu m e 3: T C P f o r Tra n s a ction s , H T T P , W T F

.: ‫ י‬:.:

U N IX ® D o m a in P ro to c o ls G a r y R . W r i g h t / W . R i c h a r d S t e v e n s , T C P / IP Illu s tra te d , V o lu m e 2: The Im p le m e ^

:

‫׳־‬:

Pr ogr am m ing wi t h

POSIX® T h r eads Dav id R. But e n h o f

▲ ▼



A DDISON-WESLEY ___________________ A n Im print o f A ddiso n We sle y Longm an, Inc. R ea d in g, M a s s a ch u s etts B erkeley, C a liforn ia B on n



A m s terd a m





H a rlow , E n gla n d

D on M ills , O n ta rio •

Tok yo







M en lo Pa rk, C a liforn ia

S yd n ey

M exico C ity

T radem ark ackno wle dgm ent s: U N IX is a regis tered tra d em a rk in th e U n ited S ta tes a n d oth er cou n tries , licen s ed exclu s ively th rou gh X / O p en C om p a n y Ltd. D igita l, D E C . D igita l U N IX, D E C th rea d s , VM S,

and

O p en V M S

a re tra d em a rk s o f D igita l E q u ip m en t C orp ora tion .

S ola ris,

S PA RC , S u n O S , a n d S u n a re tra d em a rk s o f S u n M icros ys tem s In corp ora ted . S G I a n d IR IX a re tra d em a rk s o f S ilicon G ra p h ics , In corp ora ted . H P - U X is a tra d em a rk o f H ew lett- P a ck a rd C om p a n y. A IX , IB M , a n d O S / 2 a re tra d em a rk s or regis tered tra d em a rk s o f th e IB M C orp ora tion . X / O p en is a tra d em a rk o f X / O p en C om p a n y Ltd. P O S IX is a regis tered tra d em a rk o f th e In s titu te o f E lectrica l a n d E lectron ics E n gin eers , Inc. M a n y o f th e d es ign a tion s u s ed b y m a n u fa ctu rers a n d s ellers to d is tin gu is h th eir p rod u cts a re cla im ed as tra d em a rk s . W h ere th os e d es ign a tion s a p p ea r in th is b ook a n d A d d is on - W es ley w a s a w a re o f a tra d em a rk cla im , th e d es ign a tion s h a ve b een p rin ted in in itia l ca p s or a ll ca ps . Th e a u th ors a n d p u b lis h ers h a ve ta k en ca re in th e p rep a ra tion o f th is b ook, b u t m a k e n o exp res s ed or im p lied w a rra n ty o f a n y kin d a n d a s s u m e n o res p on s ib ility for errors or om is s ion s . N o lia b ility is a s s u m ed for in cid en ta l or con s eq u en tia l d a m a ges in con n ection w ith or a ris in g ou t o f th e u s e o f th e in form a tion or p rogra m s con ta in ed h erein . Th e p u b lis h er offers d is cou n ts on th is b ook w h en ord ered in qu a n tity for s p ecia l sa les. F or m ore in form a tion , p lea s e con ta ct: C orp ora te & P rofes s ion a l P u b lis h in g G rou p A d d is on - W es ley P u b lis h in g C om p a n y O n e J a cob W a y R ea d in g, M a s s a ch u s etts 0186 7

Library o f Co ngress Cat alo ging-in-Public at io n Dat a B u ten h of, D a vid R., 1956‫־‬ P rogra m m in g w ith P O S IX th rea d s / D a vid R. B u ten h of. p.

cm. — (A d d is on - W es ley p rofes s ion a l com p u tin g series )

In clu d es b ib liogra p h ica l referen ces a n d in d ex. IS B N 0 - 2 0 1 - 6 3 3 9 2 - 2 (pb k.) 1.

Th rea d s (C om p u ter p rogra m s )

s ta n d a rd )

2. P O S IX (C om p u ter s oftw a re

3. E lectron ic d igita l com p u ters —P rogra m m in g.

I. Title

II. S eries . Q A 7 6 .7 6 .T5 5 B 8 8

1997

0 0 5 .4 ’3 2 —dc21

97- 6635 C IP

C op yrigh t © 1997 b y A d d is on W es ley Lon gm a n , Inc. A ll righ ts res erved . N o p a rt o f th is p u b lica tion m a y b e rep rod u ced , s tored in a retrieva l s ys tem , or tra n s m itted , in a n y form , or b y a n y m ea n s , electron ic, m ech a n ica l, ph otocop yin g, record in g, or oth erw is e, w ith ou t th e p rior con s en t o f th e p u b lis h er. Prin ted in th e U n ited S ta tes o f A m erica . P u b lis h ed s im u lta n eou s ly in C a n a d a . Tex t p rin ted on recycled a n d a cid - free pa p er.

2 3 4 5 6 7 8 9

2nd

P r in tin g

M A

0 0 9 9 98 9 7

O c to b e r , 1997

T o An n e, A m y, and A l yssa .

Q a o u ackno wle dgm ents: A m e rica n H e rita ge D iction a ry o f the E n glis h Language : p a ge 1. IS O / IE C 9 945- 1:1996 , © 1996 b y IE E E : p a ge 29.

L ew is C a rroll, A lice*s A d v e n tu re s in W ond erland : p a ges xv, 47, 70, 88, 97, 98, 106, 131, 142, 161, 189, 197. R ep rod u ced b y p erm is s ion o f M a cm illa n C h ild ren ’s B ooks . Lew is C a rroll, Throu gh the Looking- G las s : p a ges 1, 4, 8, 20, 25, 29, 35, 45, 172, 214, 241, 283, 290, 302. R ep rod u ced b y p erm is s ion o f M a cm illa n C h ild ren ’s B ooks . Lew is C a rroll, The H u n tin g o f the Snark. p a ges 3, 13, 28, 39, 120, 131, 134, 289, 367. R ep rod u ced b y p erm is s ion o f M a cm illa n C h ild ren ’s B ooks .

C o n te n ts

L is t o f E x a m p le P ro g ra m s ................................................................

x ii

P r e f a c e ...........................................................................................

xv

In ten d ed a u d ie n c e ..................................................................... x vi A b o u t th e a u th o r ....................................................................... x vi A c k n o w le d g m e n ts ..................................................................... x vii

1 I n t ro d uc t i o n ........................................................... 1.1

T h e “b a ilin g p ro g ra m m e rs ” .....................................................

1.2 D e fin itio n s a n d te rm in o lo g y .....................................................

1 3 4

1.2.1

A s y n c h r o n o u s .................................................................

4 4

1.2.2

C o n c u r r e n c y ...................................................................

1.2.3

U n ip r oc es s o r a n d m u ltip r o c e s s o r ..................................

5

1.2.4

P a r a lle lis m .....................................................................

5

1.2.5

T h r e a d s a fe ty a n d r e e n t r a n c y ........................................

6

1.2.6

C o n c u r r en c y c o n tr o l fu n c tio n s ........................................

7

1.3 A s y n ch ro n o u s p ro g ra m m in g is in tu itiv e ....................................

8

1.3.1

. . . b e ca u s e U N IX is a s y n c h r o n o u s ................................

9

1 .3.2

. . . b e ca u s e th e w o r ld is a s y n c h r o n o u s ..........................

11

1.4 A b o u t the e xa m p le s in this b o o k .............................................. 1.5 A s y n ch ro n o u s p ro g ra m m in g , b y e x a m p le ................................

12 13

1.5.1

T h e b a s elin e , s yn c h r o n o u s v e r s i o n ................................

14

1 .5.2

A v e r s io n u s in g m u ltip le p r o c e s s e s ................................

15

1 .5.3

A ve r s io n u s in g m u ltip le t h r e a d s ....................................

17

1.5.4

S u m m a r y .......................................................................

19

1.6 B e n e fits o f th re a d in g ............................................................... 2 0

1.6.1

P a r a lle lis m .....................................................................

1.6.2

C o n c u r r e n c y ...................................................................

22

1 .6.3

P r o g r a m m in g m o d e l.........................................................

24

1.7 C os ts o f th re a d in g ..................................................................

20

25

1.7.1

C o m p u tin g o v e r h e a d .......................................................

26

1.7.2

P r o g r a m m in g d is c ip lin e ...................................................

26

1.7.3

H a r d er to d e b u g .............................................................

27

1.8 T o thre a d o r n ot to th re a d ? .....................................................

28

1.9 P O S IX thre a d c o n c e p ts ...........................................................

29

1.9.1

A r c h itec tu r a l o v e r v ie w .....................................................

30

1.9.2

T yp es a n d in te r fa c e s .......................................................

30

C o n t e nt s

v iii

1 .9.3

C h e c k in g fo r e r r o r s .........................................................

31

2 T hre ads................................................................... 35 2 .1

C re a tin g a n d u s in g th r e a d s ...................................................

35

2 .2 T h e life o f a th re a d .................................................................

39

2 .2.1

C r e a tio n ......................................................................... ... 4 0

2 .2 .2

S t a r t u p ......................................................................... ... 41

2 .2 .3

R u n n in g a n d b l o c k in g ................................................... ... 4 2

2 .2 .4

T e r m in a tio n ................................................................... ... 4 3

2 .2 .5

R e c y c lin g ....................................................................... ... 4 4

3 Sy n c h ro n i z at i o n ...................................................... 45 3 .1 In v a ria n ts , critica l s e ctio n s , a n d p re d ic a te s ............................

45

3 .2 M u te x e s ..................................................................................

47

3 .2 .1

C r e a tin g a n d d e s tr o yin g a m u t e x ..................................

49

3 .2 .2

L o c k in g a n d u n lo c k in g a m u t e x ....................................

52

3 .2 .2 .1 N o n b lo c k in g m u tex l o c k s .................................. ... 5 8 3 .2 .3

U s in g m u tex es fo r a to m ic ity .......................................... ... 61

3 .2 .4

S izin g a m u te x to fit th e j o b .............................................. 6 2

3 .2 .5

3 .3

U s in g m o r e th a n on e m u t e x .......................................... ... 63 3 .2 .5 .1 L o c k h ie r a r c h y ...................................................

63

3 .2 .5 .2 L o ck c h a in in g .....................................................

70

C on d itio n v a ria b le s .................................................................

3 .3 .1 3 .3 .2

70

C r e a tin g a n d d e s tr o yin g a c o n d itio n v a r i a b l e ................ ... 74 W a itin g o n a c o n d itio n v a r ia b le ...................................... ... 77

3 .3 .3

W a k in g c o n d itio n va r ia b le w a ite r s .................................. ... 81

3 .3 .4

O n e fin a l a la r m p r o g r a m .................................................. 82

3 .4 M e m o ry v is ib ility b e tw e e n th re a d s ..........................................

88

4 A fe w way s t o use t h r e a d s ........................................ 97 4 .1 P ip e lin e ..................................................................................

98

4 .2

W o rk C re w .............................................................................. 106

4 .3

C lie n t/ S e rv e r .......................................................................... 120

5 A dv anc e d t hre ade d p r o g r a m m i n g ............................. 131 5 .1

O n e - tim e in itia liz a tio n ............................................................. 131

5 .2 A ttrib u te s o b j e c ts .................................................................. 134 5 .2.1

M u te x a ttr ib u te s .............................................................

135

5 .2 .2

C on d itio n va r ia b le a tt r ib u te s ........................................

137

5 .2 .3

T h r e a d a ttr ib u te s ...........................................................

138

5 .3

C a n c e lla tio n .......................................................................... 142

5 .3.1

D e fer r ed c a n c e la b ility .....................................................

147

5 .3 .2

A s yn c h r o n o u s c a n c e la b ility ...........................................

150

Co n t en t s

5.3.3 Cle aning u p ................................................................. 154

5.4 T h r ead-specific d a t a ........................................................... 161 5.4.1 Cre at ing thre ad-spe c ific d a t a ........................................ 163 5.4.2 Usin g t hre ad-spec ific d a t a ............................................ 166 5.4.3 Usin g destructo r f u n c t i o n s .......................................... 167 5.5 Realtim e scheduling ............................................................. 172 5.5.1 POSIX realtim e o p t io n s............................................... 173 5.5.2 Sc he duling policies and p r i o r i t i e s ................................ 174 5.5.3 Contention sc o pe and allo catio n d o m a i n ....................... 181 5.5.4 Pro blem s wit h realtim e sc h e d u li n g .............................. 183 5.5.5 Prio rit y -aw are m u t e x e s................................................185 5.5.5.1 Priority ceiling m ut e x e s.................................... 186 5.5.5.2 Priority inherit ance m ut e x e s............................ 188 5.6 T hr eads and k ernel entities.................................................. 189 5.6.1 M any -t o -o ne (use r le v e l)............................................... 190 5.6.2 One -to -o ne (kernel le v e l )..............................................191 5.6.3 M any -t o -fe w (two l e v e l )............................................... 193

6 POSES adjust s t o t h re a d s.......................................... 197 6.1 f o r k .................................................................................. 197 6.1.1 Fo rk h a n d le rs ............................................................. 199 6.2 e x e c .................................................................................. 204 6.3 Pr oc ess e x i t ...................................................................... 204 6.4 Stdio .................................................................................. 204 6.4.1 flockfile and fun lo c k file ................................................205 6.4.2 ge tc har_unlo ck ed and put c har_unlo c k e d....................... 207

6.5 T h r ead-safe f u n c t i o n s ................................................ ........ 209 6.5.1 Use r an d te rm inal id e n t ific at io n .................................. 210 6.5.2 Direct ory se arc h in g ..................................................... 212 6.5.3 String t o k e n ............................................................... 212 6.5 .4 T im e re p re se n t at io n ................................................... 212 6.5 .5 R andom num be r g e n e ra t io n ........................................ 213 6.5.6 Gro up and use r d a t a b a s e ............................................ 213 6.6 Signals.............................................................................. 214 6.6.1 Signal a c t io n s............................................................. 215 6.6.2 Signal m ask s............................................................... 216 6.6.3 p t h r e a d jd ll................................................................. 217 6.6 .4 sigwait and sig w a it i n f o ................................................227 6.6.5 S I G E V J H R E A D ......................................................... 230 6.6 .6 Se m apho res: sy nchro niz ing wit h a signal-c at c hin g f u n c t i o n .............................................. 234

7

“ R e al c o de ” ............................................................. 241

ix

Co n t en t s

7A

E x te n d e d s y n c h ro n iz a tio n ..................................................... 241

7.1.1

B a r r ie r s ......................................................................... 2 4 2

7 .1 .2

R e a d - w r ite lo c k s ............................................................. 2 5 3

7.2

W o rk q u e u e m a n a g e r ............................................................. 2 7 0

7.3 B u t w h a t a b o u t e xis tin g lib ra rie s ? ........................................ 2 8 3 7.3.1

M od ifyin g lib ra r ie s to b e th r e a d - s a fe .............................. 2 8 4

7 .3 .2

L ivin g w ith le g a c y lib r a r ie s .............................................2 8 5

8 Hint s t o av o id de bug g i ng .......................................... 289 8 .1 A v o id in g in co rre ct c o d e ......................................................... 2 9 0 8 .1 .1

A v o id r e lyin g on “th r e a d in e r tia ’' .................................... 291

8 .1 .2

N e ve r b e t y o u r m o r tg a g e o n a th r e a d r a c e ...................... 2 9 3

8 .1 .3

C o o p e r a te to a void d e a d lo c k s ........................................ 2 9 7

8 .1 .4

B ew a r e o f p r io r ity in v e r s io n ...........................................2 9 9

8 .1 .5

N eve r s h a r e c o n d itio n va r ia b le s b e tw e en

8 .1 .6

S h a r in g s ta c k s a n d r ela ted m em o r y

p r e d ic a t e s ..................................................................... 3 0 0 c o r r u p t e r s ..................................................................... 301 8 .2 A v o id in g p e rfo rm a n ce p ro b le m s .............................................3 0 2

8 .2 .1

B ew a r e o f c o n cu r r e n t s e r ia liz a tio n ................................ 3 0 2

8 .2 .2

U s e th e r ig h t n u m b e r o f m u te x e s .................................. 3 0 3

8 .2 .3

N e ve r fig h t o ve r ca c h e lin e s ............................................ 3 0 4

8 .2 .2 .1 T o o m a n y m u tex e s w ill n o t h e l p ........................ 3 0 4

9 P OSIX t hre ads m i n i -re f e re n c e ...................................307 9.1

P O S IX 1 0 0 3 .1 0 - 1 9 9 5 o p tio n s .................................................3 0 7

9 .2 P O S IX 1 0 0 3 A < ^ 1995 lim its ..................................................... 3 0 8 9 .3 P O S IX 1 0 0 3 A c - 1 9 9 5 in te rfa c e s ..............................................3 0 9

9 .3 .1

E r r or d e tec tio n a n d r e p o r tin g ........................................ 3 1 0

9 .3 .2

U s e o f vo id * ty p e ............................................................. 311

9 .3 .3

T h r e a d s ......................................................................... 311

9 .3 .4

M u te x e s ......................................................................... 3 1 6

9 .3 .5

C o n d itio n v a r ia b le s ......................................................... 3 1 9

9 .3 .6

C a n c e lla tio n ................................................................... 3 2 3

9 .3 .7

T h r ea d - s p e cific d a ta ....................................................... 3 2 5

9 .3 .8

R ea ltim e s c h e d u lin g ....................................................... 3 2 6

9 .3 .9

F or k h a n d le r s ................................................................. 3 3 6

9 .3 .1 0

S td io ............................................................................. 3 3 6

9 .3 .1 1

T h r e a d - s a fe fu n c tio n s .................................................. 3 3 8

9 .3 .1 2

S ig n a ls ......................................................................... 342

9 .3 .1 3

S e m a p h o r e s ................................................................. 3 4 5

10 Fut ure st an dard i z at i o n ............................................ 347 10.1 X / O p e n X S H 5 [U N IX 9 8 ] ......................................................... 3 4 7

xi

Co n t en t s

10.1.1 10.1.2 10.1.3 10.1.4 10.1.5 10.1.6

P OSIX o ptions fo r X S H 5 ............................................ 348 M ute x t y p e ............................................... ............... 349 Set co ncurrency le v e l................................................. 351 St ac k guard s i z e ....................................................... 353 Paralle l I / O ............................................................... 354 Cance llat ion p o i n t s ................................................... 355

10.2 POS IX 1003. l j .................................................................. 356 10.2.1 Barrie rs.................................................................... 358 10.2.2 R ead-w rlte l o c k s ....................................................... 358 10.2.3 S p i n lo e k s ............... . ............................................... 359 10.2.4 Condition v ariable w ait c lo c k ...................................... 359 10.2.5 T hread a b o r t ............................................................. 361 10.3 POS IX 1003.14 .................................................................. 361 Bi blio g r a p h y .............................................................................. 363 T hread r esour ces on the In t er n et .................................................. 367 In d ex ......................................................................................... 369

E xam ple p ro g ra m s

s a m p le .c p a r t

1 s a m p le i n f o .....................................................

13

a l a r m . c .........................................................................................

14

a la r m _ f o r k . c .................................................................................

15

a la r m _ th r e a d . c

17

p a rt

1 d e f i n i t i o n s ..........................................

a la r m _ _ th r e a d .c p a r t

2 a l a r m _ th r e a d ........................................

18

a la r m _ th r e a d . c

3 m a i n .......................................................

18

p a rt

t h r e a d _ e r r o r . c .............................................................................

32

e r r o r s . h .......................................................................................

33

l i f e c y c l e , c ...................................................................................

38

m u te x _ s ta tic . c .............................................................................

50

m u tex _ d yn a m ic. c ...........................................................................

50

a la r m _ m u tex . c p a r t

1 d e f i n i t i o n s .............................................

52

a la r m _ m u te x ,c

p a rt

2 a la r m _ th r e a d ..........................................

54

a la r n w n u te x .c

p a rt

3 m a in .........................................................

56

t r y l o c k . c .....................................................................................

59

b a c k o ff, c

66

.....................................................................................

c o n d _ s t a t i c . c ...............................................................................

74

con d _ _ d yn a m ic. c .............................................................................

75

c o n d . c ...........................................................................................

78

a la r m _ c o n d .c p a r t

83

a la r m _ c o n d .c

1 d e c l a r a t i o n s .............................................

p a r t 2 a l a r m _ i n s e r t .............................................

a la r m _ c o n d .c p a r t

3 a l a r m _ r o u t in e ...........................................

a la r m _ c o n d .c p a r t

84 86

4 m a in ...........................................................

87

p ip e . c

p a rt

1 d e f i n i t i o n s .........................................................

99

p ip e . c

p a rt

2 p ip e _ s e n d ............................................................. 100

p ip e . c

p a r t 3 p i p e _ s t a g e ........................................................... 101

p ip e . c

p a r t 4 p i p e _ c r e a t e ......................................................... 102

p ip e . c

p a r t 5 p ip e _ s ta r t,

p ip e . c

p a rt

p i p e _ r e s u l t .................................. 104

c r e w .c

p a rt

1 d e f i n i t i o n s ......................................................... 108

c r e w .c

p a rt

2 w o r k e r _ r o u t i n e ................................................... 110

c r e w .c

p a rt

3 c r e w _ c r e a t e ......................................................... 115

c r e w .c

p a rt

4 c r e w _ s t a r t ........................................................... 117

c r e w .c

p a rt

5 m a i n ..................................................................... 119

6 m a i n ..................................................................... 105

s e r v e r .c

p a rt

s e r v e r .c

p a r t 2 t t y _ s e r v e r _ r o u t i n e .........................................123

1 d e f i n i t i o n s ..................................................... 121

s e r v e r .c

p a rt

s e r v e r .c

p a r t 4 c l i e n t _ r o u t i n e .................................................127

xii

3 t t y _ s e r v e r _ r e q u e s t .........................................125

x Ui

E x a m p le p r og r a m s

s e r ve r .c

p a r t 5 m a in ................................................................... 129

o n c e . c ............................................................................................ 133 m u t e x _ a t t r . c ....................................................... * ........................ 136 c o n d _ a t t r . c ................................................................................... 137 t h r e a d _ a t t r . c ............................................................................... 140 c a n c e l.c

....................................................................................... 145

c a n c e l _ d is a b l e . c ......................................................................... 149 c a n ce l_ a s yn c < ,c . * ......................................................................... 152 c a n c e l _ c l e a n u p . c .............. .......................................................... 156 c a n c e l_ s u b c o n tr a c t . c ................................................................... 158 t s d _ o n c e . c ..................................................................................... 164 t s d _ d e s t r u c t o r . c ......................................................................... 169 s c h e d ^ a t t r . c ................................................................................. 176 s c h e d _ th r e a d . c ............................................................................. 179 a tfo r k . c flo c k . c

....................................................................................... 201 ..................................................................... .................... 2 0 5

p u tc h a r . c

..................................................................................... 2 0 8

g e t l o g i n , c ..................................................................................... 211 s u s p .c p a r t

1 s ig n a l - c a t c h in g fu n c t io n s .................................. 2 1 8

s u s p .c p a r t 2 i n i t i a l i z a t i o n

................................................... 2 2 0

s u s p .c p a r t 3 th d _ j3 u s p e n d ......................................................... 22 1 s u s p .c p a r t 4 t h d _ c o n t in u e ....................................................... 2 2 3 s u s p .c p a r t 5 s a m p le p r o g r a m ..................................................... 2 2 5 s ig w a it. c

..................................................................................... 2 2 8

s i g e v _ t h r e a d . c ............................................................................. 2 3 2 s e m a p h o r e 's i g n a l . c ..................................................................... 2 3 8 b a r r ie r . h

p a rt

b a r r ie r . h

p a r t 2 in te r fa c e s

1 b a r r i e r ^ t ....................................................... 2 4 5

b a r r ie r . c

p a rt

..................................................... 2 4 5

1 b a r r i e r ^ i n i t ................................................... 2 4 6

b a r r i e r • c p a r t 2 b a r r i e r _ d e s t r o y ............................................. 2 4 7 b a r r ie r . c

p a rt

3 b a r r i e r _ w a i t ................................................... 2 5 0

b a r r ie r _ m a in . c . ........................................................................... 2 51 r w lo c k . h

p a rt

r w lo c k . h

p a r t 2 in t e r f a c e s

1 r w l o c k _ t ....................................................... .. . 2 5 5

r w lo c k . c

p a rt

....................................................... 2 5 7

1 r w l _ i n i t ........................................................... 2 5 7

r w lo c k . c p a r t 2 r w l _ d e s t r o y ..................................................... 2 5 9 r w lo c k . c p a r t 3 c le a n u p h a n d l e r s .............................................2 6 0 r w lo c k . c p a r t 4 r w l _ r e a d l o c k ................................................... 261 r w lo c k . c p a r t 5 r w l _ r e a d t r y l o c k ............................................... 2 6 2 r w lo c k . c

p a r t 6 r w l_ r e a d u n lo c k ................................................. 2 6 3

r w lo c k . c p a r t

7 r w l _ w r it e l o c k ................................................... 2 6 3

r w lo c k . c p a r t 8 r w l _ w r i t e t r y l o c k ............................................. 2 6 4 r w lo c k . c

p a r t 9 r w l_ _ w r ite u n lo c k ............................................... 2 6 5

r w lo c k _ m a in . c ............................................................................... 2 6 6 w o r k q .h p a r t

1 w o r k q ^ t............................................................... 271

xiv

w o r k q .h

Exam ple program s

p a r t 2 i n t e r f a c e s ......................................................... 2 7 2

w o r k q .c p a r t

1 w o r k q _ in it ......................................................... 2 7 2

w o r k q .c p a r t 2 w o r k q _ d e s tr o y ...................................................2 7 4 w o r k q .c p a r t

3 w o r k q _ a d d ........................................................... 2 7 5

w o r k q .c p a r t 4 w o r k q _ s e r v e r ..................................................... 2 7 7 w o r k q _ jn a in . c ............................................................................... 2 8 0 i n e r t i a , c ..................................................................................... 291

P re fa c e

The W hite R a b b it p u t o n hi$ s p e c ta c le s , “W h ere s ha ll I b e g in , p le a s e y o u r M a je s ty ?” h e a s k e d . “B egin a t th e b e g in n in g ,” th e K ing said, v e ry g ra ve ly, "a n d g o o n till y o u c o m e to th e e n d : th e n s top ”

—Lewis Carroll, Alice's Adventures in Wonderland

T h is b o o k is a b o u t “th r e a d s ” a n d h o w to u s e th em . “T h r e a d ” is ju s t a n a m e for a b a s ic s oftw a r e “th in g ” th a t c a n d o w o r k on a com p u ter. A th r e a d is s m a ller, fa s ter, a n d m o r e m a n eu ver a b le th a n a tr a d itio n a l p r o ces s . In fa ct, o n c e th r ea d s h a ve b ee n a d d e d to a n o p e r a tin g s ys tem , a “p r o c e s s ” b e c o m e s ju s t d a ta — a d d r es s s p a ce, files , a n d s o fo r th — p lu s o n e o r m o r e th r ea d s th a t d o s o m eth in g w ith a ll th a t d a ta . W ith th r e a d s , yo u c a n b u ild a p p lic a tio n s th a t u tilize s ys te m r es o u r ce s m o r e e ffic ie n tly, th a t a r e m o r e fr ie n d ly to u s ers , th a t r u n b la zin g ly fa s t o n m u ltip r o c es s ors , a n d th a t m a y e ve n b e e a s ier to m a in ta in . T o a c c o m p lis h a ll th is , yo u n e ed o n ly a d d s om e r ela tive ly s im p le fu n c tio n c a lls to y o u r cod e, a d ju s t to a n e w w a y o f th in k in g a b o u t p r o g r a m m in g , a n d lea p o ve r a fe w ya w n in g c h a s m s . R e a d in g th is b o o k c a r e fu lly w ill, I h op e, h e lp yo u to a cc o m p lis h a ll th a t w ith o u t lo s in g y o u r s en s e o f h u m or. T h e th r e a d s

m od el u s ed

in

th is b o o k is

c o m m o n ly ca lled

“P th r e a d s ,” or

“P O S IX th r e a d s .” O r, m o r e fo r m a lly (s in ce yo u h a ve n ’t y e t b e e n p r o p er ly in tro d u c ed ), th e P O S IX 1003. lc - 1 9 9 5 s ta n d a r d . I’ll g ive yo u a fe w o th e r n a m e s la ter — b u t fo r n ow , “P th r e a d s ” is a ll yo u n e ed to w o r r y a b ou t. A s I w r ite th is , S u n ’s S ola r is , D ig ita l’s D ig ita l U N IX , a n d S G I’s IR IX a lr ea d y s u p p o r t P th r ea d s . T h e o th e r m a jo r c o m m e r cia l U N IX o p e r a tin g s ys te m s w ill s o o n h a ve P th r e a d s a s w ell, m a yb e e ve n b y th e tim e yo u r ea d th is , in c lu d in g IB M ’s A IX a n d H e w le tt- P a c k a r d ’s H P - U X . P th r e a d s im p le m e n ta tio n s a r e a ls o a va ila b le fo r L in u x a n d o th e r U N IX o p er a tin g s ys tem s . In th e p er s o n a l c o m p u te r m a r k et, M ic r o s o ft’s W in 3 2 A P I (th e p r im a r y p rog r a m m in g in ter fa c e to b o th W in d o w s N T a n d W in d o w s 9 5 ) s u p p o r ts th r ea d ed p ro g r a m m in g , a s d o e s IB M ’s O S / 2 . T h e s e th re a d ed p r o g r a m m in g m o d els a r e q u ite d iffe r e n t fr o m P th r ea d s , b u t th e im p o r ta n t fir s t s tep to w a r d u s in g th e m p ro d u c tive ly is u n d e r s ta n d in g c o n cu r r en c y, s yn ch r o n iza tio n , a n d s ch e d u lin g . T h e r e s t is (m or e or les s ) a m a tte r o f s yn ta x a n d s tyle, a n d a n e x p er ie n ce d th r e a d p rog r a m m er ca n a d a p t to a n y o f th es e m od els .

xv

xv i

Pr efa c e

T h e th r ea d ed m o d e l c a n b e (a n d h a s b een ) a p p lie d w ith g r ea t s u c ce s s to a w id e r a n g e o f p r o g r a m m in g p ro b lem s . H ere a r e ju s t a few : • •

L a r g e s ca le, c o m p u ta tio n a lly in ten s ive p ro g r a m s H ig h - p e r fo r m a n c e a p p lic a tio n p ro g r a m s a n d lib r a r y c od e th a t c a n ta k e a d va n ta g e o f m u ltip r o c e s s o r s ys te m s



L ib r a r y c od e th a t ca n b e u s ed b y th r ea d ed a p p lica tio n p ro g r a m s



R e a ltim e a p p lica tio n p r o g r a m s a n d lib r a r y cod e



A p p lic a tio n p ro g r a m s a n d lib r a r y c od e th a t p e r fo r m I/ O to s lo w e x te r n a l d evic e s (s u ch a s n e tw o r k s a n d h u m a n b ein g s ).

In te n d e d a u d ie n c e T h is b o o k a s s u m es th a t yo u a r e a n e x p e r ie n c ed p ro g r a m m er , fa m ilia r w ith d e ve lo p in g c od e fo r a n o p e r a tin g s ys te m in “th e U N IX fa m ily ” u s in g th e A N S I C la n g u a g e. I h a ve tr ie d n o t to a s s u m e th a t yo u h a ve a n y e x p e r ie n c e w ith th r ea d s o r o th e r fo r m s o f a s yn ch r o n ou s p ro g r a m m in g . T h e In tro d u ctio n ch a p te r p r o vid e s a g e n e r a l o ve r vie w o f th e te r m s a n d c o n ce p ts y o u ’ll n e ed fo r th e r es t o f th e b ook . I f yo u d o n ’t w a n t to r ea d th e In tr o d u c tio n firs t, th a t’s fin e, b u t if yo u e ve r fe e l lik e y o u ’re “m is s in g s o m e th in g ” yo u m ig h t tr y s k ip p in g b a c k to g e t in tro d u ce d . A lo n g th e w a y y o u ’ll fin d e x a m p le s a n d s im p le a n a lo g ie s fo r ever yth in g . In th e en d I h o p e th a t y o u ’ll b e a b le to c o n tin u e c o m fo r ta b ly th r e a d in g a lo n g o n yo u r ow n . H a ve fu n , a n d “h a p p y th r e a d in g .”

A b o u t th e a u th o r I h a ve b e en in vo lve d in th e P th r ea d s s ta n d a r d s in c e it b e g a n , a lth o u g h I s ta ye d a t h o m e fo r th e fir s t fe w m eetin g s . I w a s fin a lly fo r c ed to s p en d a g r u e lin g w e e k in th e a va la n c h e - p r o o f c o n cr e te b u n k e r a t th e b a s e o f S n o w b ir d s k i r e s o r t in

U ta h , w a tc h in g h a r d - w o r k in g

s ta n d a r d s

r e p r e s e n ta tive s

fr o m

a r ou n d

th e

w o r ld w a x th eir s k is . T h is w a s ve r y d is tra ctin g , b e ca u s e I h a d ex p ec te d a s ta n d a rds

m ee tin g to b e

a

fo r m a l

and

s tu ffy e n vir o n m e n t.

As

a

r es u lt o f th is

m is u n d e r s ta n d in g , I w a s fo r ced to r en t s k i e q u ip m en t in s te a d o f u s in g m y ow n . A fte r th e P th r e a d s s ta n d a r d w e n t in to b a llotin g , I w o r k ed on a d d ition a l th r e a d s yn ch r o n iza tio n in te r fa c e s a n d m u ltip r o c e s s o r is s u e s w ith s e ve r a l P O S IX w o rk in g g r o u p s . I a ls o h e lp e d to d e fin e th e A s p e n th r ea d s e x ten s io n s , w h ic h w e r e fa s ttr a c k ed in to X / O p e n X S H 5 . I h a ve w o r k e d a t D ig ita l E q u ip m e n t C o r p o r a tio n fo r (m u m b le, m u m b le) yea rs , in va r io u s lo c a tio n s th r o u g h o u t M a s s a ch u s e tts a n d N e w H a m p s h ire . I w a s on e o f th e c r e a to r s o f D ig ita l’s ow n th r e a d in g a r ch ite ctu r e, a n d I d es ig n e d (a n d im p lem e n te d m u c h of) th e P th r ea d s in te r fa ce s on D ig ita l U N IX 4 .0. I h a ve b e en h e lp in g p e o p le d eve lo p a n d d e b u g th r ea d ed c od e fo r m o r e th a n e ig h t yea r s .

xv ii

Pr efa c e

M y u n o ffic ia l m o tto is “B e tte r L ivin g T h r o u g h C o n c u r r e n c y.” T h r e a d s a r e n o t s liced b r ea d , b u t th en , w e ’re p r o g r a m m e r s , n o t b a k er s , s o w e d o w h a t w e ca n .

A c k n o w le d g m e n ts T h is is th e p a r t w h e r e I w r ite th e s tu ff th a t I’d lik e to s ee p r in ted , a n d th a t m y fr ien d s a n d c ow o r k er s w a n t to s ee. Y ou p r o b a b ly d o n ’t ca re, a n d I p ro m is e n o t to b e a n n o yed if yo u s k ip o ve r it— b u t if y o u ’re c u r iou s , b y a ll m ea n s r ea d on . N o p r o je c t s u ch a s th is b o o k c a n tr u ly b e a c co m p lis h e d b y a s in g le p er s on , d e s p ite th e fa c t th a t o n ly o n e n a m e a p p e a rs on th e cover. I co u ld h a ve w r itte n a b o o k a b o u t th re a d s w ith o u t a n y h e lp — I k n o w a g r ea t d ea l a b o u t th r ea d s , a n d I a m a t lea s t r ea s o n a b ly c o m p e te n t a t w r itte n c o m m u n ic a tio n . H ow ever, th e r e s u lt w o u ld n o t h a ve b e e n this b oo k , a n d this b o o k is b e tte r th a n th a t h yp oth etic a l w o r k co u ld p o s s ib ly h a ve b een . T h a n k s fir s t a n d fo r e m o s t to m y m a n a g e r J e a n F u ller to n , w h o g a ve m e th e tim e a n d e n c o u r a g e m e n t to w r ite th is b o o k o n th e jo b — a n d th a n k s to th e r es t o f th e D E C th r e a d s

te a m w h o k e p t th in g s g o in g w h ile I w r ote , in c lu d in g B r ia n

K ea n e, W eb b S ca les , J a c q u e lin e B erg , R ic h a r d L ove, P e te r P or ta n te , B r ia n S ilver, M a r k S im on s , a n d S teve J oh n s on . Th a n k s

to G a r re t S w a r t w h o,

w h ile h e w a s w ith

D ig ita l a t th e S ys te m s

R e s e a r c h C en ter, g ot u s in vo lved w ith P O S IX . T h a n k s to N a w a f B ita r w h o w o r k e d w ith G a r re t to crea te, lite r a lly o ver n ig h t, th e fir s t d r a ft o f w h a t b e ca m e P th r ea d s , a n d w h o b e ca m e P O S IX th re a d e v a n g e lis t th r o u g h th e d iffic u lt p er io d o f g e ttin g ever yo n e to u n d e r s ta n d ju s t w h a t th e h e c k th is th r e a d in g th in g w a s a ll a b o u t a n yw a y. W ith o u t G a r ret, a n d e s p e c ia lly N a w a f, P th r e a d s m ig h t n o t ex is t, a n d ce rta in ly

w o u ld n ’t b e

as

good

as

it

is .

(Th e

la c k

o f p e r fe c tio n

is

n ot

th eir

r es p o n s ib ility— th a t’s th e w a y life is .) T h a n k s to e ve r yo n e w h o c o n tr ib u te d to th e d e s ig n o f cm a , P th r ea d s , U N IX 9 8 , a n d to th e u s e r s o f D C E th r e a d s a n d D E C th r ea d s , for a ll th e h elp , th ou g h t- p r o vo k in g

d is co u r s e ,

and

a s s o r ted

s k in - th ick e n in g

ex er cis es ,

in c lu d in g A n d r e w

B irr ell, P a u l B or m a n , B ob C on ti, B ill C ox , J e ff D en h a m , P e te r G ilb er t, R ic k G reer, M ik e G rier, K evin H a r ris , K e n H ob d a y, M ik e J o n e s , S teve K leim a n , B o b K n ig h ten , L e s lie L a m p or t, D ou g L ock e, P a u la L on g , F in n b a r r P. M u r p h y, B ill N oyce, S im o n P a tien ce, H a r old S eigel, A1 S im on s , J im W o od w a r d , a n d J o h n Z o ln o w s k y. M a n y th a n k s to a ll th o s e w h o p a tie n tly r evie w e d th e d r a fts o f th is b o o k (a n d even to th os e w h o d id n ’t s eem s o p a tien t a t tim es ). B r ia n K e m ig h a n , R ich S teven s , D a ve B r o w n e ll, B ill G a llm eis ter , Ila n G in zb u r g , W ill M or s e, B r ya n O ’S u lliva n , B ob R o b illa r d , D a ve R u d d oc k , B il L ew is , a n d m a n y o th e rs s u g g e s ted o r m o tiva ted im p r o ve m e n ts in s tr u c tu r e a n d d eta il— a n d p ro vid ed a d d itio n a l s k in - th ick e n in g e x e r cis es to k ee p m e in s h a p e. D e va n g S h a h a n d B a r t S m a a ld e r s a n s w er ed s om e S o la r is q u e s tion s , a n d B r ya n O ’S u lliva n s u g g e s ted w h a t b e c a m e th e “b a ilin g p rog r a m m e r s ” a n a log y.

xv iii

Pr efa c e

T h a n k s to J o h n W a it a n d L a n a L a n g lo is a t A d d is o n W e s ley L on g m a n , w h o w a ite d w ith g r e a t p a tie n c e a s a fir s t- tim e w r ite r s tr u g g le d to b a la n c e w r itin g a b o o k w ith e n g in e e r in g a n d c o n s u ltin g c om m itm e n ts . T h a n k s to P a m ela Y ee a n d E r in S w ee n ey, w h o m a n a g ed th e b o o k ’s p ro d u c tio n p r o ces s , a n d to a ll th e tea m (m a n y o f w h o s e n a m e s I’ll n e ve r k n o w ), w h o h e lp e d . T h a n k s to m y w ife, A n n e L ed er h o s , a n d o u r d a u g h te r s A m y a n d A lys s a , fo r a ll th e th in g s fo r w h ic h a n y w r ite rs m a y th a n k th e ir fa m ilies , in c lu d in g s u p p or t, toler a n c e, a n d ju s t b e in g th er e. A n d th a n k s to C h a r les D o d g s o n (L e w is C a r r oll), w h o w r o te e x ten s ive ly a b o u t th r e a d ed p r o g r a m m in g (a n d n e a r ly e ver yth in g els e) in h is cla s s ic w o r k s A lic e ' s A d v e n tu re s in W o n d e rla n d , T h ro u g h the L o o k in g - G la s s , a n d Th e H u n tin g o f the S n a rk .

D a ve B u te n h o f D ig ita l E q u ip m en t C o r p o r a tio n 110 S p it B r o o k R oa d , Z K 0 2 - 3 / Q 1 8 N ashu a, N H 03062 b u te n h o f@ zk o .d ec .com D e c em b e r 1996

1 In tro d u c tio n

,,The tim e h as c o m e ,” th e Walrus said, ,,To ta lk o f m a n y things; O f shoes— a n d ships— a n d s e a lin g w a x — O f c a b b a g e s — a n d kings— A n d w h y th e s e a is b o ilin g h o t— A n d w h e th e r p ig s h a v e w in g s ”

—Lewis Carrol Through the Looking-Glass

In a d iction a r y, yo u w o u ld p r o b a b ly s ee th a t o n e o f s e ve r a l d e fin ition s for “th r ea d " is a lo n g th e lin e s o f th e th ird d efin itio n in th e A m e r ic a n H e r ita g e p a p er b a c k d ic tio n a r y on m y d es k : “A n yth in g s u g g e s tive o f th e c o n tin u o u s n es s a n d s e q u e n c e o f th r e a d .” In c o m p u te r ter m s , a th r ea d is th e s et o f p ro p er tie s th a t s u g g e s t “c o n tin u o u s n e s s a n d s e q u e n c e ” w ith in th e m a ch in e. A th r e a d c o m p ris e s th e m a c h in e s ta te n ec e s s a r y to e x ecu te a s e q u e n c e o f m a c h in e in s tr u c tio n s — th e loca tio n o f th e c u r r e n t in s tr u ctio n , th e m a c h in e’s a d d r es s a n d d a ta reg is ters , a n d so forth . A U N IX p r o c es s c a n b e th o u g h t o f a s a th rea d , p lu s a n a d d r es s s p a ce, file d e s c rip tor s , a n d a n a s s o r tm e n t o f o th e r d a ta . S o m e ve r s io n s o f U N IX s u p p o r t “lig h tw e ig h t” or “va r ia b le w e ig h t” p r o c es s e s th a t a llo w yo u to s tr ip s o m e o r a ll o f th a t d a ta fr o m s om e o f y o u r p r o ce s s e s fo r efficien c y. N ow , w h e th e r y o u ’re u s in g a “th r e a d ” or a “lig h tw e ig h t p r o c e s s ,” yo u s till n eed th e a d d r es s s p a ce, file d es cr ip tors , a n d e ve r yth in g els e. S o, y o u m ig h t a s k , w h a t’s th e p o in t? T h e p o in t is th a t yo u c a n h a ve m a n y th r e a d s s h a r in g a n a d d r e s s s p a ce, d o in g d iffer e n t th in g s . O n a

m u ltip r o c es s or ,

th e

th r e a d s

in

a

p r o ces s

ca n

be

d oin g

d iffe r e n t th in g s

s im u lta n e ou s ly. W h e n c om p u ter s lived in g la s s c a ves a n d w e r e fed c a r e fu lly p r e p a r ed p u n c h ca rd s , th e r ea l w o r ld o u ts id e c ou ld b e k e p t w a itin g w ith n o c on s e q u e n c e s m or e s eve r e th a n s om e g r u m b lin g p r o g r a m m e r s . B u t th e r ea l w o r ld d o e s n ’t d o on e th in g a t a tim e, a n d g r a d u a lly c o m p u te rs b e g a n to m o d e l th a t w o r ld b y a d d in g ca p a b ilities s u ch a s m u ltip r o g r a m m in g , tim e s h a rin g , m u ltip r o c es s in g , a n d , even tu a lly, th rea d s . T h r e a d s c a n h elp yo u b r in g y o u r a p p lic a tio n ou t o f th e ca ve, a n d P th r ea d s h elp s yo u d o it in a w a y th a t w ill b e n ea t, e fficien t, a n d p or ta b le. T h is c h a p te r b r ie fly in tr o d u c es yo u

to w h a t yo u

n e ed

to b e g in

u n d e r s ta n d in g a n d

u s in g

th r ea d s . D o n ’t w o r r y— th e r es t o f th e b o o k w ill fo llo w u p o n th e d eta ils left d a n g lin g in th is ch a p ter. S e c tio n 1.1 p re s e n ts th e fr a m e w o r k fo r a n u m b e r o f a n a log ie s th a t I w ill u s e to e x p la in th r e a d in g a s w e go. T h e r e is n o th in g a ll th a t u n u s u a l in th e b r ie f s to r y—

1

2

CH A P T E R 1

In t r odu c t ion

b u t h er e a fte r yo u w ill u n d e r s ta n d w h e n I ta lk a b o u t p r o g r a m m e r s a n d b u c k ets , w h ich , oth e rw is e , m ig h t s eem m ild ly od d . S e ctio n 1.2 d efin es s om e e s s e n tia l c o n ce p ts a n d ter m s u s ed in th is b ook . T h e m o s t im p o r ta n t o f th es e c o n ce p ts d es e r ve s a s p ec ia l in tr o d u ction , w h ic h w ill a ls o s er ve to d e m o n s tr a te th e c o n ve n tio n w ith w h ic h va r io u s p a r tic u la r ly im p o r ta n t p oin ts s h a ll b e e m p h a s ize d th r o u g h o u t th is b ook : A s y n c h ro n o u s :

I

A n y tw o o p e r a tio n s a r e " a s y n c h ro n o u s " w h e n t h e y c a n p r o c e e d in d e p e n d e n t ly o f e a c h o th e r.

S ec tio n 1.3 d e s c r ib es h o w yo u a lr ea d y u s e a s yn ch r on o u s p r o g r a m m in g on a r e g u la r b a s is , b o th a s a U N IX p r o g r a m m e r a n d u s er, a n d a s a h u m a n b e in g in th e r ea l w o r ld . I w o u ld n ’t d a r e to c la im th a t a s yn ch r o n o u s p r o g r a m m in g is ea s y, b u t th e b a s ic c o n ce p ts it tr ies to m o d e l a r e s o e a s y a n d n a tu r a l th a t yo u r a r e ly n eed e ven to th in k a b o u t th em u n til yo u tiy to a p p ly th e m to s oftw a re. T h r e a d s a re, to s om e ex ten t, ju s t o n e m o r e w a y to m a k e a p p lic a tio n s a s yn ch r on ou s , b u t th r e a d s h a ve s o m e a d va n ta g es o ve r o th e r m o d e ls th a t h a ve b een u s ed to b u ild a s yn c h r o n o u s a p p lic a tion s . S e ctio n 1.5 w ill s h o w yo u s om e o f th e a d va n ta g es a s w e a p p ly va r io u s p r o g r a m m in g m eth o d s in s eve ra l ve r s io n s o f a s im p le a la r m clock . Y ou w ill g et to s ee “th r ea d s in a c tio n ’' r ig h t a w a y, w ith a b r ie f d e s c r ip tio n o f th e fe w P th r e a d s in ter fa ce s n e ed ed to b u ild th is s im p le a p p lica tion . A r m e d , n ow , w ith a b a s ic u n d e r s ta n d in g o f w h a t th r e a d s a r e a ll a b ou t, yo u c a n g o o n to S ec tio n 1.6, w h e r e w e w ill e x p lo r e s o m e o f th e fu n d a m e n ta l a d va n ta g es o f a th r ea d ed p r o g r a m m in g m od el. A lth o u g h th e r e a r e a lo t o f e x c e lle n t r e a s o n s to u s e th r e a d s , th er e is a p r ic e to b e p a id . S ec tio n 1.7 p r o vid e s a c o u n te r p o in t to th e p r evio u s s e c tio n b y d e s c r ib in g s om e o f th e cos ts . W h a t it b oils d ow n to, th ou g h , is s im p ly th a t yo u n eed to lea r n h o w th e m o d e l w o rk s , a n d th en a p p ly it c a r efu lly. It is n o t a s h a r d a s s om e fo lk s w o u ld h a ve yo u b elieve. Y ou h a ve s een s om e o f th e fu n d a m en ta l b e n e fits a n d cos ts . It m a y b e o b vio u s th a t yo u d o n o t w a n t to r u s h o u t a n d p u t th r ea d s in to e ver y a p p lica tio n or lib r a r y y o u w r ite . S ec tio n 1.8 a s k s th e q u e s tio n ‘T o th rea d , o r n o t to th r e a d ?” a n d I w ill a tte m p t to g u id e yo u to w a r d d e te r m in in g th e p r o p e r a n s w e r in va r io u s ca s es . Y ou w ill k n o w a t th a t p o in t w h a t th r ea d s a re, w h a t th e y d o, a n d w h e n to u s e th em . A s id e fr o m b r ie f ex a m p les , yo u h a ve n ’t y e t s een a n y d e ta iled in fo r m a tio n a b o u t th e p a r tic u la r p r o g r a m m in g in ter fa ce s (A P Is ) th a t c om p o s e P th r ea d s . S ectio n 1.9 p o in ts o u t s om e o f th e b a s ic la n d m a r k s o f th e P th r ea d s u n ive r s e to g et yo u o r ien te d b e fo r e w e p lu n g e a h ea d . T h e m o s t im p o r ta n t p a r t o f th is s e ction is 1.9.3, w h ic h d e s c r ib es th e P th r ea d s m o d e l fo r r e p o r tin g e r r o r s — w h ich is s om ew h a t d iffe r e n t th a n th e r e s t o f U N IX a n d P O S IX .

3

T h e “ba i l i n g p r o g r a m m e r s ”

1.1 The "b a ilin g p ro g ra m m e rs " This w as c h a rm in g , n o d o u b t: b u t th e y shortly fo u n d o u t That th e C a p ta in th e y tru sted so w eli H a d o n ly o n e n o tion for crossing th e o c e a n , A n d th a t w as to tin g le his b ell.

—Lewis Carroll, The Hunting of the Snark

Three p ro g ra m m e rs sail o u t to se a o n e fin e d a y in a sm all b o a t, They sail q u ite s o m e dista n c e fro m shore, e n jo y in g th e sun a n d se a b re e z e , a llo w in g th e w in d to c a rry th e m . The sky d a rk e n s , a n d a storm strikes. The sm all b o a t is to ss ed v io le n tly a b o u t, a n d w h e n th e storm a b a te s th e p ro g ra m m e rs a re missing th e ir b o a t's sail a n d m o s t o f th e m ast. The b o a t has s prun g a sm all le a k , a n d th e re is n o la n d in sight. The b o a t is e q u ip p e d w ith fo o d , w a te r, oars, a n d a b a ilin g b u c k e t, a n d th e p ro g ra m m e rs set to w ork. O n e p ro g ra m m e r rows, a n d m o n ito rs th e a c c u m u la tin g w a te r in th e b o tto m o f th e b o a t. The o th e r p ro g ra m m e rs a lte rn a te ly s le e p , w a tc h th e w a te r le ve l, o r s c a n th e h oriz on fo r s igh t o f la n d o r a n o th e r ship. A n id le p ro g ra m m e r m a y n o tic e rising w a te r in th e b o a t, a n d b e g in b a ilin g . W h e n b o th id le p ro g ra m m e rs a re a w a k e , a n d b e c o m e s im u lta n e o u s ly c o n c e r n e d re g a rd in g th e ir in c re a s in g d a m p n e s s , th e y m a y b o th lu n g e fo r th e b a ilin g b u c k e t— b u t o n e will in e v ita b ly re a c h it first, a n d th e o th e r w ill h a v e to w a it. If th e ro w e r d e c id e s t h a t b a ilin g is re q u ire d w h ile b o th his c o m p a n io n s s le e p , a n u d g e is usually s u fficien t to a w a k e n a p ro g ra m m e r, a llo w in g th e o th e r to c o n tin u e sle e p in g . But if th e row e r is in a b a d m o o d , h e m a y resort to a lo u d yell, a w a k e n in g b o th s le e p in g prog ra m m ers . W hile o n e p ro g ra m m e r assum es th e n e c e s s ary d u ty , th e o th e r c a n try to fall a s le e p a g a in . W h e n th e ro w er tires, h e c a n signal o n e o f th e o th e r p ro g ra m m e rs to ta k e o v e r th e task, a n d im m e d ia te ly fall in to a d e e p s le e p w a itin g to b e s ig n a le d in turn. In this w a y, th e y jo u rn e y o n fo r s o m e tim e . S o, ju s t w h a t d o th e B a ilin g P r o g r a m m e r s h a ve to d o w ith th r e a d s ? I’m g la d yo u

a s k ed ! T h e e lem e n ts

o f th e s to r y r e p r es en t a n a lo g ie s

th a t a p p ly to th e

P th r e a d s p r o g r a m m in g m od el. W e ’ll e x p lo r e s om e a d d itio n a l a n a lo g ie s in la te r s ection s , a n d e ve n e x p a n d th e s to r y a little, b u t fo r n o w co n s id e r a fe w b a s ics : A p ro g ram m e r is a n e n tity th a t is c a p a b le o f in d e p en d e n t a ctivity. O u r p rogra m m ers

r ep r e s e n t

th rea d s .

A

th r ea d

is

n ot

r ea lly

m u ch

lik e

a

p ro g r a m m er , w h o, a s w e a ll k n o w , is a fa s c in a tin g ly s o p h is tica ted m ix tu r e o f en g in eer, m a th e m a tic ia n , a n d a r tis t th a t n o c o m p u te r c a n m a tch . S till, a s a r ep r es e n ta tio n o f th e “a c tive e le m e n t” in o u r p r o g r a m m in g m od el, it w ill b e s u fficien t. T h e bai li n g buc k e t a n d th e o ars a r e “to k e n s ” th a t c a n b e h e ld b y o n ly on e in d ivid u a l a t a tim e. T h e y ca n b e th o u g h t o f a s s h a r ed d a ta , o r a s s yn ch r on iza tio n ob jects . T h e p r im a r y P th r ea d s s yn c h r o n iza tio n ob ject, b y th e w a y, is ca lled a m u tex.

4

CHA P T E R 1

In tr odu c t io n

Nud g e s a n d sho ut s a r e c o m m u n ica tio n m ec h a n is m s a s s oc ia te d w ith a s yn c h r o n iza tio n

ob ject,

on

w h ic h

in d ivid u a ls

w a it

fo r

s om e

con d ition .

P th r e a d s p ro vid es co n d itio n v a ria b le s , w h ich m a y b e s ig n a led o r b r o a d c a s t to in d ic a te c h a n g e s in s h a r ed d a ta s ta te.

1.2 D efinitions a n d te rm in o lo g y ,,W hen I use a w o r d ” H u m p ty D u m p ty said, in ra th e r a sco rn ful to n e , ,,it m e a n s just w h a t I c h o o s e it to m e a n — n e ith e r m o re n o r less ”

—Lewis Carroll,Through the Looking-Glass

T h is b o o k w ill u s e s e ve r a l c r itic a l ter m s th a t m a y b e u n fa m ilia r to yo u u n les s yo u V e a lr e a d y h a d s om e e x p e r ie n c e w ith p a r a llel o r a s yn c h r o n o u s p r o g r a m m in g . E ve n if y o u a r e fa m ilia r w ith th em , s om e o f th e te r m s h a ve s een a s s o r ted a n d e ven c o n tr a d ic to r y u s es w ith in r es e a r c h a n d in d u s tr y, a n d th a t is c le a r ly n o t g o in g to h e lp c o m m u n ica tio n . W e n eed to b eg in b y c o m in g to a m u tu a l a g r ee m e n t r eg a r d in g th e m ea n in g o f th es e term s , a n d , s in c e I a m w r itin g th e b ook , w e w ill a g r e e to u s e m y d efin itio n s . (T h a n k yo u .)

1.2.1

A s yn ch ro n o u s A s y n ch ro n o u s m e a n s th a t th in g s h a p p e n in d e p e n d e n tly (co n cu r r en tly) u n les s

th e r e ’s s om e e n fo r c ed d e p e n d en c y. L ife is a s yn c h r o n ou s . T h e d e p e n d e n c ie s a re s u p p lied b y n a tu r e, a n d e ve n ts th a t a r e n o t d e p e n d en t on o n e a n o th e r c a n o c c u r s im u lta n e ou s ly. A p r o g r a m m e r c a n n o t r o w w ith o u t th e oa rs , o r b a il e ffec tive ly w ith o u t th e b u c k e t— b u t a p r o g r a m m e r w ith oa rs c a n r o w w h ile a n o th er p rog r a m m e r w ith a b u c k e t b a ils . T r a d itio n a l c o m p u te r p r o g r a m m in g , on th e o th e r h a n d , c a u s e s a ll e ve n ts to o c c u r in s e ries u n le s s th e p r o g r a m m e r ta k es “e x tr a o r d in a r y m e a s u r e s ” to a llo w th e m to h a p p e n c o n cu r r en tly. T h e g r e a te s t c o m p lic a tio n o f “a s yn c h r o n y” h a s b e e n th a t th e r e ’s little a d va n ta g e to b e in g a s yn c h r o n o u s u n le s s yo u c a n h a ve m o r e th a n o n e a c tivity g o in g a t a tim e. If yo u c a n s ta r t a n a s yn c h r o n o u s op e r a tion , b u t th en yo u c a n d o n o th in g b u t w a it fo r it, y o u ’r e n o t g e ttin g m u c h b e n e fit fr o m th e a s yn c h r on y.

1.2 .2

C o n c u rre n c y C o n cu rre n cy , w h ic h a n E n g lis h d ic tio n a r y w ill tell yo u r efer s to th in g s h a p -

p e n in g a t th e s a m e tim e, is u s ed to r e fe r to th in g s th a t a p p e a r to h a p p en a t th e s a m e tim e, b u t w h ic h m a y o c c u r s eria lly. C o n c u r r e n c y d es cr ib e s th e b e h a vio r o f th r ea d s o r p r o c e s s e s o n a u n ip r o c e s s o r s ys tem . T h e d e fin itio n o f c o n cu r r e n t

5

D efi n i t i o n s a n d ter m i n o l o g y

e x e c u tio n in P O S IX r eq u ir e s th a t “fu n c tio n s th a t s u s p e n d th e e x e cu tio n o f th e c a llin g th r ea d s h a ll n o t c a u s e th e e x e c u tio n o f o th e r th r e a d s to b e in d e fin ite ly s u s p e n d e d .” C o n cu r r e n t o p e r a tio n s

m ay be

a r b itra r ily in te r le a ve d

so

th a t th e y m a k e

p ro g r e s s in d e p e n d e n tly (on e n e ed n o t b e c om p lete d b efor e a n o th er b e g in s ), b u t c on c u r r e n c y d oes n o t im p ly th a t th e o p e r a tio n s p ro c ee d s im u lta n e ou s ly. N eve r th eles s ,

c o n c u r r e n c y a llo w s

a p p lic a tio n s

to ta k e a d va n ta g e o f a s yn ch r on o u s

ca p a b ilities , a n d “d o w o r k ” w h ile in d e p e n d e n t o p e r a tio n s a re p r o cee d in g . M o s t p r o g r a m s h a ve a s yn c h r o n o u s a s p e cts th a t m a y n o t b e im m e d ia tely ob viou s . U s ers , fo r ex a m p le, p r e fe r a s yn c h r o n o u s in ter fa c es . T h e y e x p e c t to b e a b le to is s u e a c om m a n d w h ile th e y’re th in k in g a b o u t it, e ven b efo r e th e p r o g r a m h a s fin is h e d w ith th e la s t on e. A n d w h e n a w in d o w in g in ter fa c e p r o vid es s ep a r a te w in d o w s ,

d o n ’t yo u

in tu itive ly e x p e ct th o s e w in d o w s to a c t a s yn c h r o n o u s ly?

N o b o d y lik e s a “b u s y ” cu rs or. P th r e a d s p r o vid e s yo u w ith b o th c o n c u r r e n c y a n d a s yn c h r on y, a n d th e c o m b in a tio n is e x a c tly w h a t yo u n eed to e a s ily w r ite r es p on s ive a n d e ffic ie n t p r o g r a m s . Y o u r p r o g r a m c a n “w a it in p a r a lle l” fo r s low I/ O d evices , a n d a u to m a tic a lly ta k e a d va n ta g e o f m u ltip r o c e s s o r s ys te m s to co m p u te in p a r a llel.

1.2.3

U nipro cessor a n d m u ltip ro c ess o r T h e te r m s u n ip ro ce s s o r a n d m u ltip ro ce s s o r a re fa ir ly s tra ig h tfor w a r d , b u t le t’s d efin e th em ju s t to m a k e s u r e th e r e ’s n o c on fu s ion . B y u n ip ro ce s s o r I m ea n a c o m p u ter w ith a s in g le p r o g r a m m e r - vis ib le e x ec u tio n u n it (p r o ces s or ). A s in g le g e n e r a l- p u r p o s e p r o c e s s o r w ith s u p e r s c a la r p ro ces s in g , o r ve c to r p r o ces s o r s , o r o th e r m a th o r I/ O c op r o c e s s o r s is s till u s u a lly c o n s id e r ed a u n ip r oces s or . B y m u ltip ro ce s s o r I m ea n a c o m p u te r w ith m o r e th a n on e p r o c es s o r s h a r in g a c o m m o n in s tr u c tio n s et a n d a c ce s s to th e s a m e p h ys ica l m em or y. W h ile th e p roc es s o r s n eed n o t h a ve e q u a l a c ce s s to a ll p h ys ic a l m em or y, it s h o u ld b e p os s ib le fo r a n y p r o c e s s o r to g a in a c ce s s to m o s t m em or y. A “m a s s ive ly p a r a lle l p r o c e s s o r ” (M P P ) m a y o r m a y n o t q u a lify a s a m u ltip r o c e s s o r fo r th e p u r p o s es o f th is b ook . M a n y M P P s ys te m s d o q u a lify, b e c a u s e th ey p ro vid e a cc es s to a ll p h ys ic a l m em o r y fr o m e ve r y p roces s or , e ve n th o u g h th e a cc es s tim e s m a y v a r y w id e ly.

1.2.4

P arallelism P a ra lle lis m d e s c r ib es c o n cu r r e n t s e q u e n c es th a t p r o ce ed s im u lta n e ou s ly. In

o th e r w o r d s , s oftw a r e “p a r a lle lis m ” is th e s a m e a s E n g lis h “c o n cu r r e n c y” a n d d iffe r en t fr o m s oftw a r e “c o n c u r r e n c y.” P a r a llelis m h a s a va g u e ly r e d e e m in g a n a lo g y to th e E n g lis h d efin ition : It r efer s to th in g s p r o c e e d in g in th e s a m e d ir e ctio n in d e p e n d e n tly (w ith ou t in ter s e ction ). T r u e p a r a llelis m ca n o c c u r o n ly o n a m u ltip r o c e s s o r s ys tem , b u t c o n c u r r e n c y ca n o c c u r on b o th u n ip r o ce s s o r a n d m u ltip r o c e s s o r s ys tem s . C o n c u r r en c y c a n

6

CH A P T E R 1

In t r odu c t io n

o cc u r o n a u n ip r o c e s s o r b e ca u s e c o n c u r r e n c y is , e s s e n tia lly, th e illu s io n o f p a r a llelis m .

W h ile

p a r a llelis m

r eq u ir e s

th a t a

p rogra m

be

a b le

to

p e r fo r m

tw o

c o m p u ta tio n s a t on ce, c o n c u r r e n c y r e q u ir es o n ly th a t th e p r o g r a m m e r b e a b le to p r e ten d th a t tw o th in g s ca n h a p p e n a t on ce.

1.2.5 T h re a d s a fe ty a n d re e n tra n c y ‘T h r e a d - s a fe ” m e a n s th a t th e cod e ca n b e c a lled fr o m m u ltip le th r e a d s w ith o u t d e s tr u c tive r es u lts .

It d oe s

n o t r eq u ir e th a t th e c o d e r u n

e fficie n tly

in

m u ltip le th rea d s , o n ly th a t it ca n o p er a te s a fe ly in m u ltip le th r e a d s . M o s t ex is tin g

fu n ctio n s

m u te x e s ,

ca n

be

m ade

c o n d itio n va r ia b le s ,

th r ea d - s a fe and

u s in g

to o ls

p ro vid ed

th r e a d - s p ec ific d a ta .

b y P th r e a d s —

F u n ctio n s

th a t d o n ’t

r e q u ir e p e r s is te n t c o n te x t c a n b e m a d e th r e a d - s a fe b y s e r ia lizin g th e e n tir e fu n ction , fo r ex a m p le, b y lo ck in g a m u te x o n e n tr y to th e fu n c tio n , a n d u n lo c k in g th e m u te x b e fo r e r etu r n in g . F u n c tio n s m a d e th r e a d - s a fe b y s e r ia lizin g th e en tire fu n ctio n c a n b e c a lled in m u ltip le th r ea d s — b u t o n ly on e th r e a d c a n tr u ly p e r fo r m th e fu n c tio n a t a tim e. M o r e u s efu lly, th r e a d - s a fe fu n ctio n s c a n b e b r o k en d ow n in to s m a lle r c r itic a l s ection s . T h a t a llo w s

m or e th a n

on e th r e a d

to e x e c u te w ith in

th e fu n ction ,

a lth o u g h n o t w ith in th e s a m e p a rt. E ven b etter, th e c od e c a n b e r ed e s ig n ed to p r o te c t c r itic a l d a ta r a th e r th a n c ritic a l cod e, w h ich m a y a llo w fu lly p a r a lle l ex ec u tio n o f th e cod e, w h e n th e th r ea d s d o n ’t n e ed to u s e th e s a m e d a ta a t th e s a m e tim e. T h e p u tc h a r fu n c tion , fo r ex a m p le, w h ic h w r ite s a c h a r a c te r in to a s ta n d a r d I/ O (s td io ) b u ffer , m ig h t b e m a d e th r ea d - s a fe b y tu r n in g p u tc h a r in to a c ritic a l s ection . T h a t is , p u tc h a r m ig h t lo c k a “p u tc h a r m u te x ,” w r ite th e ch a r a cter , a n d th en u n lo ck th e p u tc h a r m u tex . Y ou cou ld c a ll p u tc fia r fr o m tw o th rea d s , a n d n o d a ta w o u ld b e c o r r u p te d — it w o u ld b e th r e a d - s a fe. H ow ever, o n ly on e th r ea d cou ld w r ite its c h a r a c te r a t a tim e, a n d th e o th e r s w o u ld w a it, e ven if th e y w er e w r itin g to d iffe r e n t s td io s tr ea m s . T h e c o r r e c t s o lu tio n is to a s s oc ia te th e m u te x w ith th e s trea m , p r o te c tin g th e d a ta r a th e r th a n th e cod e. N o w yo u r th rea d s , a s lo n g a s th e y a r e w r itin g to d iffe re n t s tr ea m s , c a n e x e c u te p u tc h a r in p a r a lle l. M o r e im p o r ta n tly, a ll fu n c tio n s th a t a c ce s s a s tr ea m c a n u s e th e s a m e m u te x to s a fe ly c oo r d in a te th e ir a c ce s s to th a t s tr ea m . T h e te r m “r e e n tr a n t” is s o m etim e s u s ed to m ea n “e ffic ie n tly th r e a d - s a fe .” T h a t is , th e c od e w a s m a d e th r e a d - s a fe b y s o m e m o r e s op h is tic a te d m ea s u r es th a n c o n ver tin g th e fu n c tio n or lib r a r y in to a s in g le s e ria l r eg ion . A lth o u g h e x is tin g c od e ca n u s u a lly b e m a d e th r ea d - s a fe b y a d d in g m u tex es a n d th r ea d - s p ec ific d a ta , it is o ften n e c e s s a r y to c h a n g e th e in ter fa c e to m a k e a fu n c tio n r een tr a n t. R e en tr a n t co d e s h o u ld a void r e lyin g o n s ta tic d a ta a n d , id ea lly, s h o u ld a void relia n ce on a n y fo r m o f s yn c h r o n iza tio n b e tw e e n th rea d s . O ften , a fu n c tio n c a n a void in ter n a l s yn c h r o n iza tio n b y s a vin g s ta te in a “con te x t s tr u c tu r e ” th a t is c o n tr o lle d b y th e ca ller. T h e c a lle r is th en r es p o n s ib le fo r

7

D ef i n i t i o n s a n d t er m i n o l o g y

a n y n e c e s s a r y s yn c h r o n iza tio n o f th e d a ta . T h e U N IX r e a d d ir fu n ction , fo r ex a m p ie, r e tu r n s e a c h d ir e c to r y e n tr y in s eq u en ce. T o m a k e r e a d d ir th re a d - s a fe, yo u m ig h t a d d a m u tex th a t r e a d d ir loc k e d e a c h tim e it w a s ca lled , a n d u n lo c k e d b e fo re it r etu r n e d to th e ca ller. A n o th e r a p p r o a c h , a s P th r e a d s h a s ta k en w ith r e a d d ir _ r , is to a void a n y lo ck in g w ith in th e fu n c tion , le ttin g th e c a lle r a llo c a te a s tr u ctu r e th a t m a in ta in s th e c o n te x t o f r e a d d ir _ r a s it s ea r c h e s a d ir ecto r y. A t fir s t g la n ce, it m a y s eem th a t w e ’re ju s t m a k in g th e c a lle r p e r fo r m w h a t o u g h t to b e th e jo b o f r e a d d ir _ r . B u t r e m e m b e r th a t o n ly th e c a ller k n o w s h o w th e d a ta w ill b e u s ed . If o n ly on e th r e a d u s es th is p a r tic u la r d ir e c to r y con tex t, for ex a m p le, th en n o s yn c h r o n iza tio n is n eed ed . E ve n w h en

th e d a ta is s h a r ed

b e tw e e n th r ea d s , th e c a lle r m a y b e a b le to s u p p ly m o r e e ffic ie n t s yn ch r on iza tio n , for ex a m p le, if th e c o n tex t c a n b e p ro te cted u s in g a m u te x th a t th e a p p lica tio n a ls o u s es for o th e r d a ta .

1.2.6

C o n c u rre n c y c o n tro l fu n ctio n s A n y “c o n cu r r e n t s ys te m ” m u s t p ro vid e a cor e s et o f e s s e n tia l fu n c tio n s th a t y o u n e ed to c r e a te c o n c u r r e n t e x e cu tio n c on te x ts , a n d c on tr o l h o w th e y o p er a te w ith in yo u r lib r a r y o r a p p lica tion . H er e a r e th r e e e s s e n tia l fa c ilities , o r a s p ects , o f a n y c on cu r r e n t s ys tem : 1. E x e cu tio n co n te x t is th e s ta te o f a c o n cu r r e n t en tity. A c o n cu r r e n t s ys te m m u s t p r o vid e a w a y to c re a te a n d d e le te e x e c u tio n co n te x ts , a n d m a in ta in th eir s ta te in d ep en d en tly. It m u s t b e a b le to s a ve th e s ta te o f o n e c on tex t a n d d is p a tc h to a n o th er a t va r io u s tim es , fo r e x a m p le, w h e n o n e n e ed s to w a it fo r a n e x te r n a l even t. It m u s t b e a b le to c on tin u e a c o n tex t fro m th e p oin t w h e r e it la s t e x ecu ted , w ith th e s a m e r e g is ter c on ten ts , a t a la te r tim e. 2.

S ch e d u lin g d e te r m in e s w h ic h c o n te x t (or s et o f c on te x ts ) s h o u ld e x e c u te a t

a n y g ive n p o in t in tim e, a n d s w itc h e s b e tw e en c on te x ts w h e n n e ce s s a ry. 3.

S y n ch ro n iz a tio n p r o vid es m ec h a n is m s for c o n cu r r e n t e x e c u tio n co n te x ts to

c o o r d in a te th e ir u s e o f s h a r ed r es ou r c es . W e u s e th is te r m in a w a y th a t is n e a r ly th e o p p o s ite o f th e s ta n d a r d d ic tion a r y m ea n in g . Y o u ’ll fin d a d efin itio n m u c h lik e “c a u s e to o c cu r a t th e s a m e tim e ,” w h e r e a s w e u s u a lly m e a n s o m eth in g th a t m ig h t b e tte r b e ex p res s e d a s “p r e ve n t fro m o c c u r r in g a t th e s a m e tim e .” In a th es a u r u s , yo u m a y fin d th a t “c o o p e r a te ” is a s yn on ym

fo r “s yn c h r o n ize ”— a n d

s yn ch r o n iza tio n

is th e m e c h a n is m

by

w h ich th r e a d s co o p e ra te to a cc o m p lis h a ta s k . T h is b o o k w ill u s e th e ter m “s yn c h r o n iza tio n ,” th ou g h , b e c a u s e th a t is w h a t y o u ’ll s ee u s ed , a lm o s t u n ive rs a lly. T h e r e a r e m a n y w a ys to p ro vid e e a c h o f th es e fa c ilitie s — b u t th e y a r e a lw a ys p r e s e n t in s om e for m . T h e p a r tic u la r c h o ice s p re s en te d in th is b o o k a r e d ic ta ted b y th e b o o k ’s s u b je ct— P th r ea d s . T a b le 1.1 s h o w s a fe w e x a m p le s o f th e th ree fa c ilities in va r io u s s ys tem s .



CH A P T E R 1

R e al t raff i c

In t r o d u c t i o n

Exe c ut io n c o nt ext

Sc he duling

Sy nc hro niz at io n

a u to m o b ile

tr a ffic lig h ts a n d

tu r n s ig n a ls a n d b ra k e

s ig n s

lig h ts w a it a n d p ip es

UNI X (be f o re t hre ad s)

p r o ce s s

p rio r ity (n ic e )

P t hre ad s

th r e a d

p olicy, p r io rity

c o n d itio n va r ia b le s a n d m u te x e s

TABLE 1.1

E x e c u t i o n c o n t ex t s, sc h e d u l e r s, a n d syn c h r o n i z a t i o n

A s ys te m ’s s c h e d u lin g fa cility m a y a llo w e a c h th r e a d to r u n u n til it vo lu n ta r ily yie ld s th e p r o c e s s o r to a n o th er th r e a d (“r u n u n til b lo c k ”). It m a y p ro vid e tim e s licin g , w h e r e ea c h th r e a d is for ced to p e r io d ic a lly yie ld s o th a t o th er th r ea d s m a y r u n (“r o u n d - r o b in ”). It m a y p ro vid e va r io u s s c h e d u lin g p o lic ie s th a t a llo w th e a p p lica tio n to c on tr o l h o w e a c h th re a d is s c h e d u le d a c c o r d in g to th a t th r e a d ’s fu n c tion . It m a y p r o vid e a “c la s s s c h e d u le r ” w h e r e d e p e n d e n c ie s b e tw e e n th r e a d s a r e d es cr ib e d s o th a t, fo r e x a m p le, th e s c h e d u ler ca n en s u r e th a t m e m b er s o f a tig h tly c ou p le d p a r a lle l a lg o r ith m a r e s ch ed u le d a t th e s a m e tim e. S yn c h r o n iza tio n m a y b e p r o vid e d u s in g a w id e va r ie ty o f m ec h a n is m s . S o m e o f th e m o s t c om m o n fo r m s a r e m u te x e s , c o n d itio n va r ia b les , s e m a p h o r es , a n d even ts . Y ou m a y a ls o u s e m es s a g e p a s s in g m ec h a n is m s , s u c h a s U N IX p ip es , s ock ets , P O S IX m e s s a g e q u eu es , o r o th e r p r o toc ols fo r c o m m u n ic a tin g b e tw e en a s yn c h r o n o u s p ro c es s es — on th e s a m e s ys tem o r a cr os s a n etw or k . A n y fo r m o f c o m m u n ic a tio n p r o toc o l co n ta in s s om e fo r m o f s yn ch r o n iza tio n , b e ca u s e p a s s in g d a ta a r ou n d w ith n o s yn ch r on iza tio n r es u lts in ch a os , n o t c o m m u n i c a t i o n . T h e te r m s t h r e a d , m u t e x , a n d c o n d i t i o n v a r i a b l e a r e th e m a in top ics o f th is b ook . F o r n ow , it is en o u g h to k n o w th a t a t h r e a d r ep r e s e n ts a n “e x e cu ta b le th in g ” on yo u r com p u ter. A m u t e x p r o vid e s a m e ch a n is m to p r e ve n t th re a d s fro m collid in g u n ex p ected ly, a n d a c o n d i t i o n v a r i a b l e a llow s a th rea d , on ce it h a s a void ed s u ch a collis ion , to w a it u n til it is s a fe to p roceed . B o th m u tex e s a n d c on d ition va r ia b les a re u s ed to s yn ch r on ize th e o p er a tio n o f th rea d s .

3. ‫ו‬

A sy n ch ro n o u s p ro g ra m m in g is in tu itive ... “In m o s t g a r d e n s ," th e Tiger-lily s a id , "th e y m a k e th e b e d s to o soft— so th a t th e flow ers a r e a lw a y s a s le e p .1' This s o u n d e d a v e ry g o o d re as o n , a n d A lic e w as q u ite p le a s e d to k n o w it. ,,I n e v e r th o u g h t o f th a t b e fo r e !” she said.

—Lewis Carroll,Through the Looking-Glass

I f yo u h a ve n ’t b e en in vo lve d in tr a d ition a l r ea ltim e p r o g r a m m in g , a s yn c h r on o u s p r o g r a m m in g m a y s eem n e w a n d d iffer en t. B u t y o u ’ve p r o b a b ly b e en u s in g

9

A s y n c h r o n o u s p r o g r a m m i n g i s i n t u i t i ve .

a s yn c h r o n o u s p r o g r a m m in g te c h n iq u e s a ll a lon g . Y o u ’ve p r o b a b ly u s ed U N IX , for e x a m p le, a n d , e ve n a s a u s er, th e c om m o n U N IX s h e lls fr o m sh to ks h h a ve b e en d es ig n e d for a s yn c h r o n o u s p r o g r a m m in g . Y o u ’ve a ls o b e e n u s in g a s yn ch r on o u s “p r o g r a m m in g ” te c h n iq u e s in r ea l life s in c e yo u w e r e b or n . M o s t p eo p le u n d e r s ta n d a s yn ch r on o u s b e h a vio r m u c h m o r e th o r o u g h ly th a n th ey

ex p ect,

o n ce

th e y g e t p a s t th e

co m p lica tion s

o f for m a l a n d

r es tr icted

d efin ition s .

1.3.1

. . . b e c a u s e U N IX is a s y n c h ro n o u s In a n y U N IX s ys tem , p r o ce s s e s e x e c u te a s yn c h r o n o u s ly w ith r e s p e c t to e a ch oth er, even w h e n th er e is o n ly a s in g le p roces s or . Y es , u n til r e c e n tly it w a s d iffic u lt to w r ite in d ivid u a l p r o g r a m s fo r U N IX th a t b e h a ved a s yn c h r o n o u s ly— b u t U N IX h a s a lw a ys m a d e it fa ir ly e a s y fo r y o u to b e h a ve a s yn c h r o n o u s ly. W h e n yo u typ e a c om m a n d to a s h ell, yo u a r e r e a lly s ta r tin g a n in d e p e n d e n t p ro g r a m — if yo u r u n th e p r o g r a m in th e b a c k g r ou n d , it r u n s a s yn c h r o n o u s ly w ith th e s h ell. W h e n yo u p ip e th e o u tp u t o f on e c om m a n d to a n o th er yo u a re s ta r tin g s eve ra l in d e p en d e n t p ro g r a m s , w h ic h s yn ch r on ize b e tw e en th e m s elves u s in g th e p ip e.

I T im e is a s y n c h ro n iz a tio n m e c h a n is m . In m a n y ca s es yo u p ro vid e s yn ch r o n iza tio n b etw e en a s eries o f p ro ces s es yo u r s elf, m a yb e w ith o u t e ven th in k in g a b ou t it. F or ex a m p le, yo u r u n th e co m p iler a fte r y o u ’ve fin is h e d e d itin g th e s ou r ce files . It w o u ld n ’t o cc u r to you to c om p ile

th em firs t, o r even a t th e s a m e tim e. T h a t’s e le m e n ta r y r ea l- life s yn ch r on iza tion .

I

UNIX p ip e s a n d files c a n b e s y n c h ro n iz a tio n m e c h a n is m s .

In o th e r ca s es yo u m a y u s e m o r e c om p lic a te d s oftw a r e s yn c h r o n iza tio n m ech a n is m s . W h en

yo u

typ e “Is |m ore” to

a

s h e ll to p a s s

th e o u tp u t o f th e

Is

c om m a n d in to th e m ore com m a n d , y o u ’re d e s cr ib in g s yn c h r o n iza tio n b y s p ecifyin g a d a ta d ep e n d en c y. T h e s h e ll s ta r ts b o th c o m m a n d s r ig h t a w a y, b u t th e m ore c o m m a n d c a n ’t g e n e r a te a n y o u tp u t u n til it r e ce ives in p u t fr o m Is th r o u g h th e p ip e. B o th c om m a n d s p r o cee d c o n c u r r e n tly (or e ve n in p a r a lle l on a m u ltip r o ces s or) w ith I s s u p p lyin g d a ta a n d m ore p r o c e s s in g th a t d a ta , in d e p e n d e n tly o f ea ch oth er. I f th e p ip e b u ffe r is b ig en o u g h , I s c ou ld c om p lete b e fo r e m ore e ver s ta r ted ; b u t m ore c a n ’t e ver g e t a h ea d o f Is. S o m e U N IX c om m a n d s p e r fo r m s yn c h r o n iza tio n in ter n a lly. F o r ex a m p le, th e c om m a n d “c c

-o

th r e a d

t h r e a d . c ” m ig h t in vo lve a n u m b e r o f s ep a r a te p ro-

ces s es . T h e c c c om m a n d m ig h t b e a “fr o n t e n d ” to th e C la n g u a g e e n vir on m e n t, w h ich r u n s a filte r to e x p a n d p r e p r o c e s s o r c o m m a n d s (lik e #in c lu d e a n d # if ) , a c o m p ile r to tr a n s la te th e p r o g r a m in to a n in te r m e d ia te for m , a n o p tim ize r to r e o r d e r th e tr a n s la tion , a n a s s e m b le r to tr a n s la te th e in te r m e d ia te fo r m in to o b jec t la n g u a g e , a n d a lo a d e r to tr a n s la te th a t in to a n e x ec u ta b le b in a r y file. A s w ith

10

CHA P T E R 1

In t r o d u c t i o n

I s |m ore, a ll th es e p r o g r a m s m a y b e r u n n in g a t th e s a m e tim e, w ith s yn c h r on iza tio n p r o vid e d b y p ip es , or b y a c ce s s to te m p o r a r y files . U N IX p ro c es s es c a n o p er a te a s yn ch r o n o u s ly b e ca u s e e a c h p r o c es s in c lu d es a ll th e in fo r m a tio n n e ed ed to e x e c u te cod e. T h e o p e r a tin g s ys tem c a n s a ve th e s ta te o f on e p r o ces s a n d s w itc h to a n o th e r w ith o u t a ffe c tin g th e o p e r a tio n o f eith er. A n y g e n e r a l- p u r p o s e a s yn c h r o n o u s “e n tity ” n e e d s e n o u g h s ta te to e n a b le th e o p e r a tin g s ys te m to s w itc h b e tw e en th em a r b itr a rily. B u t a U N IX p ro ces s in c lu d es a d d itio n a l s ta te th a t is n o t d ir ec tly r ela ted to “e x e c u tio n c o n te x t,” s u ch a s a n a d d r es s s p a ce a n d file d es cr ip tor s . A th r ea d is th e p a r t o f a p r o ce s s th a t’s n ec e s s a r y to e x e c u te cod e. O n m os t co m p u ter s th a t m e a n s e a ch th r e a d h a s a p o in te r to th e th r e a d ’s c u r r e n t in s tr u ctio n (ofte n c a lled a “P C ” o r “p ro g r a m c o u n te r ”), a p o in te r to th e top o f th e th r e a d ’s s ta c k (S P ), g e n er a l r eg is ter s , a n d floa tin g - p o in t or a d d r es s r e g is te rs if th ey a re k e p t s ep a ra te. A th r ea d m a y h a ve o th e r th in g s , s u c h a s p r o c es s o r s ta tu s a n d c o p r o c e s s o r c o n tr o l r eg is ter s . A th r e a d d oe s n o t in c lu d e m o s t o f th e r es t o f th e s ta te a s s oc ia ted w ith a p r o ces s ; fo r ex a m p le, th r ea d s d o n o t h a ve th eir o w n file d e s c r ip to r s o r a d d r es s s p a ce. A ll th r e a d s w ith in a p r o c es s s h a r e a ll o f th e files a n d m em or y, in c lu d in g th e p r o g r a m tex t a n d d a ta s eg m en ts .

I T h re a d s a r e " s im p le r" t h a n p ro c e s s e s . Y ou c a n th in k o f a th r e a d a s a s or t o f “s tr ip p ed d o w n ” p r o ces s , lea n a n d m ea n a n d r e a d y to go. T h e s ys tem ca n s w itc h b e tw e e n tw o th r e a d s w ith in a p r o ces s m u c h fa s ter th a n it c a n s w itc h b e tw e en p r o ces s es . A la r g e p a r t o f th is a d va n ta g e co m e s fr o m th e fa ct th a t th r e a d s w ith in a p r o c es s s h a r e th e a d d r es s s p a c e— cod e, d a ta , s ta ck , e ver yth in g . W h e n a p r o c e s s o r s w itc h e s b e tw e en tw o p ro ces s es , a ll o f th e h a r d w a r e s ta te fo r th a t p r o c es s b e c o m e s in va lid . S o m e m a y n e ed to b e c h a n g e d a s p a r t o f th e c on tex t s w itc h p r o c ed u r e — d a ta c a c h e a n d vir tu a l m em o r y tr a n s la tio n en tr ie s m a y b e flu s h ed , fo r e x a m p le. E ven w h e n th ey d o n o t n ee d to b e flu s h e d im m e d ia tely, h ow ever , th e d a ta is n o t u s efu l to th e n e w p r o ces s . E a c h p r o c es s h a s a s e p a ra te vir tu a l m e m o r y a d d r es s s p a ce, b u t th r ea d s r u n n in g w ith in th e s a m e p ro ces s s h a r e th e vir tu a l a d d r e s s s p a c e a n d a ll o th e r p r o c es s d a ta . T h r e a d s ca n m a k e h ig h - b a n d w id th c o m m u n ica tio n e a s ier b e tw e en in d e p e n d en t p a r ts o f y o u r p r o g r a m . Y ou d o n ’t h a ve to w o r r y a b o u t m es s a g e p a s s in g m e ch a n is m s lik e p ip es o r a b o u t k e ep in g s h a r ed m e m o r y r eg io n a d d r es s r efe r en c es c o n s is te n t b e tw e en s e ve r a l d iffe r e n t a d d r es s s p a ces . S yn c h r o n iza tio n is fa s ter, a n d p r o g r a m m in g is m u c h m o r e n a tu r a l. I f yo u c re a te or op en a file, a ll th r e a d s c a n u s e it. If yo u a llo ca te a d yn a m ic d a ta s tr u c tu r e w ith m a llo c , yo u ca n p a s s th e a d d r es s to o th e r th r e a d s a n d th ey ca n r efe r e n c e it. T h r e a d s m a k e it ea s y to ta k e a d va n ta g e o f c on cu r r en cy.

A s y n c h r o n o u s p r o g r a m m i n g i s i n t u i t i ve

1.3.2

11

. . . b e c a u s e th e w o rld is asy n c h ro n o u s T h in k in g a s yn c h r o n o u s ly c a n s eem a w k w a r d a t firs t, b u t it’ll b e co m e n a tu r a l w ith a little p r a ctice . S ta r t b y g e ttin g o ve r th e u n n a tu r a l e x p e cta tio n th a t ever yth in g w ill h a p p en s e r ia lly u n les s yo u d o s o m e th in g “u n u s u a l.” O n a o n e - la n e r oa d c a r s p r o c ee d on e a t a tim e — b u t on a tw o - la n e r oa d tw o c a r s g o a t on ce. Y ou c a n g o o u t fo r a cu p o f coffee, le a vin g y o u r c o m p u te r c o m p ilin g s om e c od e a n d fu lly e x p e ctin g th a t it w ill p ro cee d w ith o u t you . P a r a lle lis m h a p p en s e ver yw h e re in th e r ea l w o r ld , a n d yo u e x p e c t it. A r o w o f c a s h ie r s in a s tor e s e rve c u s tom e r s in p a r a llel; th e c u s to m er s in e a c h lin e g en e r a lly w a it th eir tu r n . Y ou c a n im p r o ve th r o u g h p u t b y o p e n in g m or e lin es , a s lo n g a s th er e a r e r e g is ter s a n d c a s h ie r s to s e rve th em , a n d e n o u g h c u s tom e rs to b e s er ved b y th em . C r e a tin g tw o lin e s for th e s a m e r e g is te r m a y a void con fu s ion b y k ee p in g lin es s h o r te r — b u t n o b o d y w ill g e t s e rved fa s ter. O p e n in g th r e e r eg is te rs to s erve tw o cu s tom er s m a y lo o k g ood , b u t it is ju s t a w a s te o f r es ou rces . In a n a s s e m b ly lin e, w o r k e r s p e r fo r m va r io u s p a r ts o f th e c om p lete jo b in p a r a llel, p a s s in g w o r k d ow n th e lin e. A d d in g a s ta tio n to th e lin e m a y im p r ove p e r fo r m a n c e if it p a r a llels o r s u b d ivid e s a s tep in th e a s s em b ly th a t w a s s o com p lic a ted th a t th e o p e r a to r a t th e n e x t s ta tio n s p e n t a lot o f tim e w a itin g fo r ea ch p iece. B ew a r e o f im p r o vin g on e s tep s o m u c h th a t it g en e r a tes m or e w o r k th a n th e n e x t s tep on th e a s s e m b ly lin e c a n h a n d le. In a n office, e a ch p r o je c t m a y b e a s s ig n e d to a “s p e c ia lis t.” C o m m o n s p ecia lties in c lu d e m a r k e tin g , m a n a g em e n t, e n g in e er in g , typ in g p ool, s a les , s u p p or t, a n d s o for th . E a ch s p ec ia lis t h a n d les h e r p ro jec t in d e p e n d e n tly o n b e h a lf o f th e c u s to m e r o r s o m e o th er s p ecia lis t, r e p o r tin g b a c k in s om e fa s h io n w h e n d on e. A s s ig n in g a s eco n d s p e c ia lis t to s om e ta s k , o r d e fin in g n a r r o w e r s p e cia ltie s (for ex a m p le, a s s ig n in g a n e n g in e e r or m a n a g e r p e r m a n en tly to on e p r o d u ct) m a y im p r o ve p e r fo r m a n c e a s lo n g a s th e r e ’s e n o u g h w o r k to k eep h e r b u s y. If n ot, s om e s p e cia lis ts p la y g a m e s w h ile o th e r s ’ in - b a s k ets over flow . M o to r veh ic le s m o ve in p a r a llel on a h ig h w a y. T h e y ca n m o ve a t d iffe re n t s p eed s , p a s s e a c h oth er, a n d e n te r a n d ex it th e h ig h w a y in d e p e n d e n tly. T h e d rivers m u s t a g ree to c er ta in con ve n tio n s in o r d er to a void collis ion s . D e s p ite s p eed lim its a n d tr a ffic s ign s , co m p lia n c e w ith th e “ru les o f th e r o a d ” is m os tly volu n ta ry. S im ila r ly, th re a d s m u s t b e cod ed to “a g r e e ” to r u les th a t p ro te ct th e p rog r a m , o r r is k e n d in g u p u n d e r g o in g e m e r g e n cy d eb u g g in g a t th e th r ea d h os p ita l. S o ftw a r e c a n a p p ly p a r a llelis m in th e s a m e w a ys yo u m ig h t u s e it in rea l life, a n d fo r th e s a m e r ea s o n s . W h e n yo u h a ve m or e th a n on e “th in g ” c a p a b le o f d oin g w o rk , yo u n a tu r a lly e x p ec t th em to a ll d o w o r k a t th e s a m e tim e. A m u ltip r o ces s o r s ys te m ca n p e r fo r m m u ltip le c om p u ta tio n s , a n d a n y tim e - s h a r in g s ys tem ca n p e r fo r m c o m p u ta tio n s w h ile w a itin g fo r a n e x te r n a l d evice to r es p on d . S o ftw a r e

12

CH A P T E R 1

In t r o d u c t i o n

p a r a lle lis m is s u b jec t to a ll o f th e c o m p lic a tio n s a n d p ro b lem s th a t w e h a ve s e en in r ea l life— a n d th e s o lu tio n s m a y n o t b e a s e a s y to s ee o r to a p p ly. Y ou n e ed e n o u g h th rea d s , b u t n o t to o m a n y; e n o u g h c om m u n ic a tio n , b u t n o t to o m u ch . A k e y to g o o d th r e a d e d p r o g r a m m in g is le a r n in g h o w to ju d g e th e p r o p e r b a la n ce fo r ea ch s itu a tion . E a c h th r e a d c a n p r o c es s s im ila r p a r ts o f a p r o b lem , ju s t lik e s u p e r m a r k e t c a s h ie r s h a n d lin g cu s to m e rs . E a ch th r e a d c a n p e r fo r m a s p ec ific o p er a tion on e a c h d a ta ite m in tu r n , ju s t lik e th e w o r k e r s on a n a s s e m b ly lin e. E a c h th re a d c a n s p e cia lize in s om e s p ec ific o p e r a tio n a n d p e r fo r m th a t o p e r a tio n r e p e a te d ly on b e h a lf o f o th e r th r ea d s . Y ou c a n c o m b in e th es e b a s ic m o d e ls in a ll s or ts o f w a ys ; fo r ex a m p le, in p a r a lle l a s s e m b ly lin e s w ith s om e s tep s p e r fo r m e d b y a p o o l o f s ervers . A s yo u r ea d th is b o o k y o u ’ll b e in tr o d u c ed to c o n ce p ts th a t m a y s eem u n fa m ilia r:

m u te x e s ,

c o n d itio n

va r ia b les ,

r a ce

c on d itio n s ,

d ea d lo c k s ,

and

p r io r ity

in ver s io n s . T h r e a d e d p r o g r a m m in g m a y feel d a u n tin g a n d u n n a tu r a l. B u t I’ll e x p la in a ll th os e c o n ce p ts a s w e m o ve th r o u g h th is b ook , a n d o n ce y o u ’v e b e e n w r itin g m u ltith r ea d e d c od e fo r a w h ile yo u m a y fin d y o u r s e lf n o tic in g r ea l- w o r ld a n a lo g ies to th e con ce p ts . T h r e a d s a n d a ll th is o th e r s tu ff a r e fo r m a lize d a n d r es tr ic te d r e p r e s e n ta tio n s o f th in g s yo u a lr ea d y u n d e rs ta n d . I f yo u fin d y o u r s e lf th in k in g th a t s om eo n e s h o u ld n ’t in te r r u p t yo u b ec a u s e yo u h a ve th e c o n ve r s a tio n m u te x lock ed , y o u ’ve b e g u n to d eve lo p a n in tu itive u n d e r s ta n d in g o f th r ea d ed p r o g r a m m in g .* Y ou c a n a p p ly th a t u n d e r s ta n d in g to h e lp yo u d es ig n b e tte r th r ea d ed c od e w ith le s s effo r t. I f s o m e th in g w o u ld n ’t m a k e s en s e in r ea l life, yo u p r o b a b ly s h o u ld n ’t t iy it in a p r o g r a m eith er.

1.4 A b o u t th e e x a m p le s in this b o o k T h is b o o k c on ta in s a n u m b e r o f ex a m p les . A ll a r e p re s en te d a s c om p lete p rog r a m s , a n d th e y h a ve b e en b u ilt a n d te s ted on D ig ita l U N IX 4 .0 d a n d S o la r is 2.5. A ll o f th es e p ro g r a m s d o s om e th in g , b u t m a n y d o n o t d o a n yth in g o f a n y p a r tic u la r

im p o rta n c e.

Th e

p u rp os e

o f th e e x a m p le s

is

to

d e m o n s tr a te

th rea d

m a n a g e m e n t a n d s yn c h r o n iza tio n te ch n iq u e s , w h ic h a r e m e r e o ver h e a d in m o s t r e a l p r o g r a m s . T h e y w o u ld b e les s e ffec tive a t r e ve a lin g th e d e ta ils if th a t “o ver h e a d ” w a s b u r ie d w ith in la r g e p r o g r a m s th a t “d id s o m e th in g .” W ith in th e b oo k , e x a m p les a re p r e s en te d in s ection s , u s u a lly on e fu n c tio n a t a tim e. T h e s o u r ce c od e is s ep a r a ted fro m th e s u r r o u n d in g te x t b y a h e a d e r a n d tr a ile r b lo c k w h ic h in c lu d e th e file n a m e a n d , if th e e x a m p le c om p r is e s m o r e th a n o n e s ection , a s e ctio n n u m b e r a n d th e n a m e o f th e fu n ction . E a c h lin e o f th e s o u r ce c od e h a s a lin e n u m b e r a t th e left m a rg in . M a jo r fu n c tio n a l b lo c k s o f e a ch s ectio n a r e d es cr ib e d in s p ec ia lly fo r m a tte d p a r a g r a p h s p r e c e d in g th e s ou r ce cod e. T h e s e p a r a g r a p h s a r e m a r k e d b y lin e n u m b e r s o u ts id e th e le ft m a r g in o f

*Itmay also be a good time to take a break and read some healthy escapist fiction for a while.

A syn c h r o n o u s p r o g r a m m i n g , by ex a m p l e

13

th e p a r a g r a p h , d e n otin g th e lin e n u m b e r s in th e s ou r ce lis tin g to w h ic h th e p a r a g r a p h r efer s . H e r e ’s a n ex a m p le: T h e s e lin es s h o w th e h e a d e r files in c lu d ed in m o s t o f th e ex a m p les . T h e

1-2

< p thread .h> h e a d e r file d ec la r es c o n s ta n ts a n d p ro to typ e s for th e P th r ea d s fu n ction s , a n d th e errors.h h e a d e r file in c lu d es va r io u s o th e r h ea d er s a n d s om e e r r o r - c h e c k in g fu n c tion s .



1 2

sample.c

part 1

sampleinfo

part 1

sampleinfo

#include #include "errors.h" ■

sample‫ ״‬c

I h a ve w r itte n th es e e x a m p les to u s e e r r o r c h e c k in g ever yw h e re. T h a t is , I c h e c k fo r e r r or s o n e a c h fu n c tio n ca ll. A s lo n g a s yo u c od e c a r efu lly, th is is n ’t n ec es s a ry, a n d s om e e x p er ts r e co m m en d te s tin g o n ly fo r e r r or s th a t c a n r es u lt fro m in s u ffic ie n t r es o u r ce s or o th e r p r o b le m s b e yo n d y o u r con tro l. I d is a g r ee, u n les s o f co u r s e y o u ’re th e s or t o f p r o g r a m m e r w h o n eve r m a k e s a m is ta k e. C h ec k in g for er r or s is n o t th a t ted iou s , a n d m a y s a ve yo u a lo t o f tr ou b le d u r in g d eb u g g in g . Y ou ca n b u ild a n d r u n a ll o f th e e x a m p les fo r y o u r s e lf— th e s ou r ce cod e is a va ila b le on lin e a t h ttp :/ / w w w .a w .c o m / b u te n h o f/ p o s ix c o d e .h tm l. A M a k efile is p r o vid e d to b u ild a ll o f th e ex a m p le s , th o u g h it r eq u ire s m o d ific a tion s fo r va r io u s p la tfor m s .

On

D ig ita l U N IX ,

th e e x a m p les w e r e b u ilt w ith

CFLAGS=-pthread

- s t d l -wl. O n S ola r is , th ey w e r e b u ilt w ith c f l a g s = ‫ ־‬d _ r e e n t r a n t - d _ p o s i x _ c _

S0URCE= 199506 -lpthread. S o m e o f th e e x a m p les r eq u ir e in te r fa c e s th a t m a y n ot b e in th e P th r ea d s lib r a ry o n y o u r s ys tem , for ex a m p le, clock_gettime, w h ic h is p a r t o f th e P O S IX . l b r ea ltim e s ta n d a r d . T h e a d d itio n a l r ea ltim e lib r a r y is s p ecified b y th e r t f l a g s va r ia b le, w h ic h is d efin ed a s RTFLAGS=-lrt on D ig ita l U N IX , a n d a s RTFLAGS=-lposix4 on S ola r is . O n S o la r is 2 .5 s ys tem s , s e ve r a l o f th e e x a m p les r eq u ire ca lls to th r _ s e tc o n c u r r e n c y to e n s u r e p r o p e r o p er a tion . T h is fu n c tio n c a u s es S o la r is to p ro vid e th e p r o ce s s w ith a d d itio n a l c o n cu r r en c y. In a fe w ca s es , th e e x a m p le w ill n o t op er a te a t a ll w ith o u t th is ca ll, a n d in o th e r ca s es , th e e x a m p le w o u ld fa il to d em o n s tr a te s om e b eh a vior .

1.5 A syn ch ro n o u s p ro g ra m m in g , b y e x a m p le ,,In o n e m o m e n t I ’v e s e e n w h a t h as hith erto b e e n E n v e lo p e d in a b s o lu te m ystery, A n d w ith o u t e x tra c h a r g e I will g iv e y o u a t la rg e A Lesson in N a tu ra l History

—Lewis Carroll, The Hunting of the Snark

14

CH A P T E R 1

In t r o d u c t i o n

T h is s ec tio n d e m o n s tr a tes s om e b a s ic a s yn c h r o n o u s p r o g r a m m in g , u s in g a s im p le p r o g r a m th a t d oes s om e th in g va g u e ly u s efu l, b y p re ten d in g to b e a n a la r m c loc k w ith a c om m a n d in te r fa c e fo r w h ich yo u w o u ld n o t c o n s id e r p a yin g a d im e in a s tore. B u t th en , th is b o o k is a b o u t th rea d s , n o t u s er in ter fa c es , a n d th e c od e th a t I n e ed to s h o w ta k es u p q u ite e n o u g h s p a c e a lr ea d y. T h e p r o g r a m p r o m p ts fo r in p u t lin e s in a lo o p u n til it r e ce ives a n e r r o r o r en d o f file o n s td in . O n ea c h lin e, th e firs t n o n b la n k to k e n is in te r p r e te d a s th e n u m b e r o f s eco n d s to w a it, a n d th e r es t o f th e lin e (u p to 6 4 c h a r a c te r s ) is a m e s s a g e th a t w ill b e p r in ted w h e n th e w a it c om p letes . I w ill o ffe r tw o a d d itio n a l ve r s io n s — o n e u s in g m u ltip le p r o ces s e s , a n d on e u s in g m u ltip le th rea d s . W e ’ll u s e th e th r e e e x a m p les to c om p a r e th e a p p r o a c h e s .

1.5.1

The b a s e lin e , syn chro no u s version In c lu d e

1

th e

h ea d er

file

< u n is td . h > a n d < s td io . h >

errors.h, w h ic h

in c lu d es

s ta n d a r d

h ea d ers

lik e

a n d d e fin e s e r r o r r ep o r tin g m a c ro s th a t a r e u s ed

th r o u g h o u t th e e x a m p le s in th is b ook . W e d o n ’t u s e th e e r r o r r e p o r tin g m a cr o s in th is p a r tic u la r ex a m p le, b u t c o n s is te n c y is n ice, s om etim es . T h e “b a s e lin e ” ver s io n , alarm.c, is a s yn c h r o n o u s a la r m p r o g r a m w ith a s in -

9-26

g le r ou tin e, main. M o s t o f main is a loop , w h ic h p r o c es s es s im p le c o m m a n d s u n til

fgets r e tu r n s a n u l l (e rr o r o r en d o f file). E a c h lin e is “p a r s e d ” w ith sscanf to s e p a ra te th e n u m b e r o f seconds to w a it (%d, th e fir s t s eq u e n c e o f d igits ) fro m th e

message s tr in g to p r in t (%64 [A \n ], th e r e s t o f th e lin e, u p to 6 4 c h a r a cter s e x clu d in g n ew lin e).



1

alarm.c

!include "errors.h"

2

3 4 5 6 7

int main (int argc, char * argv[]) { int seconds; char line[128]; char m e s s a g e [64];

8

9 10 11 12 13 14 15 16 17 18

while (1) { printf ("Alarm> "); if (fgets (line, sizeof (line), stdin) == NULL) if (strlen (line) "); if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (strlen (line) seconds); printf (‫( ״‬%d) % s \n", alarm->seconds, alarm->message); free (alarm); return NULL; } ■

alarm_thread.c

part 2

alarm_thread

T h e main p r o g r a m o f alarm_thread.c is m u c h th e s a m e a s th e o th e r tw o va r ia n ts . It loo p s , r ea d in g a n d in te r p r e tin g c om m a n d lin e s a s lo n g a s it c a n r ea d fr o m

stdin. In th is va r ia tio n , main a llo c a tes h e a p s to r a g e (alarm_t) fo r e a c h a la r m com -

12-25

m a n d . T h e a la r m tim e a n d m e s s a g e a r e s tor ed in th is s tr u ctu r e, s o e a c h th r ea d ca n b e g iven th e a p p r o p r ia te in fo r m a tio n . I f th e sscanf c a ll fa ils to “p a r s e ” a c or r e c t c om m a n d , th e h e a p s to r a g e is freed . A n a la r m th r ea d is c re a ted , r u n n in g fu n c tio n a la r m _ th r e a d , w ith th e a la r m

26-29

d a ta (a la r m _ t) a s th e th r e a d ’s a r g u m e n t.



alarm_thread.c

1

int main (int argc, char * argv[])

2

{

3 4 5 6 7 8 9 10 11 12 13 14 15 16

17 18 19 20

part 3

int status; char line[128]; alarm__t *alarm; pthread_t thread; while (1) { printf ("Alarm> M ); if (fgets (line, sizeof (line), stdin) == NULL) exit if (strlen (line) 0) sleep (sleep_time); else sched_yield (); /* * If a timer expired, print the message and free the * structure. */ if (alarm != NULL) { printf ("(%d) %s\n", alarm->seconds, alarm->message); free (alarm); }

}

68

69

} ■

alarm_mutex.c

A n d fin a lly, th e cod e for th e m a in p r o g r a m

part 2

alarm_thread

fo r alarm_mutex.c. T h e b a s ic

s tr u c tu r e is th e s a m e a s a ll o f th e o th e r ve r s io n s o f th e a la r m p r o g r a m th a t w e ’ve d e ve lo p ed — a loop , r ea d in g s im p le c o m m a n d s fr o m stdin a n d p r o c e s s in g e a c h in tu r n . T h is tim e, in s te a d o f w a itin g s yn c h r o n o u s ly a s in alarm, c, o r c r ea tin g a n e w a s yn c h r o n o u s e n tity to p r o c es s e a ch a la r m c om m a n d a s in alarm_fork.c a n d alarm_j:hread.c, e a c h r eq u e s t is q u e u e d to a s e r ver th r ea d , alarm__thread. A s s oo n a s main h a s q u e u e d th e r eq u es t, it is fr ee to r ea d th e n e x t com m a n d . 8-11

C r ea te th e s e r ve r th r e a d th a t w ill p r o c es s a ll a la r m r eq u e s ts . A lth o u g h w e d o n ’t u s e it, th e th r e a d ’s ID is r e tu rn e d in lo ca l va r ia b le th r e a d .

13-28

R ea d a n d p r o c es s a c om m a n d , m u c h a s in a n y o f th e o th e r ve r s io n s o f ou r a la r m p ro g r a m . A s in a la r m _ th r e a d .c , th e d a ta is s tor ed in a h e a p s tru c tu r e a llo ca ted b y m a llo c .

30-32

T h e p r o g r a m n e ed s to a d d th e a la r m r e q u e s t to alarm_list, w h ic h is s h a r ed b y b o th alarm_thread a n d main. S o w e s ta r t b y lo c k in g th e m u te x th a t s yn ch r on izes a cc es s to th e s h a r ed d a ta , alarm_mutex.

33

B e ca u s e alarm__thread p r o c es s es q u e u e d r eq u e s ts , s eria lly, it h a s n o w a y o f k n o w in g h o w m u c h tim e h a s e la p s e d b e tw e e n r ea d in g th e c om m a n d a n d p r o ces s in g it. T h e r e fo r e, th e a la r m s tr u c tu r e in c lu d es th e a b s o lu te tim e o f th e a la r m e x p ir a tion , w h ic h w e c a lc u la te b y a d d in g th e a la r m in ter va l, in s eco n d s , to th e

56

CH A P T E R 3

S yn c h r o n i za t i o n

c u r r e n t n u m b e r o f s ec on d s s in c e th e U N IX E p och , a s r etu r n e d b y th e tim e fu n ction . T h e a la r m s a r e s or ted in o r d er o f e x p ir a tio n tim e on th e a l a r m _ l is t q u eu e.

39-49

T h e in s e r tio n c od e s ea r ch es th e q u e u e u n til it fin d s th e firs t e n tr y w ith a tim e g r e a te r th a n o r e q u a l to th e n e w a la r m ’s tim e. T h e n e w e n tr y is in s er te d p r eced in g th e loc a ted en try. B ec a u s e a l a r m _ l is t is a s im p le lin k e d lis t, th e tr a ve r s a l m a in ta in s a c u r r en t e n tr y p o in te r ( t h is ) a n d a p o in te r to th e p r eviou s e n tr y’s l in k m em b er, or to th e a l a r m _ l is t h ea d p o in te r ( l a s t) . 56-59

If n o a la r m w ith a tim e g r e a te r th a n or e q u a l to th e n e w a la r m ’s tim e is fou n d , th en th e n e w a la r m is in s er te d a t th e en d o f th e lis t. T h a t is , if th e a la r m p o in te r is n u l l o n e x it fr o m th e s e a r c h loo p (th e la s t e n tr y on th e lis t a lw a ys h a s a l i n k p o in ter o f n u l l ), th e p r eviou s e n tr y (or q u e u e h ea d ) is m a d e to p o in t to th e n ew en try.



alarm_mutex.c

1

int main

2

{

3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

part 3

(int argc, char *ar g v [ ])

int status; char line[128]; alarm_t *alarm, **last, pthread_t thread;

*next;

status = pthread_create ( &thread, NULL, alarm_thread, NULL); if (status != 0) err_abort (status, ‫ ״‬Create alarm thr e a d ‫;) ״‬ while (1) { printf ("alarm> "); if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (strlen (line) link) printf ("%d(%d)[\ " %s\"] ", next->time, next->time - time (NULL), next->message); printf ("]\n"); #endif

66

status = pthread_mutex_unlock (&alarm_jmutex); if (status != 0) err abort (status, "Unlock mutex");

67 68

69 70 71 72 ■

alarm__mutex.c

part 3

main

T h is s im p le p r o g r a m h a s a fe w s eve re fa ilin g s . A lth o u g h it h a s th e a d va n ta g e , c om p a r e d to alarm_f o r k .c o r alarm_thread.c, o f u s in g fe w e r r es ou r c es , it is le s s r es p o n s ive . O n ce alarm_thread h a s a cc ep ted a n a la r m r e q u e s t fr o m th e q u eu e, it

58

CH A P T E R 3

S yn c h r o n i z a t i o n

s leep s u n til th a t a la r m ex p ir es . W h e n it fa ils to fin d a n a la r m r eq u e s t o n th e lis t, it s leep s for a s e co n d a n yw a y, to a llo w main to a c c e p t a n o th er a la r m c om m a n d . D u r in g a ll th is s leep in g , it w ill fa il to n o tice a n y a la r m r eq u es ts a d d e d to th e h ea d o f th e q u e u e b y main, u n til it r etu r n s fro m s le e p . T h is p r o b lem c ou ld b e a d d r es s ed in va r io u s w a ys . T h e s im p les t, o f cou r s e, w o u ld b e to g o b a c k to alarm_thread.c, w h e r e a th r e a d w a s c re a ted fo r e a ch a la r m r eq u es t. T h a t w a s n ’t s o b a d , s in c e th r e a d s a r e r e la tive ly ch ea p . T h e y ’r e s till n o t a s c h e a p a s th e alarm_t d a ta s tr u ctu r e, h ow ever , a n d w e ’d lik e to m a k e efflc ie n t p ro g r a m s — n o t ju s t r es p o n s ive p r o g r a m s . T h e b e s t s o lu tion is to m a k e u s e o f c o n d itio n va r ia b le s fo r s ig n a lin g c h a n g e s in th e s ta te o f s h a r ed d a ta , s o it s h o u ld n ’t b e a s u r p r is e th a t y o u ’ll b e s ee in g on e fin a l ve r s io n o f th e a la r m p rog ra m , alarm_cond.c, in S e c tio n 3 .3 .4 .

3.2 .2.1 N o n b lo c k in g m u te x lo cks W h e n yo u lo c k a m u te x b y c a llin g pthread_mutex_lock, th e c a llin g th r e a d w ill b lo c k i f th e m u te x is a lr ea d y lock ed . N o r m a lly, th a t’s w h a t yo u w a n t. B u t o c c a s io n a lly yo u w a n t y o u r cod e to ta k e s om e a lte r n a te p a th if th e m u te x is lock ed . Y ou r p r o g r a m m a y b e a b le to d o u s efu l w o r k in s te a d o f w a itin g . P th r ea d s p r o vid es th e pthread_mutex_trylock fu n c tion , w h ic h w ill r etu r n a n e r r o r s ta tu s

(e b u s y ) in s te a d o f b loc k in g if th e m u te x is a lr e a d y lock ed . W h e n yo u u s e a n o n b lo c k in g m u tex lock , b e c a r efu l to u n lo ck th e m u te x o n ly if pthread_mutex_trylock r e tu rn e d w ith s u c ce s s s ta tu s . O n ly th e th r ea d th a t o w n s a m u te x m a y u n lo ck it. A n e rr o n e o u s ca ll to pthread_mutex_unlock m a y r e tu r n a n error, o r it m a y u n lo ck th e m u te x w h ile s om e o th e r th r e a d r elie s o n h a vin g it loc k e d — a n d th a t w ill p r o b a b ly c a u s e y o u r p r o g r a m to b r e a k in w a ys th a t m a y b e v e r y d iffic u lt to d eb u g . T h e fo llo w in g p r o g r a m , trylock.c, u s es pthread_mutex_trylock to oc ca s io n a lly r ep o r t th e va lu e o f a c o u n te r — b u t o n ly w h e n its a c ce s s d oes n o t co n flict w ith th e c o u n tin g th rea d . 4

T h is

d e fin itio n

c o n tr o ls h o w

lo n g counter_thread h o ld s th e m u te x w h ile

u p d a tin g th e counter. M a k in g th is n u m b e r la r g e r in c r e a s es th e c h a n ce th a t th e

14-39

pthread_mutex_trylock in monitor_thread w ill o c c a s io n a lly r e tu r n EBUSY. T h e counter_thread w a k e s u p a p p r o x im a te ly e a c h s eco n d , lo c k s th e m u tex , a n d s p in s fo r a w h ile, in c r e m e n tin g counter. T h e counter is th e r e fo r e in c r ea s ed b y SPIN e a c h s econ d .

4 6-72

T h e monitor_thread w a k e s u p e ve r y th r e e s eco n d s , a n d tr ie s to lo ck th e m u tex . I f th e a ttem p t fa ils w ith EBUSY, monitor_thread c ou n ts th e fa ilu r e a n d w a its

80-88

a n o th er th r e e s eco n d s . If th e pthread_mutex_trylock s u cceed s , th en monitor_thread p r in ts th e c u r r e n t va lu e o f counter (s ca led b y s p i n ). O n S o la r is 2.5, c a ll thr_setconcurrency to s et th e th r e a d c o n c u r r e n c y level to 2. T h is a llo w s th e counter_thread a n d monitor_thread to r u n c o n cu r r e n tly o n a u n ip r oces s or . O th er w is e , monitor_thread w o u ld n o t r u n u n til counter_

thread ter m in a ted .

59

M u t ex es



1 2

3 4 5 6

7 8

trylock.c

#include !include "errors.h" #define SPIN 10000000 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; long counter; time__t end_time;

9 10

/*

* Thread start routine that repeatedly locks a mutex and * increments a counter.

11

12

13 14 15 16 17 18 19

*/

void *counter_thread (void *arg) {

int status; int spin; /*

* * * *

20 21 22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

Until end_time, increment the counter each second. Instead of just incrementing the counter, it sleeps for another second with the mutex locked, to give monitor_thread a reasonable chance of running.

*/

while

(time (NULL) < end_time)

{

status = pthread_mutex_lock (&mutex); if (status 1= 0) err_abort (status, ,,Lock mutex"); for (spin = 0; spin < SPIN; spin++) counter++; status = pthread_mutex_unlock (&mutex); if (status != 0) err_abort (status, "Unlock mutex"); sleep (1); }

printf (,1Counter is %#lx\n", counter); return NULL; } /*

* Thread start routine to "monitor" the counter. Every 3 * seconds, try to lock the mutex and read the counter. If the * trylock fails, skip this cycle. */

void *monitor_thread (void *arg)

60

CH A P T E R 3

S yn c h r o n i za t i o n

{

int status; int misses = 0;

/*

52 53 54 55 56 57 58 59 60 61 62 63 64 65

* Loop until end__time, checking the counter every 3 seconds. */

while

sleep (3); status = pthread_mutex_trylock (&mutex); if (status != EBUSY) {

if (status != 0) err_abort (status, "Trylock mutex"); printf ("Counter is %ld\n"‫ ׳‬counter/SPIN); status = pthread_mutex_unlock (&mutex); if (status != 0) err_abort (status, "Unlock mutex"); > else misses++; /* Count "misses" on the lock */

66

67 68

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

87 88

89 90 91 92 93 94

(time (NULL) < end_time)

{

}

printf ("Monitor thread missed update %d times.\n", misses); return NULL;

int main (int argc, char * argv[])
else { if (status 1= 0) err_abort (status, "Lock mutex"); DPRINTF ((" forward locker got %d\n", > > /*

* Yield processor, if needed to be sure locks get * interleaved on a uniprocessor• */

if (yield_flag) { if (yield_flag > 0) sched_yield (); else sleep (1); >

66

} /*

67 68

* Report that we got

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

*/

void *lock__backward (void *arg)

86

{

87

i));

printf ( ‫ ״‬lock forward got pthread_mutex_unlock pthread_mutex_unlock pthread_mutex_unlock sched_yield ();

'em, and unlock to try again.

all locks, %d backoffs\n”, backoffs); (&mutex[2]); (&mutex [1 ]); (& m u t e x [0]);

}

return NULL;

/*

* This is a thread start routine that locks all mutexes in * reverse order, to ensure a conflict with lock_forward, which * does the opposite. */

88

int i, iterate, backoffs; int status;

89 90 91 92 93 94 95 96

for (iterate = 0; iterate < ITERATIONS; iterate++) { backoffs = 0; for (i = 2; i >= 0; i— ) { if (i == 2) { status = pthread_mutex_lock (&mutex[i]); if (status != 0) err_abort (status, "First lock");

68

CH A P T E R 3

97 98 99

> else { if (backoff) status = pthread_mutex_trylock (&mutex[i]); else status = pthread_mutex__lock (&mutex[i]); if (status == EBUSY) { backoffs++; DPRINTF (( " [backward locker backing off at %d]\n",

100

101 102

103 104 105 106 107 108 109

i ) );

for (; i < 3; i++) { status = pthread__mutex_unlock (fcmutex[i ] ); if (status != 0) err_abort (status, "Backoff");

110 1 11

>

112

} else { if (status != 0) err__abort (status, "Lock mutex"); DPRINTF ((" backward locker got %d\n",

113 114 115 116 117 118 119

i));

> } /*

* Yield processor, if needed to be sure locks get * interleaved on a uniprocessor.

120 121

*/

122

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

S yn c h r o n i z a t i o n

if (yield_flag) { if (yield_flag > 0) sched__yield (); else sleep (1); } > /*

* Report that we got

'em, and unlock to try again.

*/

printf ( "lock backward got all locks, %d backoffs\n", backoffs); pthread_mutex_unlock (& m u t e x [0]); pthread_mutex__unlock (&mutex [1 ]); pthread__mutex_unlock (&mutex [2 ]); sched_yield (); >

return NULL; }

int main (int argc, char *argv[]) {

pthread t forward, backward;

69

M u t ex es

int status; #ifdef sun /*

149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187

* On Solaris 2.5, threads are not timesliced. To ensure * that our threads can run concurrently, we need to * increase the concurrency level. */

DPRINTF (("Setting concurrency level to 2\n")); thr_setconcurrency (2); #endif /*

* * * *

If the first argument is absent, or nonzero, a backoff algorithm will be used to avoid deadlock. If the first argument is zero, the program will deadlock on a lock "collision."

*/

if (argc > 1) backoff = atoi

(argv[l]);

/*

* * * * * * * *

If the second argument is absent, or zero, the two threads run "at speed.‫ ״‬On some systems, especially uniprocessors, one thread may complete before the other has a chance to run, and you won't see a deadlock or backoffs. In that case, try running with the argument set to a positive number to cause the threads to call sched_yield() at each lock; or, to make it even more obvious, set to a negative number to cause the threads to call sleep(1) instead.

*/

if (argc > 2) yield_flag = atoi (argv[2]); status = pthread__create ( &forward, NULL, lock_forward, NULL); if (status 1= 0) err_abort (status, "Create forward"); status = pthread_create { *backward, NULL, lock_backward, NULL); if (status != 0) err_abort (status, "Create backward"); pthread_exit (NULL); > ■

backoff.c

W h a te ve r typ e o f h ie r a r c h y yo u ch o os e, d o c u m e n t it, c a r efu lly, c o m p letely, a n d often . D o c u m e n t it in e a c h fu n c tio n th a t u s e s a n y o f th e m u te x e s . D o c u m e n t it w h e r e th e m u tex es a r e d efin ed . D o c u m e n t it w h er e th e y a r e d e cla r e d in a p r o je c t

70

CH A P T E R 3

S yn c h r o n i z a t i o n

h e a d e r file. D o c u m e n t it in th e p r o je ct d e s ig n n otes . W r ite it on y o u r w h ite b o a r d . A n d th en tie a s tr in g a r ou n d y o u r fin g e r to b e s u r e th a t yo u d o n o t forget. Y ou a xe fre e to u n lo ck th e m u tex es in w h a te ve r o r d er m a k es th e m o s t s en s e. U n lo c k in g m u te x e s c a n n ot r e s u lt in d e a d loc k . In th e n e x t s ection , I w ill ta lk a b o u t a s o r t o f “o ve r la p p in g h ie r a r c h y” o f m u tex e s , c a lle d a “lo c k c h a in ,” w h er e th e n o r m a l m o d e o f o p e r a tio n is to loc k on e m u tex , lo c k th e n ex t, u n lo c k th e firs t, a n d s o on . I f yo u u s e a “tr y a n d b a c k o f f ’ a lg or ith m , h ow ever , yo u s h o u ld a lw a ys tr y to r e lea s e th e m u tex es in r ever s e ord er. T h a t is, i f yo u lo c k m u te x 1, m u te x 2, a n d th en m u tex 3, yo u s h o u ld u n loc k m u tex 3, th en m u te x 2, a n d fin a lly m u te x 1. I f yo u u n lo ck m u tex 1 a n d m u tex 2 w h ile m u tex 3 is s till lock ed , a n o th er th rea d m a y h a ve to lo c k b oth m u te x 1 a n d m u te x 2 b e fo re fin d in g it c a n n ot lo ck th e en tir e h ier a r ch y, a t w h ich p o in t it w ill h a ve to u n loc k m u te x 2 a n d m u te x 1, a n d th en retry. U n lo c k in g in r ever s e o r d e r r ed u c es th e c h a n ce th a t a n o th er th r e a d w ill n ee d to b a c k off.

3 .2 .5 .2 Lock c h a in in g “C h a in in g ” is a s p ec ia l c a s e o f lo c k in g h ier a r ch y, w h e r e th e s co p e o f tw o lo c k s over la p . W ith on e m u te x lock ed , th e cod e e n ter s a r eg io n w h e r e a n o th er m u te x is r eq u ire d . A fte r s u cc e s s fu lly lo c k in g th a t s eco n d m u tex , th e fir s t is n o lo n g e r n e ed e d , a n d c a n b e r elea s ed . T h is te ch n iq u e c a n b e v e r y va lu a b le in tr a ve r s in g d a ta s tr u c tu r es s u c h a s tr e es o r lin k ed lis ts . In s te a d o f lo c k in g th e e n tir e d a ta s tr u ctu r e w ith a s in g le m u tex , a n d th e r e b y p r e ve n tin g a n y p a r a lle l a cces s , e a c h n o d e o r lin k h a s a u n iq u e m u tex . T h e tr a ve r s a l c od e w o u ld fir s t lo c k th e q u e u e h ea d , o r tr ee root, fin d th e d es ir ed n od e, lo c k it, a n d th e n r ele a s e th e r o o t o r q u e u e h e a d m u tex . B ec a u s e c h a in in g is a s p ec ia l fo r m o f h ier a r ch y, th e tw o te c h n iq u e s a r e com p a tib le, if yo u a p p ly th em ca r efu lly. Y ou m ig h t u s e h ie r a r c h ic a l lo c k in g w h e n b a la n c in g o r p r u n in g a tree, fo r ex a m p le, a n d c h a in in g w h e n s ea r c h in g fo r a s p ec ific n od e. A p p ly lo c k c h a in in g w ith c a u tio n , h ow ever. It is e x c e p tio n a lly e a s y to w r ite c od e th a t s p e n d s m o s t o f its tim e lo c k in g a n d u n lo c k in g m u te x e s th a t n eve r e x h ib it a n y c o n te n tio n , a n d th a t is w a s te d p r o c e s s o r tim e. U s e lo c k c h a in in g o n ly w h e n m u ltip le th r e a d s w ill a lm os t a lw a ys b e a c tive w ith in d iffe r e n t p a r ts o f th e h ier a r ch y.

3.3 C o n d itio n v a ria b le s “There's n o sort o f use In k n o c k in g ” s a id th e F o o tm a n , ,,a n d th a t for tw o reasons. First, b e c a u s e I ’m o n th e s a m e s id e o f th e d o o r as y o u a re : s ec o n d ly , b e c a u s e th e y ’re m a k in g su ch a n o ise inside, n o o n e c o u id p o ss ib ly h e a r y o u .”

—Lewis Carroll, Alice's Adventures in Wonderland

,C o n d i t i o n v a r i a b l e s

FIG U RE 3 .3

71

C ond ition v ariab le analogy

A c o n d itio n va r ia b le is u s ed fo r c o m m u n ic a tin g in fo r m a tio n a b o u t th e s ta te o f s h a r ed d a ta . Y ou w o u ld u s e a c o n d itio n va r ia b le to s ig n a l th a t a q u e u e w a s n o lo n g e r em p ty, o r th a t it h a d b e c o m e em p ty, o r th a t a n yth in g e ls e n e e d s to b e d on e o r c a n b e d o n e w ith in th e s h a r ed d a ta m a n ip u la te d b y th r ea d s in y o u r p r o g r a m . O u r s ea fa r in g p r o g r a m m e r s u s e a m ec h a n is m m u c h lik e c o n d itio n va r ia b le s to c o m m u n ic a te (F igu r e 3 .3 ). W h e n th e r o w e r n u d g es a s le ep in g p r o g r a m m e r to s ign a l th a t th e s lee p in g p r o g r a m m e r s h o u ld w a k e u p a n d s ta r t r ow in g , th e o r ig in a l r o w e r “s ig n a ls a c o n d itio n .” W h e n th e e x h a u s te d e x - r o w er s in k s in to a d e ep s lu m b er, s ecu r e th a t a n o th e r p r o g r a m m e r w ill w a k e h im a t th e a p p r o p r ia te tim e, h e is “w a itin g on a c o n d itio n .” W h e n th e h o rr ified b a ile r d is co ver s th a t w a te r is s eep in g in to th e b o a t fa s te r th a n h e ca n r em o ve it, a n d h e ye lls fo r h elp , h e is “b r o a d ca s tin g a c o n d itio n .” W h e n a th r ea d h a s m u tu a lly e x c lu s ive a c ce s s to s om e s h a r ed s ta te, it m a y fin d th a t th er e is n o m o r e it c a n d o u n til s om e o th e r th r e a d c h a n g e s th e s ta te. T h e s ta te m a y b e cor rect, a n d c o n s is te n t— th a t is, n o in va r ia n ts a r e b ro k en — b u t th e c u r r e n t s ta te ju s t d o e s n ’t h a p p e n to b e o f in te r e s t to th e th rea d . If a th r ea d s e r vic in g a q u e u e fin d s th e q u e u e em p ty, fo r ex a m p le, th e th r e a d m u s t w a it u n til a n e n tiy is a d d e d to th e q u eu e. T h e s h a r ed d a ta , fo r ex a m p le, th e q u eu e, is p r o te c te d b y a m u tex . A th r e a d m u s t lo c k th e m u te x to d e ter m in e th e c u r r e n t s ta te o f th e q u eu e, fo r e x a m p le, to d e te r m in e th a t it is em p ty. T h e th r e a d m u s t u n lo c k th e m u te x b e fo r e w a itin g (or

72

CH A P T E R 3

S yn c h r o n i z a t i o n

n o o th e r th r e a d w o u ld b e a b le to in s e r t a n e n tr y o n to th e q u e u e ), a n d th en it m u s t w a it fo r th e s ta te to ch a n g e. T h e th r ea d m igh t, fo r ex a m p le, b y s o m e m ea n s b lo c k its e lf s o th a t a th r e a d in s e r tin g a n e w q u e u e e n tr y c a n fin d its id e n tifie r a n d a w a k e n it. T h e r e is a p ro b le m

h ere, th o u g h — th e th r ea d is r u n n in g b e tw e en

u n lo c k in g a n d b lock in g . I f th e th r e a d is s till r u n n in g w h ile a n o th e r th r ea d lo ck s th e m u te x a n d in s e r ts a n e n tr y o n to th e q u eu e, th a t o th er th r ea d c a n n o t d e te r m in e th a t a th r e a d is w a itin g fo r th e n e w en try. T h e w a itin g th r ea d h a s a lr e a d y lo o k e d a t th e q u e u e a n d fo u n d it em p ty, a n d h a s u n lo c k e d th e m u tex , s o it w ill n o w b lo c k its e lf w ith o u t k n o w in g th a t th e q u eu e is n o lo n g e r em p ty. W ors e, it m a y n o t y e t h a ve r ec o r d ed th e fa c t th a t it in ten d s to w a it, s o it m a y w a it fo r e ve r b e c a u s e th e o th e r th r e a d ca n n o t fin d its id en tifier. T h e u n lo ck a n d w a it o p e r a tio n s m u s t b e a tom ic, s o th a t n o o th e r th r ea d c a n lo ck th e m u te x b e fo r e th e w a ite r h a s b e co m e b lo c k e d , a n d is in a s ta te w h e r e a n o th e r th r ea d ca n a w a k e n it.

I A c o n d it io n v a r ia b le w a it a lw a y s re tu rn s w ith t h e m u te x lo c k e d . T h a t’s w h y co n d itio n v a ria b le s ex is t. A c o n d itio n va r ia b le is a “s ig n a lin g m ech a n is m ” a s s oc ia te d w ith a m u te x a n d b y e x te n s io n is a ls o a s s o c ia ted w ith th e s h a r ed d a ta p r o te c te d b y th e m u tex . W a itin g o n a c o n d itio n va r ia b le a to m ic a lly r e lea s es th e a s s o c ia ted m u te x a n d w a its u n til a n o th e r th r ea d s ig n a ls (to w a k e on e w a iter ) o r b ro a d ca s ts (to w a k e a ll w a iter s ) th e c o n d itio n va r ia b le . T h e m u te x m u s t a lw a ys b e loc k e d w h en yo u w a it on a c o n d itio n va r ia b le a n d , w h e n a th rea d w a k e s u p fro m

a c o n d itio n va r ia b le w a it, it a lw a ys r es u m e s w ith th e m u te x

lock ed . T h e s h a r ed d a ta a s s oc ia te d w ith a c o n d itio n va r ia b le, fo r ex a m p le, th e q u e u e “fu ll” a n d “e m p ty” co n d itio n s , a r e th e p re d ic a te s w e ta lk e d a b o u t in S e c tio n 3 .1. A c o n d itio n va r ia b le is th e m e ch a n is m y o u r p r o g r a m u s es to w a it fo r a p re d ic a te to b e co m e tr u e, a n d to c o m m u n ic a te to o th e r th r e a d s th a t it m ig h t b e tru e. In o th e r w o rd s , a c o n d itio n va r ia b le a llo w s th r ea d s u s in g th e q u eu e to e x c h a n g e in fo r m a tio n a b o u t th e c h a n g e s to th e q u e u e s ta te.

I

C o n d it io n v a r ia b le s a r e fo r

s ig n a lin g

, n o t fo r m u tu a l e x c lu s io n .

C o n d itio n va r ia b le s d o n o t p ro vid e m u tu a l e x clu s ion . Y ou n ee d a m u te x to s yn c h r o n ize a cc es s to th e s h a r ed d a ta , in c lu d in g th e p re d ic a te fo r w h ic h yo u w a it. T h a t is w h y yo u m u s t s p ec ify a m u tex w h e n yo u w a it on a c o n d itio n va r ia b le. B y m a k in g th e u n lo ck a to m ic w ith th e w a it, th e P th r ea d s s ys te m e n s u r es th a t n o th r e a d c a n c h a n g e th e p r ed ic a te a fte r yo u h a ve u n lo ck ed th e m u te x b u t b e fo r e y o u r th r ea d is w a itin g on th e c o n d itio n va r ia b le. W h y is n ’t th e m u te x c re a ted a s p a r t o f th e c o n d itio n va r ia b le ? F irs t, m u te x e s a r e u s ed s e p a r a te ly fr o m a n y c o n d itio n va r ia b le a s o fte n a s th e y’re u s ed w ith con d itio n va r ia b le s . S econ d , it is c om m o n fo r o n e m u te x to h a ve m or e th a n on e a s s o cia ted c o n d itio n va r ia b le. F or ex a m p le, a q u e u e m a y b e “fu ll” o r “e m p ty.” A lth o u g h yo u m a y h a ve tw o c o n d itio n va r ia b les to a llo w th r e a d s to w a it fo r e ith e r

Co n d i t i o n va r i a bl es

73

c on d ition , yo u m u s t h a ve on e a n d o n ly o n e m u te x to s yn ch r o n ize a ll a cc es s to th e q u e u e h ea d er. A c o n d itio n va r ia b le s h o u ld b e a s s oc ia te d w ith a s in g le p r e d ica te . I f yo u tr y to s h a r e o n e c o n d itio n va r ia b le b e tw e e n s e ve r a l p r ed ica tes , o r u s e s e ve r a l c o n d itio n va r ia b les for a s in g le p red ica te, y o u ’re r is k in g d e a d lo c k o r r a c e p r o b lem s . T h e r e ’s n o th in g w r o n g w ith d o in g eith er, a s lo n g a s y o u ’re c a r e fu l— b u t it is e a s y to con fu s e y o u r p r o g r a m (co m p u te rs a r e n ’t v e r y s m a rt) a n d it is u s u a lly n o t w o r th th e ris k . I w ill e x p ou n d on th e d eta ils la ter, b u t th e r u les a r e a s follow s : F irs t, w h e n yo u s h a r e a c o n d itio n va r ia b le b e tw e en m u ltip le p red ica tes , yo u m u s t a lw a ys b ro a d c a s t n e ve r s ig n a li a n d s eco n d , s ig n a l is m o r e e ffic ie n t th a n b ro a d ca s t

B o th th e c o n d itio n va r ia b le a n d th e p r ed ica te a r e s h a r e d d a ta in y o u r p ro g ra m ; th ey a r e u s ed b y m u ltip le th r e a d s , p o s s ib ly a t th e s a m e tim e. B ec a u s e y o u ’re th in k in g o f th e c on d itio n va r ia b le a n d p re d ic a te a s b e in g loc k e d tog eth er , it is e a s y to r e m e m b e r th a t th e y’re a lw a ys c on tr o lle d u s in g th e s a m e m u tex . It is p o s s ib le (a n d leg a l, a n d o fte n e ven r ea s o n a b le ) to s ig n a l o r b ro a d ca s t a c o n d itio n va r ia b le w ith o u t h a vin g th e m u te x lock ed , b u t it is s a fer to h a ve it lock ed . F ig u r e 3 .4 is a tim in g d ia g r a m s h o w in g h o w th r ee th r ea d s , th r e a d 1, th r ea d 2, a n d th r e a d 3, in te r a c t w ith a c o n d itio n va r ia b le. T h e r o u n d e d b o x r ep r es en ts th e c o n d itio n va r ia b le , a n d th e th r e e lin e s r e p r e s e n t th e a c tio n s o f th e th r ee th rea d s .

FIG U RE 3.4

C on d ition v ariab le ope ra tion

74

CH A P T E R 3

S yn c h r o n i z a t i o n

W h e n a lin e g oe s w ith in th e b ox , it is “d o in g s o m e th in g ” w ith th e c o n d itio n va n a b le. W h e n a th r e a d ’s lin e s top s b e fo r e r e a c h in g b e lo w th e m id d le lin e th r o u g h th e b ox , it is w a itin g o n th e c o n d itio n va r ia b le; a n d w h e n a th r e a d ’s lin e r ea ch es b e lo w th e m id d le lin e, it is s ig n a lin g o r b r o a d c a s tin g to a w a k en w a iter s . T h r e a d 1 s ig n a ls th e c o n d itio n va r ia b le, w h ic h h a s n o e ffe c t s in c e th er e a r e n o w a iter s . T h r e a d 1 th en w a its on th e c o n d itio n va r ia b le . T h r e a d 2 a ls o b loc k s on th e c o n d itio n va r ia b le a n d , s h o r tly th er ea fter, th r ea d 3 s ig n a ls th e c o n d itio n va r ia b le. T h r e a d 3 ’s s ig n a l u n b lo ck s th r e a d 1. T h r e a d 3 th e n w a its on th e c o n d itio n va r ia b le . T h r e a d 1 b r o a d c a s ts th e c o n d itio n va r ia b le, u n b lo c k in g b o th th r ea d 2 a n d th r e a d 3. T h r e a d 3 w a its o n th e c o n d itio n va r ia b le s h o r tly th er ea fter, w ith a tim e d w a it. S o m e tim e la ter, th r ea d 3 ’s w a it tim e s ou t, a n d th e th r ea d a w a k en s .

3.3.1

C re a tin g a n d d e s tro y in g a c o n d itio n v a ria b le

pthread_cond_t cond = PTHREAD_COND_INITlALIZER; int pthread__cond_±nit (pthread_cond_t *cond, pthread_eondattr_t *condattr); int pthread_cond_destroy (pthread_cond_t *cond) ;

A c o n d itio n va r ia b le is r ep r es en ted in y o u r p r o g r a m b y a va r ia b le o f typ e p th r e a d _ c o n d _ t. Y ou s h o u ld n e ve r m a k e a c o p y o f a c o n d itio n va r ia b le, b e ca u s e th e r es u lt o f u s in g a co p ied c o n d itio n v a r ia b le is u n d efin ed . It w o u ld b e lik e telep h o n in g a d is c o n n ec ted n u m b e r a n d e x p e c tin g a n a n s w er. O n e th r ea d cou ld , fo r ex a m p le, w a it on o n e c op y o f th e c o n d itio n va r ia b le , w h ile a n o th e r th r ea d s ign a led or b r o a d c a s t th e o th e r c o p y o f th e c o n d itio n va r ia b le — th e w a itin g th r e a d w o u ld n o t b e a w a k e n ed . Y ou ca n , h ow ever , fr e e ly p a s s p o in ter s to a c o n d itio n va r ia b le s o th a t va r io u s fu n c tio n s a n d th r e a d s c a n u s e it fo r s yn ch r on iza tio n . M os t o f th e tim e y o u ’ll p r o b a b ly d e cla r e c o n d itio n va r ia b le s u s in g th e extern o r s t a t i c s to r a g e cla s s a t file s cop e, th a t is , o u ts id e o f a n y fu n c tion . T h e y s h o u ld h a ve n o r m a l (extern) s to r a g e cla s s if th e y a r e u s ed b y o th e r files , o r s t a t i c s to r a g e c la s s if u s e d o n ly w ith in th e file th a t d e cla r e s th e va r ia b le. W h e n y o u d ecla r e a

s ta tic c o n d itio n

va r ia b le

th a t h a s

d e fa u lt a ttr ib u tes , yo u

s h o u ld

use

th e

p t h r e a d _ c o n d _ i n i t i a l i z e r in itia liza tio n m a cro, a s s h o w n in th e fo llo w in g e x a m -

p ie, c o n d _ s t a t ic . c .

■ 1 2 3 4 5 6

cond_static.c #include #include "errors.h" /* * Declare a structure, with a mutex and condition variable, * statically initialized. This is the same as using

75

Co n d i t i o n v a r i a b l e s

7

pthread_mutex_init and pthread_cond_init, with the default * attributes.

*

8

*/

9 10

typedef struct my_struct_tag { pthread_mutex_t mutex; pthread_cond_t cond; int value; > my_struct_t;

11

12

13 14 15 16 17 18 19

/* Protects access to value */ /* Signals change to value */ /* Access protected by mutex */

my_struct_t data = { PTHREAD_MUTEX_INITIALIZER, PTHRE AD__COND_I NIT IALIZ E R , 0}; int main (int argc, char *argv[])

20

{

21

return 0;

22

} ■

cond_static.c

I

C o n d it io n v a r ia b le s a n d th e ir p r e d ic a t e s a r e " lin k e d ‫ — ״‬fo r b e s t results, tr e a t th e m th a t w a y !

W h e n you d e cla r e a c o n d itio n va r ia b le, r e m e m b e r th a t a c o n d itio n va r ia b le a n d th e a s s o c ia ted p r ed ica te a r e “loc k e d to g eth e r .” Y ou m a y s a ve y o u r s e lf (or y o u r s u c ces s o r ) s om e c o n fu s io n b y a lw a ys d e c la r in g th e c o n d itio n va r ia b le a n d p red ica te tog eth er , if p os s ib le. I r ec o m m en d th a t yo u

tr y to e n c a p s u la te a s et o f

in va r ia n ts a n d p r ed ic a te s w ith its m u te x a n d o n e o r m o r e c o n d itio n va r ia b le s a s m em b e r s in a s tr u c tu r e, a n d c a r e fu lly d o c u m e n t th e a s s oc ia tio n . S o m e tim e s yo u c a n n o t in itia liz e a c o n d itio n va r ia b le s ta tic a lly; fo r ex a m p le, w h e n yo u u s e m a llo c to c r e a te a s tr u c tu r e th a t c o n ta in s a c o n d itio n va r ia b le. T h e n yo u w ill n e ed to c a ll p th r e a d _ c o n d _ in it to in itia lize th e c o n d itio n va r ia b le d yn a m ica lly, a s s h o w n in th e fo llo w in g ex a m p le, con d _ _ d yn a m ic.c. Y ou c a n a ls o d yn a m ica lly in itia lize c o n d itio n va r ia b le s th a t yo u

d e cla r e s ta tic a lly— b u t yo u

m u s t e n s u r e th a t e a ch c o n d itio n va r ia b le is in itia lize d b efo r e it is u s ed , a n d th a t ea c h is in itia lize d o n ly on ce. Y ou m a y in itia lize it b efo r e c r e a tin g a n y th r e a d s , fo r ex a m p le, o r b y u s in g p th r e a d _ o n c e (S e ctio n 5.1). I f yo u n e ed to in itia lize a c o n d itio n va r ia b le w ith n o n d e fa u lt a ttr ib u tes , yo u m u s t u s e d yn a m ic in itia liza tio n (s ee S e c tio n 5 .2 .2 ).



1 2

3 4 5 6

7

c o n d _ dynamic.c

#include #include "errors.h" /*

* Define a structure, with a mutex and condition variable. */

typedef struct my_struct_tag {

76

8

CH A P T E R 3

pthread_mutex__t pthread_cond_t int } my_struct_t;

9 10 11

mutex; cond; value;

S yn c h r o n i z a t i o n

/* Protects access to value */ /* Signals change to value */ /* Access protected by mutex */

12

13 14 15 16 17 18 19

int main (int argc, char *argv[]) {

my_struct_t *data; int status; data = malloc (sizeof (my_struct_t)); if (data == NULL) errno_abort ("Allocate structure"); status = pthread_mutex_init (&data->mutex, NULL); if (status != 0) err_abort (status, "Init mutex"); status = pthread_cond__init (&data->cond, NULL); if (status != 0) err_abort (status, ,,Init condition"); status = pthread__cond_destroy (&data->cond); if (status != 0) err_abort (status, "Destroy condition"); status = pthread_mutex_destroy (&data->mutex); if (status != 0) err_abort (status, "Destroy mutex"); (void)free (data); return status;

20 21 22

23 24 25 26 27 28 29 30 31 32 33 34 35

} ■

c o n d _ dynamic.c

W h e n yo u d yn a m ica lly in itia lize a c o n d itio n va r ia b le, yo u s h o u ld d es tr oy th e c o n d itio n va r ia b le w h e n yo u n o lo n g e r n eed it, b y c a llin g pthread_cond_destroy. Y o u d o n o t n e e d to d e s tr o y a c o n d itio n va r ia b le th a t w a s s ta tic a lly in itia lize d u s in g th e p t h r e a d _ c o n d _ i n i t i a l i z e r m a cro. It is s a fe to d e s tr o y a c o n d itio n va r ia b le w h e n yo u k n o w th a t n o th r e a d s ca n b e b lo ck e d on th e c o n d itio n va r ia b le , a n d n o a d d ition a l th r e a d s w ill tr y to w a it on , s ig n a l, o r b r o a d c a s t th e c o n d itio n va r ia b le. T h e b e s t w a y to d ete rm in e th is is u s u a lly w ith in a th r ea d th a t h a s ju s t s u cc e s s fu lly b r o a d c a s t to u n b lo c k a ll w a iter s , w h e n p r o g r a m log ic e n s u r es th a t n o th r ea d s w ill tr y to u s e th e c o n d itio n va r ia b le la ter. W h e n a th r e a d r e m o ve s a s tr u c tu r e c o n ta in in g a c o n d itio n va r ia b le fro m a lis t, fo r ex a m p le, a n d th en b r o a d c a s ts to a w a k en a n y w a iter s , it is s a fe (a n d a ls o a v e r y g oo d id ea ) to d e s tr o y th e c o n d itio n va r ia b le b efor e fr e e in g th e s tor a g e th a t th e c o n d itio n va r ia b le o ccu p ies . T h e a w a k e n e d th r ea d s s h o u ld c h e ck th e ir w a it p r ed ic a te w h e n

th ey

r es u m e,

s o yo u

m u st m ake

su re

th a t yo u

d o n ’t free

r es o u r ce s r eq u ir ed fo r th e p r ed ica te b efo r e th e y ’ve d o n e s o— th is m a y r eq u ir e a d d itio n a l s yn ch r on iza tio n .

77

Co n d i t i o n va r i a bl es

3 .3 .2

W a itin g o n a c o n d itio n v a ria b le

int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_timedwait (pthread_cond__t *condr pthread_mutex_t *mutex, struct timespec *expiration); E a c h c o n d itio n va r ia b le m u s t b e a s s o c ia ted w ith a s p ec ific m u te x , a n d w ith a p r e d ic a te c on d ition . W h e n a th r ea d w a its on a c o n d itio n v a r ia b le it m u s t a lw a ys h a ve th e a s s oc ia ted m u te x lock ed . R e m e m b e r th a t th e c o n d itio n va r ia b le w a it o p e r a tio n w ill u n lo ck th e m u te x fo r yo u b efor e b lo c k in g th e th rea d , a n d it w ill re lo ck th e m u te x b e fo re r e tu r n in g to y o u r cod e.

A ll th r ea d s th a t w a it on a n y on e c o n d itio n va r ia b le c o n cu r r e n tly (a t th e s a m e tim e) m u s t s p e cify th e s a m e a s s o c ia ted m u tex . P th r e a d s d oe s n o t a llo w th r e a d 1, fo r e x a m p le, to w a it on c o n d itio n va r ia b le A s p e cifyin g m u te x A w h ile th r e a d 2 w a its on c o n d itio n va r ia b le A s p e c ifyin g m u te x B . It is , h ow ever , p e r fe c tly r ea s o n a b le fo r th re a d 1 to w a it o n c on d itio n va r ia b le A s p ec ifyin g m u te x A w h ile th r e a d 2 w a its o n c on d itio n va r ia b le B s p ec ifyin g m u te x A . T h a t is . e a c h c o n d itio n va r ia b le m u s t b e a s s ocia ted , a t a n y g ive n tim e, w ith o n ly on e m u te x — b u t a m u te x m a y h a ve a n y n u m b e r o f c o n d itio n va r ia b le s a s s o c ia ted w ith it. It is im p o r ta n t th a t yo u tes t th e p re d ic a te a fte r lo c k in g th e a p p r o p r ia te m u tex a n d b e fo r e w a itin g on th e c o n d itio n va r ia b le. If a th r ea d s ig n a ls o r b r o a d c a s ts a c o n d itio n va r ia b le w h ile n o th r e a d s a r e w a itin g , n o th in g h a p p e n s . I f s om e o th e r th r e a d ca lls p th r e a d _ c o n d _ w a it r ig h t a fte r th a t, it w ill k e ep w a itin g r e g a r d les s o f th e fa c t th a t th e c o n d itio n va r ia b le w a s ju s t s ig n a led , w h ic h m e a n s th a t if a th r e a d w a its w h e n it d o e s n ’t h a ve to. it m a y n e v e r w a k e u p . B ec a u s e th e m u te x r em a in s loc k e d u n til th e th r ea d is b loc k ed o n th e c o n d itio n va r ia b le , th e p red ic a te c a n n o t b e co m e s et b e tw e e n th e p r e d ica te te s t a n d th e w a it— th e m u te x is loc k e d a n d n o o th er th re a d c a n c h a n g e th e s h a r ed d a ta , in c lu d in g th e p red ica te.

I A lw a y s te s t y o u r p r e d ic a t e ; a n d th e n te s t it a g a in ! It is e q u a lly im p o r ta n t th a t yo u

tes t th e p r ed ica te a g a in w h en th e th r ea d

w a k e s u p . Y ou s h o u ld a lw a ys w a it fo r a c o n d itio n va r ia b le in a loop , to p r o te ct a g a in s t p r o g r a m err or s , m u ltip r o c e s s o r r a ces , a n d s p u r io u s w a k eu p s . T h e follow in g s h o r t p r o g r a m , cond.c, s h o w s h o w to w a it o n a c o n d itio n va r ia b le. P ro p e r p r e d ic a te loo p s a r e a ls o s h o w n in a ll o f th e e x a m p le s in th is b o o k th a t u s e c on d itio n va r ia b les , fo r e x a m p le, alarm_cond.c in S e c tio n 3.3.4.

20-37

T h e wait_thread s leep s fo r a s h o r t tim e to a llo w th e m a in th r ea d to r ea ch its c o n d itio n w a it b efor e w a k in g it, s ets th e s h a r ed p r ed ica te (data.value), a n d th e n s ig n a ls th e c o n d itio n va r ia b le. T h e a m o u n t o f tim e fo r w h ic h wait_thread w ill

sleep is c on tr o lled b y th e hibernation va r ia b le, w h ich d e fa u lts to on e s econ d .

78

CH A P T E R 3

S yn c h r o n i z a t i o n

If th e p r o g r a m w a s r u n w ith a n a r gu m e n t, in te r p r e t th e a r g u m e n t a s a n in te-

51-52

g e r va lu e , w h ic h is s tor ed in hibernation. T h is c o n tr o ls th e a m o u n t o f tim e fo r w h ic h wait .thread w ill s leep b e fo r e s ig n a lin g th e c o n d itio n va r ia b le. T h e m a in th r ea d c a lls pthread_cond_timedwait to w a it fo r u p to tw o s eco n d s

68-83

(fro m th e c u r r e n t tim e). I f hibernation h a s b e e n s et to a va lu e o f g r e a te r th a n tw o s eco n d s , th e c o n d itio n w a it w ill tim e ou t, r e tu r n in g ET1MED0UT. I f hibernation h a s b ee n s e t to tw o, th e m a in th r ea d a n d wait_thread ra ce, a n d . in p r in c ip le, th e r e s u lt c ou ld d iffe r e a c h tim e yo u r u n th e p ro g r a m . I f hibernation is s et to a va lu e le s s th a n tw o, th e c o n d itio n w a it s h o u ld n o t tim e ou t.



cond.c

1 #include 2 #include 3 #include "errors.h" 4 5 typedef struct my_struct_tag { 6 pthread_mutex__t mutex; /* Protects access to value */ 7 pthread_cond_t cond; /* Signals change to value */ /* Access protected by mutex */ 8 int value; 9 } my_str u c t _ t ; 10 11 my struct_t data = { 12 PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0}; 13 14 int hibernation = 1 ; /* Default to 1 second */ 15 16 /* * Thread start routine. It will set the main t h r e a d ’s predicate 17 * and signal the condition variable. 18 19 */ 20 void * 21 wait thread (void *arg) 22 { 23 int status; 24 25 sleep (hibernation); 26 status = pthread mutex lock (&data.mutex); 27 if (status != 0) 28 err_abort (status, "Lock mutex"); 29 data.value = 1 ; /* Set predicate */ status = pthread_cond_signal (sdata.cond); 30 31 if (status != 0) 32 err_abort (status, "Signal condition‫;) ״‬ 33 status = pthread mutex unlock (&data.mutex); 34 if (status != 0) 35 err abort (status, "Unlock mutex"); 36 return NULL; 37 }

79

Co n d i t i o n v a r i a b l e s

int main (int argc, char *argv[]) {

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

int status? pthread_t wait_thread__id; struct timespec timeout; /*

* * * * */

if (argc > 1) hibernation = atoi (argv[l]); /*

* Create wait__thread. */

status = pthread_create ( &wait_thread_id, NULL, wait_thread, N U L L ) ; if (status i= 0) err_abort (status, "Create wait thread"); /*

* * * *

66

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

Wait on the condition variable for 2 seconds, or until signaled by the wait_thread. Normally, wait_thread should signal. If you raise "hibernation" above 2 seconds, it will time out.

*/

67 68

If an argument is specified, interpret it as the number of seconds for wait_thread to sleep before signaling the condition variable. You can play with this to see the condition wait below time out or wake normally.

timeout.tv_sec = time (NULL) + 2; timeo u t .tv_nsec = 0; status = pthread_mutex_lock (&data.mutex); if (status != 0) err_abort (status, "Lock mutex"); while (data.value == 0) { , status = pthread_cond_timedwait ( fcdata.cond, fcdata.mutex, stimeout); if (status == ETIMEDOUT) { printf ("Condition wait timed o u t . \ n " ); break; }

else if (status != 0) err__abort (status,

"Wait on condition1');

}

if (data.value != 0) printf ("Condition was signaled.\n");

^

80

87 88 89 90 91

CH A P T E R 3

S yn c h r o n i z a t i o n

status = pthread_mutex_unlock (Scdata, m u t e x ) ; if (status i ~ 0) err__abort (status, ‫ ״‬Unlock mutex"); return 0; } ■

cond.c T h e r e a r e a lot o f r ea s o n s w h y it is a g oo d id e a to w r ite c od e th a t d oes n o t a s s u m e th e p r ed ica te is a lw a ys tr u e on w a k e u p , b u t h e re a r e a fe w o f th e m a in

r ea s o n s :

I n t e rc e p t e d w ak e up s: R e m e m b e r th a t th r e a d s a r e a s yn c h r o n ou s . W a k in g u p fr o m a c o n d itio n va r ia b le w a it in vo lve s lo c k in g th e a s s o c ia te d m u tex . B u t w h a t if s om e o th e r th r ea d a c q u ir es th e m u te x firs t? It m a y, fo r ex a m p le, b e c h e c k in g th e p re d ic a te b efo r e w a itin g its elf. It d o e s n ’t h a ve to w a it, s in c e th e p r ed ica te is n o w tru e. I f th e p re d ica te is “w o r k a va ila b le ,” it w ill a cc ep t th e w ork . W h e n it u n lo c k s th e m u te x th er e m a y b e n o m or e w ork . It w o u ld b e ex p e n s ive, a n d u s u a lly c ou n te r p r o d u c tive , to e n s u r e th a t th e la tes t a w a k e n e d th r e a d g o t th e w o r k .

L o o se pre d ic at e s: F o r a lot o f r ea s o n s it is o fte n e a s y a n d c o n ve n ie n t to u s e a p p r o x im a tio n s o f a c tu a l s ta te. F or e x a m p le, “th er e m a y b e w o r k ” in s te a d o f “th er e is w o r k .” It is often m u c h e a s ier to s ig n a l or b r o a d c a s t b a s e d on “loo s e p r e d ic a te s ” th a n on th e r ea l ‘‘tig h t p r e d ic a te s .” I f yo u a lw a ys te s t th e tig h t p r e d ic a te s b e fo r e a n d a fter w a itin g on a c o n d itio n va r ia b le, y o u ’re fr e e to s ig n a l b a s e d on th e lo o s e a p p r o x im a tio n s w h e n th a t m a k es s en s e. A n d y o u r c od e w ill b e m u c h m o r e r o b u s t w h e n a c o n d itio n va r ia b le is s ig n a led o r b r o a d c a s t a c cid en ta lly. U s e o f lo o s e p re d ic a te s or a c c id e n ta l w a k e u p s m a y tu r n ou t to b e a p e r fo r m a n c e is s u e; b u t in m a n y c a s e s it w o n ’t m a k e a d iffe re n c e.

Sp uri o us w ak e up s: T h is m ea n s th a t w h e n yo u w a it on a c o n d itio n va r ia b le, th e w a it m a y (oc ca s io n a lly) r etu r n w h e n n o th r e a d s p ec ific a lly b ro a d c a s t or s ig n a led th a t c o n d itio n va r ia b le. S p u r io u s w a k e u p s m a y s ou n d s tr a n g e, b u t on s om e m u ltip ro c es s o r s ys tem s , m a k in g co n d itio n w a k e u p co m p letely p r e d icta b le m ig h t s u b s ta n tia lly s low a ll c o n d itio n va r ia b le op er a tion s . T h e r a ce co n d ition s th a t ca u s e s p u r io u s w a k e u p s s h o u ld b e con s id er ed ra re. It u s u a lly ta k e s o n ly a fe w in s tr u c tio n s to r e tes t yo u r p re d ica te, a n d it is a g o o d p r o g r a m m in g d is cip lin e. C o n tin u in g w ith o u t r e tes tin g th e p r ed ic a te c ou ld le a d to s e riou s a p p lic a tio n er r or s th a t m ig h t b e d iffic u lt to tr a c k d o w n la ter. S o d o n ’t m a k e a s s u m p tion s : A lw a ys w a it fo r a c o n d itio n va r ia b le in a w h ile loop te s tin g th e p red ica te. Y ou c a n a ls o u s e th e pthread_cond_timedwait fu n ction , w h ic h ca u s es th e w a it to en d w ith a n e t i m e d o u t s ta tu s a fte r a c e r ta in tim e is r ea ch ed . T h e tim e is a n a b s o lu te c lo c k tim e, u s in g th e P O S IX . l b struct

timespec fo r m a t. T h e tim e-

ou t is a b s o lu te r a th e r th a n a n in ter va l (or “d elta tim e ”) s o th a t on c e y o u ’ve c om p u te d th e tim e o u t it r em a in s va lid r e g a r d le s s o f s p u r io u s o r in ter ce p ted

Co n d i t i o n va r i a bl es

81

w a k eu p s . A lth o u g h it m ig h t s ee m e a s ie r to u s e a n in ter va l tim e, y o u ’d h a ve to r ec o m p u te it e ve r y tim e th e th r e a d w a k e s u p , b e fo r e w a itin g a g a in — w h ic h w o u ld r eq u ir e d e te r m in in g h o w lo n g it h a d a lr e a d y w a ited . W h e n a tim ed c o n d itio n w a it r etu r n s w ith th e e t i m e d o u t error, yo u s h o u ld te s t y o u r p re d ic a te b efo r e tr e a tin g th e r e tu rn a s a n error. If th e c o n d itio n fo r w h ic h yo u w e r e w a itin g is tru e, th e fa c t th a t it m a y h a ve ta k en to o lo n g u s u a lly is n ’t im p o rta n t. R e m e m b e r th a t a th r e a d a lw a ys r elo ck s th e m u te x b e fo r e r etu r n in g fro m a c o n d itio n w a it, e ven w h e n th e w a it tim e s ou t. W a itin g fo r a loc k e d m u te x a fte r tim eo u t ca n ca u s e th e tim e d w a it to a p p e a r to h a ve ta k en a lo t lon g e r th a n th e tim e yo u r eq u es ted .

3 .3 .3

W a k in g c o n d itio n v a ria b le w aiters

int pthread_cond_signal (pthread_cond_t * cond); int pthread_cond_broadcast (pthread_cond_t *cond);

O n c e y o u ’ve g o t a th re a d w a itin g o n a c o n d itio n va r ia b le for s om e p red ica te, y o u ’ll p r o b a b ly w a n t to w a k e it u p . P th r e a d s p ro vid e s tw o w a ys to w a k e a con d itio n va r ia b le w a iter. O n e is ca lled “s ig n a l” a n d th e o th e r is ca lled “b r o a d c a s t.” A s ig n a l o p e r a tio n w a k es u p a s in g le th r e a d w a itin g on th e c o n d itio n va r ia b le , w h ile b ro a d c a s t w a k es u p a ll th r ea d s w a itin g o n th e c o n d itio n va r ia b le. T h e ter m “s ig n a l” is e a s ily c o n fu s e d w ith th e “P O S IX s ig n a l” m e c h a n is m s th a t a llo w you to d e fin e “s ig n a l a c tio n s ,” m a n ip u la te “s ig n a l m a s k s ,” a n d s o forth . H ow ever, th e ter m “s ig n a l,” a s w e u s e it h ere, h a d in d e p e n d e n tly b e co m e w e ll e s ta b lis h e d in th r e a d in g lite ra tu r e, a n d even in c o m m e r cia l im p le m e n ta tio n s , a n d th e P th r ea d s w o r k in g g r o u p d ecid e d n o t to c h a n g e th e term . L u ck ily, th er e a r e fe w s itu a tion s w h er e w e m ig h t b e te m p ted to u s e b oth te r m s to g eth er — it is a v e r y g o o d id ea to a void u s in g s ig n a ls in th r ea d ed p ro g r a m s w h e n a t a ll p os s ib le. If w e a r e c a r e fu l to s a y “s ig n a l a c on d itio n v a r ia b le ” o r “P O S IX s ig n a l” (or “U N IX s ign a l”) w h er e th er e is a n y a m b ig u ity, w e a r e u n lik e ly to c a u s e a n yo n e s ever e d is co m for t. It is e a s y to th in k o f “b r o a d c a s t” a s a g en e r a liza tio n o f “s ig n a l,” b u t it is m or e a c cu r a te to th in k o f s ig n a l a s a n o p tim iza tio n o f b r o a d c a s t. R e m e m b e r th a t it is n e ver w r o n g to u s e b ro a d c a s t in s te a d o f s ig n a l s in c e w a iter s h a ve to a cc o u n t fo r in ter c ep te d a n d s p u r io u s w a k e s . T h e o n ly d iffe re n c e, in fa ct, is efficien c y: A b r o a d c a s t w ill w a k e a d d itio n a l th r ea d s th a t w ill h a ve to te s t th e ir p re d ic a te a n d r e s u m e w a itin g . B u t, in g en er a l, yo u c a n ’t r ep la c e a b r o a d c a s t w ith a s ig n a l. “W h e n in d ou b t, b r o a d c a s t.” U s e s ig n a l w h en o n ly on e th r e a d n ee d s to w a k e u p to p r o ces s th e c h a n g e d s ta te, a n d w h en a n y w a itin g th r e a d ca n d o s o. I f yo u u s e o n e c o n d itio n va r ia b le fo r s eve ra l p r o g r a m p r ed ic a te co n d ition s , y o u c a n ’t u s e th e s ig n a l op e r a tion ; yo u c o u ld n ’t tell w h e th e r it w o u ld a w a k e n a th re a d w a itin g fo r th a t p r e d ica te, or fo r

82

CH A P T E R 3

S yn c h r o n i za t i o n

a n o th er p r e d ica te . D o n ’t tr y to g e t a r ou n d th a t b y r e s ig n a lin g th e c o n d itio n va r ia b le w h e n yo u fin d th e p re d ic a te is n ’t tru e. T h a t m ig h t n o t p a s s o n th e s ig n a l a s yo u ex p ect; a s p u r io u s or in te r c e p ted w a k e u p co u ld r e s u lt in a s er ies o f p oin tle s s r es ig n a ls . I f yo u a d d a s in g le item to a q u eu e, a n d o n ly th re a d s w a itin g fo r a n ite m to a p p e a r a r e b lo c k ed o n th e c o n d itio n va r ia b le , th e n yo u s h o u ld p r o b a b ly u s e a s ign a l. T h a t’ll w a k e u p a s in g le th r ea d to c h e c k th e q u e u e a n d le t th e o th er s s leep u n d is tu r b ed , a void in g u n n e c e s s a r y c o n te x t s w itch es . O n th e o th e r h a n d , if yo u a d d m o r e th a n o n e item to th e q u eu e, yo u w ill p r o b a b ly n ee d to b r o a d ca s t. F or e x a m p les o f b o th b r o a d c a s t a n d s ig n a l o p e r a tio n s on c o n d itio n va r ia b les , c h e c k o u t th e “r e a d / w r ite lo c k ” p a c k a g e in S e c tio n 7 .1 .2 . A lth o u g h yo u m u s t h a ve th e a s s oc ia ted m u te x loc k e d to w a it o n a c o n d itio n va r ia b le , yo u c a n s ig n a l (or b r o a d ca s t) a c on d itio n va r ia b le w ith th e a s s o cia te d m u te x u n lo c k ed if th a t is m or e co n ve n ien t. T h e a d va n ta g e o f d o in g s o is th a t, on m a n y s ys tem s , th is m a y b e m or e e ffic ie n t. W h e n a w a itin g th r ea d a w a k en s , it m u s t firs t lo c k th e m u tex . I f th e th r e a d a w a k e n s w h ile th e s ig n a lin g th r e a d h o ld s th e m u tex , th e n th e a w a k e n e d th r e a d m u s t im m e d ia te ly b lo c k o n th e m u te x — y o u ’ve g o n e th r o u g h tw o c o n te x t s w itc h e s to g e t b a c k w h er e yo u s ta r ted . W e ig h in g on th e o th e r s id e is th e fa c t th a t, if th e m u te x is n o t lock ed , a n y th r ea d (n ot o n ly th e o n e b e in g a w a k e n ed ) c a n lo c k th e m u te x p r io r to th e th r ea d b e in g a w a k e n ed . T h is r a ce is o n e s o u r ce o f in ter c ep ted w a k eu p s . A lo w e r - p r io r ity th rea d , fo r ex a m p le, m ig h t lo ck th e m u te x w h ile a n o th e r th rea d w a s a b o u t to a w a ken

a v e r y h ig h - p r io r ity th rea d ,

d e la yin g s c h e d u lin g o f th e h ig h - p r io r ity

th rea d . I f th e m u te x r em a in s lo c k e d w h ile s ig n a lin g , th is c a n n o t h a p p en — th e h ig h - p r io r ity w a ite r w ill b e p la c ed b e fo r e th e lo w e r - p r io r ity w a ite r on th e m u tex , a n d w ill b e s c h e d u le d firs t.

3 .3 .4

O n e fin a l a la rm p ro g ra m It is tim e fo r o n e fin a l ve r s io n

o f o u r s im p le a la r m

p ro g r a m .

In

a la r m _

m u te x .c , w e r ed u c e d r es o u r c e u tiliza tio n b y e lim in a tin g th e u s e o f a s e p a ra te e x e c u tio n c o n te x t (th r ea d o r p r o ces s ) fo r e a c h a la r m . In s tea d o f s ep a r a te ex ecu tio n c on tex ts , w e u s ed a s in g le th r e a d th a t p r o ce s s e d a lis t o f a la r m s . T h e r e w a s o n e p r o b lem , h ow ever , w ith th a t a p p r o a ch — it w a s n o t r e s p o n s ive to n e w a la r m c om m a n d s . It h a d to fin is h w a itin g fo r on e a la r m b e fo r e it cou ld d e te c t th a t a n o th e r h a d b e e n e n ter ed o n to th e lis t w ith a n e a r lie r e x p ir a tio n tim e, fo r ex a m p ie, i f on e e n ter ed th e c o m m a n d s “ 10 m es s a g e 1” fo llo w e d b y “5 m es s a g e 2 .”

*T h e r e is an o pt im iz at io n, w h i c h I’v e c alle d “w ait m o rp h i n g ,” t hat m o v e s a t hre ad dire c t ly f ro m t he c o ndit i o n v ar i able w ait q u e ue to t he m ut e x w ai t q ue ue in t his c ase , w i t h o ut a c o nt e xt sw it c h, w h e n t he m ut e x is lo c ke d. T h i s o pt im iz at io n c an p r o d uc e a subst an t i al p e rf o rm an c e be n efit fo r m an y applic at i o ns.

83

Co n d i t i o n va r i a bl es

N o w th a t w e h a ve a d d e d c o n d itio n va r ia b le s to o u r a r s en a l o f th r e a d ed p rog r a m m in g tools , w e w ill s olve th a t p r o b lem . T h e n e w ve r s ion , c r e a tive ly n a m e d

alarm_cond.c, u s es a tim ed co n d itio n w a it r a th e r th a n sleep to w a it fo r a n a la r m e x p ir a tio n tim e. W h e n main in s e r ts a n e w e n tr y a t th e h e a d o f th e lis t, it s ig n a ls th e c o n d itio n va r ia b le to a w a k e n alarm_thread im m e d ia tely. T h e alarm_thread th en r eq u e u e s th e a la r m o n w h ic h it w a s w a itin g , to s or t it p r o p e r ly w ith r e s p ec t to th e n e w en try, a n d tr ie s a g a in . P a r t 1 s h o w s th e d e c la r a tio n s fo r alarm_cond.c. T h e r e a r e tw o a d d itio n s to

20,22

th is s ection , c o m p a r e d to alarm_mutex.c: a c on d itio n va r ia b le c a lled alarm_cond a n d th e current_alarm va r ia b le , w h ic h a llo w s main to d e ter m in e th e e x p ir a tio n tim e o f th e a la r m o n w h ic h alarm_thread is c u r r e n tly w a itin g . T h e current_alarm va r ia b le is a n o p tim iza tio n — main d oe s n o t n e e d to a w a k e n alarm_thread u n les s it is e ith er id le, or w a itin g fo r a n a la r m la te r th a n th e o n e main h a s ju s t in s er ted .



1 2 3 4 5 6 7 8 9 10

part 1

declarations

#include #include #include "errors.h" /* * * * * *

The "alarm" structure now contains the time__t (time since the Epoch, in seconds) for each alarm, so that they can be sorted. Storing the requested number of seconds would not be enough, since the ,,alarm thread" cannot tell how long it has been on the list.

*/

11

12 13 14 15 16 17 18 19 20 21 22

alarm_cond.c

typedef struct alarm_tag { struct alarm_tag *link; int seconds; time_t time; /* seconds from EPOCH */ char m e s s a g e [64]; } alarm_t; pthread_mutex_t alarmjnutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t alarm_cond = PTHREAD_COND_INITIALIZER; alarm_t *alarm_list = NULL; time_t current_alarm = 0; ■

alarm_cond.c

part 1

declarations

P a r t 2 s h o w s th e n e w fu n c tio n alarm_insert. T h is fu n ctio n is n e a r ly th e s a m e a s th e lis t in s e r tio n cod e fro m alarm_mutex.c, e x c e p t th a t it s ig n a ls th e c o n d itio n va r ia b le alarm_cond w h e n n ec es s a r y. I m a d e alarm_insert a s ep a r a te fu n ctio n b e c a u s e n o w it n e ed s to b e ca lle d fro m tw o p la c e s — o n ce b y main to in s e r t a n e w a la r m , a n d n o w a ls o b y alarm_thread to r ein s e r t a n a la r m th a t h a s b e e n “p ree m p te d ” b y a n e w e a r lier a la r m .

84

CH A P T E R 3

S yn c h r o n i za t i o n

I h a ve r e c o m m e n d e d th a t m u te x lo ck in g p r o to co ls b e d o c u m e n ted , a n d h e re is

9-14

a n e x a m p le: T h e alarm_insert fu n ctio n p o in ts o u t e x p lic itly th a t it m u s t b e ca lled w ith th e alarm_mutex lock ed .

48-53

If current_alarm (th e tim e o f th e n ex t a la r m e x p ir a tio n ) is 0, thread is n o t a w a r e o f a n y o u ts ta n d in g a la r m r eq u e s ts , a n d is w o r k . I f current_alarm h a s a tim e g r e a te r th a n th e e x p ir a tio n a la r m , th e n alarm_thread is n o t p la n n in g to lo o k fo r n e w w o r k

th e n th e alarm__ w a itin g fo r n e w tim e o f th e n e w s oo n e n o u g h to

h a n d le th e n e w a la r m . In e ith e r ca s e, s ig n a l th e alarm__cond c on d itio n va r ia b le s o th a t alarm_thread w ill w a k e u p a n d p r o c es s th e n e w a la r m .



alarm__cond.c

part 2

1 2 3 4

/* * Insert alarm entry on list, in order. */ void alarm_insert (alarm_t *alarm)

5

{

6 7

int status; alarm_t **last,

alarm_insert

*next;

8 9 10 11

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

/* * LOCKING PROTOCOL: *

* This routine requires that the caller have locked the * alarm_jm1tex! */ last = &alarm_list; next = *last; while (next != NULL) { if (next->time >= alarm->time) { alarm->link = next; *last = alarm; break;

> last = &next->link; next = next->link; } /* * If we reached the end of the list, insert the new alarm * there. ("next" is NULL, and "last" points to the link * field of the last item, or to the list header.) */ if (next == NULL) { *last = alarm; alarm->link = NULL; } #ifdef DEBUG printf (,,[list: ");

85

Co n d i t i o n va r i a bl es

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

for (next = alarm_list; next != NULL; next = next->link) printf ( ‫ ״‬%d(%d) [\‫ ״‬%s\" ] ", next->time, next->time - time (NULL), next->message); printf ("J\n"); #endif /* * Wake the alarm thread if it is not busy (that is, if * current_alarm is 0, signifying that it's waiting for * work), or if the new alarm comes before the one on * which the alarm thread is waiting. */ if (current_alarm == 0 || alarm->time < current_alarm) { current alarm = alarm->time; status = pthread cond signal (&alarm_cond); if (status != 0) err__abort (status, "Signal cond"); } } ■

alarm_cond.c

part 2

alarm_insert

P a r t 3 s h o w s th e a la r m _ th r e a d fu n ction , th e s ta r t fu n ctio n fo r th e “a la r m s e r ve r ” th rea d . T h e g en e r a l s tr u ctu r e o f a la r m _ th r e a d is v e r y m u c h lik e th e a la r m _ th r e a d in a la r m jm u te x .c . T h e d iffe r e n c e s a r e d u e to th e a d d itio n o f th e c o n d itio n va r ia b le.

26-31

I f th e alarm_list is em p ty, alarm_mutex.c c o u ld d o n o th in g b u t sleep a n yw a y, s o th a t main w o u ld b e a b le to p r o c es s a n e w co m m a n d . T h e r es u lt w a s th a t it c o u ld n o t s ee a n e w a la r m r eq u e s t fo r a t le a s t a fu ll s econ d . N ow , alarm_thread in s te a d w a its

on th e alarm_cond c on d itio n va r ia b le, w ith n o tim eou t. It w ill

“s le e p ” u n til yo u e n ter a n e w a la r m co m m a n d , a n d th en main w ill b e a b le to a w a k e n it im m e d ia tely. S ettin g current_alarm to 0 tells main th a t alarm_thread is id le. R e m e m b e r th a t pthread_cond_wait u n lo c k s th e m u te x b e fo re w a itin g , a n d r elo c k s th e m u te x b e fo r e r e tu r n in g to th e ca ller. 35

T h e n e w va r ia b le e x p ir e d is in itia lize d to 0; it w ill b e s et to 1 la te r if th e tim ed c on d itio n w a it ex p ires . T h is m a k es it a little e a s ie r to d ec id e w h e th e r to p r in t th e c u r r e n t a la r m ’s m e s s a g e a t th e b o tto m o f th e loop .

36-42

I f th e a la r m w e ’ve ju s t r em o ved fr o m th e lis t h a s n ’t a lr e a d y e x p ir ed , th en w e n eed to w a it for it. B ec a u s e w e ’re u s in g a tim ed c o n d itio n w a it, w h ic h r eq u ir e s a P O S IX . l b

struct timespec, r a th e r th a n th e s im p le in te g e r tim e r eq u ir e d b y sleep, w e c o n ve r t th e e x p ir a tio n tim e. T h is is ea s y, b e ca u s e a struct timespec

h a s tw o m e m b e r s — tv_sec is th e n u m b e r o f s eco n d s s in c e th e E p och , w h ic h is e x a c tly w h a t w e a lr ea d y h a ve fr o m th e time fu n ction , a n d tv_nsec is a n a d d itio n a l c ou n t o f n a n o s ec on d s . W e w ill ju s t s e t tv_nsec to 0, s in c e w e h a ve n o n e ed o f th e g r e a te r r es o lu tion .

43

R eco r d th e e x p ir a tio n tim e in th e current_alarm va r ia b le s o th a t main c a n d e te r m in e w h e th e r to s ig n a l alarm__cond w h e n a n e w a la r m is a d d ed .

86

CH A P T E R 3

S yn c h r o n i za t i o n

W a it u n til e ith e r th e c u r r e n t a la r m h a s e x p ir ed , or main r e q u e s ts th a t alarm_ thread lo o k fo r a n ew , e a r lie r a la r m . N otic e th a t th e p r ed ica te te s t is s p lit h ere,

44-53

fo r c on ve n ien c e. T h e e x p r es s io n in th e w h ile s ta te m e n t is o n ly h a lf th e p red ica te, d ete c tin g th a t main h a s c h a n g e d current_alarm b y in s e r tin g a n e a r lie r tim er. W h e n th e tim ed w a it r e tu r n s e t i m e d o u t , in d ica tin g th a t th e c u r r e n t a la r m h a s ex p ir ed , w e e x it th e w h ile lo o p w ith a break s ta te m e n t a t lin e 4 9 . 54-55

I f th e w h ile lo o p e x ite d w h e n th e c u r r e n t a la r m h a d n o t ex p ired , m a in m u s t h a ve a s k e d a la r m _ th r e a d to p r o c es s a n e a r lie r a la r m . M a k e s u r e th e c u r r e n t a la r m is n ’t lo s t b y r ein s e r tin g it o n to th e lis t.

57

I f w e r em o ve fr o m a l a r m _ l is t a n a la r m th a t h a s a lr e a d y e x p ir ed , ju s t s et th e e x p ir e d va r ia b le to 1 to e n s u r e th a t th e m es s a g e is p rin ted .



alarm__cond.c

part 3

alarm_routine

1 /* 2 * The alarm thread's start routine. 3 */ 4 void *alarm_thread (void *arg) 5 { 6 alarm t *alarm; 7 struct timespec cond__time; 8 time t now; 9 int status, expired; 10 11 /* 12 * Loop forever, processing commands. The alarm thread will 13 * be disintegrated when the process exits. Lock the mutex 14 * at the start — it will be unlocked during condition 15 * waits, so the main thread can insert alarms. 16 */ 17 status = pthread_mutex_lock (&alarm_mutex); 18 if (status != 0) 19 err abort (status, '1Lock mutex"); 20 while (1) { 21 /* 22 * If the alarm list is empty, wait until an alarm is * added. Setting current_alarm to 0 informs the insert 23 24 * routine that the thread is not busy. 25 */ current alarm = 0; 26 27 while (alarm list ‫ == ־‬NULL) { 28 status = pthread_cond wait (&alarm_cond. &alarm mutex); if (status != 0) 29 30 err abort (status, "Wait on cond"); 31 } alarm = alarm_list; 32 alarm_JList = alarm->link; 33 34 now = time (NULL);

87

Co n d i t i o n va r i a bl es

expired = 0; if (alarm->time > now) { #ifdef DEBUG printf (,,[waiting: %d( %d) V' %s\” ]\n" , alarm->time, alarm->time - time (NULL), alarm->message); #endif cond_time.tv_sec = alarm->time; cond__time. tv_nsec = 0; current__alarm = alarm->time; while (current_alarm == alarm->time) { status = pthread_cond__timedwait ( &alarm_cond, &alarm_mutex, &cond_time); if (status == ETIMEDOUT) { expired = 1; break;

35 36 37 38 39

40 41 42 43 44 45 46

47 48 49 50

>

51

if (status 1= 0) err_abort (status,

52 53

"Cond timedwait” );

}

60

if (!expired) alarm_insert (alarm); } else expired = 1; if (expired) { printf ("(%d) % s \ n ", alarm->seconds, alarm->message); free (alarm);

61

}

54 55 56 57 58 59

62 63 alarm_cond.c

part 3

alarm_routine

P a r t 4 s h o w s th e fin a l s ection o f alarm_cond.c, th e main p ro g r a m . It is n e a r ly id e n tic a l to th e main fu n ctio n fro m alarm_mutex.c. B ec a u s e th e c o n d itio n va r ia b le s ig n a l o p e r a tio n is b u ilt in to th e n e w alarm_

38

insert fu n ction , w e c a ll alarm_insert r a th e r th a n

in s e r tin g

a

n ew

a la r m

part 4

main

d ir ectly.



alarm_cond.c

1

int main

2

{

3 4 5 6

(int argc, char *argv[])

int status; char line[128]; alarm__t *alarm; pthread_t thread;

7

8 9

status = pthread_create ( &thread, NULL, alarm__thread, NULL);

88

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

CH A P T E R 3

S yn c h r o n i z a t i o n

if (status != 0) err abort (status, "Create alarm thread"); while (1) { printf ("Alarm> "); if (fgets (line, sizeof (line), stdin) == NULL) exit if (strlen (line) seconds, alarm->message) < 2) { fprintf (stderr, "Bad c o m m and\n"); free (alarm); > else { status = pthread_mutex__lock (&alarm_mutex); if (status != 0) err_abort (status, "Lock mutex"); alarm->time = time (NULL) + alarm->seconds; /* * Insert the new alarm into the list of alarms. * sorted by expiration time. */ alarm insert (alarm); status = pthread_jnutex unlock (&alarm_mutex); if (status 1= 0) err abort (status, "Unlock mutex"); > } ■

} alarm_cond.c

3.4 M e m o ry visibility b e tw e e n th re a d s The m o m e n t A lic e a p p e a r e d , she w as a p p e a l e d to b y a ll th re e to settle th e q uestion, a n d th e y r e p e a te d th eir a rg u m e n ts to her, th o u g h , a s th e y a ll s p o k e a t o n c e , she fo u n d it v e ry h a r d to m a k e o u t e x a c tly w h a t th e y said . — L e w is C a r r o l A l i c e 's A d v e n t u r e s in W o n d e r l a n d

part 4

main

M e m o r y vi si bi l i t y b e t w e e n t h r e a d s

89

In th is c h a p te r w e h a ve s een h o w yo u s h o u ld u s e m u tex e s a n d c o n d itio n va r ia b les to s yn ch r o n ize (or “c o o r d in a te ”) th r e a d a ctivitie s . N o w w e ’ll jo u r n e y o ff on a ta n g e n t, fo r ju s t a fe w p a g es , a n d s ee w h a t is r ea lly m ea n t b y “s yn c h r o n iza tio n ” in th e w o r ld o f th r ea d s . It is m o r e th a n m a k in g s u r e tw o th r e a d s d o n ’t w r ite to th e s a m e lo c a tio n a t th e s a m e tim e, a lth o u g h th a t’s p a r t o f it. A s th e title o f th is s ectio n im p lie s , it is a b o u t h o w th r ea d s s ee th e c o m p u te r ’s m em or y. P th r e a d s p r o vid e s a fe w b a s ic r u les a b o u t m e m o r y vis ib ility. Y ou c a n c o u n t o n a ll im p lem e n ta tio n s o f th e s ta n d a rd to fo llo w th es e r u les :

1. W h a te v e r m em o r y va lu e s a th r e a d c a n s ee w h e n it ca lls pthread_create c a n a ls o b e s ee n b y th e n e w th r ea d w h e n it s ta rts . A n y d a ta w r itte n to m em o r y a fte r th e ca ll to pthread_create m a y n o t n e c e s s a r ily b e s een b y th e n e w th r ea d , e ve n i f th e w r ite oc c u r s b e fo re th e th r ea d s ta rts . 2. W h a te v e r m e m or y va lu e s a th r e a d c a n s ee w h e n it u n loc k s a m u tex , e ith e r d ir e c tly o r b y w a itin g on a c o n d itio n va r ia b le , c a n a ls o b e s e en b y a n y th re a d th a t la te r loc k s th e s a m e m u tex . A g a in , d a ta w r itte n a fte r th e m u te x is u n lo c k e d m a y n o t n ec e s s a r ily b e s e en b y th e th r ea d th a t loc k s th e m u tex , e ven if th e w r ite oc c u r s b efo r e th e lock . 3. W h a te ve r m e m or y va lu e s a th r e a d c a n s ee w h e n it ter m in a tes , e ith er b y ca n c ella tio n , r e tu r n in g fro m its s ta r t fu n c tion , or b y c a llin g p th r e a d _ e x it, c a n a ls o b e s ee n b y th e th r e a d th a t jo in s w ith th e ter m in a te d th r e a d b y c a llin g p th r e a d _ jo in . A n d , o f cou r s e, d a ta w r itte n a fte r th e th r e a d ter m in a te s m a y n o t n e c e s s a r ily b e s een b y th e th r e a d th a t jo in s , e ven if th e w r ite oc c u r s b e fo re th e jo in . 4. W h a te ve r m em o r y va lu e s a th r e a d c a n s ee w h e n it s ig n a ls o r b r o a d c a s ts a c on d itio n va r ia b le c a n a ls o b e s een b y a n y th r ea d th a t is a w a k e n ed b y th a t s ig n a l o r b ro a d ca s t. A n d , on e m o r e tim e, d a ta w r itte n a fte r th e s ig n a l or b ro a d c a s t m a y n o t n e c e s s a r ily b e s een b y th e th r e a d th a t w a k e s u p , e ve n if th e w r ite oc cu r s b e fo r e it a w a k en s . F ig u r e s 3 .5 a n d 3 .6 d e m o n s tr a te s om e o f th e c on s e q u en c e s . S o w h a t s h o u ld you , a s a p r o g r a m m er , d o? F irs t, w h er e p o s s ib le m a k e s u r e th a t o n ly on e th r ea d w ill e ve r a cc es s a p iece o f d a ta . A th r e a d ’s r eg is ter s c a n ’t b e m o d ified b y a n o th er th r ea d . A th r e a d ’s s ta c k a n d h e a p m em o r y a th r ea d a llo ca tes is p r iva te u n les s th e th r ea d c o m m u n ica te s p o in te r s to th a t m em o r y to o th er th r ea d s . A n y d a ta yo u p u t in r e g i s t e r o r a u to va r ia b les c a n th er e fo r e b e r ea d a t a la te r tim e w ith n o m o r e c o m p lica tio n th a n in a c o m p lete ly s yn c h r o n o u s p r o g r a m . E a c h th r ea d is s yn c h r o n o u s w ith its elf. T h e les s d a ta yo u s h a r e b e tw e en th r ea d s , th e le s s w o r k yo u h a ve to do. S econ d , a n y tim e tw o th r e a d s n eed to a c c e s s th e s a m e d a ta , yo u h a ve to a p p ly on e o f th e P th r e a d s m e m o r y vis ib ility r u les , w h ich , in m o s t ca s es , m e a n s u s in g a m u tex . T h is is n o t o n ly to p ro te ct a g a in s t m u ltip le w r ite s — e ven w h e n a th r ea d o n ly r ea d s d a ta it m u s t u s e a m u te x to e n s u r e th a t it s e es th e m o s t r e c e n t va lu e o f th e d a ta w r itte n w h ile th e m u tex w a s lock ed .

90

CHA P T E R 3

S yn c h r o n i z a t i o n

T h is ex a m p le d oes e ver yth in g correctly. T h e left- h a n d c od e (r u n n in g in th r e a d A ) s ets th e va lu e o f s e ve ra l va r ia b le s w h ile it h a s a m u te x lock ed . T h e r ig h t- h a n d cod e (ru n n in g in th r ea d B ) r ea d s th os e va lu es , a ls o w h ile h o ld in g th e m u tex . Th rea d A

Th rea d B

pthread_mutex_lock (& mutexl); variableA = 1; variableB = 2; pthread__mutex_unlock (&m u t e x l ) ;

pthread_mutex__lock (S mutexl);

localA = variableA; localB = variableB; pthread_mutex_unlock (& m u texl); R u le 2: v is ib ility fr o m pthread_mutex_unlock to pthread_mutex_lock. W h e n th r e a d B r e tu r n s fr o m pthread_mutex_lock, it w ill s ee th e s a m e va lu e s fo r variableA a n d variableB th a t th r e a d A h a d s e en a t th e tim e it ca lled pthread mutex_unlock. T h a t is , 1 a n d 2, r es p e ctively. FIG U RE 3.5

C orre ct m e m ory v is ib ility

T h is e x a m p le s h o w s a n error. T h e left- h a n d c od e (r u n n in g in th r ea d A ) s ets th e va lu e o f va r ia b le s a fte r u n lo c k in g th e m u tex . T h e r ig h t- h a n d c od e (r u n n in g in th re a d B ) r ea d s th o s e va lu e s w h ile h o ld in g th e m u tex . Th rea d A

Th rea d B

pthread mutex lock (&mutexl); variableA = 1; pthread mutex unlock (&mutexl); variableB = 2;

pthread mutex lock (&mutexl);

localA = variableA; localB = variableB; pthread mutex unlock (fcmutexl); R u le 2: vis ib ility fr o m pthread_mutex_unlock to pthread_mutex_lock. W h e n th r ea d B r e tu r n s fr o m pthread_mutex_lock, it w ill s ee th e s a m e va lu e s for variableA a n d variableB th a t th r ea d A h a d s e en a t th e tim e it c a lle d pthread_ mutex_unlock. T h a t is , it w ill s ee th e va lu e 1 fo r variableA, b u t m a y n o t s ee th e va lu e 2 fo r variableB s in c e th a t w a s w r itte n a fte r th e m u te x w a s u n lock ed . FIG U RE 3.6

Incorre ct m e m ory v is ib ility

A s th e r u le s s ta te, th er e a r e s p ec ific ca s es w h er e yo u d o n o t n e e d to u s e a m u te x to e n s u r e vis ib ility. I f on e th re a d s ets a g lo b a l va r ia b le , a n d th en cr e a tes a n e w th r ea d th a t r ea d s th e s a m e va r ia b le , yo u k n o w th a t th e n e w th re a d w ill n o t s ee a n old va lu e . B u t if yo u c re a te a th r ea d a n d the n s et s om e va r ia b le th a t th e n e w th r ea d r ea d s , th e th r e a d m a y n o t s ee th e n e w va lu e , e ve n if th e c re a tin g th re a d s u cc ee d s in w r itin g th e n ew va lu e b efo r e th e n e w th r ea d r ea d s it.

91

M e m o r y vi s i bi l i t y b e t w e e n t h r e a d s

W a rn in g !

W e a r e n o w d e s c e n d in g b e lo w t h e P th re a d s API in to d e ta ils

o f h a r d w a r e m e m o r y a r c h it e c t u r e t h a t y o u m a y p r e fe r n o t t o k n o w . Y ou m a y w a n t t o skip this e x p la n a t io n fo r n o w a n d c o m e b a c k la te r. I f yo u a r e w illin g to ju s t tr u s t m e on a ll th a t (or if y o u ’ve h a d e n o u g h fo r n ow ), y o u m a y n o w s k ip p a s t th e e n d o f th is s ection . T h is b o o k is n o t a b o u t m u ltip r o c e s s o r m e m o r y a r ch ite ctu r e, s o I w ill ju s t s k im th e s u r fa c e— b u t e ven s o, th e d e ta ils a r e a little d eep , a n d if yo u d o n ’t c a r e r ig h t n ow , yo u d o n o t n e ed to w o r r y a b o u t th em yet. Y ou w ill p r o b a b ly w a n t to c o m e b a c k la te r a n d r ea d th e res t, th ou g h , w h e n yo u h a ve s om e tim e. In a s in g le - th r ea d ed , fu lly s yn ch r o n o u s p r o g r a m , it is “s a fe ” to r ea d or w r ite a n y m e m o r y a t a n y tim e. T h a t is , if th e p r o g r a m w r ite s a va lu e to s o m e m e m or y a d d r e s s , a n d la te r r ea d s fr o m th a t m e m o r y a d d res s , it w ill a lw a ys r e c e ive th e la s t va lu e th a t it w r o te to th a t a d d res s . W h e n yo u a d d a s yn ch r on o u s b e h a vio r (w h ich in clu d e s m u ltip r o c es s o r s ) to th e p ro g r a m , th e a s s u m p tio n s a b o u t m e m o r y vis ib ility b e co m e m or e co m p lica te d . F o r ex a m p le, a n a s yn c h r o n o u s s ig n a l c ou ld o c c u r a t a n y p o in t in th e p r o g r a m ’s e x ecu tion . If th e p r o g r a m w r ite s a va lu e to m em or y, a s ig n a l h a n d le r r u n s a n d w r ite s a d iffe r en t va lu e to th e s a m e m em o r y a d d r es s , w h e n th e m a in p ro g r a m r e s u m e s a n d r ea d s th e va lu e , it m a y n o t r ec e ive th e va lu e it w r ote. T h a t’s n o t u s u a lly a m a jo r p ro b lem , b e ca u s e yo u g o to a lot o f tr ou b le to d e cla r e a n d u s e s ig n a l h a n d ler s . T h e y r u n “s p e c ia lize d ” c od e in a d is tin c tly d iffe r e n t e n vir o n m en t fr o m th e m a in p r o g r a m . E x p er ien ce d p r o g r a m m er s k n o w th a t th e y s h o u ld w r ite g lo b a l d a ta o n ly w ith e x tr em e ca re, a n d it is p o s s ib le to k eep tr a c k o f w h a t th e y d o. I f th a t b e co m e s a w k w a r d , yo u b lo c k th e s ig n a l a r ou n d a r ea s o f c od e th a t u s e th e g lo b a l d a ta . W h e n yo u a d d m u ltip le th re a d s to th e p r o g r a m th e a s yn c h r o n o u s cod e is n o lo n g er s p ecia l. E a ch th r e a d r u n s n o r m a l p r o g r a m cod e, a n d a ll in th e s a m e u n res tr icted en vir on m e n t. Y ou c a n h a r d ly e ve r b e s u r e yo u a lw a ys k n o w w h a t e a c h th r ea d m a y b e d oin g . It is lik e ly th a t th e y w ill a ll r ea d a n d w r ite s om e o f th e s a m e d a ta . Y o u r th r e a d s m a y r u n a t u n p r e d icta b le tim e s o r e ve n s im u lta n eo u s ly on d iffe r e n t p r o c es s o r s . A n d th a t’s w h e n th in g s g e t in ter es tin g . B y th e w a y,

a lth o u g h

we

a re

ta lk in g

a b o u t p r o g r a m m in g w ith

m u ltip le

th r ea d s , n o n e o f th e p r o b lem s o u tlin ed in th is s e ctio n is s p ec ific to th rea d s . R a th er, th ey a r e a r tifa c ts o f m e m o r y a r c h ite c tu r e d es ig n , a n d th e y a p p ly to a n y s itu a tio n w h er e tw o “th in g s ” in d e p e n d e n tly a cc es s th e s a m e m em or y. T h e tw o th in g s m a y b e th r ea d s r u n n in g on s e p a r a te p r o c es s o r s , b u t th e y co u ld in s te a d b e p ro c es s es r u n n in g on s e p a r a te p r o c es s o r s a n d u s in g s h a r ed m em or y. O r on e “th in g ” m ig h t b e cod e r u n n in g o n a u n ip r oces s or , w h ile a n in d e p e n d e n t I/ O con tr o lle r r ea d s o r w r ites th e s a m e m em or y.

I

A m e m o r y a d d re s s c a n h o ld o n ly o n e v a lu e a t a tim e ; d o n 't le t th r e a d s " r a c e " t o g e t th e r e first.

W h e n tw o th r e a d s w r ite d iffe r e n t va lu e s to th e s a m e m em o r y a d d res s , on e a fte r th e oth er, th e fin a l s ta te o f m e m or y is th e s a m e a s if a s in g le th r e a d h a d

92

CHA P T E R 3

w r itte n

th o s e tw o va lu e s

in

th e s a m e

s eq u en ce.

S yn c h r o n i z a t i o n

E ith e r w a y o n ly o n e va lu e

r em a in s in m em or y. T h e p ro b le m is th a t it b e co m e s d iffic u lt to k n o w w h ic h w r ite o cc u r r e d la s t. M e a s u r in g s om e a b s o lu te e x ter n a l tim e b a s e, it m a y b e o b viou s th a t “p ro c e s s o r B ” w r o te th e va lu e “2 ” s e ve r a l m icr o s e c o n d s a fte r “p ro c e s s o r A “ w r o te th e va lu e “ 1.” T h a t d o e s n ’t m ea n th e fin a l s ta te o f m em o r y w ill h a ve a “2 .” W h y? B e ca u s e w e h a ve n ’t s a id a n yth in g a b o u t h o w th e m a c h in e ’s ca c h e a n d m em o r y b u s w ork . T h e p r o c es s o r s p r o b a b ly h a ve c a c h e m em or y, w h ic h is ju s t fa s t, loc a l m e m o r y u s ed to k eep q u ic k ly a c c es s ib le c o p ie s o f d a ta th a t w er e r e c e n tly r ea d fr o m m a in m em or y. In a w r ite - b a c k c a c h e s ys tem , d a ta is in itia lly w r itte n o n ly to ca ch e, a n d co p ied (“flu s h e d ”) to m a in m em o r y a t s om e la te r tim e. In a m a ch in e th a t d o e s n ’t g u a r a n te e r ea d / w r ite or d er in g , e a c h c a c h e b lo c k m a y b e w r itte n w h e n e ve r th e p r o ce s s o r fin d s it co n ve n ien t. I f tw o p r o c es s o r s w r ite d iffe r e n t va lu e s to th e s a m e m em o r y a d d res s , e a ch p r o c e s s o r ’s va lu e w ill g o in to its o w n ca ch e. E ven tu a lly b o th va lu e s w ill b e w r itte n to m a in m em or y, b u t a t es s en tia lly r a n d o m tim es , n o t d ir e c tly r ela ted to th e o r d er in w h ic h th e va lu e s w e re w r itte n to th e r e s p e c tive p r o c e s s o r ca ch es . E ven tw o w r ite s fr o m w ith in a s in g le th r ea d (p r o c es s or ) n e ed n o t a p p e a r in m e m o r y in th e s a m e ord er. T h e m em o r y c on tr o lle r m a y fin d it fa s ter, o r ju s t m or e co n ve n ien t, to w r ite th e va lu e s in “r e ve r s e ” ord er, a s s h o w n in F ig u r e 3 .7. T h e y m a y h a ve b e e n c a c h e d in d iffer e n t c a c h e b lock s , for ex a m p le, o r in ter lea ved to d iffe r e n t m em o r y b a n k s . In g en e ra l, th e r e ’s n o w a y to m a k e a p r o g r a m a w a r e o f th es e e ffects . If th er e w a s , a p r o g r a m th a t r elied on th em m ig h t n o t r u n c or r e ctly on a d iffe r e n t m o d e l o f th e s a m e p r o c es s o r fa m ily, m u c h les s on a d iffe r e n t typ e o f com p u ter. T h e p r o b lem s a r e n ’t r es tr ic te d to tw o th r e a d s w r i t i n g m em or y. Im a g in e th a t o n e th rea d w r ite s a va lu e to a m em o r y a d d r e s s on o n e p roces s or, a n d th en a n o th er th r ea d r ea d s fro m th a t m em o r y a d d r es s on a n o th e r p roces s or. It m a y s eem ob vio u s th a t th e th r ea d w ill s ee th e la s t va lu e w r itte n to th a t a d d res s , a n d on s om e h a r d w a r e th a t w ill b e tru e. T h is is s om e tim e s ca lled “m e m o r y c oh er e n c e ” or “r ea d / w r ite o r d er in g .” B u t it is co m p lica te d to e n s u r e th a t s or t o f s yn ch r on iza tio n b e tw e e n p ro ces s or s . It s low s th e m em o r y s ys te m a n d th e over h ea d p ro vid e s n o b en efit to m o s t cod e. M a n y m o d e r n c om p u ter s (u s u a lly a m o n g th e fa s tes t) d on ’t g u a r a n tee a n y o r d er in g o f m em o r y a c ce s s es b e tw e e n d iffer en t p ro ces s or s , u n les s th e p r o g r a m u s es s p ecia l in s tr u c tio n s c o m m o n ly k n o w n a s m e m o r y b a r r i e r s .

T im e

T hre ad 1

t

w r ite “ 1” to a d d r e s s 1 (ca ch e)

t+ I

w r ite “2 ” to a d d r es s 2 (ca ch e)

t+ 2

ca c h e s ys te m flu s h e s a d d r e s s 2

r ea d “0 ” fro m a d d r es s 1

r ea d “2 ” fr o m a d d r e s s 2

t+ 3 t+ 4

T hre ad 2

c a c h e s ys te m flu s h e s a d d r e s s 1

F I G U R E 3.7

M e m o r y o r d er i n g wi t h o u t syn c h r o n i z a t i o n

M e m o r y vi si bi l i t y b e t w e e n t h r e a d s

93

M em o ry a c ce s s e s in th e s e c o m p u te r s a re, a t le a s t in p rin c ip le, q u e u e d to th e m e m o r y con troller, a n d m a y b e p r o ce s s e d in w h a te ve r o r d e r b e co m e s m o s t efficien t. A r ea d fro m a n a d d r e s s th a t is n o t in th e p r o c e s s o r ’s c a c h e m a y b e h eld w a itin g fo r th e c a c h e fill, w h ile la te r r ea d s com p lete. A w r ite to a “d ir ty” c a ch e lin e, w h ic h r eq u ir e s th a t old d a ta b e flu s h ed , m a y b e h eld w h ile la te r w r ite s com p lete. A m em o r y b a r r ie r e n s u r e s th a t a ll m em o r y a c ce s s e s th a t w e r e in itia ted b y th e p r o c e s s o r p r io r to th e m e m or y b a r r ie r h a ve c o m p leted b efor e a n y m em o r y a c ce s s e s in itia te d a fte r th e m em o r y b a r r ie r ca n c om p lete.

I A " m e m o r y b a r r ie r ‫ ״‬is a m o v in g w a ll, n o t a " c a c h e flu s h ‫ ״‬c o m m a n d . A c om m o n m is co n ce p tio n a b ou t m em o r y b a r r ie r s is th a t th e y “flu s h ” va lu e s to m a in m em or y, th u s e n s u r in g th a t th e va lu e s a r e vis ib le to o th e r p r o ces s or s . T h a t is n o t th e ca s e, h ow ever. W h a t m em o r y b a r r ie r s d o is e n s u r e a n o r d er b e tw e e n s ets o f op e ra tion s . If e a c h m em o r y a cc es s is a n ite m in a q u eu e, yo u c a n th in k o f a m em o r y b a r r ie r a s a s p ec ia l q u e u e tok en . U n lik e o th e r m e m o r y a cce s s es , h ow ever, th e m e m o r y c o n tr o lle r c a n n ot r em o ve th e b a r rier , o r lo o k p a s t it, u n til it h a s c om p leted a ll p re viou s a cces s es . A m u tex lock , fo r ex a m p le, b eg in s b y lo c k in g th e m u tex , a n d c o m p lete s b y is s u in g a m em o r y b a r rier . T h e r e s u lt is th a t a n y m e m o r y a c ce s s e s is s u ed w h ile th e m u tex is loc k e d c a n n o t co m p lete b efo r e o th e r th r ea d s c a n s ee th a t th e m u te x w a s lock ed . S im ila r ly, a m u te x u n lo ck b e g in s b y is s u in g a m em o r y b a r r ie r a n d c o m p le te s b y u n lo c k in g th e m u tex , e n s u r in g th a t m em o r y a c ce s s e s is s u e d w h ile th e m u tex is lo c k e d c a n n o t c om p lete a fte r o th e r th re a d s ca n s ee th a t th e m u te x is u n lock ed . T h is m e m o r y b a r r ie r m o d e l is th e log ic b e h in d m y d e s c r ip tio n o f th e P th r ea d s m em o r y r u les . F o r e a c h o f th e r u les , w e h a ve a “s o u r ce ” even t, s u c h a s a th rea d c a llin g pthread_mutex_unlock, a n d a “d e s tin a tio n ” even t, s u c h a s a n o th er th r ea d r e tu r n in g fr o m pthread_mutex_lock. T h e p a s s a g e o f “m e m o r y vie w ” fro m th e fir s t to th e s eco n d o c cu r s b e ca u s e o f th e m em o r y b a r r ie r s c a r efu lly p la c ed in ea ch . E ven w ith o u t r e a d / w r ite o r d er in g a n d m em o r y b a r rier s , it m a y s e em th a t w r ite s to a s in g le m e m o r y a d d r es s m u s t b e a tom ic, m e a n in g th a t a n o th e r th r ea d w ill a lw a ys s ee e ith er th e in ta c t o r ig in a l va lu e or th e in ta ct n e w va lu e . B u t th a t’s n o t a lw a ys tru e, eith er. M o s t c o m p u te r s h a ve a n a tu r a l m e m o r y g r a n u la r ity, w h ic h d ep en d s on th e o r g a n iza tio n o f m e m o r y a n d th e b u s a r ch ite ctu r e. E ven if th e p r o c e s s o r n a tu r a lly r ea d s a n d w r ite s 8 - b it u n its , m e m o r y tr a n s fer s m a y o cc u r in 3 2 - o r 6 4 - b it “m em o r y u n its .” T h a t m a y m e a n th a t 8 ‫ ־‬b it w r ite s a r e n ’t a to m ic w ith r e s p e c t to o th e r m e m or y o p e r a tio n s th a t o ve rla p th e s a m e 3 2 - o r 6 4 - b it u n it. M o s t c o m p u ter s w r ite th e fu ll m em o r y u n it (s a y, 32 b its ) th a t c on ta in s th e d a ta y o u ’re m od ifyin g . I f tw o th re a d s w r ite d iffe r e n t 8 - b it va lu e s w ith in th e s a m e 3 2 - b it m em o r y u n it, th e r es u lt m a y b e th a t th e la s t th r ea d to w r ite th e m em o r y u n it s p ec ifies th e va lu e o f b oth b ytes , o ver w r itin g th e va lu e s u p p lied b y th e firs t w riter. F ig u r e 3 .8 s h o w s th is effect.

94

CH A P T E R 3

S yn c h r o n i z a t i o n

I f a va r ia b le c r o s s e s th e b o u n d a r y b e tw e e n m e m o r y u n its , w h ic h c a n h a p p en if th e m a ch in e s u p p o r ts u n a lig n e d m e m o r y a cces s , th e c o m p u te r m a y h a ve to s en d th e d a ta in tw o b u s tr a n s a c tio n s . A n u n a lig n e d 3 2 - b it va lu e , fo r ex a m p le, m a y b e s en t b y w r itin g th e tw o a d ja c e n t 3 2 - b it m e m o r y u n its . If e ith e r m em o r y u n it in vo lved in th e tr a n s a c tio n is s im u lta n e o u s ly w r itte n fro m a n o th er p r o ces sor, h a lf o f th e va lu e m a y b e los t. T h is is c a lled “w o rd te a r in g ,” a n d is s h o w n in F ig u r e 3.9. W e h a ve fin a lly r e tu rn e d to th e a d vic e a t th e b e g in n in g o f th is s ection : I f yo u w a n t to w r ite p o r ta b le P th r e a d s cod e, yo u w ill a lw a ys g u a r a n te e c or r e c t m e m or y v is ib ility b y u s in g th e P th r e a d s m em o r y vis ib ility r u le s in s te a d o f r elyin g o n a n y a s s u m p tio n s r eg a r d in g th e h a r d w a r e o r c o m p iler b eh a vior . B u t n ow , a t th e b otto m o f th e s ection , yo u h a ve s om e u n d e r s ta n d in g o f w h y th is is tru e. F o r a s u b s ta n tia lly m or e in - d e p th tr e a tm e n t o f m u ltip r o c e s s o r m e m o r y a r ch ite ctu r e, r e fe r to U N IX S y s te m s f o r M o d e rn A rch ite ctu re s [S ch im m el, 1994]. F ig u r e 3 .1 0 s h o w s th e s a m e s eq u e n c e a s F ig u r e 3 .7 , b u t it u s es a m u te x to e n s u r e th e d es ir e d r ea d / w r ite or d erin g . F ig u r e 3 .1 0 d oes n o t s h o w th e c a ch e flu s h s tep s th a t a r e s h o w n in F ig u r e 3 .7, b e c a u s e th o s e s tep s a r e n o lo n g e r r eleva n t. M e m o r y v is ib ility is g u a r a n te e d b y p a s s in g m u te x o w n e r s h ip in s tep s t+ 3 a n d t+ 4 , th ro u g h th e a s s o c ia ted m e m o ry b a r rier s . T h a t is, w h e n th rea d 2 h a s

95

M e m o r y vi s i bi l i t y b e t w e e n t h r e a d s

memory (unaligned value) thread 1

thread 2

XX

XX

00

01

02

xx

03

each reads the value 00

01

02

03 each modifies a byte

14 00 1 14 I 02 [ 03

each writes a new value

XX

XX

00

14

25

os

XX

XX

Each thread has written 16 b its of the 32 bit valu e FIG U RE 3.9

W ord te aring

s u c c es s fu lly loc k e d th e m u te x p r evio u s ly u n lo c k e d b y th r ea d 1, th r e a d 2 is g u a r a n te ed to s ee m e m o r y va lu e s “a t le a s t a s r e c e n t” a s th e va lu e s vis ib le to th r ea d 1 a t th e tim e it u n lo c k ed th e m u tex . T im e

Th rea d 1

t

lo c k m u te x

Th rea d 2

(m e m o r y b a r rier ) t+ 1

w r ite “ 1” to a d d r es s 1 (ca ch e)

t+ 2

w r ite “2 ” to a d d r es s 2 (ca ch e)

t+ 3

(m e m o r y b a r rier ) u n lo ck m u te x

t+ 4

lo c k m u te x (m em o r y b a r r ier )

t+ 5

r ea d “ 1” fr o m a d d r e s s 1

t+ 6

r ea d “2 ” fr o m a d d r e s s 2

t+ 7

(m e m o r y b a r rier ) u n lo c k m u te x

FIG U RE 3 .1 0

M e m ory ord e ring w ith s y nchronization

4 A fe w w a y s to use th re a d s

,,They w e re o b lig e d to h a v e h im with th e m ," th e M o c k Turtle said. ,,N o wise fish w o u ld g o a n y w h e r e w ith o u t a p o rp o is e .”

‫ ״‬W o u ld n ’t it, r e a lly ? ” s a id A lic e , in a to n e o f g r e a t surprise. “O f c o u rs e n o t,” s a id th e M o c k Turtle. ,,Why, if a fish c a m e to m e , a n d to ld m e h e w as g o in g on a Journey, I should s a y ,With w h a t p o rp o is e ? '” — L e w is C a r r o ll, A l i c e 's A d v e n t u r e s in W o n d e r l a n d

D u r in g th e in tr o d u c tio n to th is b ook , I m en tio n ed s om e o f th e w a ys yo u ca n s tr u ctu r e a th r e a d e d s o lu tio n to a p r o b lem . T h e r e a r e in fin ite va r ia tio n s , b u t th e p r im a r y m o d els o f th r ea d e d p r o g r a m m in g a r e s h o w n in T a b le 4.1.

P ip elin e

E a c h th r ea d r e p e a te d ly p e r fo r m s th e s a m e o p e r a tio n o n a s eq u e n c e o f d a ta s ets , p a s s in g e a c h r es u lt to a n o th e r th r ea d fo r th e n e x t s tep . T h is is a ls o k n o w n a s a n “a s s e m b ly lin e . ”

W o rk c r ew

E a c h th r e a d p e r fo r m s a n o p e r a tio n o n its o w n d a ta . T h r e a d s in a w o r k c r e w m a y a ll p e r fo r m th e s a m e o p e ra tion , o r e a c h a s ep a r a te op e ra tion , b u t th ey a lw a ys p ro cee d in d e p e n d en tly.

C lien t/ s e r ve r

A c lien t “c o n tr a c ts ” w ith a n in d e p e n d e n t s e r ver fo r e a c h jo b . O ften th e “c o n tr a c t” is a n o n ym o u s — a r e q u e s t is m a d e th r o u g h s om e in te r fa c e th a t q u e u e s th e w o r k item .

TA B LE 4.1

Thre ad progra m m in g m od e ls

A ll o f th es e m o d els c a n b e c o m b in e d in a r b itr a r y w a ys a n d m o d ified b e yo n d a ll r ec o g n itio n to fit in d ivid u a l s itu a tion s . A s tep in a p ip elin e co u ld in vo lve r eq u es tin g a s er vice fr o m a s e r ve r th rea d , a n d th e s er ve r m ig h t u s e a w o r k crew , a n d on e or m o r e w o r k e r s in th e c r e w m ig h t u s e a p ip elin e. O r a p a r a lle l s ea r c h “e n g in e ” m ig h t in itia te s ever a l th r ea d s , e a c h tr yin g a d iffe r e n t s e a r ch a lg or ith m .

97

98

CH A P T E R 4

A f e w w a y s t o u se t h r ea d s

4.1 P ipeline '7 w a n t a c le a n c u p ,1* in te rru p te d th e H atter: ,,le t’s a ll m o v e o n e p la c e o n ” H e m o v e d o n a s h e s p o k e , a n d th e D o rm o u s e fo llo w e d h im : th e M a r c h H a re m o v e d in to th e D o rm o u s e ’s p la c e , a n d A lic e ra th e r u n w illin g ly to o k th e p la c e o f th e M a r c h H a re . The H a tte r w as th e o n ly o n e w h o g o t a n y a d v a n ta g e fro m th e c h a n g e ; a n d A lic e w as a g o o d d e a l w orse o ff th a n b e fo re , as th e M a r c h H a re h a d ju s t u p s e t th e m ilk -ju g in to his p la te . — L e w is C a r r o ll, A l i c e 's A d v e n t u r e s in W o n d e r l a n d

In p ip e lin in g , a s tr e a m o f “d a ta ite m s ” is p ro c e s s e d s e ria lly b y a n o rd e re d s e t o f th r e a d s (F ig ure 4.1). E a c h th r e a d p e rfo rm s a specific o p e ra tio n o n e a c h ite m in se q u e n c e , p a s s in g th e d a ta o n to th e n e x t th r e a d in th e p ip e lin e. F o r ex am p le, th e d a ta m ig h t b e a s c a n n e d im ag e, a n d th r e a d A m ig h t p ro c e s s a n im ag e a rra y , th r e a d B m ig h t s e a r c h th e p ro c e s s e d d a t a fo r a sp ecific s e t o f featu r e s , a n d th r e a d C m ig h t co lle ct th e se ria l s tre a m of s e a r c h r e s u lts fro m th r e a d B in to a re p o rt. O r e a c h th r e a d m ig h t p e rfo rm a sin g le s te p in so m e s e q u e n c e of m o d ific a tio n s o n th e d a ta . T h e follow ing p ro g ra m , c a lled p i p e . c , s h o w s th e p ie c e s o f a sim p le p ip e lin e p ro g ra m . E a c h th r e a d in th e p ip e lin e in c re m e n ts its in p u t v a lu e b y 1 a n d p a s s e s it to th e n e x t th re a d . T h e m a in p ro g ra m r e a d s a s e rie s o f “c o m m a n d lin e s ” fro m s t d i n . A c o m m a n d lin e is e ith e r a n u m b e r, w h ic h is fed in to th e b e g in n in g o f th e p ip e lin e, o r th e c h a r a c te r w h ic h c a u s e s th e p ro g ra m to re a d th e n e x t r e s u lt fro m th e e n d o f th e p ip e lin e a n d p r in t it to s t d o u t .

F IG U R E 4 . 1

P ipe lin in g

99

Pip eli n e

E a c h s ta g e o f a p ip e lin e is r e p r e s e n te d b y a v a ria b le o f ty p e stage_t. stage_t c o n ta in s a mutex to s y n c h ro n iz e a c c e s s to th e sta g e . T h e a v a i l c o n d itio n v a ria b le is u s e d to s ig n a l a s ta g e t h a t d a ta is re a d y for it to p ro c e s s , a n d e a c h s ta g e s ig n a ls its o w n ready c o n d itio n v a ria b le w h e n it is re a d y fo r n e w d a ta . T h e data m e m b e r is th e d a t a p a s s e d fro m th e p re v io u s s ta g e , thread is th e th r e a d o p e ra tin g th is s ta g e , a n d next is a p o in te r to th e follow ing s ta g e . T h e pipe_t s tr u c t u r e d e s c rib e s a p ip e lin e . It p ro v id e s p o in te rs to th e firs t a n d la s t s ta g e o f a p ip e lin e. T h e firs t s ta g e , head, r e p r e s e n ts th e firs t th r e a d in th e p ip e lin e. T h e la s t sta g e , tail, is a sp e c ia l stage_t th a t h a s n o th r e a d —it is a p la c e to s to re th e fin al r e s u lt o f th e p ip e lin e.

9-17

23-29



pipe.c

part 1

definitions

1 #include 2 #include ”errors.h" o J 4 /* 5 * Internal structure describing a "stage" in the 6 * pipeline. One for each thread, plus a result 7 * stage" where the final thread can stash the value. 8 */ 9 typedef struct stage_ tag { 10 pthread_mutex_t mutex; /* Protect data */ 11 pthread_cond_t avail; /* Data available */ 12 pthread_cond_t re a d y ; /* Ready for data */ 13 int data_ready; /* Data present */ 14 long data; /* Data to process */ 15 pthread t thread; /* Thread for stage */ 16 struct stage_tag *next; /* Next stage */ 17 } stage__t; 18 19 /* 20 * External structure representing the entire 21 * pipeline. 22 */ 23 typedef struct pipe_tag { 24 pthread mutex_t mutex; /* Mutex to protect pipe */ 25 stage_t *head; /* First stage */ 26 stage_t *tail; /* Final stage */ 27 int stages; /* Number of stages */ 28 int active; /* Active data elements */ 29 } pipe_t;



pipe.c

part 1

definitions

P a r t 2 s h o w s p ip e se n d , a u tility fu n c tio n u s e d to s t a r t d a t a a lo n g a p ip e lin e, a n d a lso c a lled b y e a c h s ta g e to p a s s d a t a to th e n e x t s ta g e .

100

CH A P T E R 4

A f e w w a y s to u se t h r ea d s

It b e g in s b y w a itin g o n th e sp ecified p ip e lin e s ta g e ’s re a d y c o n d itio n v a ria b le u n til it c a n a c c e p t n e w d a ta . *30 S to re th e n e w d a ta v a lu e , a n d th e n te ll th e s ta g e t h a t d a ta is av ailab le. ■ 23



1 2

pipe.c

part 2

pipe_senc

/* * Internal function to send a "message" to the * specified pipe stage. Threads use this to pass * along the modified data item.

3 4 5

*/

6

int pipe_send (stage_t *stage,

7

{

8

long data)

int s tatus;

9 status = pthread__mutex__lock (&stage->mutex); if (status != 0) return status;

10 11 12

/*

13 14 15 16 17 18 19

* If there's data in the pipe stage, wait for it * to be consumed.

*/ while (stage->data_ready) { status = pthread_cond_wait (&stage->ready, &stage‫> ־ ־‬mu t e x ) ; if (status 1= 0) { pthread_mutex_unlock (&stage->mutex); return status;

20 21

>

22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

} /* * Send the new data

*/ stage->data = data; stage->datalready = 1;

status = pthread_cond_signal (&stage->avail); if (status !=0) { pthread_mutex_unlock (&stage->mutex); return status;

} status = pthread_mutex_unlock (fitstage->mutex); return status;



pipe.c

part 2

pipe_send

P a rt 3 sh o w s p ip e _ s t a g e , th e s t a r t fu n c tio n for e a c h th r e a d in th e p ip e lin e. ‫ ׳‬The th r e a d ’s a r g u m e n t is a p o in te r to its s t a g e _ t s tr u c tu r e . T h e th r e a d lo o p s forever, p ro c e s s in g d a ta . B e c a u s e th e m u te x is lo ck ed o u tsid e th e loop, th e th r e a d a p p e a r s to h a v e th e p ip e lin e s ta g e ’s mutex lo c k ed all th e

101

P i p el i n e

tim e. H ow ever, it s p e n d s m o s t o f its tim e w a itin g for n e w d a ta , o n th e a v a i l co n d itio n v a ria b le . R e m e m b e r t h a t a th r e a d a u to m a tic a lly u n lo c k s th e m u te x a s s o c ia te d w ith a c o n d itio n v a ria b le , w h ile w a itin g o n t h a t c o n d itio n v a ria b le . In re a lity , th e re fo re , th e th r e a d s p e n d s m o s t o f its tim e w ith m u tex u n lo c k e d . W h e n given d a ta , th e th r e a d in c re a s e s its ow n d a t a v a lu e b y o n e, a n d p a s s e s th e r e s u lt to th e n e x t s ta g e . T h e th r e a d th e n re c o rd s t h a t th e s ta g e n o lo n g e r h a s d a ta b y c le a rin g th e data_ready flag, a n d s ig n a ls th e ready c o n d itio n v a ria b le to w a k e a n y th r e a d th a t m ig h t b e w a itin g for th is p ip e lin e sta g e .

22-26



pipe.c

part 3

pipe_stage

1 /* * The thread start routine for pipe stage threads. 2 * Each will wait for a data item passed from the 3 * caller or the previous stage, modify the data 4 * and pass it along to the next (or final) stage. 5 */ 6 7 void *pipe_stage (void *arg) 8 s 9 stage_t *stage = (stage_t*)arg; 10 stage t *next_stage = stage->next; 11 int status; 12 13 status = pthread_mutex_lock (&stage->mutex); 14 if (status != 0) 15 err_abort (status, ,,Lock pipe stage"); 16 while (1) { 17 while (stage->data_ready ! = 1 ) { 18 status = pthread cond wait (&stage‫> ־‬avail, &stage->mutex); 19 if (status != 0) 20 err abort (status, "Wait for previous stage"); 21 > 22 pipe send (next stage, stage->data + 1); 23 stage->data ready = 0; 24 status = pthread_cond_signal (&stage->ready); 25 if (status != 0) 26 err abort (status, "Wake next stage"); 27 } 28 /* * Notice that the routine never unlocks the stage->mutex. 29 * The call to pthread_cond_wait implicitly unlocks the 30 31 * mutex while the thread is waiting, allowing other threads 32 * to make progress. Because the loop never terminates, this * function has no need to unlock the mutex explicitly. 33 34 */ 35 > ■

pipe.c

part 3

pipe_stage

102

CH A P T E R 4

A f e w w a y s to u se t h r ea d s

P a rt 4 sh o w s p i p e _ c r e a t e , th e fu n c tio n th a t c re a te s a p ip e lin e. It c a n c re a te a p ip e lin e o f a n y n u m b e r of s ta g e s , lin k in g th e m to g e th e r in a list. 18-34 F o r e a c h sta g e , it a llo c a te s a n e w stage_t s tr u c t u r e a n d in itia liz e s th e m e m b e rs . N otice t h a t o n e a d d itio n a l “s ta g e ” is a llo c a te d a n d in itia liz e d to h o ld th e fin al r e s u lt o f th e p ip e lin e. 36-37 T h e link m e m b e r o f th e fin al s ta g e is s e t to NULL to te rm in a te th e list, a n d th e p ip e lin e ’s tail is s e t to p o in t a t th e fin al s ta g e . T h e tail p o in te r allo w s pipe_ result to e a sily fin d th e fin a l p r o d u c t of th e p ip e lin e, w h ic h is s to re d in to th e fin a l sta g e . 52-59 A fter all th e s ta g e d a ta is in itia lize d , pipe_create c re a te s a th r e a d for e a c h s ta g e . T h e e x tra “fin al s ta g e ” d o e s n o t g e t a th r e a d —th e te rm in a tio n c o n d itio n of th e f o r loop is t h a t th e c u r r e n t s ta g e ’s next lin k is n o t n u l l ,w h ic h m e a n s t h a t it w ill n o t p ro c e s s th e fin a l sta g e . ■ 1 2 3 4 5 6 7 8 9 10

pipe.c

part 4

pipe_create

/* * External interface to create a pipeline. All the * data is initialized and the threads created. They'll * wait for data. */ int pipe_create (pipe_t *pipe, int stages) { int pipe__index; stage_t **link = &pipe->head, *new_stage, *stage; int status;

11

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

status = pthread_mutex_init (&pipe->mutex, NULL); if (status != 0) err__abort (status, "Init pipe mutex"); pipe->stages = stages; pipe->active = 0; for (pipe_index = 0; pipe_index mutex, NULL); if (status 1= 0) err_abort (status, "Init stage mutex"); status = pthread_cond_init (&new_stage->avail, NULL); if (status != 0) err_abort (status, "Init avail condition"); status = pthread_cond__init (&new_stage->ready, NULL); if (status I= 0) err_abort (status, "Init ready condition"); new_stage->data_ready = 0; *link = new stage;

Pip eli n e

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

link = &new_stage->next; > *link = (stage_t*)NULL; /* Terminate list */ pipe->tail = new_stage; /* Record the tail */ /* * Create the threads for the pipe stages only after all * the data is initialized (including all links). Note * that the last stage doesn't get a thread, it's just * a receptacle for the final pipeline value. * * At this point, proper cleanup on an error would take up * more space than worthwhile in a "simple example," so * instead of cancelling and detaching all the threads * already created, plus the synchronization object and * memory cleanup done for earlier errors, it will simply * abort. */ for ( stage = pipe->head; stage->next 1= NULL; stage = stage->next) { status = pthread_create ( &stage->thread, NULL, pipe__stage, (void*)s tage); if (status != 0) err_abort (status, "Create pipe stage"); } return 0;

}

61



22—‫ד‬

: 4 7 -‫־‬

55-?‫י‬

103

pipe.c

part 4

pipe_create

P a r t 5 sh o w s p i p e _ s t a r t a n d p i p e _ r e s u l t . T h e p i p e _ s t a r t fu n c tio n p u s h e s a n ite m of d a ta in to th e b e g in n in g o f th e p ip e lin e a n d th e n r e tu r n s im m e d ia te ly w ith o u t w a itin g fo r a re s u lt. T h e p i p e _ r e s u l t fu n c tio n allo w s th e c a lle r to w a it for th e fin al re s u lt, w h e n e v e r th e r e s u lt m ig h t b e n e e d e d . T h e p i p e _ s t a r t fu n c tio n s e n d s d a ta to th e firs t s ta g e of th e p ip e lin e. T h e fu n c tio n in c re m e n ts a c o u n t o f “a c tiv e ” ite m s in th e p ip e lin e, w h ic h allo w s p ip e _ r e s u l t to d e te c t th a t th e re a re n o m o re activ e ite m s to collect, a n d to r e tu r n im m e d ia te ly in s te a d of b lo c k in g . You w o u ld n o t a lw ay s w a n t a p ip e lin e to b e h a v e th is w ay —it m a k e s s e n s e for th is e x a m p le b e c a u s e a sin g le th r e a d a lte rn a te ly “fe e d s ” a n d “r e a d s ” th e p ip e lin e , a n d th e a p p lic a tio n w o u ld h a n g fo rever if th e u s e r in a d v e rte n tly r e a d s o n e m o re ite m t h a n h a d b e e n fed. T h e p i p e _ r e s u l t fu n c tio n firs t c h e c k s w h e th e r th e re is a n activ e ite m in th e p ip e lin e. If n o t, it r e t u r n s w ith a s t a t u s o f 0, a fte r u n lo c k in g th e p ip e lin e m u te x . If th e re is a n o th e r ite m in th e p ip e lin e, pipe_result lo c k s th e tail (final) sta g e , a n d w a its for it to receiv e d a ta . It co p ie s th e d a t a a n d th e n re s e ts th e s ta g e so it c a n receiv e th e n e x t ite m of d a ta . R e m e m b e r t h a t th e fin al s ta g e d o e s n o t h a v e a th re a d , a n d c a n n o t re s e t itself.

104



1 2

pipe.c

* * * * * *

4 5

6 7

8 10

A f e w w a y s t o u se t h r ea d s

part 5

External interface to start a pipeline by passing data to the first stage. The routine returns while the pipeline processes in parallel. Call the pipe_result return to collect the final stage values (note that the pipe will stall when each stage fills, until the result is collected).

*/ int pipe__start (pipe__t *pipe,

long value)

{ int status;

11 12

status = pthread_mutex_lock (&pipe‫> ־‬mutex); if (status 1= 0) err_abort (status, ‫ ״‬,Lock pipe m u t e x ” ); pipe->active++; status = pthread_mutex__unlock (&pipe->mutex); if (status != 0) err_abort (status, ,,Unlock pipe mutex"); pipe__send (pipe->head, value); return 0;

13 14 15 16 17 18 19 20

21 22

}

23 24

/* * Collect the result of the pipeline. Wait for a * result if the pipeline hasn't produced one.

25 26

*/

27 28

int pipe_result

29

{

30 31 32 33

(pipe_t *pipe,

long *result)

stage_t *tail = pipe->tail; long value; int empty = 0; int status;

34 35 36 37 38 39 40 41

status = pthread_mutex_lock (&pipe->mutex); if (status 1= 0) err_abort (status, "Lock pipe mutex"); if (pipe->active ־‬active— ;

42 43 44 45 46 47

status = pthread_mutex_unlock (&pipe->mutex); if (status != 0) err_abort (status, "Unlock pipe mutex"); if (empty) return 0;

48 49

pipe_start,pipe_result

/*

3

9

CH A P T E R 4

pthread__mutex__lock (&tail->mutex);

105

P i p el i n e

while (itail->data_ready) pthread_cond_wait (&tail->avail, &tail->mutex); *result = tail->data; tail->data_ready = 0; pthread_cond_signal (&tail->ready); pthread_mutex__unlock (&tail->mutex); return 1;

50 51 52 53 54 55 56

}

57 ■

pipe.c

part 5

pipe__start,pipe_result

P a rt 6 sh o w s th e m ain p ro g ra m t h a t d riv e s th e p ip e lin e. It c r e a te s a p ip e lin e, a n d th e n lo o p s re a d in g lin e s fro m s t d i n . If th e lin e is a sin g le “=” c h a ra c te r, it p u lls a r e s u lt fro m th e p ip e lin e a n d p r in ts it. O th e rw ise , it c o n v e rts th e lin e to a n in te g e r v a lu e , w h ic h it fe e d s in to th e p ip e lin e. ■

1 2

pipe.c

part 6

main

/* * The main program to "drive" the pipeline...

*/

3 4

int main (int argc,

5

{

6

char *argv[])

pipe_t my_pipe; long value, result; int status; char line[128];

7

8 9 10

pipe_create (&my__pipe, 10); printf ("Enter integer values, or \"=\" for next result\n");

11 12

13

while (1) { printf ("Data> "); if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (strlen (line) mutex); if (status 1= 0) err__abort (status, "Lock crew mutex");

/* * There won't be any work when the crew is created, * until something's put on the queue.

so wait

*/ while (crew->work_count = = 0 ) { status = pthread_cond_wait (&crew->go, if (status != 0) err_abort (status, "Wait for go");

&crew->mutex);

} status * pthread_mutex_unlock (Screw->mutex); if (status != 0) err_abort (status, "Unlock mutex"); DPRINTF

(("Crew %d starting\n", m i ne->index));

/* * Now, as long as there's work, keep doing it.

*/

111

Work c r e w

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

while (1) {

/* * * * *

Wait while there is nothing to do, and the hope of something coming along later. If crew->first is NULL, there's no work• But if crew->work__count goes to zero, we're done.

*/ status = pthread_mutex_lock (screw->mutex); if (status 1= 0) err_abort (status, "Lock crew mutex"); DPRINTF (("Crew %d top: first is %#lx, count is %d\n", mine->index, crew->first, crew->work_count)); while (crew->first == NULL) { status = pthread__cond_wait (&crew->go, &crew->mutex); if (status I - 0) err_abort (status, "Wait for work");

>

66 67

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

87

88 89 90 91 92 93 94 95 96

DPRINTF (("Crew %d woke: %#lx, %d\n", mine->index, crew->first, crew->work_count));

/* * Remove and process a work item.

*/ work = crew->first; crew->first = work->next; if (crew->first == NULL) crew->last = NULL; DPRINTF (("Crew %d took %#lx, leaves first %#lx, last %#lx\n", m i n e ‫> ־‬index, work, crew->first, c r e w ->last)); status = pthread_mutex_unlock (&crew->mutex); if (status != 0) err_abort (status, "Unlock mutex");

/* * We have a work item. Process it, which may involve * queuing new work i t e m s .

*/ status = lstat (work->path,

&filestat);

if (S_ISLNK (filestat.st_mode)) printf ( "Thread %d: %s is a link, skipping.\n", mine->index, w o r k - > p a t h ); else if (S_ISDIR (filestat.st_mode)) {

CH A P T E R 4

97 98 99 100

DIR *directory; struct dirent *result;

/*

101

* If the file is a directory, search it and place * all files onto the queue as new work items.

102

103 104 105 106 107 108 109 110

111

A J e w w a y s to u se t h r ea d s

*/ directory = opendir (work->path); if (directory == NULL) { fprintf ( stderr, "Unable to open directory %s: %d (%s)\n", work->path, errno, strerror (errno)); continue;

>

112

113 114 115 116 117 118 119 120 121

while (1) { status = readdir_r (directory, entry, &result); if (status 1= 0) { fprintf ( stderr, "Unable to read directory %s: %d (%s)\n", work->path, status, strerror (status)); break;

1 22

>

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

if (result == NULL) break;

/* End of directory */

/* * Ignore "." and

" entries.

*/ if (strcmp (entry->d_name, ".") == 0) continue; if (strcmp (entry->d_name, ".«.") == 0) continue; new_work = (work_p)malloc (sizeof (work_t)); if (new_work == NULL) errno_abort ("Unable to allocate space"); new_work->path = (char*)malloc (path_max); if (new_work->path == NULL) errno_abort ("Unable to allocate path"); strcpy (new_work->path, work->path); strcat (new_work->path, "/")? strcat (new_work->path, entry->d_name); new__work->string = work->string; new_work->next = NULL; status = pthread_mutex_lock (&crew->mutex);

113

W ork c r ew

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192

if (status != 0) err_abort (status, "Lock mutex"); if (crew->first == NULL) { crew->first = new_work; crew->last » new_work; > else { crew->last->next = new__work; crew->last = new__work;

} crew->work_count++; DPRINTF (( "Crew %d: add %#lx, first %#lx, last %#lx, mine->index, new^work, crew->first, crew->last, crew->work_count)); status = pthread_cond_signal (&crew->go); status = pthread__mutex_unlock (&crew->mutex); if (status != 0) err_abort (status, "Unlock mutex");

} closedir (directory); > else if (S_ISREG (filestat.st_ m o d e )) { FILE *search; char b u f f e r [256], *bufptr, *search__ptr;

/* * If this is a file, not a directory, then search * it for the string.

*/ search = fopen (work->path, "r"); if (search == NULL) fprintf ( stderr, "Unable to open %s: %d (%s)\n", work->path, errno, strerror (errno)); else { while (1) { bufptr = fgets ( buffer, sizeof (buffer), search); if (bufptr == NULL) { if (feof (search)) break; if (ferror (search)) { fprintf ( stderr, "Unable to read %s: %d (%s)\n", work->path,

%d \ n M,

CH A P T E R 4

193 194 195 196 197 198 199

errno,

} } search_ptr = strstr (buffer, work->string); if (search_ptr != NULL) { printf ( "Thread %d found \"%s\" in %s\n", mine->index, work->string, work->path); break;

201

202

210 211 2 1 2

213 214 215 216 217 218 219 220 221

strerror (errno));

break;

200

203 204 205 206 207 208 209

A f e w w a y s t o u se t h r ea d s

> > fclose (search);

} > else fprintf ( stderr, "Thread %d: %s is type %o (%s))\n", mine->index, work->path, filestat•st_mode & S_IFMT, (S_ISFIFO (filestat.st_mode) ? "FIFO" : (S_ISCHR (filestat.st_mode) ? "CHR" ‫( ג‬S_ISBLK (filestat.stjmode) ? "B L K " : (S_ISSOCK (filestat.st_mode) ? "SOCK" 2 "unknown"))))); free (work->path); free (work);

/* Free path buffer */ /* We're done with this */

222

223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241

/* * Decrement count of outstanding work items, and wake * waiters (trying to collect results or start a new * calculation) if the crew is now idle.

* * I t 's important that the count be decremented AFTER * processing the current work item. That ensures the * count won't go to 0 until we're really done.

*/ status = pthread_mutex_lock (screw->mutex); if (status 1= 0) err_abort (status, "Lock crew mutex"); crew->work_count— ; DPRINTF (("Crew %d decremented work to %d\n", mine->index, crew‫> ־‬work__count) ); if (crew->work_count mutex); if (status != 0) return status; /* * If the crew is busy, wait for them to finish. */ while (crew->work_count > 0 ) { status = pthread_cond_wait (&crew->done, Screw->mutex); if (status != 0) { pthread_mutex_unlock (&crew->mutex); return status; > > errno = 0; path_max = pathconf

(filepath, _PC_PA T H_ M A X );

118

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

CH A P T E R 4

A f e w w a y s t o u se t h r ea d s

if (path_max == -1) { if (errno == 0) path_max =1024; /* "No limit" */ else errno__abort ("Unable to get PATH_MAX"); } errno = 0; name__max = pathconf (filepath, _PC_NAME_MAX); if (name_max =- -1) { if (errno == 0) name_max = 256; /* "No limit" */ else errno_abort ("Unable to get NAME_MAX"); > DPRINTF (( "PATH_MAX for %s is %ldf NAME_MAX is %ld\n", filepath, path__max, name_max)); path__max++; /* Add null byte */ name_max++; /* Add null byte */ request = (work_p)malloc (sizeof (work_t)); if (request == NULL) errno_abort ("Unable to allocate request"); DPRINTF (("Requesting %s\n", filepath)); request->path = (char*)malloc (path_max); if (request->path — NULL) errno_abort ("Unable to allocate path"); strcpy (request->path, filepath); request->string - search; request->next = NULL; if (crew->first == NULL) { crew->first = request; crew->last = request; > else { crew->last->next = request; crew->last = request; }

66

67

68 69 70 71 72 73 74 75 76 77

crew->work_count++; status = pthread_cond_signal (&crew->go); if (status !=0) { free (crew‫> ־‬first); crew->first = NULL; crew->work_count = 0; pthread_mutex__unlock (&crew->mutex); return status; } while (crew->work_count >0) { status = pthread_cond_wait (&crew->done, screw->mutex);

119

Work c r ew

78 79 80 81 82 83 84 85

if (status 1= 0) err_abort (status,

,,waiting for crew to finish‫;) ״‬ } status = pthread_mutex_unlock (&crew->mutex); if (status != 0) err_abort (status, "Unlock crew mutex"); return 0; > ■

10-13 15-23

24-30

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

part 4

crew_start

P a rt 5 s h o w s th e in itia l th r e a d (main) for th e little w o rk crew sa m p le . T h e p ro g ra m r e q u ire s th r e e a r g u m e n ts —th e p ro g ra m n a m e , a s trin g for w h ic h to s e a rc h , a n d a p a th n a m e . F o r e x am p le, “crew b u te n h o f ‫” ׳ י‬ O n a S o la ris s y ste m , ca ll t h r _ s e t c o n c u r r e n c y to e n s u r e t h a t a t le a s t o n e LWP (k e rn e l e x e c u tio n co n tex t) is c re a te d fo r e a c h crew m e m b e r. T h e p ro g ra m will w o rk w ith o u t th is call, b u t, o n a u n ip ro c e s s o r, y o u w o u ld n o t se e a n y c o n c u rre n c y . S ee S e c tio n 5 .6 .3 for m o re in fo rm a tio n o n “m a n y to few ” s c h e d u lin g m o d e ls, a n d S e c tio n 1 0 .1 .3 for in fo rm a tio n o n “s e t c o n c u rre n c y ” fu n c tio n s . C re a te a w o rk crew , a n d a s s ig n to it th e c o n c u r r e n t file s e a rc h . ■

1 2 3 4 5 6 7 8 Q y

crew.c

crew.c

part 5

/* * The main program to "drive‫ ״‬the c r e w . •. */ int main (int argc, char *argv[]) { crew_t my_crew; char line[128], int status;

*next;

if (argc < 3) { fprintf (stderr, return -1; >

"Usage:

%s string path\n" , argv[0]);

s'

#ifdef sun /* * On Solaris 2.5, threads are not timesliced. To ensure * that our threads can run concurrently, we need to * increase the concurrency level to CREW SIZE • */ DPRINTF (("Setting concurrency level to %d\n". C R EW _SIZE)) ; thr setconcurrency (CREW SIZE); #endif status = crew_create (&my_crew, CREW___SIZE); if (status != 0) err_abort (status, "Create crew");

main

120

27 28 29 30 31 32 33

CH A P T E R 4

status = crew_start (&my_crew, argv[2], if (status 1= 0) err_abort (status, "Start crew");

A f e w w a y s t o u se t h r ea ds

argv[l]);

return 0; } ■

crew.c

part 5

main

4.3 C lie n t/S e rv e r But th e J u d g e s a id h e n e v e r h a d s u m m e d u p b e fo re ; So th e S n ark u n d e rto o k it in s te a d , A n d s u m m e d it so w e il th a t it c a m e to fa r m o re Than th e Witnesses e v e r h a d s a id i

—Lewis Carroll, The Hunting o f the Snark

In a c lie n t/s e r v e r s y ste m , a “c lie n t” r e q u e s ts t h a t a “s e rv e r” p e rfo rm so m e o p e ra tio n o n a s e t of d a ta (F ig ure 4.3). T h e s e rv e r p e rfo rm s th e o p e ra tio n in d e p e n d e n tly —th e c lie n t c a n e ith e r w a it for th e s e rv e r o r p ro c e e d in p a ra lle l a n d loo k for th e r e s u lt a t a la te r tim e w h e n th e r e s u lt is re q u ire d . A lth o u g h it is s im p le s t to h a v e th e c lie n t w a it fo r th e serv er, t h a t ’s ra re ly v ery u s e fu l—it c e rta in ly d o e s n ’t

FIGURE 4 .3

C lie n t/ S e rv e r

121

C l i e n t /S e r u e r

p ro v id e a s p e e d a d v a n ta g e to th e clien t. O n th e o th e r h a n d , it c a n b e a n e a s y w ay to m a n a g e s y n c h ro n iz a tio n fo r so m e c o m m o n re s o u rc e . If a s e t o f th r e a d s all n e e d to re a d in p u t fro m stdin, it m ig h t b e c o n fu s in g for th e m to e a c h is s u e in d e p e n d e n t p r o m p t- a n d - r e a d o p e ra tio n s . Im ag in e t h a t tw o t h r e a d s e a c h w rite s its p ro m p t u s in g printf, a n d th e n e a c h r e a d s th e re s p o n s e u s in g gets —y o u w o u ld h a v e n o w ay o f k n o w in g to w h ic h th r e a d y o u w ere re s p o n d in g . If o n e th r e a d a s k s “OK to s e n d m a il? ” a n d th e o th e r a s k s “OK to d e le te ro o t d ire c to ry ? ” y o u ’d p ro b a b ly like to k n o w w h ic h th r e a d w ill receiv e y o u r r e s p o n s e . O f c o u rs e th e re a re w a y s to k e e p th e p ro m p t a n d re s p o n s e “c o n n e c te d ” w ith o u t in tro d u c in g a s e rv e r th re a d ; for e x am p le, b y u s in g th e flockfile a n d funlockfile fu n c tio n s to lo ck b o th stdin a n d stdout a r o u n d th e p r o m p t- a n d r e a d s e q u e n c e s , b u t a s e rv e r th r e a d is m o re in te re s tin g —a n d c e rta in ly m o re relev a n t to th is se c tio n . In th e follow ing p ro g ra m , s e r v e r , c, e a c h o f fo u r th r e a d s w ill re p e a te d ly re a d , a n d th e n ech o , in p u t lin es. W h e n th e p ro g ra m is r u n y o u s h o u ld se e th e th r e a d s p ro m p t in v a ry in g o rd e rs , a n d a n o th e r th r e a d m a y p ro m p t b efo re th e ech o . B u t y o u ’ll n e v e r see a p ro m p t o r a n e c h o b e tw e e n th e p ro m p t a n d re a d p e rfo rm e d b y th e “p ro m p t se rv e r.” 7-9 T h e s e sy m b o ls d efin e th e c o m m a n d s t h a t c a n b e s e n t to th e “p ro m p t s e rv e r.” It c a n b e a s k e d to re a d in p u t, w rite o u tp u t, o r quit. 14-22 T h e request_t s tr u c tu r e d e fin e s e a c h r e q u e s t to th e serv er. T h e o u ts ta n d in g r e q u e s ts a re lin k e d in a lis t u s in g th e next m e m b e r. T h e operation m e m b e r co n ta in s o n e o f th e r e q u e s t c o d e s (read, w rite, o r q u it). T h e synchronous m e m b e r is n o n z e ro if th e c lie n t w is h e s to w a it fo r th e o p e ra tio n to b e c o m p le te d (sy n ch ro n o u s), o r 0 if it d o e s n o t w is h to w a it (a s y n c h ro n o u s). 27-33 T h e tty_server_t s tr u c t u r e p ro v id e s th e c o n te x t for th e s e rv e r th re a d . It h a s th e s y n c h ro n iz a tio n o b je c ts (mutex a n d request), a flag d e n o tin g w h e th e r th e s e rv e r is running, a n d a lis t of r e q u e s ts t h a t h a v e b e e n m a d e a n d n o t y e t p ro c e s s e d (first a n d last). 35-37 T h is p ro g ra m h a s a sin g le serv er, a n d th e c o n tro l s tr u c t u r e ( t t y _ s e r v e r ) is s ta tic a lly a llo c a te d a n d in itia liz e d h e re . T h e lis t of r e q u e s ts is e m p ty , a n d th e s e rv e r is n o t r u n n in g . T h e m u te x a n d c o n d itio n v a ria b le a re s ta tic a lly in itia lize d . 43-45 T h e m a in p ro g ra ip a n d c lie n t th r e a d s c o o rd in a te th e ir s h u td o w n u s in g th e s e s y n c h ro n iz a tio n o b je c ts ( c lie n t_ m u te x a n d c lie n ts _ _ d o n e ) r a th e r t h a n u s in g p th re a d _ jo in . ■ 1 2 3 4 5

server.c

part 1

definitions

!include !include !include "errors.h" !define CLIENTJTHREADS

4

/* Number of clients */

!define REQ_READ !define REQ WRITE

1 2

/* Read with prompt */ /* Write */

6 7 8

122

#define REQ_QUIT

9

CH A P T E R 4

A f e w w a y s to u se t h r ea d s

/* Quit server */

3

10

/* * Internal to server "package" — one for each request. */ typedef struct request _tag { struct request tag *next; /* Link to next */ operation; int /* Function code */ int synchronous; /* Nonzero if synchronous */ int done flag; /* Predicate for wait */ done; pthread cond t /* Wait for completion */ char p r o m p t [32]; /* Prompt string for reads */ char te xt[128]; /* Read/write text */ } request t;

11 12 13 14 15 16 17 18 19 20 21 22 23

/* * Static context for the server */ typedef struct tty_server tag { request t *first; request t *last; int running; pthread mutex t mutex; request; pthread_cond t } tty_server_t;

24 25 26 27 28 29 30 31 32 33 34

tty server t tty server = { NULL, NULL, 0, PTHREAD_MUTEX_INITIALIZER,

35 36 37

PTHREAD__COND_INITIALIZER};

38

/* * Main program data */

39 40 41 42 43 44 45

int client threads; pthread mutex t client mutex = PTHREAD MUTEX_INITIALIZER; pthread cond^t clients jione = PTHREAD_COND_ INITIALIZER; ■

25-30

31-34 43-66

server.c

part 1

definitions

P a rt 2 sh o w s th e s e rv e r th r e a d fu n c tio n , tty_server_routine. It lo o p s, p ro c e s s in g r e q u e s ts c o n tin u o u s ly u n til a s k e d to q u it. T h e s e rv e r w a its fo r a r e q u e s t to a p p e a r u s in g th e r e q u e s t c o n d itio n v a ria b le . R em ove th e firs t r e q u e s t fro m th e q u e u e —if th e q u e u e is n o w em p ty , a lso c le a r th e p o in te r to th e la s t e n try ( t t y _ s e r v e r . l a s t ) . T h e s w itc h s ta te m e n t p e rfo rm s th e r e q u e s te d w o rk , d e p e n d in g o n th e o p e r a t i o n giv en in th e r e q u e s t p a c k e t, r e q q u i t te lls th e s e rv e r to s h u t d o w n . r e q _ r e a d te lls th e s e rv e r to re a d , w ith a n o p tio n a l p ro m p t s trin g . r e q _ w r i t e te lls th e s e rv e r to w rite a s trin g .

123

C l i e n t /S e r v e r

67-79

8 0 -8 1

If a r e q u e s t is m a rk e d “s y n c h r o n o u s ” (synchronous flag is n o n zero ), th e se rv e r s e ts done_f l a g a n d s ig n a ls th e done c o n d itio n v a ria b le . W h e n th e r e q u e s t is sy n c h ro n o u s , th e c lie n t is re s p o n s ib le fo r freein g th e request p a c k e t. If th e r e q u e s t w a s a s y n c h r o n o u s , th e s e rv e r fre e s request o n c o m p le tio n . If th e r e q u e s t w a s req_quit, te rm in a te th e s e rv e r th r e a d b y b re a k in g o u t o f th e w h ile loop, to th e r e t u r n s ta te m e n t. ■

server.c

part 2

tty_server_routine

1 /* * The server start routine. It waits for a request to appear 2 ★ in tty_server.requests using the request condition variable. 3 * It processes requests in FIFO order. If a request is marked 4 * "synchronous” (synchronous != 0), the server will set done_flag 5 * and signal the request's condition variable. The client is 6 * responsible for freeing the request. If the request was not 7 * synchronous, the server will free the request on completion. 8 ★ / 9 10 void *tty_server_routine (void *arg) 11 { static pthread_mutex t prompt__mutex = PTHREAD_MUTEX_INITIALIZER; 12 13 request_t *request; 14 int operation, len; int status; 15 16 17 while (1) { status = pthread_mutex_lock (&tty_server.mutex); 18 if (status != 0) 19 20 err_abort (status, "Lock server mutex"); 21 22 /* 23 * Wait for data 24 */ ^ 25 while (tty_server.first == NULL) { status = pthread_cond_wait ( 26 &t t y _ server.req u e s t , &tty_server.m u t e x ); 27 28 if (status != 0) 29 err abort (status, "Wait for request"); 30 > 31 request = tty__server. first; 32 tty server.first = request->next; if (tty_server.first == NULL) 33 34 tty_server.last = NULL; status = pthread_jnutex__unlock (&tty_server.mutex); 35 if (status != 0) 36 37 err_abort (status, ,,Unlock server mutex"); 38 39 /* * Process the data 40 41 */

124

CHA P T E R 4

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

A f e w w a y s t o u s e t h r ea d s

operation = request->operation; switch (operation) { case REQ_QUIT: break; case REQ_READ: if (strlen (request->prompt) > 0) printf (request->prompt); if (fgets (request->text, 128, stdin) == NULL) request->text[0] = '\0';

/* * * * *

Because fgets returns the newline, and we don't want it, we look for it, and turn it into a null (truncating the input) if found. It should be the last character, if it is there.

*/ len = strlen (request->text); if (len > 0 && request->text[len-1J == request->text[le n - 1 ] = '\ 0 '; break; case R E Q _ WRITE: puts (request->text); break; default: break;

'\ n ')

66

}

67

if (request->synchronous) { status = pthread_mutex_lock (&tty_server.mutex); if (status != 0) err_abort (status, "Lock server m u t e x ‫;) ״‬ request->done_flag = 1; status = pthread_cond_signal (&request->done); if (status != 0) err_abort (status, "Signal server condition‫;) ״‬ status = pthread_mutex_unlock (&tty_server.mutex); if (status 1= 0) err_abort (status, "Unlock server mutex"); } else free (request); if (operation == REQ_QUIT) break;

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

} return NULL; server.c

part 2

tty_server_routine

P a rt 3 s h o w s th e fu n c tio n th a t is ca lle d to in itia te a r e q u e s t to th e tty s e rv e r th re a d . T h e c a lle r sp ecifies th e d e s ire d operation (REQ_QUIT, REQ_READ, o r REQ__ w r i t e ), w h e th e r th e o p e ra tio n is s y n c h ro n o u s o r n o t (sync), a n o p tio n a l p ro m p t

125

C l i e n t /S e r v e r

string (prompt) for r e q _ r e a d operations, a n d the pointer to a string (input for r e q _ w r i t e , or a buffer to return the result of an r e q _ r e a d operation). 16-40

45-76

81-83 88-105

If a tty s e rv e r th r e a d is n o t a lre a d y r u n n in g , s t a r t o n e. A te m p o ra ry th r e a d a ttr ib u t e s o b je c t ( d e t a c h e d _ a t t r ) is c re a te d , a n d th e d e ta ch s ta te a t tr ib u t e is s e t to p t h r e a d _ c r e a t e _ d e t a c h e d .T h re a d a ttr ib u te s w ill b e e x p la in e d la te r in S e c tio n 5 .2 .3 . In th is c a se , w e a re j u s t sa y in g t h a t w e will n o t n e e d to u s e th e th r e a d id e n tifier a fte r c re a tio n . A llocate a n d in itialize a s e rv e r r e q u e s t ( r e q u e s t_ t ) p a c k e t. If th e r e q u e s t is s y n c h ro n o u s , in itia lize th e c o n d itio n v a ria b le (done) in th e r e q u e s t p a c k e t—o th e rw ise th e c o n d itio n v a ria b le is n ’t u s e d . T h e n e w re q u e s t is lin k e d o n to th e re q u e s t queue. W ak e th e s e rv e r th r e a d to h a n d le th e q u e u e d re q u e s t. If th e r e q u e s t is s y n c h ro n o u s , w a it for th e se rv e r to s e t done_f lag a n d sig n a l th e done c o n d itio n v a ria b le . If th e o p e ra tio n is REQ_READ, co p y th e r e s u lt s trin g in to th e o u tp u t b u ffer. F in ally , d e s tro y th e c o n d itio n v a ria b le , a n d free th e r e q u e s t p a c k e t. ■

1

server.c

tty_server_request

/*

2

* Request an operation

3

*/

4 5 6 7 8

void tty_server_request ( int operation, int sync, const char *prompt, char *string)

9

{

10 11

part 3

request_t *request; int status;

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

status = pthread_mutex_lock (&tty_server.mutex); if (status != 0) err_abort (status, "Lock server mutex"); if ( !tty__server.running) { pthread_t thread; pthread_attr__t detached_attr; status = pthread_attr_init (&detached_attr); if (status != 0) err_abort (status, "Init attributes object"); status = pthread_attr_setdetachstate ( &detached_attr, PTHREAD_CREATE_DETACHED); if (status 1= 0) err_abort (status, "Set detach state"); tty_server.running = 1; status = pthread_create (&thread, &detached_attr, tty_server_routine, NULL);

126

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

66

CH A P T E R 4

if (status 1= 0) err__abort (status,

"Create server");

/* * * * *

Ignore an error in destroying the attributes object. It's unlikely to fail, there's nothing useful we can do about it, and it's not worth aborting the program over i t .

*/ pthread_attr_destroy (&detached_attr);

> /* * Create and initialize a request structure.

*/ request = (request_t*)malloc (sizeof (request_t)); if (request == NULL) errno_abort ("Allocate request"); request->next = NULL; request->operation = operation; request->synchronous = sync; if (sync) { request->done__f lag = 0; status = pthread__cond_init (&request->done, NULL); if (status != 0) err_abort (status, "Init request condition");

} if (prompt != NULL) strncpy (request->prompt, prompt, 32); else request->prompt[0] = *\0'; if (operation == REQ_WRITE && string != NULL) strncpy (request->text, string, 128); else request->text[0] = '\0';

/* * Add the request to the queue, maintaining the first and * last pointers.

67

68 69 70 71 72 73 74 75 76 77 78

A f e w w a y s to u s e t h r ea d s

*/ if (tty_server.first == NULL) { tty_server.first = request; t ty_server.last = request; > else { (tty_server.l a s t )->next = request; t t y _server.last = request;

} /*

127

C l i e n t /S e r v e r

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

* Tell the server that a request is available. */ status = pthread_cond_signal (&tty_server.req u e st ); if (status 1= 0) err_abort (status, "Wake server” ); /* * If the request was "synchronous”, then wait for a reply. */ if (sync) { while (!request->done_flag) { status = pthread_cond_wait ( &request->done, &tty_server.mutex); if (status != 0) err_abort (status, ‫ ׳‬,Wait for sync r equest‫;) ״‬ } if (operation == R E Q _ R E A D ) { if (strlen (request->text) > 0) strcpy (string, request->text); else string[0] = '\0 ‫; ״‬

}

100

101 102 103 104 105 106 107 108 109

status = pthread_cond_destroy (&request->done); if (status I - 0 ) err_abort (status, "Destroy request condition"); free (request); } status = pthread_mutex__unlock (&tty_server.mutex); if (status != 0) err_abort (status, "Unlock mutex"); > ■

server.c

part 3

tty_server_request

P a rt 4 sh o w s th e th r e a d s t a r t fu n c tio n for th e c lie n t th r e a d s , w h ic h re p e a te d ly q u e u e tty o p e ra tio n r e q u e s ts to th e server. R ead a lin e th r o u g h th e tty server. If th e re s u ltin g s trin g is e m p ty , b r e a k o u t of th e loop a n d te rm in a te . O th e rw ise , loo p fo u r tim e s p r in tin g th e r e s u lt s trin g , a t o n e -s e c o n d in te rv a ls . W hy fo u r? It j u s t “m ix es th in g s u p ” a little. D e c re a s e th e c o u n t o f c lie n t th r e a d s , a n d w a k e th e m a in th r e a d if th is is th e la s t c lie n t th r e a d to te rm in a te .

12-22

26-31



server.c

part 4

1

/*

2 3 4

* Client routine — multiple copies will request server. */ void *client_routine (void *arg)

client_routine

128

5

CHA P T E R 4

A f e w w a y s t o u se t h r ea ds

{

6 7 8 9

int my_number = (int)arg, loops; char p r o m p t [32]; char string[128], formatted[128]; int status;

10 11 12 13 14 15 16 17 18 19 20

sprintf (prompt, "Client %d> ", my_number); while (1) { tty_server_request (REQ_READ, 1, prompt, string); if (strlen (string) == 0) break; for (loops = 0; loops < 4; loops++) { sprintf ( formatted, ‫( ״‬%d#%d) %s", my_number, loops, string); tty_server_request (REQ_WRITE, 0, NULL, formatted); sleep (1);

21 22

} }

23 24 25 26 27 28 29 30 31 32 33 34 35 36

status = pthread__mutex_lock (&client_mutex); if (status != 0) err__abort (status, "Lock client mutex"); client_threads— ; if (client_threads }

20 21

int main (int argc, char *argv[])

22

{

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

pthread__t thread_id; void *result; int status; #ifdef sun

/* * On Solaris 2.5, threads are not timesliced. To ensure * that our two threads can run concurrently, we need to * increase the concurrency level to 2.

*/ DPRINTF (("Setting concurrency level to 2\n")); thr__setconcurrency (2 ); #endif status = pthread_create ( &thread__id, NULL, thread_routine, NULL); if (status 1= 0) err_abort (status, "Create thread"); sleep (2); DPRINTF (("calling cancel\n")); status = pthread__cancel (thread_id); if (status != 0) err_abort (status, "Cancel thread");



DPRINTF (("calling j oin\n")); status = pthread_join (thread_id, &result); if (status 1= 0) err_abort (status, "Join thread"); if (result == PTHREAD_CANCELED) printf ("Thread canceled at iteration %d\n", counter); else printf ("Thread was not canceled\n"); return 0; cancel.c

147

Ca n c el l a t i o n

A th r e a d c a n d is a b le c a n c e lla tio n a r o u n d s e c tio n s of co d e t h a t n e e d to com p le te w ith o u t in te rru p tio n , b y c a llin g pthread_setcancelstate. F o r e x a m p le , if a d a ta b a s e u p d a te o p e ra tio n ta k e s tw o s e p a r a te write calls, y o u w o u ld n ’t w a n t to co m p le te th e firs t a n d h a v e th e s e c o n d c a n c e le d . If y o u re q u e s t t h a t a th r e a d b e c a n c e le d w h ile c a n c e lla tio n is d is a b le d , th e th r e a d re m e m b e rs t h a t it w a s c a n celed b u t w o n ’t do a n y th in g a b o u t it u n til a fte r c a n c e lla tio n is e n a b le d a g a in . B e c a u s e e n a b lin g c a n c e lla tio n is n ’t a ca n ce lla tio n p o in t y o u a lso n e e d to te s t for a p e n d in g c a n c e l r e q u e s t if y o u w a n t a c a n c e l p ro c e s s e d im m ed iately . W h e n a th r e a d m a y b e c a n c e le d w h ile it h o ld s p riv a te re s o u rc e s , s u c h a s a lo ck ed m u te x o r h e a p s to ra g e t h a t w o n ’t ev er b e freed b y a n y o th e r th r e a d , th o s e re s o u r c e s n e e d to b e re le a s e d w h e n th e th r e a d is c a n c e le d . If th e th r e a d h a s a m u te x lo ck ed , it m a y a lso n e e d to “r e p a ir ” s h a r e d d a t a to r e s to r e p ro g ra m in v a ria n ts . C le a n u p h a n d le rs p ro v id e th e m e c h a n is m to a c c o m p lish th e c le a n u p , s o m e w h a t like p ro c e s s atexit h a n d le r s . A fter a c q u irin g a re s o u rc e , a n d befo re a n y c a n c e lla tio n p o in ts , d e c la re a c le a n u p h a n d le r b y c a llin g pthread_cleanup_ push. B efore re le a s in g th e re s o u rc e , b u t a fte r a n y c a n c e lla tio n p o in ts , rem o v e th e c le a n u p h a n d le r b y callin g pthread__cleanup_pop. If y o u d o n ’t h a v e a th r e a d ’s id en tifier, y o u c a n ’t c a n c e l th e th re a d . T h a t m e a n s th a t, a t le a s t u s in g p o rta b le POSIX fu n c tio n s , y o u c a n ’t w rite a n “idle th re a d k ille r” t h a t will a rb itra rily te rm in a te th r e a d s in th e p ro c e s s . You c a n o n ly c a n c e l th r e a d s t h a t y o u c re a te d , o r th r e a d s for w h ic h th e c re a to r (or th e th r e a d itself) gav e y o u a n id entifier. T h a t g e n e ra lly m e a n s t h a t c a n c e lla tio n is r e s tric te d to o p e ra tin g w ith in a s u b s y s te m .

5.3.1

D e fe rre d c a n c e la b ility “D eferred can c e la b ility ” m e a n s t h a t th e th r e a d ’s c a n c e la b ility ty p e h a s b e e n se t a n d th e th r e a d ’s can c e la b ility e n a b le h a s b e e n s e t to p t h r e a d __c a n c e l __e n a b l e . T h e th r e a d will o n ly re s p o n d to c a n c e lla tio n re q u e s ts w h e n it re a c h e s o n e of a s e t o f “c a n c e lla tio n p o in ts .” T h e follow ing fu n c tio n s a re a lw a y s c a n c e lla tio n p o in ts o n a n y P th re a d s sy ste m : to

p t h r e a d _c a n c e l _ d e f e r r e d

pthread_cond_wait pthread__cond_timedwait pthread_join pthread__testcancel sigwait aio^suspend close creat fcntl (F_SETLCKW)

fsync mq__receive mq_send msync nanosleep open pause read sem_wait

sigwaitinfo sigsuspend sigtimedwait sleep system tcdrain wait waitpid write

T h e follow ing list of f u n c tio n s m a y b e c a n c e lla tio n p o in ts. You s h o u ld w rite y o u r co d e so th a t it will fu n c tio n c o rre c tly if a n y of th e s e a re c a n c e lla tio n p o in ts

148

CH A P T E R 5

A d va n c e d t h r ea d ed p r og r a m m in g

a n d a lso so t h a t it will n o t b r e a k if a n y of th e m a re n o t. If y o u d e p e n d u p o n a n y p a r tic u la r b eh av io r, y o u m a y lim it th e p o rta b ility of y o u r co de. You’ll h a v e to look a t th e c o n fo rm a n c e d o c u m e n ta tio n to fin d o u t w h ic h , if a n y , a re c a n c e lla tio n p o in ts for th e s y s te m y o u a re u sin g : closedir ctermid fclose fcntl (except F_SETLCKW) fflush f getc fgets fopen fprintf fputc fputs fread freopen fscanf f seek ftell fwrite getc

getc unlocked getchar getchar unlocked getcwd getgrgid getgrgid r getrtnam getgrnam r getlogin getlogin r getpwnam getpwnam r getpwuid getpwuid_r gets lseek opendir perror

printf putc putc_unlocked putchar putchar_unlocked puts readdir remove rename rewind rewinddir scanf tmpfile tmpname ttyname ttyname r ungetc

P th r e a d s sp ecifies t h a t a n y ANSI C o r POSIX fu n c tio n n o t sp ecified in o n e of th e tw o lis ts c a n n o t b e a c a n c e lla tio n p o in t. H owever, y o u r s y s te m p ro b a b ly h a s m a n y a d d itio n a l c a n c e lla tio n p o in ts. T h a t’s b e c a u s e few UNIX s y s te m s are “PO SIX .” T h a t is, th e y s u p p o r t o th e r p ro g ra m m in g in te rfa c e s a s w ell—s u c h a s B SD 4 .3 , S y s te m V R e le a se 4, UNIX95, a n d so fo rth . PO SIX d o e s n ’t reco g n ize th e e x iste n c e o f f u n c tio n s s u c h a s select o r poll, a n d th e re fo re it c a n ’t s a y w h e th e r o r n o t th e y a re c a n c e lla tio n p o in ts. Yet clearly b o th a re fu n c tio n s th a t m a y b lo c k for a n a r b itr a r y p e rio d of tim e, a n d p ro g ra m m e rs u s in g th e m w ith c a n c e lla tio n w o u ld r e a s o n a b ly e x p e c t th e m to b e h a v e a s c a n c e lla tio n p o in ts. X /O p e n is c u rre n tly a d d re s s in g th is p ro b le m fo r U NIX98 (X / O p e n S y s te m In te rfa ce s , Is s u e 5). b y e x te n d in g th e P th r e a d s lis t o f c a n c e lla tio n p o in ts. M o st c a n c e lla tio n p o in ts involve I /O o p e ra tio n s t h a t m a y b lo c k th e th r e a d for a n “u n b o u n d e d ” tim e. T h ey ’re c a n c e la b le so t h a t th e w a its c a n b e in te rru p te d . W h e n a th r e a d r e a c h e s a c a n c e lla tio n p o in t th e s y s te m d e te rm in e s w h e th e r a c a n c e l is p e n d in g for th e c u r r e n t (“ta rg e t”) th r e a d . A c a n c e l will b e p e n d in g if a n o th e r th r e a d h a s called pthread_cancel for th e ta rg e t th r e a d sin c e th e la s t tim e th e ta rg e t th r e a d r e tu r n e d from a c a n c e lla tio n p o in t. If a c a n c e l is p e n d in g , th e s y ste m will im m e d ia te ly b e g in callin g c le a n u p fu n c tio n s , a n d th e n th e th re a d w ill te rm in a te . If n o c a n c e l is c u rre n tly p e n d in g , th e fu n c tio n w ill p ro cee d . If a n o th e r th r e a d r e q u e s ts t h a t th e th r e a d b e c a n c e le d w h ile th e th r e a d is w a itin g for s o m e th in g (s u c h a s I/O ) t h e n th e w a it w ill b e in te r r u p te d a n d th e th r e a d w ill b e g in its c a n c e lla tio n c le a n u p .

Ca n c e l l a t i o n

149

23-32

If y o u n e e d to e n s u r e t h a t c a n c e lla tio n c a n ’t o c c u r a t a p a r tic u la r c a n c e lla tio n p o in t, o r d u rin g so m e s e q u e n c e of c a n c e lla tio n p o in ts , y o u c a n te m p o ra rily d isa b le c a n c e lla tio n in t h a t re g io n o f code. T h e follow ing p ro g ra m , ca lle d cancel_ disable.c, is a v a r ia n t o f cancel.c. T h e “ta rg e t” th r e a d p e rio d ic a lly c a lls sleep, a n d d o e s n o t w a n t th e call to b e c a n c e la b le . A fter e a c h cycle of 7 5 5 ite ra tio n s , thread_routine will call sleep to w a it a se c o n d . (The v a lu e 7 5 5 is j u s t a n a r b itr a r y n u m b e r t h a t p o p p e d in to m y h e a d . Do a r b itr a r y n u m b e r s ev er p o p in to y o u r h e a d ? ) P rio r to sleep in g , thread_routine d is a b le s c a n c e lla tio n b y s e ttin g th e c a n c e la b ility s ta te to p t h r e a d _ c a n c e l _ d i s a b l e . A fter sleep r e tu r n s , it re s to r e s th e sa v e d c a n c e la b ility s ta te b y c a llin g pthread_setcancelstate a g ain . J u s t a s in c a n c e l . c, te s t for a p e n d in g c a n c e l ev ery 100 0 ite ra tio n s .

33-35



cancel_disable.c

1 #include 2 #include "errors.h" ‫­ג ג‬ 4 static int counter; 5 6 /* * Thread start routine. 7 8 */ 9 void *thread routine (void *arg) 10 { 11 int state; 12 int s tatus; 13 for (counter = 0 ; ; counter++) { 14 15 16 /* 17 * Each 755 iterations, disable cancellation and sleep * for one second. 18 * 19 * Each 1000 iterations, test for a pending cancel by 20 * calling pthread t e s tcancel(). 21 22 */ if ((counter % 755) = = 0 ) { 23 24 status = pthread setcancelstate ( PTHREAD_CANCEL__DI SABLE , &State ) ; 25 if (status != 0) 26 err abort (status, "Disable cancel") ; 27 28 sleep (1); status = pthread setcancelstate ( 29 state, fcstate); 30 if (status 1= 0) 31 err abort (status, "Restore cancel") ; 32

150

CHA P T E R 5

33 34 35 36

} else if ((counter % 1000) == 0) pthread_testcancel (); }

37

}

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

int main (int argc, char *argv[]) { pthread_t thread_id; void *result; int status; status = pthread_create ( &thread_id, NULL, thread_routine, NULL); if (status 1= 0) err_abort (status, ‫ ״‬,Create thread"); sleep (2); status = pthread_cancel (thread_id); if (status != 0) err_abort (status, "Cancel thread"); status = pthread_join (thread_id, &result); if (status != 0) err_abort (status, "Join thread"); if (result == PTHREAD_CANCELED) printf ("Thread canceled at iteration %d\n", counter); else printf ("Thread was not canceled\n"); return 0; } ■

5 .3 .2

A d va n c e d t h r ea d ed p r o g r a m m in g

cancel_disable.c

A sy n ch ro n o u s c a n c e la b ility A s y n c h ro n o u s c a n c e lla tio n is u s e fu l b e c a u s e th e “ta rg e t th r e a d ” d o e s n ’t n e e d to poll fo r c a n c e lla tio n r e q u e s ts by u s in g c a n c e lla tio n p o in ts . T h a t c a n b e v a lu a b le for a th r e a d t h a t r u n s a tig h t c o m p u te -b o u n d loop (for e x am p le, s e a rc h in g for a p rim e n u m b e r factor) w h e re th e o v e rh e a d o f callin g p t h r e a d _ t e s t c a n c e l m ig h t b e sev ere.

I

A v o id a s y n c h ro n o u s c a n c e lla t io n ! It is d iffic u lt t o us e c o r r e c t ly a n d is ra re ly u s e fu l.

T h e p ro b le m is t h a t y o u ’re lim ited in w h a t y o u c a n do w ith a s y n c h r o n o u s c a n c e lla tio n e n a b le d . You c a n ’t a c q u ire a n y r e s o u rc e s , for e x am p le, in c lu d in g lo ck in g a m u te x . T h a t’s b e c a u s e th e c le a n u p co d e w o u ld h a v e n o w ay to d e te rm in e

Ca n c el l a t i o n

151

w h e th e r th e m u te x h a d b e e n lo ck ed . A sy n c h ro n o u s c a n c e lla tio n ca n o c c u r a t a n y h a rd w a re in s tru c tio n . O n so m e c o m p u te rs it m a y ev en b e p o ssib le to in te r r u p t so m e in s tr u c tio n s in th e m id d le. T h a t m a k e s it really d ifficu lt to d e te rm in e w h a t th e c a n c e le d th r e a d w a s do in g. F o r ex am p le, w h e n y o u call m a llo c th e s y ste m a llo c a te s so m e h e a p m e m o ry for y o u , s to re s a p o in te r to t h a t m e m o ry so m e w h e re (p o ssib ly in a h a rd w a re reg ister), a n d th e n r e tu r n s to y o u r co d e, w h ic h p ro b a b ly m o v e s th e r e t u r n v a lu e in to so m e local s to ra g e for la te r u s e . T h e re a re lo ts of p la c e s t h a t m a llo c m ig h t b e in te r r u p te d b y a n a s y n c h r o n o u s c a n c e l, w ith v a ry in g effects. It m ig h t b e in te rr u p te d b efo re th e m e m o ry w a s a llo c a te d . O r it m ig h t b e in te r r u p te d a fte r a llo c a tin g sto ra g e b u t b efo re it s to re d th e a d d r e s s fo r r e tu r n . O r it m ig h t ev en r e t u r n to y o u r code, b u t g et in te r r u p te d b efo re th e r e tu r n v a lu e co u ld b e co p ied to a local v a ria b le . In a n y of th o s e c a s e s th e v a ria b le w h e re y o u r co d e e x p e c ts to fin d a p o in te r to th e a llo c a te d m e m o ry will b e u n in itia liz e d . You c a n ’t tell w h e th e r th e m e m o ry re a lly w a s a llo c a te d y et. You c a n ’t free th e m e m o ry , so t h a t m e m o ry (if it w a s a llo c a te d to you) w ill re m a in a llo c a te d for th e life of th e p ro g ra m . T h a t’s a m e m o ry leak , w h ic h is n o t a d e s ira b le fe a tu re . O r w h e n y o u call pthread_mutex_lock, th e s y s te m m ig h t b e in te r r u p te d w ith in a fu n c tio n call e ith e r b efo re o r a fte r lo ck in g th e m u te x . A gain, th e r e ’s n o w ay for y o u r p ro g ra m to fin d o u t, b e c a u s e th e in te r r u p t m a y h a v e o c c u rre d b e tw e e n a n y tw o in s tr u c tio n s , ev en w ith in th e pthread_mutex_lock fu n c tio n , w h ic h m ig h t leave th e m u te x u n u s a b le . If th e m u te x is lo ck ed , th e a p p lic a tio n will likely e n d u p h a n g in g b e c a u s e it w ill n e v e r b e u n locke d .

I

C a ll n o c o d e w ith a s y n c h ro n o u s c a n c e lla t io n e n a b le d unless y o u w r o t e it t o b e a s y n c - c a n c e l s a fe — a n d e v e n th e n , th in k t w ic e !

You a re n o t allow ed to call a n y fu n c tio n t h a t a c q u ire s re s o u rc e s w h ile a s y n c h r o n o u s c a n c e lla tio n is e n a b le d . In fact, y o u s h o u ld n e v e r call a n y fu n c tio n w h ile a s y n c h r o n o u s c a n c e lla tio n is e n a b le d u n le s s th e fu n c tio n is d o c u m e n te d a s “a s y n c -c a n c e l s a f e .” T h e o n ly fu n c tio n s re q u ire d to b e a s y n c sa fe b y P th r e a d s a re pthread_cancel, pthread_setcancelstate, a n d pthread_setcanceltype. (And th e re is n o r e a s o n to call pthread_cancel w ith a s y n c h r o n o u s c a n c e la b ility e n a b le d .) No o th e r POSIX o r ANSI C fu n c tio n s n e e d b e a s y n c -c a n c e l safe, a n d y o u s h o u ld n e v e r call th e m w ith a s y n c h r o n o u s c a n c e la b ility e n a b le d . P th r e a d s s u g g e s ts t h a t all lib ra ry fu n c tio n s s h o u ld d o c u m e n t w h e th e r o r n o t th e y a re a s y n c -c a n c e l safe. H ow ever if th e d e s c rip tio n of a fu n c tio n d o e s n o t sp e cifically s a y it is a s y n c -c a n c e l safe y o u s h o u ld a lw a y s a s s u m e t h a t it is n o t. T h e c o n s e q u e n c e s of a s y n c h r o n o u s c a n c e lla tio n in a fu n c tio n t h a t is n o t a s y n c c a n c e l safe c a n b e sev ere. A nd w o rse, th e effects a r e se n s itiv e to tim in g —so a fu n c tio n th a t a p p e a r s to b e a s y n c -c a n c e l sa fe d u rin g e x p e rim e n ta tio n m a y in fa c t c a u s e all s o r ts of p ro b le m s la te r w h e n it e n d s u p b e in g c a n c e le d in a slig h tly diffe re n t p la ce. T h e follow ing p ro g ra m . cancel_async .c, s h o w s th e u s e o f a s y n c h r o n o u s c a n c e lla tio n in a c o m p u te -b o u n d loop. U se o f a s y n c h ro n o u s c a n c e lla tio n m a k e s th is

152

CHA P T E R 5

A d va n c e d t h r ea d ed p r o g r a m m i n g

loop 4‘m o re re s p o n s iv e ” t h a n th e d e fe rre d c a n c e lla tio n loop in cancel.c. H ow ever, th e p ro g ra m w o u ld b e c o m e u n re lia b le if a n y fu n c tio n c a lls w ere m a d e w ith in th e loop, w h e re a s th e d e fe rre d c a n c e lla tio n v e rs io n w o u ld c o n tin u e to fu n c tio n c o r ‫־‬ rectly . In m o s t c a s e s , s y n c h ro n o u s c a n c e lla tio n is p re fe ra b le . 24-28 To k e e p th e th r e a d r u n n in g aw h ile w ith s o m e th in g m o re in te re s tin g th a n a n e m p ty loop, c a n c e l_ a s y n c .c u s e s a sim p le m a trix m u ltip ly n e s te d loop. The m a tr ix a a n d m a tr ix b a rra y s a re in itialized w ith , resp ectiv ely , th e ir m a jo r o r m in o r a rra y in d ex . 34-36 T h e c a n c e lla tio n ty p e is c h a n g e d to p t h r e a d _ c a n c e l _ a s y n c h r o n o u s , allow ing a s y n c h r o n o u s c a n c e lla tio n w ith in th e m a trix m u ltip ly lo ops. 39-44 T h e th r e a d r e p e a ts th e m a trix m u ltip ly u n til c a n c e le d , o n e a c h ite ra tio n re p la c in g th e firs t s o u rc e a r r a y (matrixa) w ith th e r e s u lt of th e p re v io u s m u ltip lic a tio n (matrixc). 66-74 O n ce a g a in , o n a S o la ris s y ste m , s e t th e th r e a d c o n c u rre n c y level to 2, allow in g th e m a in th r e a d a n d t h r e a d _ r o u t i n e to r u n c o n c u rre n tly o n a u n ip ro c e ss o r. T h e p ro g ra m will h a n g w ith o u t th is s te p , s in c e u s e r m o d e th r e a d s a re n o t tim e slic e d o n S o la ris. ■

can c el_ asy n c. c

1 #include 2 #include "errors.h" 3 4 #define SIZE 10 /* array size */ 5 6 static int matrixa[SIZE][SIZE]; 7 static int m a trixb[SIZE][S I Z E ]; 8 static int m a t r i x c [S I Z E ][S I Z E ]; 9 10 /* 11 * Loop until canceled. The thread can be canceled at any 12 * point within the inner loop, where asynchronous cancellation 13 * is enabled. The loop multiplies the two matrices matrixa 14 * and matrixb. 15 */ 16 void *thread_routine (void *arg) 17 { 18 int cancel_type, status; 19 int i, j, k, value = 1; 20 21

/*

22 23 24 25 26 27 28 29

* Initialize the matrices to something arbitrary. */ for (i = 0; i < SIZE; i++) for (j = 0; j < SIZE; j++) { m a t r i x a [ i ][j ] = i; m a t r i x b [ i ][j ] = j; }

153

Ca n c e l l a t i o n

32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

67 68

69 70 71 72 73 74 75 76 77 78 79

while (1) { /* * Compute the matrix product of matrixa and matrixb. */ status = pthread_setcanceltype ( PTHREAD_CANCEL_ASYNCHR0N0US, &cancel_type); if (status != 0) err_abort (status, "Set cancel type"); for (i = 0; i < SIZE; i++) for (j = 0; j < SIZE; j++) { matrixc[i][j] = 0; for (k = 0; k < SIZE; k++) matrixc[i][j] += matrixa[i][k] * matrixb[k][j]; } status = pthread_setcanceltype ( cancel_type, Srcancel_type); if (status != 0) err_abort (status, "Set cancel type"); /* * Copy the result (matrixc) into matrixa to start again */ for (i = 0; i < SIZE; i++) for (j = 0; j < SIZE; j++) m a t r ixa[i][j ] = m a t rixc[i][j ];

> }

int main (int argc, char *argv[]) { pthread_t thread__id; void *result; int status; #ifdef sun /* * On Solaris 2.5, threads are not timesliced. To ensure * that our two threads can run concurrently, we need to * increase the concurrency level to 2. */ DPRINTF ((,,Setting concurrency level to 2\n")); thr_setconcurrency (2); #endif status = pthread_create ( &thread_id, NULL, thread_routine, NULL); if (status != 0) err_abort (status, "Create thread"); sleep (1);

154

80 81 82 83 84 85 86 87 88 89 90 91

CHA P T E R 5

A d va n c e d t h r ea d ed p r og r a m m in g

status = pthread_cancel (thread_id); if (status != 0) err__abort (status, ,,Cancel thread"); status = pthread_join (thread_id, &result); if (status != 0) err__abort (status, "Join thread"); if (result == PTHREAD_CANCELED) printf ("Thread canceled\n"); else printf ("Thread was not canceled\n"); return 0; > ■

cancel_async.c I W a rn in g : d o n o t le t "D C E th r e a d s 7‫ ״‬h a b its c a r r y o v e r t o P th re a d s !

I’ll e n d th is s e c tio n w ith a w a rn in g . D C E th r e a d s , a c ritic a l c o m p o n e n t o f th e O p e n S o ftw are F o u n d a tio n 's D is trib u te d C o m p u tin g E n v iro n m e n t, w a s d e sig n e d to b e in d e p e n d e n t of th e u n d e rly in g UNIX k e rn e l. S y s te m s w ith n o th r e a d s u p p o rt a t all o ften e m u la te d “th r e a d s y n c h ro n o u s ” I /O in u s e r m o d e, u s in g n o n b lo c k in g I /O m o d e, so t h a t a th r e a d a tte m p tin g I /O o n a b u s y file w a s b lo c k ed o n a co nditio n v a ria b le u n til a la te r select o r poll sh o w e d t h a t th e I /O co u ld co m p lete . D C E lis te n e r th r e a d s m ig h t b lo c k in d e fin itely o n a so c k e t re a d , a n d it w a s im p o rt a n t to b e a b le to c a n c e l t h a t re a d . W h e n D C E w a s p o rte d to n e w e r k e rn e ls t h a t h a d th r e a d s u p p o rt, b u t n o t P th r e a d s s u p p o r t, th e u s e r m o d e I /O w ra p p e rs w ere u s u a lly o m itte d , re s u ltin g in a th r e a d b lo c k e d w ith in a k e rn e l th a t d id n o t s u p p o r t d e fe rre d c a n c e lla tio n . U se rs d isc o v e re d th a t, in m a n y c a s e s , th e s e s y s te m s im p le m e n te d a s y n c h r o n o u s c a n c e lla tio n in s u c h a w ay th a t, q u ite b y co in c id e n c e , a k e rn e l w a it m ig h t b e c a n c e le d “safely ” if th e th r e a d sw itc h e d to a s y n c h r o n o u s c a n c e lla tio n im m ed ia te ly b efo re th e k e rn e l call, a n d s w itc h e d b a c k to d e fe rre d c a n c e lla tio n im m e d ia te ly afte r. T h is o b s e rv a tio n w a s p u b lic iz e d in D C E d o c u m e n ta tio n , b u t it is a v ery d a n g e ro u s h a c k , ev en o n s y s te m s w h e re it s e e m s to w o rk . You s h o u ld n e v e r try th is o n a n y P th r e a d s sy stem ! If y o u r s y s te m c o n fo rm s to POSIX 10 03. lc - 1 9 9 5 (or POSIX 1 0 0 3 .1 , 1 9 9 6 e d itio n , o r la ter), it s u p p o r ts d e fe rre d c a n c e lla tio n of, a t m in im u m , k e rn e l fu n c tio n s s u c h a s re a d a n d w rite. You do n o t n e e d a s y n c h r o n o u s c a n c e lla tio n , a n d u s in g it c a n b e ex tre m e ly d a n g e ro u s .

5 .3 .3

C le a n in g u p

I

W h e n y o u w r ite a n y lib ra ry c o d e , d e s ig n it t o h a n d le d e f e r r e d c a n c e lla t io n g ra c e fu lly . D is a b le c a n c e lla t io n w h e r e it is n o t a p p r o p r ia t e , a n d a lw a y s u s e c le a n u p h a n d le rs a t c a n c e lla t io n p o in ts .

Ca n c el l a t i o n

10-17

24-34

47 54-58

60

155

If a se c tio n of co d e n e e d s to re s to re so m e s ta te w h e n it is c a n c e le d , it m u s t u s e c le a n u p h a n d le rs . W h e n a th r e a d is c a n c e le d w h ile w a itin g fo r a c o n d itio n v a riab le , it w ill w a k e u p w ith th e m u te x lo ck ed . B efore th e th r e a d te r m in a te s it u s u a lly n e e d s to re s to re in v a ria n ts , a n d it a lw ay s n e e d s to re le a s e th e m u te x . E a c h th r e a d m a y b e c o n s id e re d to h a v e a s ta c k of activ e c le a n u p h a n d le rs . C le a n u p h a n d le rs a re a d d e d to th e s ta c k b y calling pthread_cleanup_push, a n d th e m o s t re c e n tly a d d e d c le a n u p h a n d le r is rem o v e d b y c a llin g pthread_cleanup_ pop. W h e n th e th r e a d is c a n c e le d o r w h e n it e x its b y c a llin g pthread_exit, P th r e a d s c a lls e a c h activ e c le a n u p h a n d le r in tu r n , b e g in n in g w ith th e m o s t re c e n tly a d d e d c le a n u p h a n d le r. W h e n all a c tiv e c le a n u p h a n d le r s h a v e re tu r n e d , th e th r e a d is te rm in a te d . P th r e a d s c le a n u p h a n d le r s a r e d e s ig n e d so t h a t y o u c a n o fte n u s e th e c le a n u p h a n d le r ev en w h e n th e th r e a d w a s n ’t c a n c e le d . It is o ften u s e fu l to r u n th e s a m e c le a n u p fu n c tio n re g a rd le s s of w h e th e r y o u r co d e is c a n c e le d o r c o m p le te s n o rm a lly. W h e n p th r e a d _ c le a n u p _ p o p is called w ith a n o n z e ro v a lu e , th e c le a n u p h a n d le r is e x e c u te d ev en if th e th r e a d w a s n o t ca n c e le d . You c a n n o t p u s h a c le a n u p h a n d le r in o n e fu n c tio n a n d p o p it in a n o th e r fu n c tio n . T h e pthread_cleanup_push a n d pthread_cleanup_pop o p e ra tio n s m a y b e d efin ed a s m a c ro s, s u c h th a t pthread_cleanup_push c o n ta in s th e o p e n in g b ra c e “{” of a block, w hile pthread_cleanup_pop c o n ta in s th e m a tc h in g clo sin g b ra c e o f th e blo ck . You m u s t alw ay s k e e p th is re s tric tio n in m in d w h ile u s in g c le a n u p h a n d le rs , if y o u w ish y o u r co d e to b e p o rta b le . T h e follow ing p ro g ra m , c a n c e l _ c l e a n u p .c , sh o w s th e u s e of a c le a n u p h a n d le r to re le a s e a m u te x w h e n a c o n d itio n v a ria b le w a it is c a n c e le d . T h e c o n tro l s tr u c t u r e (control) is u s e d b y all th r e a d s to m a in ta in s h a r e d sy n c h ro n iz a tio n o b je c ts a n d in v a ria n ts . E a c h th r e a d in c re a s e s th e m e m b e r counter b y o n e w h e n it s ta r ts , a n d d e c re a s e s it a t te rm in a tio n . T h e m e m b e r b u sy is u s e d a s a d u m m y c o n d itio n w a it p re d ic a te —it is in itia lize d to 1, a n d n e v e r cle a re d , w h ic h m e a n s t h a t th e c o n d itio n w a it lo o p s w ill n e v e r te rm in a te (in th is exam ple) u n til th e th r e a d s a r e c a n c e le d . T h e fu n c tio n cleanup_handler is in s ta lle d a s th e c a n c e lla tio n c le a n u p h a n d le r for e a c h th re a d . It is called o n n o rm a l te rm in a tio n a s w ell a s th r o u g h c a n c e lla tio n , to d e c re a s e th e c o u n t o f activ e th r e a d s a n d u n lo c k th e m u te x . T h e fu n c tio n thread_routine e s ta b lis h e s cleanup_handler a s th e activ e c a n c e lla tio n c le a n u p h a n d le r. W ait u n til th e control s tr u c t u r e ’s busy m e m b e r is s e t to 0, w h ic h , in th is ex am p le, will n e v e r o ccu r. T h e c o n d itio n w a it loop will ex it o n ly w h e n th e w a it is ca n c e le d . A lth o u g h th e c o n d itio n w a it loop in th is e x a m p le w ill n o t ex it, th e fu n c tio n c le a n s u p b y rem o v in g th e activ e c le a n u p h a n d le r. T h e n o n z e ro a r g u m e n t to p th r e a d _ c le a n u p _ p o p , re m e m b e r, m e a n s t h a t th e c le a n u p h a n d le r w ill b e called ev en th o u g h c a n c e lla tio n d id n o t o ccu r. In so m e c a s e s , y o u m a y o m it “u n r e a c h a b le s ta t e m e n t s ” like th is pthread_ cleanup_pop call. H owever, in th is c a se , y o u r co d e m ig h t n o t co m p ile w ith o u t it. T h e pthread__cleanup_push a n d pthread_cleanup_pop m a c ro s a re sp e c ia l, a n d m a y e x p a n d to fo rm , resp ectiv ely , th e b e g in n in g a n d e n d in g of a b lo ck . D igital

156

CH A P T E R 5

A d va n c e d t h r ea d ed p r og r a m m in g

UNIX d o e s th is , fo r ex am p le, to im p le m e n t c a n c e lla tio n o n to p o f th e co m m o n s tr u c tu r e d e x c e p tio n h a n d lin g p ro v id ed b y th e o p e ra tin g s y ste m . ■

cancel_cleanup.c

!include !include "errors.h" !define THREADS 5

/* * Control structure shared by the test threads, containing * the synchronization and invariant data.

*/

9 10

11 12

13 14 15 16 17 18 19

typedef struct control_tag { int counter, busy; pthread_mutex__t mutex; pthread_cond_t cv; } control_t; control_t control = {0, 1, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};

/* * This routine is installed as the cancellation cleanup * handler around the cancelable condition wait. It will * be called by the system when the thread is canceled.

20 21

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

*/ void cleanup_handler (void *arg)

{ control_t *st = (control_t *)arg; int status; st->counter— ; printf ("cleanup_handler: counter == %d\n", st->counter); status = pthread_mutex_unlock (&st->mutex); if (status != 0) err_abort (status, ,’Unlock in cleanup handler");

} /* * * * * *

Multiple threads are created running this routine (controlled by the THREADS macro). They maintain a "counter" invariant, which expresses the number of running threads. They specify a nonzero value to pthread_cleanup_pop to run the same "finalization" action when cancellation does not occur.

*/ void *thread_routine

{ int status;

(void *arg)

157

Ca n c el l a t i o n

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

67 68

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

pthread_cleanup_push

status = pthread_mutex_lock (fccontrol.mutex); if (status != 0) err_abort (status, "Mutex lock” ); cont r o l .counter++; while (control.busy) { status = pthread_cond_wait (&control.cv, &control.mutex); if (status != 0) err_abort (status, "Wait on condition");

} pthread_cleanup_pop (1); return NULL;

} int main

(int argc, char *argv[])

{ pthread_t t h read_id[T H R E A D S]; int count; void *result; int status; for (count = 0; count < THREADS; count++) { status = pthread_create ( &thread_id[c o u n t ], NULL, thread_routine, NULL); if (status I= 0) err_abort (status, "Create thread");

} sleep (2); for (count = 0; count < THREADS; count++) { status = pthread_cancel (thread_id[count]); if (status 1= 0) err_abort (status, "Cancel thread"); status = pthread__join (thread_id[count], &result); if (status != 0) err_abort (status, "Join thread"); if (result == PTHREAD__CANCELED) printf ("thread %d canceled\n", count); else printf ("thread %d was not canceled\n", count);

86

87 88

89 90 91 92 93 94

(cleanup_handler, (v o i d * )&control);

} return 0;

cancel_cleanup.c

158

9-12

18-25

31-46

53-76

78-104

A d va n c e d t h r ea d ed p r o g r a m m i n g

If o n e of y o u r th r e a d s c r e a te s a s e t of th r e a d s to “s u b c o n tr a c t” so m e fu n c tio n , say , a p a ra lle l a rith m e tic o p e ra tio n , a n d th e “c o n tra c to r ” is c a n c e le d w h ile th e fu n c tio n is in p ro g re s s , y o u p ro b a b ly w o n ’t w a n t to leave th e s u b c o n tr a c to r th r e a d s r u n n in g . In s te a d , y o u co u ld “p a s s o n ” th e c a n c e lla tio n to e a c h s u b c o n tr a to r th re a d , le ttin g th e m h a n d le th e ir ow n te rm in a tio n in d e p e n d e n tly . If y o u h a d o rig in ally in te n d e d to jo in w ith th e s u b c o n tr a c to r s , re m e m b e r th a t th e y will c o n tin u e to c o n s u m e so m e re s o u rc e s u n til th e y h a v e b e e n jo in e d or d e ta c h e d . W h e n th e c o n tra c to r th re a d c a n c e ls th e m , y o u s h o u ld n o t d e la y c a n c e lla tio n b y jo in in g w ith th e s u b c o n tr a c to r s . In s te a d , y o u c a n c a n c e l e a c h th re a d a n d im m e d ia te ly d e ta c h it u s in g p th r e a d _ d e ta c h . T h e s u b c o n tr a c to r re s o u rc e s c a n th e n b e recy cled im m e d ia te ly a s th e y fin ish , w h ile th e c o n tra c to r c a n w ra p th in g s u p in d e p e n d e n tly . T h e follow ing p ro g ra m , cancel_subcontract .c, sh o w s o n e w ay to p ro p a g a te c a n c e lla tio n to s u b c o n tr a c to r s . T h e te a m _ t s tr u c t u r e d e fin e s th e s ta te of th e te a m o f s u b c o n tr a c to r th re a d s . T h e j o i n _ i m e m b e r re c o rd s th e in d e x o f th e la s t s u b c o n tr a c to r w ith w h ic h th e c o n tra c to r h a d jo in e d , so o n c a n c e lla tio n fro m w ith in p t h r e a d _ j o i n , it c a n c a n c e l th e th r e a d s it h a d n o t y e t jo in e d . T h e w o rk e rs m e m b e r is a n a r r a y re c o rd in g th e th r e a d id e n tifie rs o f th e s u b c o n tr a c to r th r e a d s . T h e s u b c o n tr a c to r th r e a d s a re s ta r te d r u n n in g th e w o r k e r _ r o u tin e fu n c tio n . T h is fu n c tio n lo o p s u n til c a n c e le d , callin g p t h r e a d _ t e s t c a n c e l ev ery 1000 ite ra tio n s . T h e c le a n u p fu n c tio n is e s ta b lis h e d a s th e activ e c le a n u p h a n d le r w ith in th e c o n tra c to r th r e a d . W h e n th e c o n tra c to r is c a n c e le d , c le a n u p ite r a te s th r o u g h th e re m a in in g (u n jo in ed ) s u b c o n tra c to rs , c a n c e llin g a n d d e ta c h in g e a c h . N ote th a t it d o e s n o t jo in th e s u b c o n tr a c to r s —in g e n e ra l, it is n o t a good id e a to w a it in a c le a n u p h a n d le r. T h e th re a d , a fte r all, is ex p ec ted to c le a n u p a n d te rm in a te , n o t to w a it a r o u n d fo r s o m e th in g to h a p p e n . B u t if y o u r c le a n u p h a n d le r re a lly n e e d s to w a it fo r s o m e th in g , d o n ’t b e a fra id , it w ill w o rk j u s t fine. T h e c o n tra c to r th re a d is s ta rte d ru n n in g thread_routine. T h is fu n c tio n c re a te s a s e t of s u b c o n tr a c to r s , th e n jo in s w ith e a c h s u b c o n tra c to r. A s it jo in s e a c h th r e a d , it re c o rd s th e c u r r e n t in d e x w ith in th e workers a r r a y in th e team_t m em b e r join_i. T h e c le a n u p h a n d le r is e s ta b lis h e d w ith a p o in te r to th e te a m s tr u c t u r e so t h a t it c a n d e te rm in e th e la s t o ffset a n d b e g in c a n c e llin g th e re m a in in g s u b c o n tr a c to r s . T h e m a in p ro g ra m c re a te s th e c o n tra c to r th r e a d , r u n n in g t h r e a d _ r o u t i n e , a n d th e n s le e p s for five se c o n d s . W h e n it w a k e s u p , it c a n c e ls th e c o n tra c to r th r e a d , a n d w a its for it to te rm in a te . |

1 2 3 4

CH A P T E R 5

cancel_subcontract.c

!include !include ,,errors.h" !define THREADS 5

159

Ca n c el l a t i o n

/* 7

* Structure that defines the threads in a "team."

8 9 10 11

12

13 14 15 16 17 18 19

*/ typedef struct team_tag { int join_i; pthread_t w o r k e r s [THR E A D S ]; > team_jt;

/* join index */ /* thread identifiers */

/* * Start routine for worker t h r e a d s . They loop waiting for a * cancellation request.

*/ void *worker_routine

(void *arg)

{ int counter;

20 21

for (counter = 0 ; ; counter++) if ((counter % 1000) == 0) pthread_testcancel ();

22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

> /* * Cancellation cleanup handler for the contractor thread. * will cancel and detach each worker in the team.

It

*/ void cleanup (void *arg)

{ team_t *team = (team_t *)arg; int count, status; for (count = team->join_i; count < THREADS; count++) status = pthread__cancel (team->workers[count ]); if (status 1= 0) err_abort (status, "Cancel w o r k e r ” );

{

status = pthread_detach (team->workers[c o u n t ]); if (status != 0) err_abort (status, "Detach w o r k e r ” ); printf (”Cleanup: canceled %d \ n ", count);

} } /* * Thread start routine for the contractor. It creates a team of * worker threads, and then joins with them. When canceled, the * cleanup handler will cancel and detach the remaining threads.

*/ void *thread_routine

(void *arg)

160

CH A P T E R 5

A d va n c e d t h r ea d ed p r o g r a m m i n g

54

team_t team; int count; void *result; int status;

55 56 57 58

/* team info */ /* Return status */

59

for (count = 0; count < THREADS; count++) { status = pthread_create ( &team.workers[c o u n t ], NULL, worker__routine, NULL); if (status != 0) err_abort (status, ”Create worker");

60 61 62 63 64 05

}

66

pthread_cleanup_push (cleanup,

(void*)Steam);

67

68

71

for (team.join_i = 0; team.join_i < THREADS; team.join_i++) { status = pthread_join (team.workers[team.join_i], Sresult); if (status != 0) err_abort (status, "Join worker");

72

}

69 70

73

pthread_cleanup_pop return NULL;

74 75 76

(0);

}

77 78

int main (int argc, char *argv[])

79

{

80 81

pthread_t thread_id; int status;

82 83

#ifdef sun

84

/*

85

86 87

88 89 90 91 92 93 94 95 96 97 98 99

100

* * * *

On Solaris 2.5, threads are not timesliced. To ensure that our threads can run concurrently, we need to increase the concurrency level to at least 2 plus THREADS (the number of workers).

*/ DPRINTF (("Setting concurrency level to %d\n", THREADS+2)); thr__setconcurrency (THREADS+2); #endif status = pthread_create (sthread_id, NULL, thread_routine, NULL); if (status 1= 0) err_abort (status, "Create team"); sleep (5); printf ("Cancelling...\ n " ); status = pthread_cancel (thread_id); if (status != 0) err abort (status, "Cancel team");

T h r e a d -s p e c i f i c d a t a

101 102 103 104

161

status = pthread_join (thread_id, NULL); if (status ! = 0 ) err_abort (status, "Join team"); } ■

cancel_subcontract.c

5.4 T h re a d -s p e c ific d a ta N o, I ’v e m a d e u p m y m in d a b o u t it: if Vm M a b e l, I ’ll s ta y d o w n h e re . It ’ll b e n o use th eir p u ttin g their h e a d s d o w n a n d s a y in g ,,C o m e u p a g a in , d e a r !” i s h a ll o n ly lo o k u p a n d s a y ,,W ho a m I, th en? Tell m e th a t first, a n d then, if I lik e b e in g th a t p erso n , I ’ll c o m e up: if not, I ’ll s ta y d o w n h e re till i ’m s o m e b o d y e ls e .”

—Lewis Carroll, Alice's Adventures in Wonderland

W h e n a fu n c tio n in a sin g le th r e a d e d p ro g ra m n e e d s to c re a te p riv a te d a ta t h a t p e r s is ts a c ro s s c a lls to t h a t fu n c tio n , th e d a ta c a n b e a llo c a te d s ta tic a lly in m em o ry . T h e n a m e ’s s c o p e c a n b e lim ited to th e fu n c tio n o r file t h a t u s e s it (static) o r it c a n b e m a d e g lo b al (extern). It is n o t q u ite th a t sim p le w h e n y o u u s e th r e a d s . All th r e a d s w ith in a p ro c e s s s h a r e th e s a m e a d d r e s s sp a c e , w h ic h m e a n s t h a t a n y v a ria b le d e c la re d a s static o r extern, o r in th e p ro c e s s h e a p , m a y b e re a d a n d w ritte n b y all th r e a d s w ith in th e p ro c e s s . T h a t h a s s e v e ra l im p o r ta n t im p lic a tio n s for co d e t h a t w a n ts to sto re “p e r s is te n t” d a ta b e tw e e n a s e rie s of fu n c tio n c a lls w ith in a th re a d : •



T h e v a lu e in a static o r extern v a ria b le , o r in th e h e a p , w ill b e th e v a lu e la s t w ritte n b y a n y th re a d . In so m e c a s e s th is m a y b e w h a t y o u w a n t, for e x am p le, to m a in ta in th e se e d of a p s e u d o ra n d o m n u m b e r s e q u e n c e . In o th e r c a s e s , it m a y n o t b e w h a t y o u w a n t. T h e o n ly sto ra g e a th r e a d h a s t h a t ’s tru ly “p riv a te ” a re p ro c e s s o r re g is te rs. E v en s ta c k a d d r e s s e s c a n b e s h a re d , a lth o u g h o n ly if th e “o w n e r” d e lib e ra te ly e x p o se s a n a d d r e s s to a n o th e r th re a d . In a n y ev en t, n e ith e r re g is te rs n o r “p riv a te ” s ta c k c a n re p la c e u s e s of p e r s is te n t s ta tic s to ra g e in n o n th r e a d e d code.

So w h e n y o u n e e d a p riv a te v a ria b le , y o u m u s t firs t d ecid e w h e th e r all th r e a d s s h a r e th e s a m e v a lu e , o r w h e th e r e a c h th r e a d s h o u ld h a v e its ow n v a lu e . If th e y s h a re , th e n y o u c a n u s e static o r extern d a ta , j u s t a s y o u co u ld in a sin g le th r e a d e d p ro g ra m ; how ever, y o u m u s t s y n c h ro n iz e a c c e s s to th e s h a r e d d a ta a c ro s s m u ltip le th r e a d s , u s u a lly b y a d d in g o n e o r m o re m u te x e s . If e a c h th r e a d n e e d s its ow n v a lu e for a p riv a te v a ria b le , th e n y o u m u s t sto re all th e v a lu e s so m e w h e re , a n d e a c h th r e a d m u s t b e a b le to lo c a te th e p ro p e r v a lu e . In so m e c a s e s y o u m ig h t b e ab le to u s e s ta tic d a ta , for ex am p le, a ta b le

162

CH A P T E R 5

A d va n c ed t h r ea ded pr ogr a m m in g

w h e re y o u c a n s e a r c h for a v a lu e u n iq u e to e a c h th r e a d , s u c h a s th e th r e a d ’s p t h r e a d _ t . In m a n y in te re s tin g c a s e s y o u c a n n o t p re d ic t h o w m a n y th r e a d s m ig h t call th e fu n c tio n —im a g in e y o u w ere im p le m e n tin g a th re a d -s a fe lib ra ry t h a t co u ld b e called b y a r b itra ry code, in a n y n u m b e r of th re a d s . T h e m o s t g e n e ra l s o lu tio n is to m a llo c so m e h e a p in e a c h th r e a d a n d s to re th e v a lu e s th e re , b u t y o u r co d e will n e e d to b e a b le to find th e p ro p e r p riv a te d a ta in a n y th r e a d . You co u ld c re a te a lin k e d lis t of all th e p riv a te v a lu e s, s to rin g th e erea tin g th r e a d ’s id e n tifie r ( p th r e a d _ t) so it co u ld b e fo u n d a g a in , b u t t h a t w ill b e slo w if th e re a re m a n y th r e a d s . You n e e d to s e a r c h th e lis t to fin d th e p ro p e r v a lu e , a n d it w o u ld b e d ifficu lt to reco v e r th e s to ra g e t h a t w a s a llo c a te d b y te rm in a te d th r e a d s —y o u r fu n c tio n c a n n o t k n o w w h e n a th r e a d te rm in a te s . I

N e w in te r fa c e s s h o u ld n o t re ly o n im p lic it p e rs is te n t s to ra g e !

W h e n y o u a re d e sig n in g n ew in te rfa c e s , th e r e ’s a b e tte r s o lu tio n . You s h o u ld re q u ire th e c a lle r to a llo c a te th e n e c e s s a ry p e r s is te n t s ta te , a n d tell y o u w h ere it is. T h e re a re m a n y a d v a n ta g e s to th is m o d el, in c lu d in g , m o s t im p o rta n tly : •



In m a n y c a s e s , y o u c a n avoid in te r n a l s y n c h ro n iz a tio n u s in g th is m odel, a n d , in ra r e c a s e s w h e re th e c a lle r w is h e s to s h a r e th e p e r s is te n t s ta te b e tw e e n th r e a d s , th e c a lle r c a n s u p p ly th e n e e d e d s y n c h ro n iz a tio n . T h e c a lle r c a n in s te a d c h o o se to a llo c a te m o re t h a n o n e s ta te b u ffe r for u s e w ith in a sin g le th re a d . T h e r e s u lt is s e v e ra l in d e p e n d e n t s e q u e n c e s of ca lls to y o u r f u n c tio n w ith in th e s a m e th re a d , w ith n o conflict.

T h e p ro b le m is t h a t y o u o ften n e e d to s u p p o r t im p licit p e r s is te n t s ta te s . You m a y b e m a k in g a n e x istin g in te rfa c e th re a d -s a fe , a n d c a n n o t a d d a n a r g u m e n t to th e fu n c tio n s , o r re q u ire t h a t th e c a lle r m a in ta in a n e w d a ta s tr u c tu r e for y o u r b e n e fit. T h a t’s w h e re th re a d -s p e c ific d a ta co m e s in . T h re a d -sp e c ific d a ta allo w s e a c h th r e a d to h a v e a s e p a r a te co p y of a v a ria b le , a s if e a c h th r e a d h a s a n a r r a y of th re a d -sp e c ific d a ta v a lu e s, w h ic h is in d e x e d b y a c o m m o n “k ey ” v a lu e . Im ag in e th a t th e b a ilin g p ro g ra m m e rs a re w e a rin g th e ir c o rp o ra te ID b a d g e s , c lip p e d to th e ir s h ir t p o c k e ts (F ig ure 5.2). W hile th e in fo rm a tio n is d iffe re n t for e a c h p ro g ra m m e r, y o u c a n fin d th e in fo rm a tio n easily w ith o u t a lre a d y k n o w in g w h ic h p ro g ra m m e r y o u ’re ex a m in in g . T h e p ro g ra m c r e a te s a ke y (so rt of like p o s tin g a c o rp o ra te re g u la tio n t h a t em p lo y ee id e n tific a tio n b a d g e s alw ay s be d isp la y e d c lip p e d to th e left b r e a s t p o c k e t of th e em p lo y ee’s s h ir t o r ja c k e t) a n d e a c h th r e a d c a n th e n in d e p e n d e n tly s e t o r g e t its ow n v a lu e for t h a t k ey (a lth o u g h th e b a d g e is a lw ay s o n th e left p o c k e t, e a c h em p lo y ee h a s a u n iq u e b a d g e n u m b e r, a n d , in m o s t c a s e s , a u n iq u e n am e). T h e ke y is th e s a m e for all th r e a d s , b u t e a c h th r e a d c a n a s s o c ia te its ow n in d e p e n d e n t v a lu e w ith t h a t s h a r e d key. E a c h th r e a d c a n c h a n g e its p riv a te v a lu e for a k ey a t a n y tim e, w ith o u t affectin g th e k e y o r a n y v a lu e o th e r th r e a d s m a y h a v e for th e key.

163

T h r e a d -s p e c i f i c d a t a

5.4.1

C re a tin g th re a d -s p e c ific d a ta

p th re a d _ k e y _ t k e y ; i n t p th re a d _ k e y _ _ c re a te p th re a d ^ J c e y _ t in t

*k e y ,

p th r e a d _ k e y _ d e le t©

( v o id

(* d fe s tr u c to r )(v o id

*));

( p th re a d _ k e y _ _ t k e y ) ;

A th re a d -s p e c ific d a ta k ey is r e p r e s e n te d in y o u r p ro g ra m b y a v a ria b le of ty p e pthread_key_t. Like m o s t P th r e a d s ty p e s, pthread_key_t is o p a q u e a n d y o u

s h o u ld n e v e r m a k e a n y a s s u m p tio n s a b o u t th e s tr u c t u r e o r c o n te n t. T h e e a s ie s t w ay to c re a te a th re a d -s p e c ific d a t a k ey is to call pthread_key__create b efo re a n y th r e a d s tr y to u s e th e key , fo r e x a m p le e a rly in th e p ro g ra m ’s main fu n c tio n . If y o u n e e d to c re a te a th re a d -s p e c ific d a t a k ey la te r, y o u h a v e to e n s u r e t h a t pthread_key__create is called o n ly o n c e for e a c h pthread_key_t v a ria b le . T h a t’s b e c a u s e if y o u c re a te a k ey tw ice, y o u a r e re a lly c re a tin g tw o d iffe re n t k ey s. T h e s e c o n d k ey will ov erw rite th e first, w h ic h w ill b e lo s t forev er alo n g w ith th e v a lu e s a n y th r e a d s m ig h t h a v e s e t for th e firs t key. W h e n y o u c a n ’t a d d co d e to main, th e e a s ie s t w ay to e n s u r e t h a t a th re a d specific d a ta k ey is c re a te d only o n c e is to u s e pthread_once, th e o n e -tim e in itializ a tio n fu n c tio n , a s s h o w n in th e follow ing p ro g ram , tsd_once.c.

164

19-27 33-56



tsd_once.c

!include !include "errors.h" /* * Structure used as the value for thread-specific data key.

6 7 8 9 10

A d va n c e d t h r ea d ed p r o g r a m m i n g

T h e t s d j t s tr u c t u r e is u s e d to c o n ta in p e r - th r e a d d a ta . E a c h th r e a d a llo c a te s a p riv a te tsd_t s tr u c tu r e , a n d s to re s a p o in te r to t h a t s tr u c t u r e a s its v a lu e for th e th re a d -s p e c ific d a t a k ey tsd_key. T h e thread_id m e m b e r h o ld s th e th r e a d ’s id e n tifie r (pthread_t), a n d th e string m e m b e r h o ld s th e p o in te r to a “name** s trin g for th e th re a d . T h e v a ria b le tsd_key h o ld s th e th re a d -sp e c ific d a ta key u s e d to a c c e s s th e tsd_t s tr u c tu r e s . O n e -tim e in itia liz a tio n (pthread_once) is u s e d to e n s u r e t h a t th e k ey tsd_key is c re a te d b efo re th e firs t a c c e s s . T h e th r e a d s b e g in in th e th r e a d s t a r t fu n c tio n thread_routine. T h e a rg u m e n t (arg) is a p o in te r to a c h a r a c te r s tr in g n a m in g th e th re a d . E a c h th r e a d c alls pthread_once to e n s u r e t h a t th e th re a d -s p e c ific d a t a k ey h a s b e e n c re a te d . T h e th r e a d th e n a llo c a te s a tsd_t s tr u c tu r e , in itia liz e s th e thread_id m e m b e r w ith th e th r e a d ’s id en tifier, a n d co p ie s its a r g u m e n t to th e string m em b er. T h e th r e a d g e ts th e c u r r e n t th re a d -sp e c ific d a ta v a lu e b y callin g p th r e a d _ g e t s p e c i f i c , a n d p r in ts a m e s s a g e u s in g th e th r e a d ’s n a m e . It th e n s le e p s for a few s e c o n d s a n d p r in ts a n o th e r m e s s a g e to d e m o n s tr a te th a t th e th re a d -sp e c ific d a t a v a lu e r e m a in s th e s a m e , ev en th o u g h a n o th e r th r e a d h a s a s s ig n e d a differe n t t s d _ t s tr u c t u r e a d d r e s s to th e s a m e th re a d -sp e c ific d a t a key.

7-10

1 2 3 4 5

CHA P T E R 5

*/ typedef struct tsd_tag { pthread__t thread_id; char *string; } tsd_t;

11 12 13 14 15 16 17 18 19

pthread_key_t tsd_key; /* Thread-specific data key */ pthread_once_t key_once = PTHREAD_ONCE_INIT; /* * One-time initialization routine used with the pthread_once * control block. */ void once_routine (void)

20

{

21

int status;

22 23 24 25 26 27

printf (,,initializing k e y \ n " ); status = pthread_key_create (&tsd__key, NULL); if (status != 0) err__abort (status, ‫ ״‬Create key"); }

T h r e a d -s p e c i f i c d a t a

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

/* * Thread start routine that uses pthread_once to dynamically * create a thread-specific data key.

*/ void *thread_routine (void *arg)

{ tsd_t *value; int status; status = pthread_once (&key_once, once_routine); if (status != 0) err_abort (status, "Once in i t ” ); value = (tsd_t*)malloc (sizeof (tsd_t)); if (value == NULL) errno_abort ("Allocate key v a l u e " ); status = pthread_setspecific (tsd_key, value); if (status 1= 0) err_abort (status, "Set t s d " ); printf ("%s set tsd value %p\n", arg, value); value->thread_id = pthread_self (); value->string = (char*)arg; value = (tsd_t*)pthread_getspecific (tsd_key); printf ("%s starting...\ n " , value->string); sleep (2); value = (tsd_t*)pthread_getspecific (tsd_key); printf ("%s done...\n", value->string); return NULL;

> void main (int argc, char *argv[])

{ pthread_t threadl, thread2; int status; status = pthread_create ( &threadl, NULL, thread__routine, "thread 1"); if (status 1= 0) err_abort (status, "Create thread 1"); status = pthread_create ( &thread2, NULL, thread_routine, "thread 2"); if (status 1= 0) err_abort (status, "Create thread 2"); pthread__exit (NULL);

66 67

68 69 70 71 72 ■

> tsd_once.c

165

166

CH A P T E R 5

A d va n c e d t h r ea d ed p r og r a m m in g

P th r e a d s allo w s y o u to d e s tro y a th re a d -s p e c ific d a ta k ey w h e n y o u r p ro g ra m n o lo n g e r n e e d s it, b y callin g p t h r e a d _ k e y _ d e le te . T h e P th r e a d s s ta n d a r d g u a ra n te e s o n ly 128 th re a d -sp e c ific d a ta k e y s a t a n y o n e tim e, so it m a y b e u s e fu l to d e s tro y a k ey t h a t y o u k n o w y o u a r e n ’t u s in g a n d w o n ’t n e e d a g a in . T h e a c tu a l n u m b e r of k e y s s u p p o r te d b y y o u r P th r e a d s s y s te m is sp ecified b y th e v a lu e of th e sy m b o l PTHRE AD__KE YS__MAX d efin e d in < l i m i t s .h > . W h en y o u d e s tro y a th re a d -s p e c ific d a ta key, it d o e s n o t affect th e c u r r e n t v a lu e of t h a t k ey in a n y th re a d , n o t ev en in th e c allin g th re a d . T h a t m e a n s y o u r co d e is c o m p lete ly re s p o n s ib le for freein g a n y m e m o iy t h a t y o u h a v e a s s o c ia te d w ith th e th re a d -s p e c ific d a ta key, in all th r e a d s . O f c o u rs e , a n y u s e of th e d eleted th re a d -s p e c ific d a ta k ey (pthread_key_t) r e s u lts in u n d e fin e d b eh av io r. D e le te t h r e a d - s p e c if ic d a t a keys o n ly w h e n y o u a r e s ure n o t h r e a d h a s a v a lu e fo r t h a t key! O r . . . d o n 't d e s tro y th e m a t all.

You s h o u ld n e v e r d e s tro y a k ey w hile so m e th r e a d still h a s a v a lu e for th a t key. S o m e la te r call to pthread_key_create, for e x am p le, m ig h t r e u s e th e pthread_key_t id e n tifie r th a t h a d b e e n a s s ig n e d to a d e le te d key. W h e n a n ex istin g th r e a d t h a t h a d s e t a v a lu e for th e old k ey r e q u e s ts th e v a lu e of th e n e w key, it will receiv e th e old v a lu e . T h e p ro g ra m w ill likely re a c t b a d ly to rece iv in g th is in c o rre c t d a ta , so y o u s h o u ld n e v e r d e le te a th re a d -sp e c ific d a t a k ey u n til y o u a re s u r e t h a t n o e x istin g th r e a d s h a v e a v a lu e for t h a t key, fo r e x am p le, b y m a in ta in in g a “re fe re n c e c o u n t” fo r th e key, a s s h o w n in th e p ro g ra m tsd_destructor .c. in S e c tio n 5 .4 .3 . E v en b e tte r, d o n ’t d e s tro y th re a d -sp e c ific d a ta k ey s. T h e re ’s ra re ly a n y n e e d to do so, a n d if y o u try y o u w ill a lm o s t c e rta in ly r u n in to d ifficu lties. Few p ro g ra m s w ill re q u ire ev en th e m in im u m P th r e a d s lim it o f 128 th re a d -sp e c ific d a ta keys. R arely w ill y o u u s e m o re th a n a few. In g e n e ra l, e a c h c o m p o n e n t t h a t u s e s th re a d -s p e c ific d a ta will h a v e a sm a ll n u m b e r o f k ey s e a c h m a in ta in in g p o in te rs to d a t a s tr u c t u r e s th a t c o n ta in re la te d d a ta . It w o u ld ta k e a lo t of c o m p o n e n ts to e x h a u s t th e a v a ila b le keys!

5 .4 .2

Using th re a d -s p e c ific d a ta

int pthr ead_s et spec ific ( pthread_key_t key, const void *value); void *pthread_getspecific (pthread_key_t key);

You c a n u s e th e pthread_getspecif ic fu n c tio n to d e te rm in e th e th r e a d ’s c u rr e n t v a lu e for a key, o r pthread_setspecif ic to c h a n g e th e c u r r e n t v a lu e . T a k e a lo o k a t S e c tio n 7 .3 .1 for id e a s o n u s in g th re a d -sp e c ific d a ta to a d a p t old lib ra rie s th a t rely o n s ta tic d a ta to b e th re a d -s a fe .

T h r e a d -s p e c i f i c d a t a

167

A t h r e a d - s p e c if ic d a t a v a lu e o f n u l l m e a n s s o m e th in g s p e c ia l t o P th re a d s — d o n o t s e t a t h r e a d - s p e c if ic d a t a v a lu e o f n u l l unless y o u re a lly m e a n it.

T h e in itia l v a lu e for a n y n e w k e y (in all th re a d s ) is n u l l . A lso, P th r e a d s s e ts th e th re a d -s p e c ific d a ta v a lu e for a k ey to n u l l b efo re callin g t h a t k e y ’s d e s tru c to r (p a s s in g th e p re v io u s v a lu e of th e key) w h e n a th r e a d te rm in a te s . If y o u r th re a d -s p e c ific d a ta v a lu e is th e a d d r e s s o f h e a p s to ra g e , for ex am p le, a n d y o u w a n t to free t h a t s to ra g e in y o u r d e s tru c to r, y o u m u s t u s e th e a r g u m e n t p a s s e d to th e d e s tr u c to r r a th e r th a n callin g p t h r e a d _ g e t s p e c i f ic . P th r e a d s w ill n o t call th e d e s tr u c to r for a th re a d -sp e c ific d a ta k ey if th e te rm in a tin g th r e a d h a s a v a lu e of n u l l for t h a t key. n u l l is sp e c ia l, m e a n in g “th is k ey h a s n o v a lu e .” If y o u ev er u s e p t h r e a d _ s e t s p e c i f i c to s e t th e v a lu e of a th re a d specific d a ta k ey to n u l l , y o u n e e d to re m e m b e r th a t y o u a re n o t s e ttin g th e v a lu e n u l l , b u t r a th e r s ta tin g t h a t th e k ey n o lo n g e r h a s a v a lu e in th e c u r r e n t th re a d .

I

D e s tru c to r fu n c tio n s a r e c a lle d o n ly w h e n t h e t h r e a d te r m in a te s , n o t w h e n t h e v a lu e o f a t h r e a d - s p e c if ic d a t a k e y is c h a n g e d .

A n o th e r im p o rta n t th in g to re m e m b e r is t h a t th re a d -sp e c ific d a ta k ey d e s tru c to r fu n c tio n s a re n o t ca lle d w h e n y o u re p la c e a n e x istin g v a lu e fo r t h a t key. T h a t is, if y o u a llo c a te a s t r u c t u r e in h e a p a n d a s s ig n a p o in te r to t h a t s tr u c t u r e a s th e v a lu e of a th re a d -sp e c ific d a ta key, a n d th e n la te r a llo c a te a n e w s tr u c tu r e a n d a s s ig n a p o in te r to th a t n e w s tr u c t u r e to th e s a m e th re a d -s p e c ific d a ta key, in th e s a m e th r e a d , y o u a re re s p o n s ib le for freein g th e old s tr u c tu r e . P th r e a d s will n o t free th e old s tr u c tu r e , n o r will it call y o u r d e s tr u c to r fu n c tio n w ith a p o in te r to th e old s tr u c tu r e .

5 .4 .3

Using d e s tru c to r fu n ctio n s W h e n a th r e a d e x its w h ile it h a s a v a lu e d efin e d fo r so m e th re a d -s p e c ific d a ta key, y o u u s u a lly n e e d to d o s o m e th in g a b o u t it. If y o u r k ey ’s v a lu e is a p o in te r to h e a p m e m o ry , y o u w ill n e e d to f r e e th e m e m o ry to avoid a m e m o ry le a k e a c h tim e a th r e a d te rm in a te s . P th r e a d s allo w s y o u to d efin e a d e s tru cto r fu n c tio n

* T h a t is , u n f o r t u n a t e ly , n o t w h a t t h e s t a n d a r d s a y s . T h is i s o n e o f t h e p r o b le m s w it h fo r m a l s ta n d a r d s — th e y s a y w h a t th e y s a y , n o t w h a t th e y w e r e in te n d e d to sa y . S o m e h o w , a n e r ro r c r e p t i n , a n d t h e s e n t e n c e s p e c i f y i n g t h a t “t h e i m p l e m e n t a t i o n c l e a r s t h e t h r e a d - s p e c i f i c d a t a v a l u e b e fo r e c a llin g t h e d e s tr u c to r " w a s d e le t e d . N o b o d y n o t ic e d , a n d t h e s t a n d a r d w a s a p p r o v e d w it h t h e e r r o r . S o t h e s t a n d a r d s a y s (b y o m is s io n ) t h a t if y o u w a n t to w r it e a p o r t a b le a p p lic a t io n u s i n g

pthread_setspecif ic w i t h i n y o u r d e s t r u c t o r f u n c t i o n t o c h a n g e t h e v a l u e t o null. T h i s w o u l d b e s i l l y , a n d a n y t h r e a d - s p e c if ic d a t a , t h a t w ill n o t h a n g o n t h r e a d t e r m in a t io n , y o u m u s t c a ll

s e r io u s im p le m e n t a t io n o f P t h r e a d s w ill v io la t e t h e s t a n d a r d in t h i s r e s p e c t . O f c o u r s e , t h e s t a n d a r d w ill b e fix e d , p r o b a b ly b y t h e 1 0 0 3 . I n a m e n d m e n t ( a s s o r t e d c o r r e c t io n s to 1 0 0 3 . l c - 1 9 9 5 ) , b u t t h a t w ill t a k e a w h ile .

168

w h e n

CH A P T E R 5

y o u

n o n -N U L L c a lle d

w ith

c r e a te v a lu e th e

a fo r

th r e a d -s p e c ific a

d a ta

th r e a d -s p e c ific

c u r r e n t v a lu e

o f th e

k e y .

d a ta

A d va n c e d t h r ea d ed p r og r a m m in g

W h e n

k e y ,

th e

a

th r e a d

k e y ’s

te r m in a te s

d e str u c to r

(if

w ith

a

a n y )

is

k e y .

I T h r e a d -s p e c ific d a t a d e s tru c to rs a r e c a lle d in " u n s p e c ifie d o rd e r."

P th r e a d s c h e c k s all th re a d -s p e c ific d a ta k e y s in th e p ro c e s s w h e n a th r e a d ex its, a n d fo r e a c h th re a d -sp e c ific d a ta k ey w ith a v a lu e t h a t ’s n o t n u l l , it s e ts th e v a lu e to n u l l a n d th e n c a lls th e k e y ’s d e s tr u c to r fu n c tio n . G oing b a c k to o u r an alo g y , so m e o n e m ig h t co lle ct th e id e n tity b a d g e s of all p ro g ra m m e rs b y rem ov in g w h a te v e r is h a n g in g fro m e a c h p ro g ra m m e r’s left s h ir t p o c k e t, sa fe in th e k n o w led g e t h a t it w ill a lw ay s b e th e p ro g ra m m e r’s b a d g e . Be ca re fu l, b e c a u s e th e o rd e r in w h ic h d e s tr u c to r s a re c a lled is u n d e fin e d . T ry to m a k e e a c h d e s tr u c to r a s in d e p e n d e n t a s p o ssib le . T h re a d -sp e c ific d a ta d e s tr u c to r s c a n s e t a n e w v a lu e for th e k ey for w h ic h a v a lu e is b e in g d e s tro y e d o r for a n y o th e r key. You s h o u ld n e v e r do th is directly, b u t it c a n ea sily h a p p e n in d ire c tly if y o u call o th e r f u n c tio n s fro m y o u r d e s tru c tor. F o r ex am p le, th e ANSI C lib ra ry ’s d e s tr u c to r s m ig h t b e c a lled b efo re y o u rs — a n d callin g a n ANSI C fu n c tio n , for ex am p le, u s in g f p r i n t f to w rite a log m ess a g e to a file, c o u ld c a u s e a n e w v a lu e to b e a s s ig n e d to a th re a d -sp e c ific d a ta key. T h e s y s te m m u s t re c h e c k th e lis t of th re a d -sp e c ific d a ta v a lu e s for y o u sifter all d e s tr u c to r s h a v e b e e n calle d .

I

lf y o u r th r e a d - s p e c if ic d a t a d e s tr u c to r c r e a te s a n e w t h r e a d - s p e c if ic d a t a v a lu e , y o u w ill g e t a n o t h e r c h a n c e . M a y b e t o o m a n y c h a n c e s !

T h e s ta n d a r d re q u ire s t h a t a P th r e a d s im p le m e n ta tio n m a y re c h e c k th e list so m e fixed n u m b e r of tim e s a n d th e n give u p . W h e n it gives u p , th e fin al th re a d sp ecific d a t a v a lu e is n o t d e s tro y e d . If th e v a lu e is a p o in te r to h e a p m e m o ry , th e r e s u lt m a y b e a m e m o ry le a k , so b e c a re fu l. T h e d i m i t s .h > h e a d e r d e fin e s _ p t h r e a d _ d e s t r u c t o r _ i t e r a t i o n s to th e n u m b e r o f tim e s th e s y s te m will ch ec k , a n d th e v a lu e m u s t b e a t le a s t 4. A lte rn a te ly , th e s y s te m is allo w ed to k eep c h e c k in g forever, so a d e s tr u c to r fu n c tio n t h a t a lw ay s s e ts th re a d -sp e c ific d a ta v a lu e s m a y c a u s e a n in fin ite loop. U su a lly , n e w th re a d -s p e c ific d a ta v a lu e s a re s e t w ith in a d e s tr u c to r o n ly w h e n s u b s y s te m 1 u s e s th re a d -sp e c ific d a ta t h a t d e p e n d s o n a n o th e r in d e p e n d e n t s u b s y s te m 2 t h a t a lso u s e s th re a d -sp e c ific d a ta . B e c a u se th e o rd e r in w h ic h d e s tr u c to r f u n c tio n s r u n is u n sp e c ifie d , th e tw o m a y b e called in th e w ro n g order. If th e s u b s y s te m 1 d e s tr u c to r n e e d s to call in to s u b s y s te m 2, it m a y in a d v e rte n tly r e s u lt in a llo c a tin g n e w th re a d -sp e c ific d a ta for s u b s y s te m 2. A lth o u g h th e s u b s y ste m 2 d e s tr u c to r will n e e d to b e called a g a in to free th e n e w d a ta , th e s u b s y s te m 1 th re a d -sp e c ific d a ta r e m a in s N U L L , s o th e loop w ill te rm in a te . T h e follow ing p ro g ra m , t s d _ d e s t r u c t o r .c , d e m o n s tr a te s u s in g th re a d sp ecific d a ta d e s tr u c to r s to re le a s e m e m o ry w h e n a th r e a d te rm in a te s . It a lso k e e p s tr a c k of h o w m a n y th r e a d s a re u s in g th e th re a d -s p e c ific d a ta , a n d d e le te s

T h r e a d -s p e c i f i c d a t a

169

th e th re a d -sp e c ific d a ta k ey w h e n th e d e s tr u c to r is r u n for th e fin al th re a d . T h is p ro g ra m is s im ila r in s tr u c t u r e to ts d _ o n c e .c , fro m S e c tio n 5 .3 , so o n ly th e relev a n t d iffe re n c e s will b e a n n o ta te d h e re . 12-14 In a d d itio n to th e k ey v a lu e (identity_key), th e p ro g ra m m a in ta in s a c o u n t of th r e a d s t h a t a re u s in g th e k ey (identity_key_counter), w h ic h is p ro te c te d b y a m u te x (identity_key_mutex). 22-42 T h e fu n c tio n identity_key_destructor is th e th re a d -s p e c ific d a ta k e y ’s d e s tr u c to r fu n c tio n . It b e g in s b y p rin tin g a m e s s a g e so w e c a n o b se rv e w h e n it r u n s in e a c h th re a d . It fre e s th e s to ra g e u s e d to m a in ta in th re a d -sp e c ific d a ta , th e private_t s tr u c tu r e . T h e n it lo c k s th e m u te x a s s o c ia te d w ith th e th re a d sp ecific d a ta k ey (identity_key_mutex) a n d d e c re a s e s th e c o u n t of th r e a d s u s in g th e key. If th e c o u n t re a c h e s 0, it d e le te s th e k ey a n d p r in ts a m e ss a g e . 48-63 T h e fu n c tio n identity_key_get c a n b e u s e d a n y w h e re (in th is e x am p le, it is u s e d o n ly o n c e p e r th re a d ) to g e t th e v a lu e o f identity_key fo r th e c a llin g th re a d . If th e re is n o c u r r e n t v a lu e (the v a lu e is NULL), th e n it a llo c a te s a n e w private_t s tr u c tu r e a n d a s s ig n s it to th e k ey for f u tu r e re feren c e. 68-78 T h e fu n c tio n thread_routine is th e th r e a d s t a r t fu n c tio n u s e d b y th e ex am pie. It a c q u ire s a v a lu e for th e k ey b y callin g identity_key_get, a n d s e ts th e m e m b e rs of th e s tr u c tu r e . T h e string m e m b e r is s e t to th e th r e a d ’s a rg u m e n t, c re a tin g a g lo bal “n a m e ” for th e th re a d , w h ic h c a n b e u s e d fo r p rin tin g m e ss a g e s . 80-114 T h e m a in p ro g ra m c re a te s th e th re a d -sp e c ific d a ta k ey tsd_key. N otice th a t, u n lik e tsd_ o n c e .c, th is p ro g ra m d o e s n o t b o th e r to u s e pthread_once. A s I m e n tio n e d in th e a n n o ta tio n for th a t ex am p le, in a m a in p ro g ra m it is p e rfe c tly safe, a n d m o re efficient, to c re a te th e k ey in s id e main, b efo re c re a tin g a n y th r e a d s . 101 T h e m a in p ro g ra m in itia liz e s th e re fe re n c e c o u n te r (identity_key_counter) to 3. It is c ritic a l t h a t y o u d efin e in a d v a n c e h o w m a n y th r e a d s w ill re fe re n c e a k ey t h a t will b e d e le te d b a s e d o n a re fe re n c e c o u n t, a s w e in te n d to do. T h e c o u n te r m u s t b e s e t b efo re a n y th r e a d u s in g th e k ey c a n p o ssib ly te rm in a te . You c a n n o t, for ex am p le, co d e identity_key_get so th a t it d y n a m ic a lly in c re a s e s th e c o u n te r w h e n it firs t a s s ig n s a th re a d -s p e c ific v a lu e for identity^ key. T h a t is b e c a u s e o n e th r e a d m ig h t a s s ig n a th re a d -s p e c ific v a lu e for identity_key a n d th e n te rm in a te b efo re a n o th e r th r e a d u s in g th e k ey h a d a c h a n c e to s ta r t. If t h a t h a p p e n e d , th e firs t th r e a d ’s d e s tr u c to r w o u ld find n o re m a in in g re fe re n c e s to th e key, a n d it w o u ld d e le te th e key. L a te r th r e a d s w o u ld th e n fail w h e n try in g to s e t th re a d -sp e c ific d a ta v a lu e s. ■

1 2 3 4 5

6

tsd_destructor.c

#include #include 1’errors, h" /* * Structure used as value of thread-specific data key.

*/

170

CH A P T E R 5

A d va n c ed t h r ea ded pr ogr a m m in g

typedef struct private_tag { pthread__t thread_id; char *string; > private_t;

13 14 15 16 17 18 19

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

pthread_key_t identity_key; /* Thread-specific data key */ pthread_mutex_t identity_key_mutex = PTHRE AD__MUTEX__I N ITIALIZER; long identity_key_counter = 0;

/* * * * *

This routine is called as each thread terminates with a value for the thread-specific data key. It keeps track of how many threads still have values, and deletes the key when there are no more references.

*/ void identity_key_destructor (void *value)

{ private_t *private = (private_t*)value; int status; printf ("thread \"%s\" exit i n g . ..\ n " , private->string); free (value); status = pthread_mutex_lock (&identity__key_mutex); if (status 1= 0) err_abort (status, "Lock key mutex"); identity_key_counter— ; if (identity_key__counter /* * Helper routine to allocate a new value for thread-specific * data key if the thread d o e s n ’t already have one.

*/ void *identity_key_get (void)

{ void *value; int status; value = pthread_getspecific

(identity_key);

171

T h r e a d -s p e c i f i c d a t a

57 58 59 60 61 62 63 64 65

if (value == NULL) { value = malloc (sizeof (private_t)); if (value == NULL) errno_abort ("Allocate key value"); status = pthread_setspecific (identity_key, (void*)value); if (status != 0) err_abort (status, "Set T S D M );

} return value;

> /*

66

* Thread start routine to use thread-specific data.

*/

67

68

void *thread_routine

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

{ private_t *value; value = (private_t*)identity_key_get (); value->thread_id = pthread_self (); value->string = (char*)arg; printf (”thread \ ”%s\" starting...\ n " , value->string); sleep (2); return NULL;

void main (int argc, char *argv[])

{ pthread_t thread_l, thre a d _ 2 ; private_t *value; int status;

86

/*

87

* * * * * *

88 89 90 91 92 93 94 95 96 97 98 99 100

(void *arg)

Create the TSD key, and set the reference counter to the number of threads that will use it (two thread_routine threads plus main). This must be done before creating the threads! Otherwise, if one thread runs the k e y ’s destructor before any other thread uses the key, it will be deleted.

* * Note that there's rarely any good reason to delete a * thread-specific data key.

*/ status = pthread_key_create ( &identity_key, identity_key_destructor); if (status != 0) err_abort (status, "Create key");

172

CH A P T E R 5

A d va n c e d t h r ea d ed p r o g r a m m i n g

identity_key__counter = 3; value = (private_t*)identity_key_get (); value->thread_id = pthread_j3elf ( ) ; value->string = "Main thread"; status = pthread_create (&thread_l, NULL, thread__routine, "Thread 1"); if (status != 0) err_abort (status, "Create thread 1"); status = pthread_create (&thread_2, NULL, thread_routine, "Thread 2"); if (status 1= 0) err_abort (status, "Create thread 2"); pthread_exit (NULL);

101 102

103 104 105 106 107 108 109 110 111

112

113 114

} ■

tsd_destructor.c

5.5 R e a ltim e s c h e d u lin g “Well, it’s n o use your ta lk in g a b o u t w a k in g h im ,” s a id T w e e d le d u m , “w h e n y o u ’re o n ly o n e o f th e things in his d re a m . You k n o w v e ry w e ll y o u ’re n o t r e a l.” “I a m r e a l!” s a id A lic e , a n d b e g a n to cry. “You w o ’n ’t m a k e y ou rself a b it r e a lle r b y c ry in g ,” T w e e d le d e e re m a r k e d : “th e r e ’s n o th in g to c ry a b o u t.” — ,L e w is C a r r o l T h r o u g h t h e L o o k in g -G ia s s

O n ce u p o n a tim e, re a ltim e p ro g ra m m in g w a s c o n s id e re d a n a r c a n e a n d ra re a rt. R ealtim e p ro g ra m m e rs w ere d o in g u n u s u a l th in g s , o u ts id e o f th e p ro g ra m m in g m a in s tre a m , like co n tro llin g n u c le a r re a c to rs o r a irp la n e n a v ig atio n a l sy ste m s. B u t th e POSIX. lb re a ltim e e x te n sio n d efin e s re a ltim e a s “th e ab ility of th e o p e ra tin g sy ste m to provid e a re q u ire d level of service in a b o u n d e d re s p o n s e tim e .” W h a t a p p lie s to th e o p e ra tin g sy ste m a lso a p p lie s to y o u r a p p lic a tio n o r lib rary . “B o u n d e d ” re s p o n s e tim e d o e s n o t n e c e s s a rily m e a n “f a s t” re s p o n s e , b u t it d o e s m e a n “p r e d ic ta b le ” re s p o n s e . T h e re m u s t b e so m e w ay to d efin e a s p a n of tim e d u rin g w h ic h a s e q u e n c e of o p e ra tio n s is g u a r a n te e d to co m p lete . A s y ste m c o n tro llin g a n u c le a r r e a c to r h a s m o re s tr ic t re s p o n s e re q u ire m e n ts th a n m o s t p ro g ra m s y o u w ill w rite, a n d c e rta in ly th e c o n s e q u e n c e s o f failin g to m e e t th e r e a c to r ’s re s p o n s e re q u ire m e n ts a re m o re sev ere. B u t a lo t o f co d e y o u w rite will n e e d to p ro v id e so m e “re q u ire d level o f se rv ic e ” w ith in so m e “b o u n d e d re s p o n s e tim e .” R ealtim e p ro g ra m m in g j u s t m e a n s t h a t th e so ftw a re lives in th e re a l w orld. R ealtim e p ro g ra m m in g co v ers s u c h a v a s t a r e a th a t it is c o m m o n to div ide it in to tw o s e p a r a te c a te g o rie s. “H a rd re a ltim e ” is th e tra d itio n a l s o r t m o s t p eo p le

R ea l t i m e sc h ed u l i n g

173

th in k of. W h e n y o u r n u c le a r r e a c to r will go c ritic a l if a fu el ro d a d ju s tm e n t is d e la y e d b y a m ic ro s e c o n d o r y o u r a irp la n e will c r a s h if th e n a v ig a tio n s y s te m ta k e s a h a lf se c o n d to re s p o n d to a w in d sh e e r, t h a t ’s h a rd realtim e. H a rd re a ltim e is un forgiv ing, b e c a u s e th e re q u ire d level o f serv ice a n d b o u n d e d re s p o n s e tim e a re d efin ed b y p h y s ic s o r so m e th in g e q u ally u n y ie ld in g . “Soft re a ltim e ” m e a n s th a t y o u n e e d to m e e t y o u r s c h e d u le m o s t of th e tim e, b u t th e c o n s e q u e n c e s of failing to m e e t th e s c h e d u le a re n o t sev ere. M an y s y s te m s t h a t in te r a c t w ith h u m a n s s h o u ld b e d e sig n e d a c c o rd in g to so ft re a ltim e p rin c ip le s. A lth o u g h h u m a n s r e a c t slow ly, in c o m p u te r te rm s , th e y ’re s e n s itiv e to re s p o n s e tim e. M ake y o u r u s e r s w a it too o fte n w h ile th e s c re e n re d ra w s b efo re a c c e p tin g th e n e x t m o u s e click, a n d th e y ’ll b e a n n o y e d . N obody lik e s a “b u s y c u r s o r ”—m o s t p eo p le e x p e c t re s p o n s e to b e a t le a s t p re d ic ta b le , e v en w h e n it c a n n o t b e fa st. T h re a d s a re u s e fu l for all ty p e s of re a ltim e p ro g ra m m in g , b e c a u s e c o d in g for p re d ic ta b le re s p o n s e is fa r e a s ie r w h e n y o u c a n k e e p th e o p e ra tio n s s e p a ra te . Y our “u s e r in p u t f u n c tio n ” d o e s n ’t h a v e to w a it for y o u r s o rt o p e ra tio n o r for y o u r s c re e n u p d a te o p e ra tio n b e c a u s e it e x e c u te s in d e p e n d e n tly . A chieving p re d ic ta b ility re q u ire s a lo t m o re th a n j u s t s e p a r a tin g o p e ra tio n s in to d iffe re n t th r e a d s , how ever. F o r o n e th in g , y o u n e e d to m a k e s u r e t h a t th e th r e a d y o u n e e d to r u n “s o o n ” w o n ’t b e left s ittin g o n a r u n q u e u e so m e w h e re w h ile a n o th e r th r e a d u s e s th e p ro c e sso r. M o st s y s te m s , b y d e fa u lt, w ill try to d istr ib u te re s o u r c e s m o re o r le s s fairly b e tw e e n th re a d s . T h a t’s n ic e fo r a lo t of th in g s —b u t re a ltim e i s n ’t fair. R e altim e m e a n s ca re fu lly giving p re c e d e n c e to th e p a r ts of th e p ro g ra m t h a t lim it e x te rn a l r e s p o n s e tim e.

5.5.1

PO SIX re a ltim e o p tio n s T h e POSIX s ta n d a r d s a re flexible, b e c a u s e th e y ’re d e sig n e d to b e u s e fu l in a w id e ra n g e of e n v iro n m e n ts . In p a rtic u la r, s in c e tra d itio n a l UNIX s y s te m s d o n ’t s u p p o r t a n y fo rm of re a ltim e s c h e d u lin g co n tro l, all o f th e to o ls fo r c o n tro llin g re a ltim e re s p o n s e a re o p tio n a l. T h e fa c t t h a t a giv en im p le m e n ta tio n o f UNIX “c o n fo rm s to 1 0 0 3 .1 c -1 9 9 5 ” d o e s n o t m e a n y o u c a n w rite p re d ic ta b le re a ltim e p ro g ra m s . If th e s y s te m d e fin e s _ p o s i x _ t h r e a d _ p r i o r i t y _ s c h e d u l i n g , it p ro v id e s s u p p o rt for a s s ig n in g re a ltim e s c h e d u lin g p rio ritie s to th r e a d s . T h e POSIX p rio rity s c h e d u lin g m o d el is a little m o re c o m p lic a te d t h a n th e tra d itio n a l UNIX p rio rity m odel, b u t th e p rin c ip le is sim ilar. P rio rity s c h e d u lin g allo w s th e p ro g ra m m e r to give th e s y s te m a n id e a of h o w im p o r ta n t a n y tw o th r e a d s a re , rela tiv e to e a c h o th e r. W h e n e v e r m o re th a n o n e th r e a d is re a d y to e x e c u te , th e s y s te m w ill ch o o se th e th r e a d w ith th e h ig h e s t p rio rity .

174

5 .5 .2

CH A P T E R 5

A d va n c ed t h r ea ded p r ogr a m m in g

S c h e d u lin g p o lic ie s a n d p rio rities

i n t s c h e d _ g e t_ p r io r ity _ m a x ( i n t p o l i c y ) ; i n t s c h e d _ g e t_ j> r i o r i ty _ m in ( i n t p o l i c y ) ; m t p th re a d _ d ttr_ g e tin h e rits c h e d ( c o n st p th r e a d _ a ttr _ t * a t tr , i n t * in h e rits c h e d ); in t p th re a d _ a ttr_ s e tin h e rits c h e d ( p th r e a d _ a ttr _ t * a t tr , i n t in h e rits c h e d ); i n t p th r e a d _ a t t r _ g e t s c h e d p a r a m ( co n st p th re a d ^ a ttr_ t * a ttr , s t r u c t s c h e d jp a ra m * p a ra m ); i n t p th r e a d _ a t t r _ s e t s c h e d p a r a m ( p th re a d _ a ttr_ t * a ttr , c o n s t s t r u c t s c h e d jp a ra m * p a ra m ); i n t p th r e a d ^ a t tr _ _ g e t s c h e d p o lic y ( c o n st p th r e a d _ a ttr _ t * a t t r , i n t * p o lic y ); i n t p th re a d _ a ttr_ s e ts c h e d p o lic y ( p th re a d _ a ttr_ t * a t tr , in t p o lic y ) ; i n t p th r e a d _ g e ts c h e d p a r a m ( p t h r e a d _ t t h r e a d , i n t * p o l i c y , s t r u c t sched_j>aram * p a ra m ); i n t p th r e a d _ s e ts c h e d p a r a m ( p th re a d _ t th r e a d , in tV p o lic y , c o n s t s t r u c t s c h e d jp a ra m * p a ra m ); A P th r e a d s s y s te m th a t s u p p o r ts _ p o s i x _ t h r e a d _ p r i o r i t y _ s c h e d u l i n g m u s t p ro v id e a d e fin itio n of th e s t r u c t s c h e d jp a ra m s tr u c t u r e t h a t in c lu d e s a t le a s t th e m e m b e r s c h e d _ p r i o r i t y . T h e s c h e d _ p r i o r i t y m e m b e r is th e o n ly s c h e d u lin g p a r a m e te r u s e d b y th e s ta n d a r d P th r e a d s s c h e d u lin g po licies, S C H E D _ F I F 0 a n d S C H E D _ _ R R . T h e m in im u m a n d m a x im u m p rio rity v a lu e s ( s c h e d _ p r i o r i t y m e m b er) t h a t a re allo w ed for e a c h s c h e d u lin g policy c a n b e d e te rm in e d b y callin g s c h e d _ g e t_ p r io r ity _ m in o r s c h e d _ g e t_ p r io r ity _ m a x , resp ectiv ely , for th e sch ed u lin g policy. P th re a d s s y ste m s th a t s u p p o r t a d d itio n a l, n o n s ta n d a r d s c h e d u lin g po licies m a y in c lu d e a d d itio n a l m e m b e rs. T h e s c h e d _ f i f o [ firs t in, f ir s t out) policy allo w s a th r e a d to r u n u n til a n o th e r th r e a d w ith a h ig h e r p rio rity b e c o m e s re a d y , o r u n til it b lo c k s v o lu n ta rily . W h en a th r e a d w ith s c h e d _ f i f o s c h e d u lin g po licy b e c o m e s re a d y , it b e g in s e x e c u tin g im m e d ia te ly u n le s s a th r e a d w ith e q u a l o r h ig h e r p rio rity is a lre a d y e x e c u tin g . T h e s c h e d _ r r (ro u n d - ro b in ) policy is m u c h th e sa m e , e x c e p t t h a t if a th re a d w ith S C H E D _ R R policy e x e c u te s for m o re th a n a fixed p e rio d of tim e (the tim e s lice in te rv a l) w ith o u t b lo ck in g , a n d a n o th e r th re a d w ith S C H E D _ R R o r s c h e d _ f i f o policy a n d th e s a m e p rio rity is re a d y , th e ru n n in g th r e a d will b e p re e m p te d so th e re a d y th r e a d c a n b e e x e c u te d . W h e n th r e a d s w ith s c h e d j f i f o o r s c h e d _ r r policy w a it o n a c o n d itio n v aria b le o r w a it to lo ck a m u te x , th e y will b e a w a k e n e d in p rio rity o rd er. T h a t is, if a lo w -p rio rity s c h e d _ f i f o th r e a d a n d a h ig h -p rio rity S C H E D _ f i f o th r e a d a r e b o th

R e a l t i m e sc h e d u l i n g

175

w a itin g to lo ck th e s a m e m u te x , th e h ig h -p rio rity th r e a d will alw ay s b e u n b lo c k e d firs t w h e n th e m u te x is u n lo c k e d . P th r e a d s d e fin e s th e n a m e of a n a d d itio n a l s c h e d u lin g policy, ca lle d s c h e d _ o t h e r . P th re a d s , how ever, s a y s n o th in g a t all re g a rd in g w h a t th is s c h e d u lin g policy d o es. T h is is a n illu s tra tio n of a n u n o fficial POSIX p h ilo so p h y t h a t h a s b e e n te rm e d “a s ta n d a r d w ay to b e n o n s ta n d a r d ” (or, a lte rn a te ly , "a p o rta b le w ay to b e n o n p o rta b le ”). T h a t is, w h e n y o u u s e a n y im p le m e n ta tio n o f P th re a d s t h a t s u p p o rts th e p rio rity s c h e d u lin g o p tio n , y o u c a n w rite a p o rta b le p ro g ra m t h a t c re a te s th r e a d s r u n n in g in SCHED_0THER policy, b u t th e b e h a v io r of t h a t p ro g ra m is n o n p o rta b le . (The official e x p la n a tio n of s c h e d _ o t h e r is t h a t it p ro v id e s a p o rta b le w ay for a p ro g ra m to d e c la re th a t it d o e s n o t n e e d a re a ltim e s c h e d u lin g policy.) T h e s c h e d _ o t h e r policy m a y b e a n a lia s for s c h e d _ f i f o ,o r it m a y be s c h e d _ r r , o r it m a y b e so m e th in g en tire ly d ifferen t. T h e re a l p ro b le m w ith th is a m b ig u ity is n o t t h a t y o u d o n ’t k n o w w h a t s c h e d _ o t h e r d o es, b u t th a t y o u h a v e n o w ay o f k n o w in g w h a t s c h e d u lin g p a r a m e te r s it m ig h t re q u ire . B e c a u se th e m e a n in g of SCHED_0THER is u n d e fin e d , it d o e s n o t n e c e ss a rily u s e th e sched_priority m e m b e r of th e struct sched_param s tr u c tu re , a n d it m a y re q u ire ad d itio n a l, n o n s ta n d a r d m e m b e rs th a t a n im p le m e n ta tio n m a y a d d to th e s tru c tu re . If th e re ’s a n y p o in t to th is, it is sim p ly th a t s c h e d _ o t h e r is n o t p o rta b le . If y o u w rite a n y code th a t u s e s SCHED_0THER y o u s h o u ld b e a w a re th a t th e code is n o t p o rta b le —y o u are, b y definitio n , d e p e n d in g o n th e s c h e d _ o t h e r of th e p a r tic u la r P th re a d s im p le m e n ta tio n for w h ic h y o u w ro te th e code. T h e s ch e d p olicy a n d s ch e d p a ra m a ttr ib u te s , s e t re sp ectiv ely b y pthread_ attr_setschedpolicy a n d pthread_attr_setschedparam, sp ecify th e explicit s c h e d u lin g policy a n d p a r a m e te r s for th e a ttr ib u te s o b ject. P th re a d s d o e s n o t sp ecify a d e fa u lt v a lu e for e ith e r of th e s e a ttr ib u te s , w h ic h m e a n s th a t e a c h im p le m e n ta tio n m a y c h o o se so m e “a p p r o p r ia te ” v a lu e. A re a ltim e o p e ra tin g sy ste m in te n d e d for e m b e d d e d c o n tro lle r a p p lic a tio n s , for ex am p le, m ig h t c h o o se to c re a te th r e a d s b y d e fa u lt w ith s c h e d _ f i f o policy, a n d , p e rh a p s , so m e m e d iu m ra n g e p rio rity . M o st m u ltiu s e r o p e ra tin g s y s te m s a re m o re likely to u s e a n o n s ta n d a r d “tim es h a r e ” s c h e d u lin g policy b y d e fa u lt, c a u s in g th r e a d s to b e s c h e d u le d m o re o r le ss a s p ro c e s s e s h a v e a lw ay s b e e n s c h e d u le d . T h e s y s te m m ay , for ex am p le, te m p o ra rily re d u c e th e p rio rity o f “CPU h o g s ” so t h a t th e y c a n n o t p re v e n t o th e r th r e a d s fro m m a k in g p ro g re s s . O n e e x a m p le of a m u ltiu s e r o p e ra tin g s y ste m is D igital UNIX, w h ic h s u p p o r ts tw o n o n s ta n d a r d tim e s h a re s c h e d u lin g po licies. T h e fo re g ro u n d policy (s c h e d _ f g _ n p ), w h ic h is th e d e fa u lt, is u s e d for n o rm a l in te ra c tiv e activ ity , a n d co rres p o n d s to th e w ay n o n th re a d e d p ro c e s s e s a re s c h e d u le d . T h e b a ckg ro u n d policy (SCHED_b g _ n p ) c a n b e u s e d for le ss im p o r ta n t s u p p o r t a ctiv ities.

I

W h e n y o u s e t th e s c h e d u lin g p o lic y o r p rio rity a ttr ib u te s in a n a ttr ib u te s o b je c t , y o u m u s t a ls o s e t t h e in h e r its c h e d a ttr ib u te !

176

CH A P T E R 5

The

in h e rits ch e d

A d va n c e d t h r ea d ed p r o g r a m m i n g

a ttr ib u te , w h ic h y o u c a n s e t b y c a llin g pthread_attr_

setinheritsched, c o n tro ls w h e th e r a th r e a d y o u c re a te in h e rits s c h e d u lin g

in fo rm a tio n fro m th e c re a tin g th re a d , o r u s e s th e ex p licit s c h e d u lin g in fo rm a tio n in th e s ch e d p olicy a n d s ch e d p a ra m a ttr ib u te s . P th r e a d s d o e s n o t sp ecify a d e fa u lt v a lu e for in h e rits ch e d , eith er, so if y o u c a re a b o u t th e po licy a n d s c h e d u lin g p a r a m e te r s of y o u r th re a d , y o u m u s t a lw ay s s e t th is a ttr ib u te . S e t th e in h e rits ch e d a ttr ib u te to p t h r e a d _ i n h e r i t _ s c h e d to c a u s e a n ew th r e a d to in h e rit th e s c h e d u lin g policy a n d p a r a m e te r s o f th e c re a tin g th re a d . S c h e d u lin g in h e rita n c e is u s e fu l w h e n y o u ’re c re a tin g “h e lp e r” th r e a d s t h a t a re w o rk in g o n b e h a lf o f th e c re a to r—it g e n e ra lly m a k e s s e n s e for th e m to r u n a t th e s a m e policy a n d p rio rity . W h e n e v e r y o u n e e d to c o n tro l th e s c h e d u lin g policy o r p a r a m e te r s o f a th r e a d y o u c re a te , y o u m u s t s e t th e in h e rits ch e d a ttr ib u te to PTHREAD_EXPLICIT_SCHED.

T h e follow ing p ro g ra m , sched_attr .c, sh o w s h o w to u s e a n a ttr ib u te s o b je ct to c re a te a th r e a d w ith a n ex p lic it s c h e d u lin g policy a n d p rio rity . N otice th a t it u s e s c o n d itio n a l co d e to d e te rm in e w h e th e r th e p rio rity s c h e d u lin g fe a tu re of P th re a d s is s u p p o rte d a t co m p ila tio n tim e. It w ill p r in t a m e ss a g e if th e o p tio n is n o t s u p p o rte d a n d c o n tin u e , a lth o u g h th e p ro g ra m in t h a t c a s e w ill n o t do m u c h . (It c re a te s a th r e a d w ith d e fa u lt s c h e d u lin g b eh av io r, w h ic h c a n only s a y th a t it ran .) A lth o u g h S o la ris 2 .5 d e fin e s _ p o s i x j t h r e a d _ p r i o r i t y _ s c h e d u l i n g , it d o e s n o t s u p p o r t th e POSIX re a ltim e s c h e d u lin g p o licies, a n d a tte m p tin g to s e t th e policy a ttr ib u te to s c h e d _ r r w o u ld fail. T h is p ro g ra m tr e a ts S o la ris a s if it d id n o t d efin e th e _ p o s i x _ t h r e a d _ p r i o r i t y _ s c h e d u l i n g o p tio n .

58-118



sched_attr.c

1 2 3 4 5

#include #include #include #include

6

/*



"errors.h"

7 * Thread start routine. If priority scheduling is supported, 8 * report the thread's scheduling attributes. 9 */ 10 void *thread_routine (void *arg)

n 12 13 14 15 16 17 18 19

20

{ int my_policy; struct sched_param my_param; int status; /* * If the priority scheduling option is not defined, then we * can do nothing with the output of pthread_getschedparam, * so just report that the thread ran, and exit.

*/

177

R e a l t i m e sc h ed u l i n g

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

66 67

68 69

#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && status = pthread_getschedparam ( pthread_self (), &my_policy, &my_param); if (status != 0) err_abort (status, ‫ ״‬Get s c hed‫;) ״‬ printf ("thread_routine running at %s/%d\n", (my_policy == SCHED_FIFO ? ‫ ״‬F I F O ‫״‬ : (my_policy == SCHED_RR ? ,,RR" : (my_policy == SCHED_OTHER ? ,,O T H E R ‫״‬ : "unknown"))), my_param.sched_priority); #else printf ("thread_routine running\n"); #endif return NULL;

!defined (sun)

} int main (int argc, char *argv[])

{ pthread_t t h r e a d e d ; pthread_attr__t thread_attr; int thread_policy; struct sched_param thread_param; int status, rr_min_priority, rr_max_priority; status = pthread_attr_init (&thread_attr); if (status != 0) err_abort (status, "Init a t t r " ) ;

/* * * * * * *

If the priority scheduling option is defined, set various scheduling parameters. Note that it is particularly important that you remember to set the inheritsched attribute to PTHREAD_EXPLICIT_SCHED, or the policy and priority that you've set will be ignored! The default behavior is to inherit scheduling information from the creating thread.

*/ #if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && !defined (sun) status = pthread_attr_getschedpolicy ( &thread_attr, &thread__policy) ; if (status != 0) err_abort (status, "Get policy"); status = pthread_attr_getschedparam ( &thread_attr, &thread_param); if (status != 0) err_abort (status, "Get sched p a r a m " ); printf ( "Default policy is %s, priority is % d \ n " , (thread_policy == SCHED_FIFO ? "FIFO"

178

72 73 74 75 76 77 78 79 80 81 82 83 84 85

CHA P T E R 5

: (thread__policy == SCHED_RR ? "RR" : (thread_policy == SCHED_OTHER ? ,,OTHER" : "unknown"))), thread_param.sched_priority); y

status = pthread_attr_setschedpolicy ( &thread_attr, SCHED_RR); if (status != 0) printf ("Unable to set SCHED_RR p o l i c y .\ n " ); else {

/* * * * * * * * * *

86 87

88 89 90 91 92 93 94 95 96 97 98 99

Just for the sake of the exercise, w e ’ll use the middle of the priority range allowed for SCHED_RR. This should ensure that the thread will be run, without blocking everything else. Because any assumptions about how a t h r e a d ’s priority interacts with other threads (even in other processes) are nonportable, especially on an implementation that defaults to System contention scope, you may have to adjust this code before it will work on some systems.

*/

100 101 102

103 104 105 106 107 108 109

y

110 111 112

113 114 115 116 117

A d va n c ed t h r ea d ed p r og r a m m in g

rr_min_priority = sched_get_priority_min (SCHED_RR); if (rr_min_priority — -1) errno_abort ("Get SCHED_RR min priority"); rrjmax_priority = sched_get_priority_max (S C H ED_RR); if (rr_max_priority == -1) errno_abort ("Get SCHED_RR max priority"); thread_param.sched_priority = (rr_min__priority + rr_max_priority)/2 ; printf ( "SCHED__RR priority range is %d to %d: using %d\n", rr_min_priority, rr_max__priority, thread_param.sched_priority); status = pthread_attr_setschedparam ( &thread_attr, &thread_param); if (status != 0) err__abort (status, "Set params" ); printf ( "Creating thread at RR/% d \ n " , thread_j?aram.sched_priority); status = pthread_attr_setinheritsched ( &thread_attr, PTHREAD_EXPLICIT_SCHED); if (status != 0) err_abort (status, "Set inherit");

} #else printf

("Priority scheduling not supported\n");

R ea l t i m e sc h ed u l i n g

118 119 120 121 122 123 124 125 126 127 128

179

#endif status = pthread_create ( &thread_id, &thread_attr, thread_routine, NULL); if (status 1= 0) err__abort (status, "Create thread"); status = pthread_join (thread_id, NULL); if (status 1= 0) err_abort (status, "Join thread"); printf ("Main exiting\n"); return 0; } ■

sched_attr.c

T h e n e x t p ro g ra m , s c h e d _ t h r e a d .c , s h o w s h o w to m odify th e re a ltim e s c h e d u lin g policy a n d p a r a m e te r s for a r u n n in g th re a d . W h e n c h a n g in g th e s c h e d u lin g policy a n d p a r a m e te r s in a th r e a d a ttr ib u te s o b ject, re m e m b e r, y o u u s e tw o se p a r a te o p e ra tio n s : o n e to m odify th e s c h e d u lin g policy a n d th e o th e r to m odify th e s c h e d u lin g p a ra m e te rs . You c a n n o t m o dify th e s c h e d u lin g po licy of a r u n n in g th r e a d s e p a ra te ly from th e th r e a d ’s p a ra m e te rs , b e c a u s e th e policy a n d p a r a m e te r s m u s t a lw a y s b e co n s is te n t for s c h e d u lin g to o p e ra te co rrectly . E a c h s c h e d u lin g policy m a y h a v e a u n iq u e ra n g e o f v alid s c h e d u lin g p rio ritie s, a n d a th r e a d c a n n o t o p e ra te a t a p rio rity t h a t is n ’t v alid for its c u r r e n t policy. To e n s u r e c o n s is te n c y o f th e policy a n d p a ra m e te rs , th e y a re s e t w ith a sin g le call. 55 U n lik e s c h e d _ a t t r . c , s c h e d _ t h r e a d .c d o e s n o t c h e c k th e co m p ile -tim e feat u r e m a c ro _ p o s i x _ t h r e a d _ p r i o r i t y _ s c h e d u l i n g . T h a t m e a n s it w ill p ro b a b ly n o t co m pile, a n d a lm o s t c e rta in ly w o n ’t r u n co rrectly , o n a s y s te m t h a t d o e s n o t s u p p o r t th e o p tio n . T h e re ’s n o th in g w ro n g w ith w ritin g a p ro g ra m t h a t w ay —in fact, t h a t ’s w h a t y o u a re likely to d o m o s t of th e tim e. If y o u n e e d p rio rity sc h e d u lin g , y o u w o u ld d o c u m e n t t h a t y o u r a p p lic a tio n r e q u ire s th e __p 0SIX_ t h r e a d _ p r i o r i t y _ s c h e d u l i n g o p tio n , a n d u s e it. 57-62 S o la ris 2 .5 , d e s p ite d e fin in g _ p o s 1 x _ t h r e a d _ p r i o r i t y _ s c h e d u l i n g , d o e s n o t s u p p o r t re a ltim e s c h e d u lin g p o licies. F o r th is re a s o n , th e e n o s y s fro m sched_ get_priority_min is h a n d le d a s a sp e c ia l c a se . ■

1 2 3 4 5 6 7

8 9

10

s c h e d _thread.c

!include !include !include !include



"errors.h"

!define THREADS 5

/* * Structure describing each thread.

*/

180

11 12 13 14 15 16 17 18 19

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59

CHA P T E R 5

A d va n c e d t h r ea d ed p r o g r a m m i n g

typedef struct thread_tag { int index; pthread__t id; } thread_t; thread_t int

th r e a d s [TH R E A D S ]; rr_min_priority;

/* * Thread start routine that will set its own priority.

*/ void *thread_routine

(void *arg)

{ thread_t *self = (thr e a d _ t * )arg; int my_policy; struct sched_j?aram my_j?aram; int status; my_param. sched__priority = rr_min_priority + self->index; DPRINTF (( "Thread %d will set SCHED_FIFO, priority %d\n", self->index, my_param.sched_priority)); status = pthread_setschedparam ( self->id, SCHED RR, &my p a r a m ) ; (v:;1‫־ ׳‬ if (status 1‫ ־‬0 ( ‫־‬ ' - ' C err_abort (status, "Set sched"); status = pthread_getschedparam ( self->id, &my_policy, &my_param); if (status I= 0) err__abort (status, "Get sched"); 1printf ("thread_routine %d running at %s/%d\n", self->index, (my_policy == SCHED_FIFO ? "FIFO" : (my_policy == SCHED_RR ? "RR" : (my_policy == SCHED_OTHER ? "OTHER" : "unknown"))), my_param. sched__priority) ; return NULL;

} int main (int argc, char *argv[])

{ int count,

status;

rr_min_priority = sched_get_priority__min (SCHED_RR); if (rr_min_priority == -1) { #ifdef sun if (errno == E N O S Y S ) { fprintf (stderr, "SCHED_RR is not supported.\n");

181

R ea l t i m e sc h ed u l i n g

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76

exit (0); > #endif errno_abort ("Get SCHED_RR min priority"); > for (count = 0; count < THREADS; count++) { threads[count].index = count; status = pthread_create ( ^threads[count].id, NULL, thread_routine, (v o i d * )sthreads[count]); if (status != 0) err_abort (status, "Create thread"); > for (count = 0; count < THREADS; count++) { status = pthread_join (threads[count].id, NULL); if (status ! = 0 ) err_abort (status, "Join t h read‫;) ״‬

77

}

78 79 80

printf ("Main e xiting\n"); return 0; } ■

5 .5 .3

sched_thread.c

C o n te n tio n s c o p e a n d a llo c a tio n d o m a in

in t

p th re a d _ a ttr_ g e ts c o p e const p th re a d _ a ttr_ t

in t

( *a ttr,

p th re a d _ a ttr_ s e ts c o p e

(

p th re a d _ a ttr_ _ t

in t

*a ttr,

in t

* c o n te n tio n s c o p e );

c o n te n tio n s c o p e ) ;

B e sid e s s c h e d u lin g po licy a n d p a r a m e te r s , tw o o th e r c o n tro ls a re im p o r ta n t in re a ltim e sc h e d u lin g . U n le ss y o u a re w ritin g a re a ltim e a p p lic a tio n , th e y p ro b a b ly d o n ’t m a tte r. If y o u a re w ritin g a re a ltim e a p p lic a tio n , y o u w ill n e e d to find o u t w h ic h s e ttin g s o f th e s e c o n tro ls a re s u p p o rte d b y a sy ste m . T h e firs t c o n tro l is c a lled co n te n tio n s cop e . It is a d e s c rip tio n of h o w y o u r th r e a d s c o m p e te for p ro c e s s o r re s o u rc e s . S y s te m co n te n tio n s co p e m e a n s th a t y o u r th r e a d c o m p e te s for p ro c e s s o r r e s o u r c e s a g a in s t th r e a d s o u ts id e y o u r p ro c e ss. A h ig h -p rio rity s y s te m c o n te n tio n sco p e th r e a d in y o u r p ro c e s s c a n k e e p s y ste m c o n te n tio n sco p e th r e a d s in o th e r p ro c e s s e s fro m r u n n in g (or vice v ersa). P ro ce s s co n te n tio n s co p e m e a n s th a t y o u r th r e a d s c o m p e te o n ly a m o n g th e m selv es. U su ally , p ro c e s s c o n te n tio n sc o p e m e a n s t h a t th e o p e ra tin g s y s te m c h o o s e s a p ro c e s s to e x e c u te , p o ssib ly u s in g o n ly th e tra d itio n a l UNIX p rio rity , a n d so m e a d d itio n a l s c h e d u le r w ith in th e p ro c e s s a p p lie s th e POSIX s c h e d u lin g r u le s to d e te rm in e w h ic h th r e a d to e x ec u te.

182

CH A P T E R 5

A d va n c e d t h r ea d ed p r o g r a m m i n g

P th r e a d s p ro v id e s th e th r e a d s co p e a ttr ib u te so t h a t y o u c a n sp ecify w h e th e r e a c h th r e a d y o u c re a te s h o u ld h a v e p ro c e s s o r s y s te m c o n te n tio n sco p e. A P th r e a d s s y ste m m a y c h o o se to s u p p o r t p t h r e a d _ s c o p e _ p r o c e s s , p t h r e a d _ s c o p e _ s y s t e m , o r b o th . If y o u try to c re a te a th r e a d w ith a sc o p e th a t is n o t s u p ‫־‬ p o rte d b y th e s y ste m , pthread_attr_setscope w ill r e t u r n ENOTSUP. T h e s e c o n d c o n tro l is a llo ca tio n d o m a in . A n a llo c a tio n d o m a in is th e s e t of proc e s s o rs w ith in th e s y s te m for w h ic h th r e a d s m a y c o m p e te . A s y ste m m a y h av e o n e o r m o re a llo c a tio n d o m a in s , e a c h c o n ta in in g o n e o r m o re p ro c e s s o rs . In a u n ip ro c e s s o r s y ste m , a n a llo c a tio n d o m a in w ill c o n ta in o n ly o n e p ro c e sso r, b u t y o u m a y still h a v e m o re t h a n o n e a llo c a tio n d o m a in . O n a m u ltip ro c e ss o r, e a c h a llo c a tio n d o m a in m a y c o n ta in from o n e p ro c e s s o r to th e n u m b e r of p ro c e s s o rs in th e sy ste m . T h e re is n o P th r e a d s in te rfa c e to s e t a th r e a d ’s a llo c a tio n d o m a in . T he POSIX. 14 (M u ltip ro c e sso r Profile) w o rk in g g ro u p c o n s id e re d p ro p o s in g s ta n d a r d in te rfa c e s , b u t th e effo rt w a s h a lte d b y th e p ro s p e c t of d e a lin g w ith th e w ide ra n g e of h a rd w a re a r c h ite c tu r e s a n d e x istin g so ftw a re in te rfa c e s . D e sp ite th e la c k of a s ta n d a r d , a n y s y s te m s u p p o r tin g m u ltip ro c e s s o rs w ill h a v e in te rfa c e s to affect th e a llo c a tio n d o m a in o f a th re a d . B e c a u s e th e re is n o s ta n d a r d in te rfa c e to c o n tro l a llo c a tio n d o m a in , th e re is n o w ay to d e s c rib e p re c ise ly all th e effects o f a n y p a r tic u la r h y p o th e tic a l s itu a tio n . Still, y o u m a y n e e d to b e c o n c e rn e d a b o u t th e s e th in g s if y o u u s e a s y ste m t h a t s u p p o r ts m u ltip ro c e s s o rs . A few th in g s to th in k a b o u t: 1. H ow do s y s te m c o n te n tio n sco p e th r e a d s a n d p ro c e s s c o n te n tio n sco p e th r e a d s , w ith in th e s a m e a llo c a tio n d o m a in , in te r a c t w ith e a c h o th e r? T h ey a re c o m p e tin g for r e s o u r c e s in so m e m a n n e r, b u t th e b e h a v io r is n o t d efin e d b y th e s ta n d a r d . 2. If th e s y s te m s u p p o r ts “o v e rla p p in g ” a llo c a tio n d o m a in s , in o th e r w o rd s, if a p ro c e s s o r c a n a p p e a r in m o re th a n o n e a llo c a tio n d o m a in w ith in th e sy ste m , a n d y o u h a v e o n e s y ste m c o n te n tio n sc o p e th r e a d in e a c h o f tw o o v e rla p p in g a llo c a tio n d o m a in s , w h a t h a p p e n s ?

I

S y stem c o n t e n t io n s c o p e is P ro c e s s

c o n t e n t io n s c o p e is

p r e d ic ta b le .

cheap,

O n m o s t s y s te m s , y o u w ill g et b e tte r p e rfo rm a n c e , a n d lo w er c o st, b y u s in g on ly p ro ce s s c o n te n tio n sco p e. C o n te x t s w itc h e s b e tw e e n s y s te m c o n te n tio n sc o p e th r e a d s u s u a lly re q u ire a t le a s t o n e call in to th e k e rn e l, a n d th o s e c a lls a re rela tiv e ly ex p e n siv e c o m p a re d to th e c o s t o f s a v in g a n d re s to rin g th r e a d s ta te in u s e r m o d e. E a c h s y ste m c o n te n tio n s c o p e th re a d will b e p e rm a n e n tly a s s o c ia te d w ith o n e “k e rn e l e n tity ,” a n d th e n u m b e r of k e rn e l e n titie s is u s u a lly m o re lim ited th a n th e n u m b e r of P th r e a d s th r e a d s . P ro c e ss c o n te n tio n sc o p e th r e a d s m a y s h a r e o n e k e rn e l e n tity , o r so m e sm a ll n u m b e r of k e rn e l e n titie s . O n a giv en sy ste m c o n fig u ra tio n , for e x am p le, y o u m a y b e a b le to c re a te th o u s a n d s of p ro c e s s c o n te n tio n sc o p e th r e a d s , b u t on ly h u n d r e d s o f s y s te m c o n te n tio n sc o p e th r e a d s .

R ea l t i m e sc h ed u l i n g

183

O n th e o th e r h a n d , p ro c e s s c o n te n tio n sco p e gives y o u n o re a l c o n tro l over th e s c h e d u lin g p rio rity of y o u r th r e a d —w hile a h ig h p rio rity m a y give it p re c e d e n c e o v er o th e r th r e a d s in th e p ro c e s s , it h a s n o a d v a n ta g e o v er th r e a d s in o th e r p ro c e s s e s w ith lo w er p rio rity . S y ste m c o n te n tio n sc o p e gives y o u b e tte r p re d ic ta b ility b y allo w in g co n tro l, o fte n to th e e x te n t of b e in g ab le to m a k e y o u r th r e a d “m o re im p o r ta n t” th a n th r e a d s r u n n in g w ith in th e o p e ra tin g s y s te m k e rn e l.

I

S ystem c o n t e n t io n s c o p e is less p r e d ic t a b le w ith a n a llo c a t io n d o m a in g r e a t e r th a n o n e .

W h e n a th r e a d is a s s ig n e d to a n a llo c a tio n d o m a in w ith m o re t h a n a sin g le p ro c e sso r, th e a p p lic a tio n c a n n o lo n g e r rely o n co m p lete ly p re d ic ta b le s c h e d u lin g b eh av io r. B o th h ig h - a n d lo w -p rio rity th r e a d s m a y r u n a t th e s a m e tim e, for ex am p le, b e c a u s e th e s c h e d u le r w ill n o t allow p ro c e s s o rs to b e idle j u s t b e c a u s e a h ig h -p rio rity th r e a d is r u n n in g . T h e u n ip ro c e s s o r b e h a v io r w o u ld m a k e little s e n s e o n a m u ltip ro c e ss o r. W h e n th r e a d 1 a w a k e n s th r e a d 2 b y u n lo c k in g a m u te x , a n d th r e a d 2 h a s a h ig h e r p rio rity t h a n th r e a d 1, th r e a d 2 will p re e m p t th r e a d 1 a n d b e g in r u n n in g im m ed iately . H owever, if th r e a d 1 a n d th r e a d 2 a re r u n n in g s im u lta n e o u s ly in a n a llo c a tio n d o m a in g re a te r th a n o n e, a n d th r e a d 1 a w a k e n s th r e a d 3, w h ic h h a s lo w er p rio rity th a n th r e a d 1 b u t h ig h e r p rio rity th a n th r e a d 2, th r e a d 3 m a y n o t im m e d ia te ly p re e m p t th r e a d 2. T h re a d 3 m a y r e m a in re a d y u n til th r e a d 2 b lo c k s. F o r so m e a p p lic a tio n s , th e p re d ic ta b ility affo rd ed b y g u a r a n te e d p re e m p tio n in th e c a s e o u tlin e d in th e p re v io u s p a r a g r a p h m a y b e im p o rta n t. In m o s t c a s e s , it is n o t t h a t im p o r ta n t a s lo n g a s th r e a d 3 will e v e n tu a lly r u n . A lth o u g h POSIX d o e s n o t re q u ire a n y P th r e a d s s y s te m to im p le m e n t th is ty p e o f “c ro s s p ro c e s s o r p re e m p tio n ,” y o u a re m o re likely to fin d it w h e n y o u u s e s y s te m c o n te n tio n sco p e th r e a d s . If p re d ic ta b ility is critic a l, of c o u rs e , y o u s h o u ld b e u s in g s y s te m c o n te n tio n s c o p e an y w ay .

5 .5 .4

P ro blem s w ith re a ltim e s c h e d u lin g O n e of th e p ro b le m s of rely in g o n re a ltim e s c h e d u lin g is t h a t it is n o t m o d u lar. In re a l a p p lic a tio n s y o u will g e n e ra lly b e w o rk in g w ith lib ra rie s from a v a rie ty of s o u rc e s , a n d th o s e lib ra rie s m a y rely o n th r e a d s for im p o r ta n t fu n c tio n s like n e tw o rk c o m m u n ic a tio n a n d re s o u rc e m a n a g e m e n t. Now, it m a y s e e m re a s o n a b le to m a k e “th e m o s t im p o r ta n t th r e a d ” in y o u r lib ra ry r u n w ith S C H E D _ f i f o p olicy a n d m a x im u m p rio rity . T h e re s u ltin g th re a d , how ev er, is n ’t j u s t th e m o s t im p o r ta n t th r e a d for y o u r lib ra ry —it is (or, a t le a st, b e h a v e s as) th e m o s t im p o rt a n t th r e a d in th e e n tire p ro c e s s , in c lu d in g th e m a in p ro g ra m a n d a n y o th e r lib ra rie s . Y our h ig h -p rio rity th r e a d m a y p re v e n t all o th e r lib ra rie s, a n d in so m e c a s e s ev en th e o p e ra tin g s y ste m , from p e rfo rm in g w o rk o n w h ic h th e a p p lic a tio n relies.

184

CHA P T E R 5

A d va n c e d t h r ea d ed p r og r a m m in g

A n o th e r p ro b le m , w h ic h re a lly is n ’t a p ro b le m w ith p rio rity s c h e d u lin g , b u t w ith th e w ay m a n y p e o p le th in k a b o u t p rio rity s c h e d u lin g , is t h a t it d o e s n ’t do w h a t m a n y p eo p le ex p ec t. M an y p eo p le th in k t h a t “re a ltim e p rio rity ” th r e a d s so m e h o w “go f a s te r ” th a n o th e r th r e a d s , a n d t h a t ’s n o t tru e . R ealtim e p rio rity th r e a d s m a y a c tu a lly go slow er, b e c a u s e th e re is m o re o v e rh e a d involved in m a k in g all of th e re q u ire d p re e m p tio n c h e c k s a t all th e r ig h t tim e s —e sp e c ia lly o n a m u ltip ro c e ss o r. A m o re sev ere p ro b le m w ith fixed p rio rity s c h e d u lin g is ca lle d p rio rity in v e rs io n . P rio rity in v e rs io n is w h e n a lo w -p rio rity th r e a d c a n p re v e n t a h ig h -p rio rity th r e a d fro m r u n n in g —a n a s ty in te ra c tio n b e tw e e n s ch e d u lin g a n d s y n chro n iz a tion. S c h e d u lin g r u le s s ta te t h a t o n e th r e a d s h o u ld r u n , b u t s y n c h ro n iz a tio n re q u ire s t h a t a n o th e r th r e a d r u n , so t h a t th e p rio ritie s of th e tw o th r e a d s a p p e a r to b e re v e rse d . P rio rity in v e rsio n o c c u rs w h e n lo w -p rio rity th r e a d a c q u ire s a s h a r e d re s o u rc e (s u c h a s a m u tex ), a n d is p re e m p te d b y a h ig h -p rio rity th r e a d t h a t th e n b lo c k s on th a t s a m e re s o u rc e . W ith o n ly tw o th r e a d s , th e lo w -p rio rity th r e a d w o u ld th e n b e allo w ed to r u n , e v e n tu a lly (we a s s u m e ) re le a s in g th e m u te x . H owever, if a th ird th r e a d w ith a p rio rity b e tw e e n th o s e tw o is re a d y to r u n , it c a n p re v e n t th e lowp rio rity th r e a d fro m r u n n in g . B e c a u s e th e lo w -p rio rity th r e a d h o ld s th e m u te x t h a t th e h ig h -p rio rity th r e a d n e e d s , th e m id d le -p rio rity th r e a d is a lso k e e p in g th e h ig h e r-p rio rity th r e a d fro m r u n n in g . T h e re a re a n u m b e r of w ay s to p re v e n t p rio rity in v e rsio n . T h e s im p le s t is to av oid u s in g re a ltim e s c h e d u lin g , b u t t h a t ’s n o t a lw ay s p ra c tic a l. P th re a d s prov id e s se v e ra l m u te x lo ck in g p ro to c o ls t h a t h e lp avoid p rio rity in v e rsio n , p rio rity ce ilin g a n d p rio rity in h e rita n ce . T h e se a re d is c u s s e d in S e c tio n 5 .5 .5 . I

M o s t t h r e a d e d p r o g ra m s d o n o t n e e d r e a ltim e s c h e d u lin g .

A fin al p ro b le m is t h a t p rio rity s c h e d u lin g i s n ’t c o m p lete ly p o rta b le . P th re a d s d e fin e s th e p rio rity s c h e d u lin g f e a tu r e s u n d e r a n o p tio n , a n d m a n y im p le m e n ta tio n s t h a t a re n o t p rim a rily in te n d e d for re a ltim e p ro g ra m m in g m a y c h o o se n o t to s u p p o r t th e o p tio n . E v en if th e o p tio n is s u p p o rte d , th e re a re m a n y im p o rta n t a s p e c ts o f p rio rity s c h e d u lin g th a t a re n o t co v ered b y th e s ta n d a r d . W h e n y o u u s e s y s te m c o n te n tio n sco p e, for e x am p le, w h e re y o u r th r e a d s m a y c o m p ete d ire c tly a g a in s t th r e a d s w ith in th e o p e ra tin g s y ste m , s e ttin g a h ig h p rio rity o n y o u r th r e a d s m ig h t p re v e n t k e rn e l I /O d riv e rs fro m fu n c tio n in g o n so m e s y ste m s . P th r e a d s d o e s n o t sp ecify a th r e a d ’s d e fa u lt s c h e d u lin g po licy o r p rio rity , o r h o w th e s ta n d a r d s c h e d u lin g p o licies in te r a c t w ith n o n s ta n d a r d p o licies. So w h e n y o u s e t th e s c h e d u lin g policy a n d p rio rity of y o u r th re a d , u s in g “p o rta b le ” in te rfa c e s , th e s ta n d a r d p ro v id e s n o w ay to p re d ic t h o w t h a t s e ttin g will affect a n y o th e r th r e a d s in th e p ro c e s s o r th e s y s te m itself. If y o u re a lly n e e d p rio rity s c h e d u lin g , th e n u s e it—a n d b e a w a re t h a t it h a s sp e c ia l r e q u ire m e n ts b e y o n d sim p ly P th re a d s . If y o u n e e d p rio rity s c h e d u lin g , k e e p th e follow ing in m in d :

185

R e a l t i m e sc h e d u l i n g

1. P ro c e s s c o n te n tio n s c o p e is “n ic e r” th a n s y ste m c o n te n tio n sco p e, b e c a u s e y o u will n o t p re v e n t a th r e a d in a n o th e r p ro c e s s , o r in th e k e rn e l, fro m r u n n in g . 2. s c h e d _ r r is “n ic e r” t h a n s c h e d _ f i f o , a n d slig h tly m o re p o rta b le , b e c a u s e SCHED_ r r th r e a d s will b e p re e m p te d a t in te rv a ls to s h a r e th e av a ila b le p ro c e s s o r tim e w ith o th e r th r e a d s a t th e s a m e p rio rity . 3. Low er p rio ritie s for s c h e d _ f i f o a n d s c h e d _ r r p o licies a re n ic e r t h a n h ig h e r p rio ritie s, b e c a u s e y o u a re le ss likely to in te rfe re w ith s o m e th in g else t h a t ’s im p o rta n t. U n le ss y o u r co d e really n e e d s p rio rity s c h e d u lin g , avo id it. In m o s t c a s e s , in tro d u c in g p rio rity s c h e d u lin g will c a u s e m o re p ro b le m s t h a n it will solve.

5 .5 .5

P rio rity -a w a re m u te xe s

# i£ II in t

d e fin e d d e fin e d

( _ P O S IX _ T H R E A D _ P R IO _ P R O T E C T )

p t h r e a d _ j m u t e x a t t r —g e t p r o t o c o l c o n s t p th re a d _ m u te x a ttr_ t

in t

\

(_ P O S IX J T H R E A D _ P R IO _ IN H E R IT ) (

*a ttr,

p th r e a d _ jn u te x a ttr _ s e tp r o to c o l p th r e a d _ m u te x a ttr _ jt

*a ttr,

in t

*p ro to c o l

(

in t

p r o to c o l) ;

# e n d if # 1 f d e f _P O S IX J T H R E A D J P R IO ^PRO TECT in t

p th r e a d _ _ m u te x a ttr _ g e tp r io c e ilin g co n st p th re a d _ a ttr_ t

m t

*a ttr,

in t

p th r e a d _ jo n u te x _ g e tp r io c e ilin g c o n s t p th re a d _ m u te x ^ t

in t

in t

( * p r io c e ilin g );

p th r e a d jn u te x a ttr _ s e tp r io c e ilin g p th re a d _ m u te x a ttr_ t

m t

*a ttr,

p th re a d _ m u te x _ t in t

p r io c e ilin g ,

(

*im rfc e x ,

p th r e a d ^ m u te x ^ s e tp r io c e ilin g

(

p r io c e ilin g ); in t

* p r io c e ilin g );

(

*m u te x , in t

* o ld ^ c e ilin g );

# e n d if

P th r e a d s p ro v id e s s e v e ra l sp e c ia l m u te x a ttr ib u te s th a t c a n h e lp to avo id p rio rity in v e rs io n d e a d lo c k s. Locking, o r w a itin g for, a m u te x w ith o n e of th e s e a ttr ib u te s m a y c h a n g e th e p rio rity of th e th r e a d —o r th e p rio rity of o th e r th r e a d s — to e n s u r e t h a t th e th r e a d th a t o w n s th e m u te x c a n n o t b e p re e m p te d b y a n o th e r th r e a d t h a t n e e d s to lock th e s a m e m u te x . T h e s e m u te x a ttr ib u te s m a y n o t b e s u p p o r te d b y y o u r im p le m e n ta tio n of P th re a d s , b e c a u s e th e y a re o p tio n a l fe a tu re s . If y o u r co d e n e e d s to fu n c tio n w ith o r w ith o u t th e s e o p tio n s, y o u c a n c o n d itio n a lly co m p ile re fe re n c e s b a s e d o n th e fe a tu re te s t m a c ro s _ p o s i x j t h r e a d _ p r i o _ p r o t e c t o r _ p o s i x _ t h r e a d _ p r i o _ i n h e r i t , d efin e d in , o r y o u ca n call sysconf d u rin g p ro g ra m ex ec u tio n to c h e c k for s c t h r e a d p r i o p r o t e c t o r s c t h r e a d p r i o i n h e r i t .

186

CHA P T E R 5

A d va n c e d t h r ea d ed p r o g r a m m i n g

O n ce y o u ’ve c re a te d a m u te x u s in g o n e o f th e s e a ttr ib u te s , y o u c a n lo c k a n d u n lo c k th e m u te x ex a c tly like a n y o th e r m u te x . A s a c o n s e q u e n c e , y o u c a n easily c o n v e rt a n y m u te x y o u c re a te b y c h a n g in g th e co d e t h a t in itia liz e s th e m u te x . (You m u s t c all p th r e a d _ m u te x _ in it , how ever, b e c a u s e y o u c a n n o t s ta tica lly in itialize a m u te x w ith n o n d e fa u lt a ttrib u te s .)

I

"P rio rity c e ilin g ‫ ״‬p r o t o c o l m e a n s t h a t w h ile a t h r e a d o w n s t h e m u te x , it runs a t th e s p e c ifie d p rio rity .

If y o u r s y s te m d e fin e s _ p 0 S 1 x _ t h r e a d _ p r i 0 _ p r 0 t e c t th e n it s u p p o r ts th e a n d p rio ce ilin g a ttr ib u te s . You s e t th e p ro to co l a ttr ib u te b y callin g pthread_mutexattr_setprotocol. If y o u s e t th e p ro to co l a ttr ib u te to th e v a lu e p t h r e a d _ p r i o _ p r o t e c t , th e n y o u c a n a lso sp ecify th e p rio rity ceilin g for m u te x e s c re a te d u s in g th e a ttr ib u te s o b je c t b y s e ttin g th e p rio ce ilin g a ttr ib u te . You s e t th e p rio ce ilin g a ttr ib u te b y callin g th e fu n c tio n pthread_mutexattr_ setprioceiling. W h e n a n y th r e a d lo c k s a m u te x d efin e d w ith s u c h a n a ttr ib u te s o b je ct, th e th r e a d ’s p rio rity w ill b e s e t to th e p rio rity ceilin g o f th e m u te x , u n le s s th e th r e a d ’s p rio rity is a lre a d y th e s a m e o r h ig h e r N ote t h a t lo c k in g th e m u te x in a th r e a d r u n n in g a t a p rio rity ab o v e th e p rio rity ceilin g o f th e m u te x b r e a k s th e p ro to co l, rem o v in g th e p ro te c tio n a g a in s t p rio rity in v e rsio n .

p ro to co l

I

"P rio rity in h e r it a n c e " m e a n s t h a t w h e n a t h r e a d w a its o n a m u te x o w n e d b y a lo w e r-p rio rity t h r e a d , t h e p rio rity o f t h e o w n e r is in c r e a s e d t o t h a t o f t h e w a ite r.

If y o u r s y s te m d e fin e s _ p o s i x _ t h r e a d _ p r i o _ i n h e r i t th e n it s u p p o r ts th e p ro a ttr ib u te . If y o u s e t th e p ro to co l a ttr ib u te to th e v a lu e p t h r e a d _ p r i o _ i n h e r i t , th e n n o th r e a d h o ld in g th e m u te x c a n b e p re e m p te d b y a n o th e r th r e a d w ith a p rio rity lo w er th a n t h a t o f a n y th r e a d w a itin g fo r th e m u te x . W h e n a n y th r e a d a tte m p ts to lo c k th e m u te x w h ile a lo w e r-p rio rity th r e a d h o ld s th e m u te x , th e p rio rity o f th e th r e a d c u rre n tly h o ld in g th e m u te x w ill b e ra is e d to th e p rio rity o f th e w a ite r a s lo n g a s it o w n s th e m u te x . If y o u r s y ste m d o e s n o t define e ith e r _ p o s i x _ t h r e a d _ p r i o _ p r o t e c t o r _ p o s i x _ t h r e a d _ p r i o _ i n h e r i t th e n th e p ro to co l a ttr ib u te m a y n o t b e d efin ed . T h e d e fa u lt v a lu e of th e p ro to co l a ttr ib u te (or th e effective v a lu e if th e a ttr ib u te is n ’t defined) is P 0 S 1 X _ P R I 0 _ N 0 N E , w h ic h m e a n s t h a t th r e a d p rio ritie s a re n o t m o d ifie d b y th e a c t o f lo c k in g (or w a itin g for) a m u te x . to co l

5.5 .5 .1 Priority c e ilin g m u te xe s T h e s im p le s t o f th e tw o ty p e s of “p rio rity a w a re ” m u te x e s is th e p rio rity ce ilin g (or “p rio rity p ro te c tio n ”) p ro to c o l (F ig ure 5.3). W h e n y o u c re a te a m u te x u s in g a p rio rity ceiling, y o u sp ecify th e h ig h e s t p rio rity a t w h ic h a th r e a d w ill ev er b e r u n n in g w h e n it lo c k s th e m u te x . A ny th r e a d lo c k in g t h a t m u te x w ill h a v e its

187

R e a l t i m e sc h ed u l i n g

Ik

— lo c k m u t e x

1

j

‫ —ן‬u n lo c k m u t e x

f p rio rity

p r i o r i t y c e i l i n g .......... . t h r e a d p r io r ity

---------

tim e FIGURE 5.3

P riority ce iling m u te x ope ra tion

p rio rity a u to m a tic a lly r a is e d to t h a t v a lu e , w h ic h w ill allo w it to fin ish w ith th e m u te x b efo re it c a n b e p re e m p te d b y a n y o th e r th r e a d th a t m ig h t try to lo ck th e m u te x . You c a n a lso e x a m in e o r m odify th e p rio rity ceilin g of a m u te x th a t w a s c re a te d w ith th e p rio rity ceilin g (p rote ct) p ro to co l. A p rio rity ceilin g m u te x is n o t u s e fu l w ith in a lib ra ry t h a t c a n b e called b y th r e a d s y o u d o n ’t co n tro l. If a n y th r e a d t h a t is r u n n in g a t a p rio rity ab o v e th e ceilin g lo c k s th e p rio rity ceilin g m u te x , th e p ro to co l is b ro k e n . T h is d o e s n ’t n e c e ssa rily g u a r a n te e a p rio rity in v e rsio n , b u t it rem o v e s all p ro te c tio n a g a in s t p rio rity in v e rsio n . S in ce th e p rio rity ceilin g p ro to c o l a d d s o v e rh e a d to e a c h m u te x o p e ra tio n c o m p a re d to a n o rm a l “u n p r o te c te d ” m u te x , y o u m a y h a v e w a s te d p ro c e s s o r tim e a c c o m p lish in g n o th in g . P rio rity ceiling is p e rfe c t for a n e m b e d d e d re a ltim e a p p lic a tio n w h e re th e develo p e rs c o n tro l all s y n c h ro n iz a tio n w ith in th e s y ste m . T h e p rio rity ceiling c a n b e safely d e te rm in e d w h e n th e co d e is d e sig n e d , a n d y o u c a n avoid p rio rity in v e rsio n w ith a rela tiv ely sm a ll c o s t in p e rfo rm a n c e c o m p a re d to m o re g e n e ra l s o lu tio n s. O f c o u rs e it is alw ay s m o s t effic ient to avoid p rio rity in v e rsio n , e ith e r b y av o id in g p rio rity s c h e d u lin g o r b y u s in g a n y given m u te x only w ith in th r e a d s of e q u a l prio rity . E q u ally , of c o u rse , th e s e a lte rn a tiv e s ra re ly p ro v e p ra c tic a l w h e n y o u n e e d th e m m o st. You c a n u s e p rio rity ceilin g w ith in a lm o s t a n y m a in p ro g ra m , ev en w h e n y o u d o n ’t c o n tro l th e co d e in lib ra rie s y o u u s e . T h a t’s b e c a u s e w h ile it is c o m m o n for th r e a d s t h a t call in to lib ra ry fu n c tio n s to lo ck lib ra ry m u te x e s , it is n o t c o m m o n for th r e a d s c re a te d b y a lib ra ry to call in to a p p lic a tio n co d e a n d lo ck a p p lic a tio n m u te x e s . If y o u u s e a lib ra ry t h a t h a s “c a llb a c k s ” in to y o u r code, y o u m u s t e ith e r e n s u r e t h a t th o s e c a llb a c k s (an d a n y fu n c tio n s th e y call) d o n ’t u s e th e p rio rity ceilin g m u te x e s o r t h a t n o th r e a d in w h ic h th e c a llb a c k m ig h t b e in v o k ed will r u n a t a p rio rity ab o v e th e ceilin g p rio rity of th e m u te x .

188

CHA P T E R 5

A d va n c e d t h r ea d ed pr og r a m m in g

5 .5 .5 .2 Priority in h e rita n c e m u te x e s T h e o t h e r P t h r e a d s m u t e x p r o t o c o l i s p rio rity in h e rita n c e . I n t h e p r i o r i t y i n h e r ita n c e

p r o to c o l, w h e n

th r o u g h

th e

m u te x

m u te x , it lo o k s

a th r e a d

lo c k s a m u te x

(F ig u r e 5 .4 ).

a t th e

W hen

p r io r ity o f t h e

th e

a n o th e r

th r e a d

t h r e a d ’s p r i o r i t y i s c o n t r o l l e d

th r e a d

n eed s

th a t o w n s th e

to

b lo c k

on

m u te x . If th e

th a :

th r e a d

t h a t o w n s t h e m u t e x h a s a lo w e r p r io r ity t h a n t h e t h r e a d a t t e m p t in g to b lo c k o n th e

m u te x ,

th e

p r io r ity

o f th e

ow ner

is

r a is e d

to

th e

p r io r ity

o f th e

b lo c k in g

th r e a d . T h e p r io r ity in c r e a s e e n s u r e s t h a t t h e th r e a d t h a t h a s t h e m u t e x lo c k e d ca n * n o t b e p r e e m p t e d u n l e s s t h e w a i t i n g t h r e a d w o u l d a l s o h a v e b e e n p r e e m p t e d — in a s e n s e , t h e th r e a d o w n in g t h e m u t e x is w o r k in g o n b e h a lf o f t h e h ig h e r -p r io r ity t h r e a d . W h e n t h e t h r e a d u n l o c k s t h e m u t e x , t h e t h r e a d ’s p r i o r i t y i s a u t o m a t i c a l l y lo w e r e d secon d

to

its

n o r m a l p r io r ity a n d

th r e a d

of even

th e

h ig h e s t -p r io r ity w a ite r is

h ig h e r p r io r ity b lo c k s o n

t h e m u t e x b lo c k e d w ill a g a in

aw akened.

th e m u te x , th e th r e a d

h a v e it s p r io r ity in c r e a s e d . T h e th r e a d

If a

th a t h a s

w ill s till b e

r e t u r n e d to it s o r ig in a l p r io r ity w h e n t h e m u t e x is u n lo c k e d . T he

p r io r ity in h e r it a n c e p r o to c o l is m o r e g e n e r a l a n d

p o w e r fu l th a n

p r io r ity

c e ilin g , b u t a ls o m o r e c o m p lic a t e d a n d e x p e n s iv e . If a lib r a r y p a c k a g e m u s t m a k e u s e o f p r io r ity s c h e d u li n g , a n d c a n n o t a v o id u s e o f a m u t e x fr o m t h r e a d s o f d iffe r e n t p r io r ity , t h e n

p r io r ity in h e r it a n c e is

you

m a in

a r e w r itin g

lo c k e d

a

program ,

b y th r e a d s c r e a te d

w ith in

and a

th e o n ly c u r r e n tly a v a ila b le s o lu t io n .

know

th a t n o n e

lib r a r y , t h e n

o f y o u r m u te x e s

can

p r io r ity c e ilin g w ill a c c o m p lis h

t h e s a m e r e s u lt a s p r io r ity in h e r it a n c e , a n d w it h le s s o v e r h e a d .

th r e a d 1 lo c k s m u te x

th r e a d 2 b lo c k s

[‫־ ־‬

ik

w a it in g fo r m u t e x th r e a d 1 j~~ u n l o c k s m u t e x

‫ו‬

1

p r io r ity

th r e a d 1 p r io r ity -------th re a d 2 p r io r ity --------

f

tim e

FIGURE 5.4

P riority inhe ritance m u te x op e ration

If be

T h r ea d s a n d k er n el en t i t i es

189

5.6 Threads a n d ke rn e l e n tities ,,Two lin e s!” c r ie d th e M o c k Turtle. ,,Seals, turtles, s a lm o n , a n d so on: then , w h e n y o u ’ve c le a r e d a ll th e je lly -fis h o u t o f th e w a y — ”

‫ ״‬That g e n e ra lly ta k e s s o m e tim e ,” in te rru p te d th e G ry p h o n . ,,— y o u a d v a n c e tw ic e — " “E a c h w ith a lo b ste r as a p a r tn e r!” c r ie d th e G ry p h o n .

—Lewis Carroll, Alice's Adventures in Wonderland

P th r e a d s d e lib e ra te ly s a y s v ery little a b o u t im p le m e n ta tio n d e ta ils . T h is le av es e a c h v e n d o r free to m a k e d e c isio n s b a s e d o n th e n e e d s of th e ir u s e r s a n d to allow th e s ta te of th e a r t to a d v a n c e b y p e rm ittin g in n o v a tio n . T h e s ta n d a r d p la c e s a few e s s e n tia l re q u ire m e n ts o n th e im p le m e n ta tio n —e n o u g h t h a t y o u c a n w rite s tric tly c o n fo rm in g POSIX ap p licatio n s* th a t do u s e fu l w o rk w ith th r e a d s a n d w ill b e a b le to r u n c o rre c tly o n all co n fo rm in g im p le m e n ta tio n s of th e s ta n d a r d . A ny P th r e a d s Im p le m e n ta tio n m u s t e n s u r e t h a t "sy ste m se rv ic e s in v o k e d b y o n e th r e a d do n o t s u s p e n d o th e r th r e a d s ” so t h a t y o u do n o t n e e d to w o rry t h a t callin g r e a d m ig h t b lo c k all th r e a d s in th e p ro c e s s o n so m e s y s te m s . O n th e o th e r h a n d , th is d o e s n o t m e a n t h a t y o u r p ro c e s s w ill a lw ay s h a v e th e m a x im u m p o ssib le level of c o n c u rre n c y . N e v e rth e le ss, w h e n u s in g a s y s te m it is o ften u s e fu l to u n d e r s ta n d th e w a y s in w h ic h th e s y s te m m a y b e im p le m e n te d . W h e n w ritin g ANSI C e x p re s s io n s , for ex am p le, it is o ften h e lp fu l to u n d e r s ta n d w h a t th e co d e g e n e ra to r, a n d ev en th e h a rd w a re , will do w ith th o s e e x p re s s io n s . W ith t h a t in m in d , th e follow ing sectio n s d e sc rib e , briefly, a few of th e m a in v a ria tio n s y o u ’re likely to e n c o u n te r. T h e im p o r ta n t te rm s u s e d in th e s e s e c tio n s a re “P th r e a d s th r e a d ,” “k e rn e l e n tity ,” a n d “p ro c e s s o r.” “P th r e a d s th r e a d ” m e a n s a th r e a d t h a t y o u c re a te d by callin g pthread_create, re p re s e n te d b y a n id e n tifie r of ty p e pthread_t. T h e se a re th e th r e a d s t h a t y o u c o n tro l u s in g P th r e a d s in te rfa c e s . By “p ro c e s s o r,” I re fe r to th e p h y s ic a l h a rd w a re , th e p a r tic u la r th in g of w h ic h a “m u ltip ro c e s s o r” h a s m o re th a n one. M o st o p e ra tin g s y s te m s h a v e a t le a s t o n e a d d itio n a l level of a b s tr a c tio n b e tw e e n “P th re a d s th r e a d ” a n d “p ro c e s s o r” a n d I re fe r to t h a t a s a “k e rn e l e n tity ,” b e c a u s e t h a t is th e te rm u s e d b y P th re a d s . In so m e s y s te m s , “k e rn e l e n tity ” m a y b e a tra d itio n a l UNIX p ro c e s s . It m a y b e a D ig ital UNIX M ach th re a d , o r a S o la ris 2 .x LWP, o r a n IRIX s p ro c p ro c e s s . T h e e x a c t m e a n in g o f “k e rn e l e n tity ,” a n d h o w it in te r a c ts w ith th e P th re a d s th re a d , is th e c ru c ia l d iffere n ce b e tw e e n th e th re e m o d e ls d e sc rib e d in th e follow ing s e c tio n s.

*

Strictly conforming

is u s e d b y P O S IX to m e a n s o m e t h i n g q u it e s p e c ific : a s t r ic t ly c o n f o r m in g

a p p li c a t io n is o n e t h a t d o e s n o t r e ly o n a n y o p t io n s o r e x t e n s i o n s to t h e s t a n d a r d a n d r e q u ir e s o n ly t h e s p e c if ie d m in im u m a llo w e d v a lu e ) .

v a l u e fo r a ll i m p l e m e n t a t i o n l i m i t s ( b u t w ill w o r k c o r r e c t ly w it h a n y

190

5.6.1

CHA P T E R 5

A d va n c e d t h r ea d ed p r o g r a m m in g

M a n y -to -o n e (u s er le v e l) T h e m a n y -to -o n e m e th o d is a lso s o m e tim e s ca lle d a “lib ra ry im p le m e n ta tio n / In g e n e ra l, “m a n y -to -o n e ” im p le m e n ta tio n s a re d e sig n e d for o p e ra tin g s y s te m s w ith n o s u p p o r t fo r th re a d s . P th r e a d s im p le m e n ta tio n s t h a t r u n o n g e n e ric UNIX k e rn e ls u s u a lly fall in to th is ca te g o ry —for e x am p le, th e c la ss ic D C E th r e a d s refe re n c e im p le m e n ta tio n , o r th e S u n O S 4 .x LWP p a c k a g e (no re la tio n to th e S o la ris 2 .x LWP, w h ic h is a k e rn e l en tity). M a n y -to -o n e im p le m e n ta tio n s c a n n o t ta k e a d v a n ta g e of p a ra lle lis m o n a m u ltip ro c e s so r, a n d a n y b lo c k in g s y ste m serv ice, for e x am p le, a call to r e a d , will b lo c k all th r e a d s in th e p ro c e s s . S o m e im p le m e n ta tio n s m a y h e lp y o u av o id th is p ro b le m b y u s in g f e a tu r e s s u c h a s UNIX n o n b lo c k in g I/O , o r POSIX. l b a sy n c h ro n o u s I/O , w h e re av ailab le. H owever, th e s e f e a tu re s h a v e lim ita tio n s; for e x am p le, n o t all device d riv e rs s u p p o r t n o n b lo c k in g I/O , a n d tra d itio n a l UNIX d is k file s y s te m re s p o n s e is u s u a lly c o n s id e re d “in s ta n ta n e o u s ” a n d w ill ig n o re th e n o n b lo c k in g I /O m o d e. S o m e m a n y -to -o n e im p le m e n ta tio n s m a y n o t b e tig h tly in te g ra te d w ith th e ANSI C lib ra ry ’s s u p p o r t fu n c tio n s , a n d t h a t c a n c a u s e s e rio u s tro u b le . T h e s td io fu n c tio n s , fo r ex am p le, m ig h t b lo c k th e e n tire p ro c e s s (a n d all th re a d s ) w h ile o n e th r e a d w a its fo r y o u to e n te r a c o m m a n d . A ny m a n y -to -o n e im p le m e n ta tio n th a t c o n fo rm s to th e P th r e a d s s ta n d a r d , how ev er, h a s g o tte n a r o u n d th e s e p ro b le m s, p e r h a p s b y in c lu d in g a s p e c ia l v e rsio n o f s td io a n d o th e r fu n c tio n s . W h e n y o u re q u ire c o n c u rre n c y b u t do n o t n e e d p a ra lle lis m , a m a n y -to -o n e im p le m e n ta tio n m a y p ro v id e th e b e s t th r e a d c re a tio n p e rfo rm a n c e , a s w ell a s th e b e s t c o n te x t sw itc h p e rfo rm a n c e for v o lu n ta ry b lo c k in g u s in g m u te x e s a n d cond itio n v a ria b le s . It is f a s t b e c a u s e th e P th r e a d s lib ra ry s a v e s a n d r e s to re s th r e a d c o n te x t e n tire ly in u s e r m o d e. You c a n , for ex am p le, c re a te a lo t of th r e a d s a n d b lo c k m o s t of th e m o n c o n d itio n v a ria b le s (w aiting for so m e e x te rn a l event) very q u ick ly , w ith o u t involvin g th e k e rn e l a t all. F ig u re 5 .5 sh o w s th e m a p p in g of P th r e a d s th r e a d s (left co lu m n ) to th e k e rn e l e n tity (m iddle co lu m n ), w h ic h is a p ro c e s s , to p h y s ic a l p ro c e s s o rs (rig h t co lu m n ). In th is c a s e , th e p ro c e s s h a s fo u r P th re a d s th r e a d s , la b e le d “P th re a d 1” th ro u g h “P th re a d 4 .” T h e P th r e a d s lib ra ry s c h e d u le s th e fo u r th r e a d s o n to th e sin g le p ro c e s s in u s e r m o d e b y sw a p p in g re g is te r s ta te (SP, g e n e ra l re g is te rs , a n d so forth). T h e lib ra ry m a y u s e a tim e r to p re e m p t a P th r e a d s th r e a d th a t r u n s too long. T he k e rn e l s c h e d u le s th e p ro c e s s o n to o n e of th e tw o p h y s ic a l p ro c e s s o rs , la b eled “p ro c e s s o r 1” a n d “p ro c e s s o r 2 .” T h e im p o r ta n t c h a r a c te r is tic s of th is m o d e l a re s h o w n in T a b le 5 .2 .

T h r ea d s a n d k er n el en t i t ies

191

A d v a n ta g e s

D is a d v a n ta g e s

F a s te s t c o n te x t sw itc h tim e.

P o te n tia lly lo n g la te n c y d u rin g s y s te m serv ice b lo ck in g .

S im ple; th e im p le m e n ta tio n m a y e v e n b e (m ostly) p o rtab le.*

S in g le -p ro c e ss a p p lic a tio n s c a n n o t ta k e a d v a n ta g e of m u ltip ro c e s s o r h a rd w a re .

* T h e D C E t h r e a d s u s e r - m o d e s c h e d u le r c a n u s u a lly b e p o r te d to n e w o p e r a tin g s y s t e m s in a fe w d a y s , in v o lv in g p r im a r ily n e w a s s e m b ly la n g u a g e fo r t h e r e g is t e r c o n t e x t s w it c h in g r o u t in e s . W e u s e t h e m o t t o “S o m e A s s e m b l y R e q u i r e d . "

TABLE 5 .2

5 .6 .2

M a n y - to- on e thre ad s che d uling

O n e -to -o n e (k e rn e l le v e l) O n e -to -o n e th r e a d m a p p in g is a lso s o m e tim e s c a lled a “k e rn e l th r e a d ” im p le m e n ta tio n . T h e P th r e a d s lib ra ry a s s ig n s e a c h th r e a d to a k e rn e l e n tity . It g e n e ra lly m u s t u s e b lo c k in g k e rn e l f u n c tio n s to w a it o n m u te x e s a n d c o n d itio n v a ria b le s . W hile s y n c h ro n iz a tio n m a y o c c u r e ith e r w ith in th e k e rn e l o r in u s e r m o d e, th r e a d s c h e d u lin g o c c u rs w ith in th e k e rn e l. P th r e a d s th r e a d s c a n ta k e fu ll a d v a n ta g e o f m u ltip ro c e s s o r h a rd w a re in a o n e -to -o n e im p le m e n ta tio n w ith o u t a n y e x tra effort o n y o u r p a rt, fo r e x am p le, s e p a r a tin g y o u r co d e in to m u ltip le p ro c e s s e s . W h e n a th r e a d b lo c k s in th e k e rn e l,

192

CH A P T E R 5

A d va n c e d t h r ea d ed pr og r a m m in g

it d o e s n o t a ffect o th e r th r e a d s a n y m o re th a n th e b lo c k in g o f a n o rm a l UNIX proc e s s a ffe c ts o th e r p ro c e s s e s . O n e th r e a d c a n ev en p ro c e s s a p a g e fa u lt w ith o u t a ffectin g o th e r th r e a d s . O n e -to -o n e im p le m e n a tio n s su ffe r fro m tw o m a in p ro b le m s. T h e firs t is th a t th e y do n o t s c a le w ell. T h a t is, e a c h th r e a d in y o u r a p p lic a tio n is a k e rn e l en tity . B e c a u s e k e rn e l m e m o ry is p re c io u s, k e rn e l o b je c ts s u c h a s p ro c e s s e s a n d th r e a d s a re o ften lim ited b y p re a llo c a te d a rra y s , a n d m o s t im p le m e n ta tio n s will lim it th e n u m b e r of th r e a d s y o u c a n c re a te . It will a lso lim it th e n u m b e r of th r e a d s t h a t c a n b e c re a te d o n th e e n tire s y s te m —so d e p e n d in g o n w h a t o th e r p ro c e s s e s a r e d o in g , y o u r p ro c e s s m a y n o t b e a b le to re a c h its o w n lim it. T h e s e c o n d p ro b le m is t h a t b lo c k in g o n a m u te x a n d w a itin g o n a c o n d itio n v a ria b le , w h ic h h a p p e n fre q u e n tly in m a n y a p p lic a tio n s , a re s u b s ta n tia lly m o re e x p e n siv e o n m o s t o n e -to -o n e im p le m e n ta tio n s , b e c a u s e th e y re q u ire e n te rin g th e m a c h in e ’s p ro te c te d k e rn e l m ode. N ote t h a t lo c k in g a m u te x , w h e n it w a s n o t a lre a d y lo ck ed , o r u n lo c k in g a m u te x , w h e n th e re a re n o w a itin g th r e a d s , m a y be n o m o re ex p e n siv e th a n o n a m a n y -to ‫ ־‬o n e im p le m e n ta tio n , b e c a u s e o n m o s t syste m s th o s e f u n c tio n s c a n b e co m p le te d in u s e r m ode. A o n e -to -o n e im p le m e n ta tio n c a n b e a good ch o ice for C P U -b o u n d ap p lic a tio n s, w h ic h d o n ’t b lo c k v ery o fte n . M an y h ig h -p e rfo rm a n c e p a ra lle l a p p lic a tio n s b e g in b y c re a tin g a w o rk e r th r e a d for e a c h p h y s ic a l p ro c e s s o r in th e s y ste m , a n d . o n c e s ta r te d , th e th r e a d s r u n in d e p e n d e n tly for a s u b s ta n tia l tim e p erio d . S u c h a p p lic a tio n s will w o rk w ell b e c a u s e th e y do n o t s tr a in th e k e rn e l b y c re a tin g a lot o f th r e a d s , a n d th e y d o n ’t re q u ire a lo t of c a lls in to th e k e rn e l to b lo c k a n d u n b lo c k th e ir th r e a d s . F ig u re 5 .6 s h o w s th e m a p p in g o f P th r e a d s th r e a d s (left co lu m n ) to k e rn e l e n titie s (m iddle co lu m n ) to p h y s ic a l p ro c e s s o rs (rig h t co lu m n ). In th is c a se , th e p ro c e s s h a s fo u r P th r e a d s th r e a d s , la b e le d ‘‘P th re a d 1” th r o u g h “P th re a d 4.~ E a c h P th r e a d s th r e a d is p e rm a n e n tly b o u n d to th e c o rre s p o n d in g k e rn e l en tity . T h e k e rn e l s c h e d u le s th e fo u r k e rn e l e n titie s (along w ith th o s e fro m o th e r p ro c e sse s) o n to th e tw o p h y s ic a l p ro c e s s o rs , la b e le d “p ro c e s s o r 1” a n d “p ro c e s s o r 2.~ T h e im p o r ta n t c h a r a c te r is tic s of th is m o d el a re sh o w n in T a b le 5.3 .

193

T h r e a d s a n d k e r n e l en t i t i es

FIGURE 5.6

A dv ant age s

Disadv ant age s

C a n ta k e a d v a n ta g e of m u ltip ro c e s s o r h a rd w a re w ith in a sin g le p ro c e s s .

R elatively slo w th r e a d c o n te x t sw itc h (calls in to k ern el).

No la te n c y d u rin g sy ste m serv ice b lo ck in g .

P o o r s c a lin g w h e n m a n y th r e a d s a re u s e d , b e c a u s e e a c h P th r e a d s th r e a d ta k e s k e rn e l r e s o u r c e s from th e s y ste m .

TABLE 5.3

5 .6 .3

O ne - to- on e thre ad m apping

O ne - to- one thre ad s che d uling

M a n y ‫ ־‬to ‫ ־‬fe w (tw o le v e l) T h e m a n y -to -fe w m o d e l trie s to m erg e th e a d v a n ta g e s o f b o th th e m a n y -to o n e a n d o n e -to -o n e m o d e ls, w h ile a v o id in g th e ir d is a d v a n ta g e s . T h is m o d e l r e q u ire s c o o p e ra tio n b e tw e e n th e u s e r-le v e l P th r e a d s lib ra ry a n d th e k e rn e l. T h ey s h a r e s c h e d u lin g re s p o n s ib ilitie s a n d m a y c o m m u n ic a te in fo rm a tio n a b o u t th e th r e a d s b e tw e e n e a c h o th er.

194

CHA P T E R 5

A d va n c e d t h r ea d ed p r og r a m m in g

W h e n th e P th r e a d s lib ra ry n e e d s to sw itc h b e tw e e n tw o th r e a d s , it c a n do so d irec tly , in u s e r m o d e. T h e n e w P th r e a d s th r e a d r u n s o n th e s a m e k e rn e l e n tity w ith o u t in te rv e n tio n fro m th e k e rn e l. T h is g a in s th e p e rfo rm a n c e b e n e fit of m a n y -to -o n e im p le m e n ta tio n s for th e m o s t c o m m o n c a s e s , w h e n a th re a d b lo c k s o n a m u te x o r c o n d itio n v a ria b le , a n d w h e n a th r e a d te rm in a te s . W h e n th e k e rn e l n e e d s to b lo c k a th r e a d , to w a it fo r a n I /O o r o th e r re s o u rc e , it d o e s so. T h e k e rn e l m a y in fo rm th e P th r e a d s lib ra ry , a s in D ig ital UNIX 4 .0 , so t h a t th e lib ra ry c a n p re s e rv e p ro c e s s c o n c u rre n c y b y im m e d ia te ly s c h e d u lin g a n e w P th r e a d s th r e a d , s o m e w h a t like th e o rig in a l “s c h e d u le r a c tiv a tio n s ” m odel p ro p o s e d b y th e fa m o u s U n iv ersity o f W a sh in g to n r e s e a r c h [A n d erso n , 1991]. Or. th e k e rn e l m a y sim p ly b lo c k th e k e rn e l e n tity , in w h ic h c a s e it m a y allo w prog ra m m e rs to in c re a s e th e n u m b e r o f k e rn e l e n titie s t h a t a re a llo c a te d to th e p ro c e s s , a s in S o la ris 2 .5 — o th e rw ise th e p ro c e s s c o u ld b e s ta lle d w h e n all k e rn e l e n titie s h a v e b lo c k ed , ev en th o u g h o th e r u s e r th r e a d s a re re a d y to r u n . M an y -to -few im p le m e n ta tio n s ex cel in m o s t re a l-w o rld a p p lic a tio n s , b e c a u s e in m o s t a p p lic a tio n s , th r e a d s p e rfo rm a m ix tu re of C P U -b o u n d a n d I /O - b o u n d o p e ra tio n s , a n d b lo c k b o th in I /O a n d in P th re a d s s y n c h ro n iz a tio n . M o st a p p lic a tio n s a lso c re a te m o re th r e a d s t h a n th e re a r e p h y s ic a l p ro c e s s o rs , e ith e r d irec tly o r b e c a u s e a n a p p lic a tio n t h a t c r e a te s a few th r e a d s a lso u s e s a p a ra lle l lib ra ry t h a t c re a te s a few th r e a d s , a n d so fo rth . F ig u re 5 .7 sh o w s th e m a p p in g of P th r e a d s th r e a d s (left co lu m n ) to k e rn e l e n titie s (m iddle co lu m n ) to p h y s ic a l p ro c e s s o rs (rig h t co lu m n ). In th is c a s e , th e p ro c e s s h a s fo u r P th r e a d s th r e a d s , la b eled “P th re a d 1” th ro u g h “P th re a d 4 .” T h e P th r e a d s lib ra ry c r e a te s so m e n u m b e r of k e rn e l e n titie s a t in itia liz a tio n (an d m a y c re a te m o re la ter). ,Typically, th e lib ra ry will s t a r t w ith o n e k e rn e l e n tity (labeled “k e rn e l e n tity 1” a n d “k e rn e l e n tity 2 ”) for e a c h p h y s ic a l p ro c e sso r. T h e k e rn e l s c h e d u le s th e s e k e rn e l e n titie s (alon g w ith th o s e fro m o th e r p ro c e sse s) o n to th e

FIGURE 5 .7

M a n y - to- fe w thre ad m apping

195

T h r ea d s a n d k er n el en t i t i es

tw o p h y s ic a l p ro c e s s o rs , la b e le d “p ro c e s s o r 1" a n d “p ro c e s s o r 2 .” T h e im p o r ta n t c h a r a c te r is tic s of th is m o d e l a re s h o w n in T a b le 5.4 . A d v a n ta g e s

D is a d v a n ta g e s

C a n ta k e a d v a n ta g e o f m u ltip ro c e s s o r h a rd w a re w ith in a p ro c e s s .

M ore c o m p lic a te d th a n o th e r m o d e ls.

M ost c o n te x t s w itc h e s a re in u s e r m o d e (fast).

P ro g ra m m e rs lo se d ire c t c o n tro l over k e rn e l e n titie s , s in c e th e th r e a d ’s p rio rity m a y b e m e a n in g fu l o n ly in u s e r m o d e.

S c a le s w ell; a p ro c e s s m a y u s e o n e k e rn e l e n tity p e r p h y s ic a l p ro c e sso r, o r “a few ” m o re. Little la te n c y d u r in g s y s te m serv ice b lo ck in g . TABLE 5 .4

M a n y - to- fe w thre ad s che d uling

6 PO SIX adjusts to th re a d s

‫ ״‬W ho a re you?" s a id th e C a te rp illa r : This w as n o t a n e n c o u ra g in g o p e n in g for a c o n v ers a tio n . A lic e r e p lie d , ra th e r shyly, “I— I h a r d ly know , Sir, just a t p re s e n t— a t le a s t I k n o w w h o I was w h e n I g o t u p this m o rn in g , b u t I think I m ust h a v e b e e n c h a n g e d s e v e ra l tim es sin c e t h e n ” — L e w is C a r r o l A l i c e 's A d v e n t u r e s in W o n d e r l a n d

P th r e a d s c h a n g e s th e m e a n in g of a n u m b e r of tra d itio n a l POSIX p ro c e s s fu n c tio n s. M o st of th e c h a n g e s a re o b v io u s, a n d y o u ’d p ro b a b ly e x p e c t th e m ev en if th e s ta n d a r d h a d n ’t a d d e d sp ecific w o rd in g . W h e n a th r e a d b lo c k s fo r I/O . for e x am p le, on ly th e callin g th r e a d b lo c k s, w h ile o th e r th r e a d s in th e p ro c e s s c a n c o n tin u e to ru n . B u t th e r e ’s a n o th e r c la s s of POSIX f u n c tio n s t h a t d o e s n ’t e x te n d in to th e th r e a d e d w o rld q u ite so u n a m b ig u o u s ly . F o r e x am p le, w h e n y o u f o r k a th r e a d e d p ro c e s s , w h a t h a p p e n s to th e th r e a d s ? W h a t d o e s e x e c do in a th r e a d e d p ro c e s s ? W h a t h a p p e n s w h e n o n e o f th e th r e a d s in a th re a d e d p ro c e s s c a lls e x i t ?

6 .1

fo rk

I

A v o id u s in g fork in a t h r e a d e d p r o g r a m (if y o u c a n ) unless y o u in te n d t o exec a n e w p r o g r a m Im m e d ia t e ly

W h e n a th r e a d e d p ro c e s s c a lls f o r k to c re a te a c h ild p ro c e s s , P th r e a d s sp ecifies t h a t o n ly th e th r e a d ca llin g f o r k e x ists in th e ch ild . A lth o u g h o n ly th e callin g th r e a d e x ists o n r e tu r n fro m f o r k in th e c h ild p ro c e s s , all o th e r P th r e a d s s ta te s re m a in a s th e y w ere a t th e tim e of th e c all to f o r k . In th e c h ild p ro c e s s , th e th r e a d h a s th e s a m e th r e a d s ta te a s in th e p a re n t. It o w n s th e s a m e m u te x e s , h a s th e s a m e v a lu e for all th re a d -sp e c ific d a ta k ey s, a n d so fo rth . All m u te x e s a n d c o n d itio n v a ria b le s ex ist, a lth o u g h a n y th r e a d s t h a t w ere w a itin g o n a s y n c h ro n iz a tio n o b je ct a t th e tim e of th e f o r k a re n o lo n g e r w aitin g . (They d o n ’t e x ist in th e c h ild p ro c e s s , so h o w co u ld th e y b e w aitin g?) P th r e a d s d o e s n o t “te r m in a te ” th e o th e r th r e a d s in a fo rk ed p ro c e s s , a s if th e y ex ited w ith p t h r e a d _ e x i t o r ev en a s if th e y w ere c a n c e le d . T h ey sim p ly c e a s e to ex ist. T h a t is, th e th r e a d s do n o t r u n th re a d -sp e c ific d a t a d e s tr u c to r s o r c le a n u p h a n d le r s . T h is is n o t a p ro b le m if th e c h ild p ro c e s s is a b o u t to call e x e c to r u n a

197

198

CHA P T E R 6

P O S I X a d ju st s t o t h r ea d s

n e w p ro g ra m , b u t if y o u u s e f o r k to clo n e a th r e a d e d p ro g ra m , b e w a re t h a t y o u m a y lo se a c c e s s to m em o ry , e sp e c ia lly h e a p m e m o ry s to re d o n ly a s th re a d sp ecific d a ta v a lu e s.

I

The s ta te o f m u te x e s is n o t a f f e c t e d b y a fork. If it w a s lo c k e d in t h e p a r e n t it is lo c k e d in t h e c h ild !

If a m u te x w a s lo c k ed a t th e tim e o f th e call to f o r k , th e n it is still lo c k ed in th e ch ild . B e c a u s e a lo c k ed m u te x is o w n e d b y th e th r e a d t h a t lo c k ed it, th e m u te x c a n b e u n lo c k e d in th e ch ild only if th e th r e a d t h a t lo ck ed th e m u te x w a s th e o n e t h a t called f o r k . T h is is im p o r ta n t to re m e m b e r—if a n o th e r th r e a d h a s a m u te x lo c k ed w h e n y o u call f o r k , y o u w ill lo se a c c e s s to t h a t m u te x a n d a n y d a ta c o n tro lle d b y t h a t m u te x . D e sp ite th e c o m p lic a tio n s, y o u c a n f o r k a c h ild t h a t c o n tin u e s r u n n in g a n d ev en c o n tin u e s to u s e P th re a d s . You m u s t u s e fo rk h a n d le r s c a re fu lly to p ro te c t y o u r m u te x e s a n d th e s h a r e d d a ta t h a t th e m u te x e s a r e p ro te c tin g . F o rk h a n ‫־‬ d le rs a re d e s c rib e d in S e c tio n 6 .1 .1 . B e c a u s e th re a d -s p e c ific d a t a d e s tr u c to r s a n d c le a n u p h a n d le r s a re n o t called , y o u m a y n e e d to w o rry a b o u t m e m o ry le a k s. O n e p o s s ib le s o lu tio n w o u ld b e to c a n c e l th r e a d s c re a te d b y y o u r s u b s y s te m in th e p re p a re fo rk h a n d le r, a n d w ait for th e m to te rm in a te b efo re allo w in g th e f o r k to c o n tin u e (by re tu rn in g ), a n d th e n c re a te n e w th r e a d s in th e p a re n t h a n d le r t h a t is c a lled a fte r f o r k co m p le te s. T h is co u ld ea sily b e c o m e m e ssy , a n d I a m n o t re c o m m e n d in g it a s a s o lu tio n . In s te a d , ta k e a n o th e r lo o k a t th e w a rn in g b a c k a t th e b e g in n in g of th is sectio n : A void u s in g f o r k in th r e a d e d code e x c e p t w h e re th e c h ild p ro c e s s w ill im m ed ia te ly e x e c a n e w p ro g ra m . POSIX sp ecifies a sm a ll s e t of fu n c tio n s th a t m a y b e called safely from w ith in sig n a l-c a tc h in g fu n c tio n s (“a s y n c -s ig n a l sa fe ” fu n c tio n s), a n d f o r k is o n e o f th e m . However, n o n e of th e POSIX th r e a d s fu n c tio n s is a s y n c -s ig n a l safe (an d th e re a re good r e a s o n s fo r th is , b e c a u s e b e in g a s y n c -s ig n a l safe g e n e ra lly m a k e s a fu n c tio n s u b s ta n tia lly m o re ex pen sive). W ith th e in tro d u c tio n of fo rk h a n d le rs , how ever, a call to f o r k is a lso a call to so m e s e t of fo rk h a n d le rs . T h e p u r p o s e o f a fo rk h a n d le r is to allo w th re a d e d co d e to p ro te c t s y n c h ro n iz a tio n s ta te a n d d a t a in v a ria n ts a c ro s s a f o r k , a n d in m o s t c a s e s t h a t re q u ire s lo ck in g m u te x e s . B u t y o u c a n n o t lo ck m u te x e s fro m a s ig n a l-c a tc h in g fu n c tio n . S o w h ile it is legal to call f o r k fro m w ith in a s ig n a l-c a tc h in g fu n c tio n , d o in g so m a y (b eyond th e c o n tro l o r k n o w led g e o f th e caller) re q u ire p e rfo rm in g o th e r o p e ra tio n s t h a t c a n n o t b e p e rfo rm e d w ith in a s ig n a l-c a tc h in g fu n c tio n . T h is is a n in c o n s is te n c y in th e POSIX s ta n d a r d t h a t will n e e d to b e fixed. N ob od y y e t k n o w s w h a t th e e v e n tu a l s o lu tio n w ill b e. My ad v ice is to av oid u s in g f o r k in a s ig n a l-c a tc h in g fu n c tio n .

199

fork

6.1.1

Fork h a n d le rs

in t

p th re a d _ _ a t£ o rk

(v o id

( *p re p a re ) (v o id ),

void (*parent)(v o i d ), void (*child)(v o i d ));

P th r e a d s a d d e d th e p t h r e a d _ a t f o r k “fo rk h a n d le r ” m e c h a n is m to allow y o u r co d e to p ro te c t d a ta in v a ria n ts a c ro s s f o r k . T h is is s o m e w h a t a n a lo g o u s to a t e x i t , w h ic h allo w s a p ro g ra m to p e rfo rm c le a n u p w h e n a p ro c e s s te rm in a te s . W ith p t h r e a d _ a t f o r k y o u s u p p ly th r e e s e p a r a te h a n d le r a d d re s s e s . T h e p re p a re fo rk h a n d le r is called b efo re th e fo rk ta k e s p la c e in th e p a r e n t p ro c e s s . T h e p a re n t fo rk h a n d le r is called a fte r th e fo rk in th e p a r e n t p ro c e s s , a n d th e ch ild fo rk h a n d le r is ca lle d a fte r th e fo rk in th e c h ild p ro c e s s . If y o u w r ite a s u b s y s te m t h a t uses m u te x e s a n d d o e s n o t e s ta b lis h fo rk h a n d le rs , th e n t h a t s u b s y s te m w ill n o t f u n c t io n c o r r e c t ly in a c h ild p ro c e s s a f t e r a fork.

N o rm ally a p re p a re fo rk h a n d le r lo c k s all m u te x e s u s e d b y th e a s s o c ia te d co d e (for a lib ra ry o r a n ap p lic a tio n ) in th e c o rre c t o rd e r to p re v e n t d e a d lo c k s. T h e th r e a d c allin g f o r k will b lo ck in th e p re p a re fo rk h a n d le r u n til it h a s lo c k ed all th e m u te x e s . T h a t e n s u r e s t h a t n o o th e r th r e a d s c a n h a v e th e m u te x e s lo c k ed o r b e m o dify in g d a ta th a t th e ch ild m ig h t n e e d . T h e p a re n t fo rk h a n d le r n e e d o n ly u n lo c k all of th o s e m u te x e s , allo w in g th e p a r e n t p ro c e s s a n d all th r e a d s to co n tin u e n o rm a lly . T h e ch ild fo rk h a n d le r m a y o fte n b e th e s a m e a s th e p a re n t fo rk h a n d le r; b u t s o m e tim e s y o u ’ll n e e d to r e s e t th e p ro g ra m o r lib ra iy s ta te . F o r ex am p le, if y o u u s e “d a e m o n ” th r e a d s to p e rfo rm fu n c tio n s in th e b a c k g ro u n d y o u ’ll n e e d to e ith e r re c o rd th e fa c t t h a t th o s e th r e a d s n o lo n g e r e x ist o r c re a te n e w th r e a d s to p e rfo rm th e s a m e fu n c tio n in th e ch ild . You m a y n e e d to r e s e t c o u n te rs , free h e a p m em o ry , a n d so fo rth . I Y our fo rk h a n d le rs a r e o n ly as g o o d as e v e r y o n e e ls e 's fo rk h a n d le rs .

T h e s y ste m will r u n all p re p a re fo rk h a n d le r s d e c la re d in th e p ro c e s s w h e n a n y th r e a d c a lls f o r k . If y o u co d e y o u r p re p a re a n d ch ild fo rk h a n d le r s co rre c tly th e n , in p rin c ip le , y o u will b e ab le to c o n tin u e o p e ra tin g in th e c h ild p ro c e ss. B u t w h a t if so m e o n e else d id n ’t s u p p ly fo rk h a n d le r s o r d id n ’t do it rig h t? T h e ANSI C lib ra ry o n a th r e a d e d s y ste m , for e x am p le, m u s t u s e a s e t of m u te x e s to s y n c h ro n iz e in te r n a l d a ta , s u c h a s s td io file s tre a m s . If y o u u s e a n ANSI C lib ra iy t h a t d o e s n ’t s u p p ly fo rk h a n d le r s to p re p a re th o s e m u te x e s p ro p e rly for a fork, fo r ex am p le, th e n , so m e tim e s, y o u m a y find th a t

200

CH A P T E R 6

P O S I X a d ju st s to t h r ea d s

y o u r c h ild p ro c e s s h a n g s w h e n it c a lls p r i n t f , b e c a u s e a n o th e r th r e a d in th e p a r e n t p ro c e s s h a d th e m u te x lo c k ed w h e n y o u r th r e a d c a lled f o r k . T h e re ’s o ften n o th in g y o u c a n do a b o u t th is ty p e o f p ro b le m ex c e p t to file a p ro b le m re p o rt a g a in s t th e s y ste m . T h e se m u te x e s a re u s u a lly p riv a te to th e lib ra ry , a n d a re n 't v isib le to y o u r co d e—y o u c a n ’t lo ck th e m in y o u r p re p a re h a n d le r o r b efo re callin g fo rk . T h e p ro g ra m atfork.c sh o w s th e u s e o f fo rk h a n d le rs . W h en r u n w ith no a rg u m e n t, o r w ith a n o n z e ro a rg u m e n t, th e p ro g ra m w ill in s ta ll fo rk h a n d le rs . W h e n r u n w ith a zero a rg u m e n t, s u c h a s at fork 0, it w ill n o t. W ith fo rk h a n d le r s in s ta lle d , th e r e s u lt w ill b e tw o o u tp u t lin e s re p o rtin g th e r e s u lt o f th e f o r k call a n d , in p a r e n th e s e s , th e p id o f th e c u r r e n t p ro c e s s . W itho u t fo rk h a n d le r s , th e c h ild p ro c e s s w ill b e c re a te d w h ile th e in itia l th r e a d o w n s th e m u te x . B e c a u s e th e in itia l th r e a d d o e s n o t e x ist in th e ch ild , th e m u te x c an n o t b e u n lo c k e d , a n d th e ch ild p ro c e s s will h a n g —o n ly th e p a r e n t p ro c e s s will p r in t its m e ss a g e . 13-25 F u n c tio n f o r k _ p r e p a r e is th e p re p a re h a n d le r. T h is w ill b e called b y f o r k , in th e p a r e n t p ro c e s s , b efo re c re a tin g th e ch ild p ro c e s s . A ny s ta te c h a n g e d b y th is fu n c tio n , in p a rtic u la r, m u te x e s th a t a re lo ck ed , will b e co p ied in to th e c h ild pro c e s s . T h e f o r k _ p r e p a r e fu n c tio n lo c k s th e p ro g ra m ’s m u te x . F u n c tio n f o r k _ p a r e n t is th e p a re n t h a n d le r. T h is w ill b e c a lled b y f o r k , in th e 31-42 p a r e n t p ro c e s s , a fte r c re a tin g th e c h ild p ro c e s s . In g e n e ra l, a p a re n t h a n d le r s h o u ld u n d o w h a te v e r w a s d o n e in th e p re p a re h a n d le r, so t h a t th e p a r e n t p ro c e s s c a n c o n tin u e n o rm a lly . T h e f o r k _ p a r e n t fu n c tio n u n lo c k s th e m u te x th a t w a s lo c k ed b y f o r k _ p r e p a r e . 48-60 F u n c tio n fork_child is th e ch ild h a n d le r. T h is w ill b e called b y fork, in th e c h ild p ro c e s s . In m o s t c a s e s , th e ch ild h a n d le r will n e e d to do w h a te v e r w a s d o n e in th e fork_parent h a n d le r to “u n lo c k ” th e s ta te so t h a t th e ch ild c a n c o n tin u e . It m a y a lso n e e d to p e rfo rm a d d itio n a l c le a n u p , fo r ex am p le, f ork_child s e ts th e self_pid v a ria b le to th e c h ild p ro c e s s ’s p id a s w ell a s u n lo c k in g th e p ro c e s s m u te x . A fter c re a tin g a ch ild p ro c e s s , w h ic h w ill c o n tin u e e x e c u tin g th e thread_ 65-91 routine cod e, th e thread_routine fu n c tio n lo c k s th e m u te x . W h en r u n w ith fork h a n d le r s , th e fo rk call w ill b e b lo c k e d (w hen th e p re p a re h a n d le r lo c k s th e m u tex ) u n til th e m u te x is av ailab le. W ith o u t fo rk h a n d le r s , th e th r e a d w ill fork b efo re main u n lo c k s th e m u te x , a n d th e th r e a d will h a n g in th e ch ild a t th is p o in t. T h e m a in p ro g ra m d e c la re s fo rk h a n d le r s u n le s s th e p ro g ra m is r u n w ith a n 99-106 a r g u m e n t o f 0. T h e m a in p ro g ra m lo c k s th e m u te x b efo re c re a tin g th e th r e a d th a t w ill fork. It 108-123 th e n s le e p s for se v e ra l s e c o n d s , to e n s u r e t h a t th e th r e a d will b e a b le to call fork w h ile th e m u te x is lo ck ed , a n d th e n u n lo c k s th e m u te x . T h e th r e a d ru n n in g thread_routine w ill a lw ay s s u c c e e d in th e p a r e n t p ro c e s s , b e c a u s e it w ill sim p ly b lo c k u n til main re le a s e s th e lock. H owever, w ith o u t th e fo rk h a n d le rs , th e c h ild p ro c e s s will b e c re a te d w h ile th e m u te x is lo cked . T h e th re a d (main) t h a t lo ck ed th e m u te x d o e s n o t e x ist in th e ch ild , a n d c a n n o t u n lo c k th e m u te x in th e ch ild p ro c e ss. M u tex es c a n b e u n lo c k e d

201

fork

in

th e

c h ild

o n ly

if th e y w e r e lo c k e d

d le r s p r o v id e t h e



3 4 5

b e s t w a y

to

e n s u r e

b y th e

th r e a d

t h a t c a lle d

fo r k — a n d

fo r k h a n -

th a t.

atfork.c

!include !include !include !include



"errors.h"

6 pid_t self_pid; 7

/* pid of current process */ pthread_mutex_t mutex = PTHREAD__MUTEX__INITIALIZER;

8 9

/*

10 11 12 13 14 15 16 17 18 19

* This routine will be called prior to executing the fork, * within the parent process.

*/ void fork_prepare (void)

{ int status;

/* * Lock the mutex in the parent before creating the child, * to ensure that no other thread can lock it (or change any * associated shared state) until after the fork completes.

20

*/

21

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

status = pthread__mutex_lock (&mutex); if (status != 0) err_abort (status, "Lock in prepare handler");

> /* * This routine will be called after executing the fork, within * the parent process

*/ void fork_parent (void)

{ int status;

/* * Unlock the mutex in the parent after the child has been * created.

*/ status = pthread_mutex_unlock (&mutex); if (status 1= 0) err_abort (status, "Unlock in parent handler");

>

202

CH A P T E R 6

/*

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

void *thread__routine (void *arg)

66

{

* This routine will be called after executing the fork, within * the child process.

*/ void fork__child (void)

{ int status;

/* * Update the file scope "self_pid" within the child process, and * unlock the mutex.

*/ self_pid = getpid (); status = pthread__mutex__unlock (fcmutex); if (status 1= 0) err_abort (status, "Unlock in child handler");

} /* * Thread start routine, which will fork a new child process.

*/

pid__t child_pid; int status;

67 68

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

child_pid = fork (); if (child_pid == (pid_t)-l) errno_abort ("Fork");

/* * Lock the mutex — without the atfork handlers, the mutex will * remain locked in the child process and this lock attempt will * hang (or fail with EDEADLK) in the child.

*/ status = pthread_mutex_lock (Smutex); if (status != 0) err_abort (status, "Lock in child"); status = pthread_mutex_unlock (&mutex); if (status != 0) err_abort (status, "Unlock in child"); printf ("After fork: %d (%d)\n", child_pid, self_pid); if (child_pid ! = 0 ) { if ((pid_t)-l == waitpid (child_pid, (int*)0, 0)) errno_abort ("Wait for c h i l d " );

86

87 88

89 90 91 92 93

P O S I X a d ju st s t o t h r ea d s

} return NULL;

} int main (int argc, char *argv[])

203

fork

94 95 96 97 98 99

{

pthread_t fork_thread; int atfork_flag = 1; int status; if (argc > 1) atfork_flag = atoi (argv[l]); if (atfork_flag) { status = pthread_atfork ( fork_prepare, fork_parent, fork_child); if (status != 0) err_abort (status, "Register fork handlers");

100 101

102

103 104 105 106 107 108 109

}

110

self_pid = getpid (); status = pthread_mutex__lock (&mutex); if (status != 0) err_abort (status, "Lock mutex");

111

/* * Create a thread while the mutex is locked. It will fork a * process, which (without atfork handlers) will run with the * mutex locked.

112

113 114 115 116 117 118 119

*/ status = pthread_create ( &fork_thread, NULL, thread_routine, NULL); if (status != 0) err_abort (status, "Create thread"); sleep (5); status = pthread_mutex_unlock (&mutex); if (status != 0) err_abort (status, "Unlock mutex"); status = pthread_join (fork_thread, NULL); if (status != 0) err_abort (status, "Join thread"); return 0;

120 121 122

123 124 125 126 127 128

} ■

atfork.c

Now, im a g in e y o u a r e w ritin g a lib ra ry th a t m a n a g e s n e tw o rk s e rv e r c o n n e c tio n s, a n d y o u c re a te a th r e a d fo r e a c h n e tw o rk c o n n e c tio n t h a t lis te n s for serv ice re q u e s ts . In y o u r p re p a re fo rk h a n d le r y o u lo ck all of th e lib ra ry ’s m u te x e s to m a k e s u r e th e c h ild ’s s ta te is c o n s is te n t a n d re c o v e ra b le. In y o u r p a re n t fo rk h a n d le r y o u u n lo c k th o s e m u te x e s a n d re tu r n . W h e n d esig n in g th e ch ild fo rk h a n d le r, y o u n e e d to decid e ex ac tly w h a t a fork m e a n s to y o u r lib rary . If y o u w a n t to r e ta in all n e tw o rk c o n n e c tio n s in th e ch ild , th e n y o u w o u ld c re a te a n ew lis te n e r th r e a d for e a c h c o n n e c tio n a n d re c o rd th e ir id e n tifie rs in th e a p p ro p ria te d a t a s tr u c tu r e s before re le a s in g th e m u te x e s. If y o u w a n t th e ch ild to b eg in w ith n o o p e n c o n n ec tio n s, th e n y o u w o u ld lo cate th e ex istin g p a r e n t c o n n e c tio n d a ta s tr u c tu r e s a n d free th e m , clo sin g th e a s s o c ia te d files t h a t w ere p ro p a g a te d b y fork.

204

6.2

CH A P T E R 6

P O S I X a d ju st s to t h r ea d s

exec T h e exec fu n c tio n is n ’t affected m u c h b y th e p re s e n c e o f th r e a d s . T h e fu n c tio n o f exec is to w ip e o u t th e c u r r e n t p ro g ra m c o n te x t a n d re p la c e it w ith a n ew p ro g ra m . A call to exec im m e d ia te ly te rm in a te s all th r e a d s in th e p ro c e s s e x c e p t th e th r e a d callin g exec. T h ey d o n o t e x e c u te c le a n u p h a n d le r s o r th re a d -sp e c ific d a ta d e s tr u c to r s —th e th r e a d s sim p ly c e a s e to ex ist. All s y n c h ro n iz a tio n o b je c ts a lso v a n is h , e x c e p t for p s h a re d m u te x e s (m u te x e s c re a te d u s in g th e p t h r e a d _ p r o c e s s _ s h a r e d a ttr ib u te v alue) a n d p s h a re d co n d itio n v a ria b le s , w h ic h re m a in u s a b le a s lo n g a s th e s h a r e d m e m o ry is m a p p e d by s o m e p ro c e s s . You s h o u ld , how ever, u n lo c k a n y p s h a re d m u te x e s t h a t th e c u r r e n t p ro c e s s m a y h a v e lo c k ed —th e s y s te m will n o t u n lo c k th e m for yo u .

6.3 Process e xit In a n o n th r e a d e d p ro g ra m , a n ex p licit call to th e exit fu n c tio n h a s th e s a m e effect a s r e tu r n in g fro m th e p ro g ra m ’s main fu n c tio n . T h e p ro c e s s ex its. P th r e a d s a d d s th e pthread_exit fu n c tio n , w h ic h c a n b e u s e d to c a u s e a sin g le th r e a d to ex it w h ile th e p ro c e s s c o n tin u e s . In a th r e a d e d p ro g ra m , th e re fo re , y o u call exit w h e n y o u w a n t th e p ro c e s s to exit, o r pthread_exit w h e n y o u w a n t o n ly th e callin g th r e a d to exit. In a th r e a d e d p ro g ra m , main is effectively th e “th r e a d s t a r t fu n c tio n ” fo r th e p r o c e s s ’s in itia l th re a d . A lth o u g h r e tu r n in g fro m th e s t a r t fu n c tio n of a n y o th e r th r e a d te rm in a te s t h a t th r e a d j u s t a s if it h a d ca lle d pthread_exit, r e tu r n in g fro m main te rm in a te s th e p ro ce s s . All m e m o ry (a n d th re a d s ) a s s o c ia te d w ith th e p ro c e s s e v a p o ra te . T h re a d s d o n o t r u n c le a n u p h a n d le r s o r th re a d -sp e c ific d a ta d e s tr u c to r s . C allin g exit h a s th e s a m e effect. W h e n y o u d o n ’t w a n t to m a k e u s e of th e in itia l th r e a d o r m a k e it w a it for o th e r th r e a d s to co m p lete , y o u c a n ex it from main b y callin g pthread_exit r a th e r th a n b y r e tu r n in g o r c a llin g exit. C allin g pthread__exit fro m main w ill te rm in a te th e in itia l th r e a d w ith o u t affectin g th e o th e r th r e a d s in th e p ro c e s s , allo w in g th e m to c o n tin u e a n d co m p le te n o rm a lly . T h e exit fu n c tio n p ro v id e s a sim p le w ay to s h u t d o w n th e e n tire p ro c e s s . F o r e x am p le, if a th r e a d d e te rm in e s t h a t d a ta h a s b e e n sev erely c o rru p te d b y so m e e rro r, it m a y b e d a n g e ro u s to allow th e p ro g ra m to c o n tin u e to o p e ra te o n th e d a ta . W h e n th e p ro g ra m is so m e h o w b ro k e n , it m ig h t b e d a n g e ro u s to a tte m p t to s h u t d o w n th e a p p lic a tio n th r e a d s clean ly. In th a t case, y o u m ig h t call exit to sto p all p ro c e s s in g im m ed iate ly .

6.4

Stdio P th r e a d s sp ecifies t h a t th e ANSI C s ta n d a r d I /O [s td io ) f u n c tio n s a re th r e a d safe. B e c a u s e th e s td io p a c k a g e r e q u ire s s ta tic s to ra g e fo r o u tp u t b u ffe rs a n d file

20 5

Stdio

sta te ,

stdio

im p le m e n ta tio n s

w ill

u s e

s y n c h r o n iz a tio n ,

s u c h

a s

m u te x e s

o r

se m a p h o r e s.

6.4.1

f l o c k f i l e and f u n lo c k f ile

void flockfile (FILE *file); int ftrylockfile (FILE *file); void funlockfile (FILE *file);

19-20

In so m e c a s e s , it is im p o r ta n t t h a t a s e q u e n c e of s td io o p e ra tio n s o c c u r in u n in te r r u p te d s e q u e n c e ; for e x am p le, a p ro m p t followed b y a re a d fro m th e te rm in a l, o r tw o w rite s t h a t n e e d to a p p e a r to g e th e r in th e o u tp u t file ev en if a n o th e r th r e a d a tte m p ts to w rite d a ta b e tw e e n th e tw o s td io calls. T h ere fo re , P th r e a d s a d d s a m e c h a n is m to lo ck a file a n d sp ecifies h o w file lo c k in g in te r a c ts w ith in te rn a l s td io locking. To w rite a p ro m p t s trin g to stdin a n d re a d a re s p o n s e fro m stdout w ith o u t allo w in g a n o th e r th r e a d to re a d fro m stdin o r w rite to stdout b e tw e e n th e tw o, y o u w o u ld n e e d to lo ck b o th stdin a n d stdout a r o u n d th e tw o c a lls a s s h o w n in th e follow ing p ro g ra m , f lock.c. T h is is th e im p o r ta n t p a rt: Tw o s e p a r a te c a lls to flockfile a re m a d e , o n e for e a c h o f th e tw o file s tre a m s . To avoid p o ssib le d e a d lo c k p ro b le m s w ith in s td io , P th r e a d s re c o m m e n d s a lw ay s lo ck in g in p u t s tr e a m s b efo re o u tp u t s tre a m s , w h e n y o u m u s t lo ck b o th . T h a t’s go od ad v ice, a n d I’ve ta k e n it b y lo c k in g stdin b efo re stdout. T h e tw o c a lls to funlockfile m u s t, of c o u rs e , b e m a d e in th e o p p o s ite o rder. D e sp ite th e sp e c ia liz e d call, y o u a re effectively lo c k in g m u te x e s w ith in th e s td io lib ra ry , a n d y o u s h o u ld re s p e c t a c o n s is te n t lo ck h ie ra rc h y .

29-30



flock.c

1 #include 2 #include "errors.h" 3 4 /* 5 * This routine writes a prompt to stdout (passed as the thread's 6 * "arg"), and reads a response. All other I/O to stdin and stdout 7 * is prevented by the file locks until both prompt and fgets are 8 * complete. 9 */ 10 void *prompt_routine (void *arg) 11

12 13 14 15 16

{ char *prompt = (char*)arg; char *string; int len; string = (char*)malloc

(128);

206

21

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

CH A P T E R 6

P O S I X a d ju st s t o t h r ea d s

if (string == NULL) errno_abort ("Alloc string"); flockfile (stdin); flockfile (stdout); printf (prompt); if (fgets (string, 128, stdin) == NULL) string[0] = '\0 ‫; ״‬ else { len = strlen (string); if (len > 0 && string[len-1] == string[len-1] = '\ 0 ’;

'\n')

} funlockfile (stdout); funlockfile (stdin); return (void*)string;

int main (int argc, char *argv[]) { pthread_t threadl, thread2, thread3; char *string; int status; #ifdef sun /* * On Solaris 2.5, threads are not timesliced. To ensure * that our threads can run concurrently, we need to * increase the concurrency level. */ DPRINTF (("Setting concurrency level to 4\n")); thr_setconcurrency (4); #endif status = pthread_create ( &threadl, NULL, prompt__routine, "Thread 1> ") ; if (status != 0) err_abort (status, "Create thread"); status = pthread_create ( &thread2, NULL, prompt_routine, "Thread 2> "); if (status 1= 0) err_abort (status, ’,Create thread"); status = pthread_create ( &thread3, NULL, prompt_routine, "Thread 3> "); if (status 1= 0) err_abort (status, ,,Create thread”); status = pthread_join (threadl, (void**)&string); if (status != 0) err_abort (status, ”Join thread"); printf (”Thread 1: \"%s\”\n", string);

65

free

66

status = pthread_join (thread2, (void**)fcstring);

(s tr in g );

207

Stdio

67 68 69 70 71 72 73 74 75 76 77

if (status != 0) err_abort (status, "Join thread"); printf ("Thread Is \"%s\"\n", string);

free (string); status = pthread_join (thread3, (void**)&string); if (status ! = 0 ) err_abort (status, "Join thread"); printf ("Thread 12 \"%s\"\n", string);

free (string); return 0; > ■

flock.c

You c a n a lso u s e th e flockfile a n d funlockfile fu n c tio n s to e n s u r e t h a t a s e rie s of w rite s is n o t in te r r u p te d b y a file a c c e s s fro m so m e o th e r th r e a d . T h e ftrylockfile fu n c tio n w o rk s lik e pthread_mutex_trylock in t h a t it a tte m p ts to lo ck th e file a n d , if th e file is a lre a d y lo ck ed , r e t u r n s a n e rro r s t a t u s in s te a d of b lo ck in g .

6.4.2 getchar unlocked and putchar unlocked in t

g e tc _ u n lo c k e d

ih t

g e tc h a r ^ u n lo c k e d

{ F IL E

in t

p u tc _ u n lo c k e d

in t

p u tc h a r _ u n lo c k e d

*s tre a m );

(v o id );

(in t

c,

(in t

F IL E

*s tre a m );

c );

ANSI C p ro v id e s fu n c tio n s to g e t a n d p u t sin g le c h a r a c te r s efficiently in to b u ffe rs. T h e f u n c tio n s getchar a n d putchar o p e ra te o n stdin a n d stdout, resp ectiv ely , a n d getc a n d putc c a n b e u s e d o n a n y s td io file s tre a m . T h e s e a re tra d itio n a lly im p le m e n te d a s m a c ro s for m a x im u m p e rfo rm a n c e , d ire c tly re a d in g o r w ritin g th e file s tr e a m ’s d a ta b u ffer. P th re a d s , how ev er, re q u ire s th e s e fu n c tio n s to lo ck th e s td io s tr e a m d a ta , to p re v e n t co d e fro m a c c id e n ta lly c o rru p tin g th e s td io b u ffe rs. T h e o v e rh e a d of lo c k in g a n d u n lo c k in g m u te x e s w ill p ro b a b ly v a s tly ex ceed th e tim e s p e n t p e rfo rm in g th e c h a r a c te r copy, so th e s e f u n c tio n s a re n o lo n g e r h ig h p e rfo rm a n c e . P th r e a d s c o u ld h a v e d efin e d n e w fu n c tio n s th a t p ro v id ed th e lo c k ed v a rie ty r a th e r t h a n re d e fin in g th e e x istin g fu n c tio n s ; ho w ever, th e r e s u lt w o u ld b e t h a t e x istin g co d e w o u ld b e u n s a fe fo r u s e in th r e a d s . T h e w o rk in g g ro u p d e c id e d t h a t it w a s p re fe ra b le to m a k e e x istin g co d e slow er, r a th e r t h a n to m a k e it in c o rre c t. P th re a d s a d d s n ew fu n c tio n s th a t rep lace th e old h ig h -p e rfo rm a n c e m a c ro s w ith esse n tia lly th e sa m e im p le m e n ta tio n a s th e tra d itio n a l m a cro s. T h e fu n c tio n s getc_ unlocked, putc_unlocked, getchar_unlocked, a n d putchar_unlocked do n o t p e rform a n y locking, so you m u s t u s e flockfile a n d funlockfile a ro u n d a n y s td io

208

P O S I X a d ju st s t o t h r ea d s

s e q u e n c e of th e se o p eratio n s. If yo u w a n t to re a d or w rite a single ch ara cter, you sh o u ld u s u a lly u s e th e locked varie ty ra th e r th a n lo cking th e file stre a m , calling th e new u n lo c k ed get o r p u t fu n ctio n , a n d th e n u n lo c k in g th e file stre a m . If y o u w a n t to p e rfo rm a s e q u e n c e of fa s t c h a r a c te r a c c e s s e s , w h e re y o u w o u ld h a v e p re v io u sly u s e d getchar a n d putchar, y o u c a n n o w u s e getchar_unlocked a n d putchar_unlocked. T h e follow ing p ro g ra m , putchar.c, s h o w s th e d ifferen ce b e tw e e n u s in g putchar a n d u s in g a s e q u e n c e o f putchar_unlocked c a lls w ith in a file lock. W h e n th e p ro g ra m is r u n w ith a n o n z e ro a r g u m e n t o r n o a r g u m e n t a t all, it c re a te s th r e a d s r u n n in g th e lock_routine fu n c tio n . T h is fu n c tio n lo c k s th e stdout file s tre a m , a n d th e n w rite s its a r g u m e n t (a strin g ) to stdout o n e c h a r a c te r a t a tim e u s in g putchar_unlocked. W h en th e p ro g ra m is r u n w ith a zero a rg u m e n t, it c re a te s th r e a d s r u n n in g th e unlock_routine fu n c tio n . T h is fu n c tio n w rite s its a r g u m e n t to stdout o n e c h a r a c te r a t a tim e u s in g putchar. A lth o u g h putchar is in te rn a lly s y n c h ro n iz e d to e n s u r e t h a t th e stdio b u ffe r is n o t c o rru p te d , th e in d iv id u a l c h a r a c te r s m a y a p p e a r in a n y o rd er.

9-20

28-37

■ 1 2 3 4 5 6 7

CH A P T E R 6

putchar.c #include #include "errors.h" /* * This function writes a string (the function's arg) to stdout, * by locking the file stream and using putchar_unlocked to write * each character individually.

8

*/

9 void *lock_routine

(void *arg)

10 { 11

char *pointer;

12

13 14 15 16

flockfile (stdout); for (pointer = arg; *pointer != '\0'; pointer++) putchar_unlocked (*pointer); sleep (1);

17

}

18 19

funlockfile (stdout); return NULL;

20

{

}

21 22

/*

23 24 25 26 27 28

* This function writes a string (the function's arg) to stdout, * by using putchar to write each character individually. * Although the internal locking of putchar prevents file stream * corruption, the writes of various threads may be interleaved. */ void *unlock_routine (void *arg)

209

T h r e a d -s a f e J u n c t i o n s

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

{ char *pointer; for (pointer = arg; *pointer putchar (*pointer); sleep (1); } return NULL;

!= 0 \‫ ;' ׳‬pointer++)

{

> int main (int argc, char *argv[]) { pthread_t threadl, thread2, thread3; int flock_flag = 1; void *(*thread_func)(void *); int status; if (argc > 1) flock_flag = atoi (argv[l]); if (flock_flag) thread_func = lock_routine; else thread_func = unlock_routine; status = pthread_create ( &threadl, N U L L , thread_func, "this is thread l\n‫;) ״‬ if (status != 0) err__abort (status, ‫ ״‬Create thre a d ‫;) ״‬ status = pthread_create ( &thread2, N U L L , thread_func, "this is thread 2\n"); if (status != 0) err_abort (status, "Create thread"); status = pthread_create ( &thread3, N U L L , thread_func, "this is thread 3\n"); if (status != 0) err_abort (status, "Create thread"); pthread_exit ( N U L L ) ; } ■

putchar.c

6.5 T h re a d -sa fe fu n c tio n s A lth o u g h ANSI C a n d POSIX 1 0 0 3 .1 -1 9 9 0 w ere n o t d ev elo p ed w ith th r e a d s in m in d , m o s t o f th e fu n c tio n s th e y d efin e c a n b e m a d e th re a d -s a fe w ith o u t c h a n g in g th e e x te rn a l in te rfa c e . F o r ex am p le, a lth o u g h m a llo c a n d free m u s t b e c h a n g e d to s u p p o r t th r e a d s , code c a llin g th e s e fu n c tio n s n e e d n o t b e a w a re o f th e c h a n g e s . W h e n y o u call m a llo c , it lo c k s a m u te x (or p e r h a p s se v e ra l m u te x e s) to

210

CH A P T E R 6

P O S I X a d ju st s to t h r ea d s

p e rfo rm th e o p e ra tio n , o r m a y u s e o th e r e q u iv a le n t s y n c h ro n iz a tio n m e c h a n is m s . B u t y o u r co d e j u s t ca lls m a llo c a s it a lw ay s h a s , a n d it d o e s th e s a m e th in g a s alw ay s. In tw o m a in c la s s e s of fu n c tio n s , th is is n o t tru e : •



F u n c tio n s t h a t tra d itio n a lly r e tu r n p o in te rs to in te r n a l s ta tic b u ffe rs, for ex am p le, a s c tim e . A n in te r n a l m u te x w o u ld n ’t h e lp , s in c e th e c a lle r w ill re a d th e fo rm a tte d tim e s trin g so m e tim e a fte r th e fu n c tio n r e tu r n s a n d , th e re fo re , a fte r th e m u te x h a s b e e n u n lo c k e d . F u n c tio n s t h a t re q u ire s ta tic c o n te x t b e tw e e n a s e rie s o f calls, for ex am p le, strtok, w h ic h s to re s th e c u r r e n t p o s itio n w ith in th e to k e n s trin g in a lo cal s ta tic v a ria b le . A gain, u s in g a m u te x w ith in strtok w o u ld n ’t h elp , b e c a u s e o th e r th r e a d s w o u ld b e a b le to o v erw rite th e c u r r e n t lo c a tio n b e tw e e n tw o calls.

In th e s e c a s e s , P th r e a d s h a s d efin e d v a r ia n ts o f th e e x istin g f u n c tio n s t h a t a re th re a d -s a fe , w h ic h a re d e s ig n a te d b y th e su ffix “_ r ” a t th e e n d of th e fu n c tio n n a m e . T h e se v a r ia n ts m ove c o n te x t o u ts id e th e lib rary , u n d e r th e c a lle r’s co n tro l. W h e n e a c h th r e a d u s e s a p riv a te b u ffe r o r c o n te x t, th e fu n c tio n s a re th re a d -s a fe . You c a n a lso s h a r e c o n te x t b e tw e e n th r e a d s if y o u w a n t—b u t th e c a lle r m u s t p ro v id e s y n c h ro n iz a tio n b e tw e e n th e th r e a d s . If y o u w a n t tw o th r e a d s to s e a r c h a d ire c to ry in p a ra lle l, y o u m u s t sy n c h ro n iz e th e ir u s e of th e s h a r e d s t r u c t d i r e n t p a s s e d to r e a d d i r _ r . A few e x istin g fu n c tio n s , s u c h a s c te r m id , a re a lre a d y th re a d -s a fe a s lo n g a s c e rta in re s tric tio n s a re p la c e d o n p a ra m e te rs . T h e s e r e s tric tio n s a re n o te d in th e follow ing se c tio n s .

6.5.1

User a n d te rm in a l id e n tific a tio n

int getlogin_r (char *name, size_t namesize); char *ctermid (char * 8 ) ‫ן‬ int ttyname_r (int fildes, char *name, size_t nameeize);

T h e s e fu n c tio n s r e t u r n d a ta to a c a lle r-sp e c ifie d b u ffer. F o r getlogin_r, namesize m u s t b e a t le a s t LOG IN_NAME_MAX c h a r a c te r s . F o r ttyname_r, names ize m u s t b e a t le a s t t t y _ n a m e _ m a x c h a r a c te r s . E ith e r fu n c tio n r e t u r n s a v a lu e o f 0 o n s u c c e s s , o r a n e rro r n u m b e r o n failu re. In a d d itio n to e rro rs t h a t m ig h t be r e tu r n e d b y getlogin o r ttyname, getlogin_r a n d ttyname_r m a y r e t u r n ERANGE to in d ic a te t h a t th e name b u ffe r is to o sm all. P th r e a d s re q u ire s th a t w h e n ctermid (w hich h a s n o t ch a n g e d ) is u s e d in a th r e a d e d e n v iro n m e n t, th e s r e tu r n a r g u m e n t m u s t b e sp ecified a s a p o in te r to a

211

T h r e a d -s a f e J u n c t i o n s

c h a r a c te r w a s

b u ffe r

h a v in g

P r o g r a m

get login, c

tio n s

n o t

d e p e n d

o n

s y s te m s

d o

p r o v id e d



a t

s h o w s o n

L_ctermid

le a s t

s u ffic ie n t, w ith o u t d e fin in g

a

n e w

b y te s .

v a r ia n t to th e s e

It w a s

a ls o

h o w

to

c a ll

th r e a d s,

o r

,

fu n c tio n s . in

fe lt th a t

s p e c ify th e

a n y

N o tic e w a y ,

th is

s iz e th a t a n d

r e s tr ic tio n

o f th e b u ffe r . th e s e

m a y

t h a t d o n ’t s u p p o r t t h r e a d s .

getlogin.c

!include !include "errors.h"

2

3 4 5

/* * * * *

6

7 8

If either TTY_NAME_MAX or LOGIN_NAME_MAX are undefined (this means they are "indeterminate" values), assume a reasonable size (for simplicity) rather than using sysconf and dynamically allocating the buffers.

*/

9

!ifndef TTY_NAME_MAX ! define TTY_NAME_MAX !endif !ifndef LOGIN_NAME_MAX ! define LOGIN_NAME_MAX !endif

10 11

12

13 14 15 16 17 18 19

128

32

int main (int argc, char *argv[])

{ char login_str[LOGIN_NAME_MAX]; char stdin_str[TTY_NAME_MAX]; char cterm_str[L_ctermid], *cterm_str_ptr; int status;

20 21

22

23 24 25 26 27 28 29 30 31 32 33 34 35 36

status = getlogin_r (login_str, sizeof (login_str)); if (status != 0) err_abort (status, "Get login"); cterm_str_j?tr = ctermid (cterm_str); if (cterm_str_ptr == NULL) errno_abort ("Get c t e r m " ); status = ttyname_r (0, stdin_str, sizeof (stdin_str)); if (status != 0) err_abort (status, "Get stdin"); printf ("User: %s, cterm: %s, fd 0: % s\n", login_str, cterm_str, stdin__str); return 0;



} getlogin.c

fu n c -

e v e n

b e

212

6 .5 .2

chapter 6

P O S I X a d ju st s to t h r ea d s

D ire c to ry s e a rc h in g

int readdir_r (DIR *dirp, struct dirent *entry, struct dirent **result);

T h is fu n c tio n p e rfo rm s e s s e n tia lly th e s a m e a c tio n a s r e a d d i r . T h a t is, it r e t u r n s th e n e x t d ire c to ry e n try in th e d ire c to ry s tr e a m sp ecified b y d i r p . T h e diffe re n c e is t h a t in s te a d of r e tu r n in g a p o in te r to t h a t e n try , it co p ie s th e e n try in to th e b u ffe r sp ecified b y entry. O n s u c c e s s , it r e tu r n s 0 a n d s e ts th e p o in te r sp ecified b y result to th e b u ffe r entry. O n r e a c h in g th e e n d o f th e d ire c to ry s tre a m , it r e t u r n s 0 a n d s e ts result to n u l l . O n failu re, it r e t u r n s a n e rro r n u m b e r s u c h a s EBADF.

Refer to p ro g ra m p i p e . c, in S ectio n 4 .1 , for a d e m o n stra tio n o f u s in g readdir_r to allow y o u r th re a d s to s e a rc h m u ltip le d irec to rie s c o n c u rre n tly .

6 .5 .3

String to k e n

char *strtok_r ( char *s, const char *sep, char **lasts);

T h is fu n c tio n r e tu r n s th e n e x t to k e n in th e s trin g s. U n lik e strtok, th e co nte x t (th e c u r r e n t p o in te r w ith in th e o rig in al strin g ) is m a in ta in e d in lasts, w h ic h is sp ecified b y th e caller, r a th e r th a n in a s ta tic p o in te r in te r n a l to th e fu n c tio n . In th e firs t call of a s e rie s, th e a r g u m e n t s gives a p o in te r to th e s trin g . In s u b s e q u e n t c a lls to r e t u r n s u c c e s s iv e to k e n s o f t h a t s trin g , s m u s t b e sp ecified a s n u l l . T h e v a lu e lasts is s e t by strtok_r to m a in ta in th e fu n c tio n ’s p o sitio n w ith in th e strin g , a n d o n e a c h s u b s e q u e n t call y o u m u s t r e tu r n t h a t s a m e v a lu e o f lasts. T h e strtok_r fu n c tio n r e tu r n s a p o in te r to th e n e x t to k e n , o r NULL w h e n th e re a re n o m o re to k e n s to b e fo u n d in th e o rig in al s trin g .

6 .5 .4

T im e re p re s e n ta tio n

char *asctime^r (const struct tm *tin, char * b u f ); char *ctime_r (const time_jt *clock, char *buf); struct tm *gmt 1 me_r ( const t 1 me_t *clock, struct tm *result); struct tm *localtime_r ( const time_t *clock, struct tm *result);

T h r e a d -s a f e f u n c t i o n s

213

T h e o u tp u t b u ffe rs (bu f a n d r e s u l t ) a re su p p lie d b y th e caller, in s te a d of r e tu r n in g a p o in te r to s ta tic s to ra g e in te r n a l to th e fu n c tio n s . O th erw ise, th e y a re id e n tic a l to th e tra d itio n a l v a ria n ts . T h e a s c ti m e _ r a n d c tim e _ r ro u tin e s , w h ich r e t u r n ASCII c h a r a c te r re p r e s e n ta tio n s of a s y s te m tim e, b o th re q u ire t h a t th e ir b u f a rg u m e n t p o in t to a c h a r a c te r s trin g of a t le a s t 2 6 b y te s.

6 .5 .5

R a n d o m n u m b e r g e n e ra tio n

i n t r a n d _ r ( u n s ig n e d i n t * s e e d ) ; T h e se e d is m a in ta in e d in c a lle r-s u p p lie d s to ra g e (seed) r a th e r th a n u s in g s ta tic s to ra g e in te r n a l to th e fu n c tio n . T h e m a in p ro b le m w ith th is in te rfa c e is t h a t it is n o t u s u a lly p ra c tic a l to h a v e a sin g le se e d s h a r e d b y all a p p lic a tio n a n d lib ra ry co d e w ith in a p ro g ra m . A s a r e s u lt, th e a p p lic a tio n a n d e a c h lib ra ry will g en e ra lly h a v e a s e p a r a te “s tr e a m ” of r a n d o m n u m b e rs . T h u s , a p ro g ra m c o n ‫־‬ v e rte d to u s e r a n d _ r in s te a d of r a n d is likely to g e n e ra te d iffe re n t r e s u lts , even if n o th r e a d s a re c re a te d . (C re a tin g th r e a d s w o u ld p ro b a b ly c h a n g e th e o rd e r of c a lls to ra n d , a n d th e re fo re c h a n g e r e s u lts an yw ay .)

6 .5 .6

G ro u p a n d user d a ta b a s e Gro up d at abase :

i n t g e tg rg id _ r ( g i d _ t g i d , s t r u c t g ro u p * g r p , c h a r * b u f f e r , s i z e _ t b u f s i z e , s t r u c t g ro u p * * r e s u l t ) ; i n t g e tg rn a m _ r ( c o n s t c h a r *nam e, s t r u c t g ro u p * g r p , c h a r * b u f f e r , s i 2e _ t b u f s i z e , s t r u c t g ro u p * * r e s u l t ) ; Use r d at abase :

i n t g e tp w u id _ r ( u i d _ t u i d , s t r u c t p assw d *pwd, c h a r * b u f f e r , s i z e _ t b u f s i z e , s t r u c t p assw d * * r e s u l t ) ; i n t getpw nam _r ( c o n s t c h a r *nam e, s t r u c t p assw d *pwd, ch ar * b u ffe r, s iz e _ t b u fs iz e , s t r u c t p assw d * * r e s u l t ) ; T h e s e fu n c tio n s sto re a co py of th e g ro u p o r u s e r re c o rd (g rp o r pwd, re s p e c tively) fo r th e sp ecified g ro u p or u s e r (g id , u id , o r name) in a b u ffe r d e s ig n a te d b y

214

CH A P T E R 6

P O S I X a d ju st s t o t h r ea d s

th e a r g u m e n ts buffer a n d bufsize. T h e fu n c tio n r e t u r n v a lu e is in e a c h c a s e e ith e r 0 fo r s u c c e s s , o r a n e rro r n u m b e r (su c h a s ERANGE w h e n th e b u ffe r is too sm all) to d e s ig n a te a n erro r. If th e re q u e s te d re c o rd is n o t p r e s e n t in th e g ro u p o r p assw d d a ta b a s e , th e fu n c tio n s m a y r e tu r n s u c c e s s b u t s to re th e v a lu e n u l l in to th e result p o in te r. If th e re c o rd is fo u n d a n d th e b u ffe r is la rg e e n o u g h , result b e c o m e s a p o in te r to th e struct group o r struct p assw d re c o rd w ith in buffer. T h e m a x im u m re q u ire d size for b u f f e r c a n b e d e te rm in e d b y c a llin g s y s c o n f w ith th e a r g u m e n t _sc_GETGR_R_s 1 z e _ m a x (for g ro u p d a ta ) o r w ith th e a r g u m e n t _SC_GETPW__R_S1ZE_MAX (for u s e r d ata).

6.6 Signals B e w a re th e J a b b e rw o c k , m y son! The ja w s th a t b ite , th e c la w s th a t c a tc h ! B e w a re th e J u b ju b bird, a n d shun The frum ious B a n d e rs n a tc h !

—Lewis Carroll,Through the Looking-Glass

T h e h is to ry of th e P th r e a d s s ig n a l-h a n d lin g m o d e l is th e m o s t c o n v o lu te d a n d c o n fu s in g p a r t of th e s ta n d a r d . T h e re w ere se v e ra l d iffe re n t v ie w p o in ts, a n d it w a s d ifficu lt to d ev ise a c o m p ro m ise t h a t w o u ld s a tisfy ev ery o n e in th e w o rk in g g ro u p (m u c h le s s th e la rg e r a n d m o re d iv e rse b a llo tin g g ro u p ). T h is is n ’t s u r p r is ‫־‬ ing, s in c e s ig n a ls a r e c o m p lic a te d an y w ay , a n d h a v e a w idely d iv e rg e n t h is to ry in th e in d u s try . T h e re w ere tw o p rim a ry co n flictin g go als: •



F irs t, “s ig n a ls s h o u ld b e co m p lete ly c o m p a tib le w ith tra d itio n a l UNIX.” T h a t m e a n s sig n a l h a n d le r s a n d m a s k s s h o u ld re m a in a s s o c ia te d w ith th e p ro c e s s . T h a t m a k e s th e m v irtu a lly u s e le s s w ith m u ltip le th r e a d s , w h ic h is a s it s h o u ld b e s in c e s ig n a ls h a v e c o m p lic a tin g s e m a n tic s t h a t m a k e it d ifficu lt for s ig n a ls a n d th r e a d s to c o e x ist p eacefu lly . T a s k s s h o u ld b e a c c o m p lish e d s y n c h ro n o u s ly u s in g th r e a d s r a th e r t h a n a s y n c h ro n o u s ly u s in g s ig n a ls. S e c o n d , “s ig n a ls s h o u ld b e c o m p lete ly c o m p a tib le w ith tra d itio n a l UNIX.” T h is tim e, “c o m p a tib le ” m e a n s sig n a l h a n d le r s a n d m a s k s s h o u ld b e co m p le tely th re a d -p riv a te . M ost e x istin g UNIX co d e w o u ld th e n fu n c tio n e s s e n tia lly th e s a m e r u n n in g w ith in a th r e a d a s it h a d w ith in a p ro c e ss. C ode m ig ra tio n w o u ld b e sim p lified .

T h e p ro b le m is t h a t th e d efin itio n s of “c o m p a tib le ” w ere in c o m p a tib le . A lth o u g h m a n y p eo p le involved in th e n e g o tia tio n m a y n o t ag ree w ith th e fin al re s u lt, n e a rly ev ery o n e w o u ld a g re e t h a t th o s e w ho d ev ised th e c o m p ro m ise d id a n e x tra o rd in a rily good jo b , a n d t h a t th e y w ere q u ite c o u ra g e o u s to a tte m p t th e feat.

215

Signals

I

W h e n w ritin g t h r e a d e d c o d e , t r e a t s ig n a ls as J a b b e r w o c k s — c u rio u s a n d p o te n t ia lly d a n g e r o u s c r e a tu r e s to b e a p p r o a c h e d w ith c a u t io n , if a t all.

It is alw ay s b e s t to av oid u s in g sig n a ls in c o n ju n c tio n w ith th re a d s . A t th e s a m e tim e, it is often n o t p o ssib le o r p ra c tic a l to k e e p th e m s e p a ra te . W h e n s ig n a ls a n d th r e a d s m eet, b ew are. If a t £111 p o ssib le , u s e o n ly pthread_sigmask to m a s k sig n a ls in th e m a in th re a d , a n d sigwait to h a n d le s ig n a ls s y n c h ro n o u s ly w ith in a sin g le th re a d d e d ic a te d to t h a t p u rp o s e . If y o u m u s t u s e sigaction (or eq u iv alen t) to h a n d le s y n c h ro n o u s s ig n a ls (su ch a s s i g s e g v ) w ith in th re a d s , b e esp ecially c a u tio u s. Do a s little w ork a s p o ssib le w ith in th e sig n a l-c a tc h in g fu n c tio n .

6.6.1

S ig n al a c tio n s All sig n a l a c tio n s a re p ro c e ss-w id e . A p ro g ra m m u s t c o o rd in a te a n y u s e o f s i g a c t i o n b e tw e e n th r e a d s . T h is is n o n m o d u la r, b u t a lso rela tiv e ly sim p le, a n d s ig n a ls h a v e n e v e r b e e n m o d u la r. A fu n c tio n t h a t d y n a m ic a lly m o d ifies sig n a l a c tio n s , for e x am p le, to c a tc h o r ig n o re s i g f p e w h ile it p e rfo rm s flo a tin g -p o in t o p e ra tio n s , o r s i g p i p e w h ile it p e rfo rm s n e tw o rk I/O , will b e tric k y to co d e o n a th r e a d e d sy ste m . W hile m odifying th e p ro c e s s sig n a l actio n , for a sig n a l n u m b e r is itse lf th re a d safe, th e re is n o p ro te c tio n a g a in s t so m e o th e r th re a d s e ttin g a n e w sig n a l a c tio n im m ed iately a fte rw ard . E v en if th e code trie s to b e “good” b y sav in g th e o rig in al sig n a l a c tio n a n d re s to rin g it, it m a y b e foiled b y a n o th e r th re a d , a s sh o w n in F ig u re 6 .1 . S ig n a ls th a t a re n o t “tie d ” to a sp ecific h a rd w a re e x e c u tio n c o n te x t a re delive re d to o n e a r b itr a r y th r e a d w ith in th e p ro c e s s . T h a t m e a n s a s i g c h l d ra is e d b y a c h ild p ro c e s s te rm in a tio n , for ex am p le, m a y n o t b e deliv ered to th e th r e a d th a t c re a te d th e ch ild . S im ilarly , a call to k i l l r e s u lts in a sig n a l t h a t m a y b e d eliv ered to a n y th re a d . T hre ad 2

T hread 1 sigaction ( SIGFPE )

T h re a d l ’s sig n a l a c tio n activ e. , sigaction(SIGFPE)

G e n e ra te

T h re a d 2 ’s sig n a l a c tio n activ e. T h re a d 1 sig n a l is h a n d le d b y th e th r e a d 2 sig n a l a c tio n (b u t still in th e c o n te x t of th r e a d 1).

sigfpe

T h re a d 1 r e s to re s o rig in al sig n a l a c tio n .

R e sto re a c tio n re s to re a c tio n FIGURE 6.1

Co m m e nt s

N on m od u larity o f s ignal actions

T h re a d 2 r e s to r e s th r e a d 1 s sig n a l a c tio n — o rig in a l a c tio n is lo st.

216

CHAPTER 6

P O S I X a d ju st s to t h r ea d s

T h e s y n c h r o n o u s “h a rd w a re c o n te x t” sig n a ls, in c lu d in g s i g f p e , s i g s e g v , a n d d eliv ered to th e th r e a d t h a t c a u s e d th e h a rd w a re c o n d itio n , n e v e r to a n o th e r th re a d . s i g t r a p , a re

I

Y ou c a n n o t kill a t h r e a d b y s e n d in g it a SIGKILL o r s to p a t h r e a d b y s e n d in g it a SIGSTOP

A ny sig n a l t h a t affected a p ro c e s s still affects th e p ro c e s s w h e n m u ltip le th r e a d s a re activ e, w h ic h m e a n s t h a t s e n d in g a s i g k i l l to a p ro c e s s o r to a n y sp ecific th r e a d in th e p ro c e s s (u sin g p t h r e a d _ k i l l , w h ic h w e’ll g et to in S ectio n 6.6.3) will te rm in a te th e p ro c e s s . S e n d in g a s i g s t o p w ill c a u s e all th r e a d s to s to p u n til a s i g c o n t is receiv ed . T h is e n s u r e s t h a t e x istin g p ro c e s s c o n tro l f u n c tio n s co n tin u e to w o rk —o th e rw ise m o s t th r e a d s in a p ro c e s s co u ld c o n tin u e r u n n in g w h e n y o u s to p p e d a c o m m a n d b y s e n d in g a s i g s t o p . T h is a lso a p p lie s to th e d e fa u lt a c tio n o f th e o th e r s ig n a ls, for ex am p le, s i g s e g v , if n o t h a n d le d , will te rm in a te th e p ro c e s s a n d g e n e ra te a co re file—it w ill n o t te rm in a te only th e th r e a d th a t g e n e ra te d th e s i g s e g v . W h a t d o e s th is m e a n to a p ro g ra m m e r? It h a s a lw ay s b e e n c o m m o n w isd o m t h a t lib ra ry co d e s h o u ld n o t c h a n g e s ig n a l a c tio n s —t h a t th is is ex clu siv ely th e p ro v in c e of th e m a in p ro g ra m . T h is p h ilo so p h y b e c o m e s ev en m o re w ise w h e n y o u a re p ro g ra m m in g w ith th r e a d s . S ig n a l a c tio n s m u s t a lw ay s b e u n d e r th e co n tro l o f a sin g le c o m p o n e n t, a t le a st, a n d to a s s ig n th a t re s p o n s ib ility to th e m a in p ro g ra m m a k e s th e m o s t s e n s e in n e a rly all s itu a tio n s .

6 .6 .2

S ig n a l m asks

int pthread_sigmask (int how, const sigset^t *set, sigset_t *oset);

E a c h th r e a d h a s its o w n p riv a te sig n a l m a s k , w h ic h is m odified b y callin g pthread_sigmask. P th r e a d s d o e s n o t specify w h a t sigprocmask d o e s w ith in a th r e a d e d p ro c e s s —it m a y do n o th in g . P o rta b le th r e a d e d co d e d o e s n o t call sigprocmask. A th r e a d c a n b lo c k o r u n b lo c k s ig n a ls w ith o u t affectin g th e ab ility of

o th e r th r e a d s to h a n d le th e sig n al. T h is is p a rtic u la rly im p o r ta n t fo r s y n c h ro n o u s s ig n a ls. It w o u ld b e a w k w a rd if th r e a d A w ere u n a b le to p ro c e s s a s i g f p e b e c a u s e th re a d B w a s c u rre n tly p ro c e ssin g its ow n SIGFPE or. ev en w o rse, b e c a u s e th re a d C h a d b lo ck ed SIGFPE. W h e n a th r e a d is c re a te d , it in h e rits th e sig n a l m a s k of th e th r e a d t h a t c re a te d it—if y o u w a n t a sig n al to b e m a s k e d everyw here, m a s k it first th in g in main.

217

Signals

6 .6 .3

p th re a d jc ill

int pthread_kill (pthread_t thread, int sig);

W ith in a p ro c e s s , o n e th r e a d c a n s e n d a sig n a l to a sp ecific th r e a d (in clu d in g itself) b y c a llin g pthread_kill. W h e n c allin g pthread_kill, y o u sp ecify n o t on ly th e sig n a l n u m b e r to b e d eliv ered , b u t a lso th e p t h r e a d _ t id e n tifie r for th e th r e a d to w h ich y o u w a n t th e sig n al se n t. You c a n n o t u s e pthread_kill to s e n d a sig n al to a th re a d in a n o th e r p ro cess, how ever, b e c a u s e a th re a d id en tifier (pthread__t) is m e an in g fu l only w ith in th e p ro c e ss th a t c re a te d it. T h e sig n a l s e n t b y pthread_kill is h a n d le d like a n y o th e r sig n a l. If th e “ta r g e t” th r e a d h a s th e sig n a l m a s k e d , it w ill b e m a rk e d p e n d in g a g a in s t t h a t th re a d . If th e th r e a d is w a itin g for th e sig n a l in sigwait (covered in S e c tio n 6 .6 .4 ), th e th r e a d will receiv e th e signed. If th e th r e a d d o e s n o t h a v e th e sig n a l m a s k e d , a n d is n o t b lo c k e d in sigwait, th e c u r r e n t s ig n a l a c tio n w ill b e ta k e n . R e m e m b e r th a t, a s id e from s ig n a l-c a tc h in g fu n c tio n s , s ig n a l a c tio n s affect th e p ro c e s s . S e n d in g th e SIGKILL sig n a l to a sp ecific th r e a d u s in g pthread_kill will kill th e p ro c e s s , n o t j u s t th e sp ecified th re a d . U se pthread_cancel to g et rid of a p a r tic u la r th r e a d (see S e c tio n 5.3). S e n d in g S1GST0P to a th r e a d will s to p all th r e a d s in th e p ro c e s s u n til a SIGC0NT is s e n t b y so m e o th e r p ro c e s s . T h e r a i s e fu n c tio n specified b y ANSI C h a s tra d itio n a lly b e e n m a p p e d to a kill fo r th e c u r r e n t p ro c e s s . T h a t is, r a i s e (S1GABRT) is u s u a lly th e s a m e a s kill ( g e t p i d ( ) , SI G A B R T ). W ith m u ltip le th r e a d s , co d e c a llin g raise is m o s t likely to in te n d th a t th e sign a l b e s e n t to th e c a llin g th re a d , r a th e r th a n to so m e a r b itr a r y th r e a d w ith in th e p ro c e s s . P th re a d s sp ecifies t h a t raise (SIGABRT) is th e s a m e a s pthread_kill (pthread_self

(), SIGABRT).

T h e follow ing p ro g ra m , susp.c, u s e s pthread_kill to im p le m e n t a p o rta b le “s u s p e n d a n d r e s u m e ” (or, e q u iv alen tly , “s u s p e n d a n d c o n tin u e ”) c a p a b ility m u c h like t h a t p ro v id ed b y th e S o la ris “UI th r e a d s ” in te rfa c e s thr_suspend a n d thr_continue. You call th e thd_suspend fu n c tio n w ith th e pthread_t o f a th re a d , a n d w h e n th e fu n c tio n r e tu r n s , th e sp ecified th r e a d h a s b e e n s u s p e n d e d from e x e c u tio n . T h e th r e a d c a n n o t e x e c u te u n til a la te r cedi to thd_continue is m a d e w ith th e s a m e p th r e a d _ t. A r e q u e s t to s u s p e n d a th r e a d t h a t is a lre a d y s u s p e n d e d h a s n o effect. C allin g thd_continue a sin g le tim e for a s u s p e n d e d th r e a d w ill c a u s e it to r e s u m e ex ecu tio n , ev en if it h a d b e e n s u s p e n d e d b y m u ltip le c a lls to thd_suspend. C allin g thd_ continue for a th r e a d t h a t is n o t c u rre n tly s u s p e n d e d h a s n o effect.

* T h e a lg o r it h m (a n d m o s t o f t h e c o d e ) fo r s u s p . c w a s d e v e lo p e d b y a c o w o r k e r o f m in e , B r ia n S ilv e r . T h e c o d e s h o w n h e r e is a s im p lif ie d v e r s io n fo r d e m o n s t r a t io n p u r p o s e s .

218

CH A P T E R 6

P O S I X a d ju st s t o t h r ea d s

S u s p e n d a n d r e s u m e a re co m m o n ly u s e d to solve so m e p ro b lem s, for ex am p le, m u ltith re a d g a rb a g e co lle cto rs, a n d m a y ev en w o rk s o m e tim e s if th e p ro g ra m m e r is v ery care fu l. T h is e m u la tio n of s u s p e n d a n d re s u m e m a y th e re fo re b e v a lu a b le to th e few p ro g ra m m e rs w h o really n e e d th e s e fu n c tio n s . B ew are, how ever, th a t s h o u ld y o u s u s p e n d a th r e a d w hile it h o ld s so m e re s o u rc e (su c h a s a m u tex ), a p p lic a tio n d e a d lo c k c a n easily re s u lt. 6 T h e sy m b o l i t e r a t i o n s d e fin e s h o w m a n y tim e s th e “ta rg e t” th r e a d s w ill loop. If th is v a lu e is s e t to o sm a ll, so m e o r all o f th e th r e a d s will te rm in a te b efo re th e m a in th r e a d h a s b e e n a b le to s u s p e n d a n d c o n tin u e th e m a s it d e sire s. If t h a t h a p p e n s , th e p ro g ra m will fail w ith a n e rro r m e ssa g e —in c re a s e th e v a lu e of i t e r a t i o n s u n til th e p ro b le m goes aw ay. 12 T h e v a ria b le sentinel is u s e d to s y n c h ro n iz e b e tw e e n a s ig n a l-c a tc h in g fu n c tio n a n d a n o th e r th re a d . “O h ? ” y o u m a y a s k , in c re d u lo u s ly . T h is m e c h a n is m is n o t p e rfe c t—th e s u s p e n d in g th r e a d (th e o n e callin g thd_suspend) w a its in a loop, y ie ld in g th e p ro c e s s o r u n til th is s e n tin e l c h a n g e s s ta te . T h e volatile sto ra g e a ttr ib u te e n s u r e s t h a t th e s ig n a l-c a tc h in g fu n c tio n w ill w rite th e v a lu e to m e m o iy . R em em b er, y o u c a n n o t u s e a m u te x w ith in a s ig n a l-c a tc h in g fu n c tio n . 22-40 T h e suspend__signal_handler fu n c tio n w ill b e e s ta b lis h e d a s th e sig n alc a tc h in g fu n c tio n for th e “s u s p e n d ” sig n a l, S1GUSR1. It in itia liz e s a sig n a l m a s k to b lo c k a ll s ig n a ls e x c e p t SIGUSR2, w h ic h is th e “r e s u m e ” sig n a l, a n d th e n w a its for t h a t sig n a l b y callin g sigsuspend. J u s t b efo re s u s p e n d in g itself, it s e ts th e s e n tin e l v a ria b le to in fo rm th e s u s p e n d in g th r e a d t h a t it is n o lo n g e r e x e c u tin g u s e r co d e—for m o s t p r a c tic a l p u rp o s e s , it is a lre a d y s u s p e n d e d . T h e p u rp o s e for th is s y n c h ro n iz a tio n b e tw e e n th e s ig n a l-c a tc h in g fu n c tio n a n d th d _ s u s p e n d is th a t, to b e m o s t u se fu l, th e th r e a d ca llin g thd_suspend m u s t b e ab le to k n o w w h e n th e ta rg e t th r e a d h a s b e e n s u c c e s s fu lly s u s p e n d e d . S im p ly c a llin g p t h r e a d _ k i l l is n o t e n o u g h , b e c a u s e th e s y s te m m ig h t n o t d eliv er th e sig n a l for a s u b s ta n tia l p e rio d of tim e; w e n e e d to k n o w w h e n th e sig n a l h a s b e e n receiv ed . 47-51 T h e resume_signal_handler fu n c tio n will b e e s ta b lis h e d a s th e sig n a l-c a tc h in g fu n c tio n for th e “re s u m e ” sig n al, S1GUSR1. T h e fu n c tio n is n ’t im p o rta n t, s in c e th e sig n al is s e n t only to in te r r u p t th e call to sigsuspend in suspend_signal_handler. ■

1 2 3 4 5 6

susp.c

parti

signal-catchingfunctions

#include #include #include "errors.h" #define THREAD_COUNT #define ITERATIONS

20 40000

* A s e m a p h o r e , a s d e s c r ib e d la t e r in S e c t io n 6 . 6 .6 , w o u ld p r o v id e c le a n e r , a n d s o m e w h a t s a f er, s y n c h r o n iz a t io n . T h e t h d _ s u s p e n d w o u ld c a ll s e m _ w a it o n a s e m a p h o r e w it h a n in it ia l v a lu e o f 0 , a n d t h e s i g n a l - c a t c h i n g f u n c t i o n w o u l d c a l l s e m _ p o s t t o w a k e it .

219

Signals

unsigned long thread_count = THREAD_COUNT; unsigned long iterations = ITERATIONS; pthread_mutex_t the_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; volatile int sentinel = 0; pthread_once_t once = PTHREAD_ONCE_INIT? pthread_t *array = NULL, null_pthread = {0}; int bottom = 0; int inited = 0;

11

12

13 14 15 16 17 18 19

/* * Handle SIGUSR1 in the target thread, to suspend it until * receiving SIGUSR2 (resume).

20

*/

21

void suspend_signal_handler

22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

(int sig)

{ sigset_t signal__set;

/* * Block all signals except SIGUSR2 while suspended.

*/ sigfillset (&signal__set); sigdelset (&signal__set, SIGUSR2 ); sentinel = 1; sigsuspend (&signal_set);

/* * Once I'm here. I've been resumed, and the resume signal * handler has been run to completion.

*/ return;

} /* * Handle SIGUSR2 in the target thread, to resume it. Note that * the signal handler does nothing. It exists only because we need * to cause sigsuspend() to return.

*/ void resume_signal_handler

(int sig)

{ return;



> susp.c

part 1

signal-catchingfunctions

220

15-16

21-35

CHAPTER 6

P O S I X adjusts to threads

T h e suspend_init_routine fu n c tio n d y n a m ic a lly in itia liz e s th e s u s p e n d / r e s u m e p a c k a g e w h e n th e firs t call to thd_suspend is m a d e . It is a c tu a lly called in d ire c tly b y pthread_once. It a llo c a te s a n in itia l a r r a y of th r e a d id e n tifie rs, w h ic h is u s e d to re c o rd th e id e n tifie rs of all th r e a d s t h a t h a v e b e e n s u s p e n d e d . T h is a r r a y is u s e d to e n s u re t h a t m u ltip le c a lls to th d _ s u s p e n d h a v e n o a d d itio n a l effect o n th e ta rg e t th re a d , a n d t h a t callin g t h d _ c o n tin u e for a th r e a d t h a t is n o t s u s p e n d e d h a s n o effect. It s e ts u p sig n a l a c tio n s for th e s i g u s r i a n d S1GUSR2 sig n a ls, w h ic h w ill b e u s e d , resp ectiv ely , to s u s p e n d a n d re s u m e th r e a d s . ■

susp.c

part 2

initialization

1 /* 2 * Dynamically initialize the "suspend package" when first used 3 * (called by pthread_once). 4 */ 5 void 6 suspend_init_routine (void)

7 8 9

{ int status; struct sigaction sigusri,

sigusr2;

10

11

/*

12 13 14 15 16 17 18 19

* Allocate the suspended threads array. This array is used * to guarentee idempotency */ bottom = 10; array = (pthread_t*) calloc (bottom, sizeof (p t h r e a d _ t ));

20

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

/* * Install the signal handlers for suspend/resume. */

sigu s r i .sa_flags = 0; sigusri.sa_handler = suspend_signal_handler; sigemptyset (&sigusrl.sa_mask); sigusr2.sa_flags = 0; sigusr2.sa_handler = resume_signal_handler; sigusr2.sa_mask = sig u s r i .sa_mask; status = sigaction (SIGUSRI, Ssigusrl, NULL); if (status == -1) errno_abort ("Installing suspend handler"); status = sigaction (S IGUSR2, &sigusr2, NULL); if (status == -1) errno_abort ("Installing resume handler");

221

Signals

36 37 38

inited = 1; return;

39

> ■

susp.c

initialization

T h e thd_suspend fu n c tio n s u s p e n d s a th re a d , a n d r e t u r n s w h e n t h a t th r e a d h a s c e a se d to e x e c u te u s e r code. It firs t e n s u r e s t h a t th e s u s p e n d /r e s u m e p a c k age is in itia lize d by c a llin g pthread_once. U n d e r p ro te c tio n of a m u te x , it s e a r c h e s for th e ta rg e t th r e a d ’s id e n tifie r in th e a r r a y o f s u s p e n d e d th r e a d id e n tifiers. If th e th r e a d is a lre a d y s u s p e n d e d , thd_suspend r e t u r n s s u c c e ssfu lly . D e te rm in e w h e th e r th e re is a n e m p ty e n try in th e a r r a y of s u s p e n d e d th r e a d s a n d , if n o t, r e a l l o c th e a r r a y w ith a n e x tra en try . T h e sentinel v a ria b le is in itia liz e d to 0, to d e te c t w h e n th e ta rg e t th r e a d s u s p e n s io n o c c u rs . T h e th r e a d is s e n t a S1GUSR1 s ig n a l b y c a llin g pthread_kill, a n d thd_suspend lo o p s, c a llin g sched_yield to avo id m o n o p o lizin g a p ro c e sso r, u n til th e ta rg e t th r e a d re s p o n d s b y s e ttin g sentinel. F in ally , th e s u s p e n d e d th r e a d ’s id e n tifie r is s to re d in th e a rra y .

9-40

47-60 65-78



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

part 2

susp.c

/* * * ★ ★ * *

part 3

thd_suspend

Suspend a thread by sending it a signal (SIGUSR1), which will block the thread until another signal (SI G U S R 2 ) arrives. Multiple calls to thd_suspend for a single thread have no additional effect on the thread — a single thd__continue call will cause it to resume execution.

*/ int thd[^suspend (pthread_t target_thread) { int status; int i = 0; /* * The first call to thd suspend will initialize the * package. */ status = pthread once (&once, suspend_init routine); if (status != 0) return status; /* * Serialize access to suspend, makes life easier. */

222

27 28 29 30

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

67 68

69 70 71 72 73 74

CH A P T E R 6

P O S I X a d ju st s t o t h r ea d s

status = pthread_mutex_lock (& m u t ); if (status i= 0) return status;

/* * * * *

Threads that are suspended are added to the target_array; a request to suspend a thread already listed in the array is ignored. Sending a second SIGUSR1 would cause the thread to resuspend itself as soon as it is resumed.

*/ while (i < bottom) if (array[i++] == target_thread) { status = pthread_mutex_unlock (&mut); return status;

} /* * Ok, we really need to suspend this thread. So, let's find * the location in the array that we'll use. If we run off * the end, realloc the array for more space.

*/ i = 0; while (array[i]

!= 0)

i++? if (i == bottom) { array = (pthread__t*) realloc ( array, (++bottom * sizeof (pthread__t) ) ); if (array == NULL) { pthread_mutex_unlock (& m u t ); return errno;

} array[bottom] = null_pthread;

/* Clear new entry */

} /* * Clear the sentinel and signal the thread to suspend.

*/ sentinel = 0; status = pthread__kill (target_thread, if (status 1= 0) { pthread_mutex__unlock (& m u t ); return status;

> /* * Wait for the sentinel to change.

*/

SIGUSR1);

223

Signals

while (sentinel == 0) sched_yield ();

75

76 77 78 79 80 81 82

array[i] = target_thread; status = pthread_mutex_unlock (&mut); return status; > ■

susp.c

thd_suspend

T h e thd_continue fu n c tio n firs t c h e c k s w h e th e r th e s u s p e n d /r e s u m e p a c k ag e h a s b e e n in itia liz e d (inited is n o t 0). If it h a s n o t b e e n in itia lize d , th e n n o th r e a d s a re s u s p e n d e d , a n d thd_continue r e t u r n s w ith s u c c e s s . If th e sp ecified th r e a d id e n tifie r is n o t fo u n d in th e a r r a y o f s u s p e n d e d th r e a d s , th e n it is n o t s u s p e n d e d —a g a in , r e t u r n w ith s u c c e s s . S e n d th e r e s u m e sig n a l, SI G U S R 2 . T h e re ’s n o n e e d to w a it—th e th r e a d w ill r e s u m e w h e n e v e r it c a n , a n d th e th r e a d c a llin g th d _ c o n tin u e d o e s n ’t n e e d to know .

23-26

33-39 45-51



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

part 3

susp.c

part 4

thd_continue

/* * Resume a suspended thread by sending it SIGUSR2 to break * it out of the sigsuspend() in which it's waiting. If the * target thread isn't suspended, return with success. */ int thd_continue (pthread_t target_thread) { int status; int i = 0; /* * Serialize access to suspend, makes life easier. */ status = pthread_mutex_lock (&mut); if (status != 0) return status; /* * If we haven't been initialized, then the thread must * "resumed"; it couldn't have been suspended! */ if ( U n i t e d ) { status = pthread mutex unlock (& m u t ); return status; >

224

28

P O S I X a d ju st s to t h r ea d s

/* * Make sure the thread is in the suspend array. If not, it * h a s n ’t been suspended (or it has already been resumed) and * we can just carry on. */ while (array[i] != target_thread && i < bottom)

2?

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

i++; if (i >= bottom) { pthread__mutex unlock (& m u t ); return 0; } /* * Signal the thread to continue, and remove the thread from * the suspended array. */ status = pthread_kill (target_thread, SIG U S R 2 ); if (status ! = 0 ) { pthread__mutex_unlock (& m u t ); return status; } array[i] = 0 ; /* Clear array element */ status = pthread_mutex_unlock (&mut); return status; } ■

2-25

CHAPTER 6

susp.c

part 4

thd_continue

T h e t h r e a d _ r o u t i n e fu n c tio n is th e th r e a d s t a r t ro u tin e for e a c h of th e “ta rg e t” th r e a d s c re a te d b y th e p ro g ra m . It sim p ly lo o p s for a s u b s ta n tia l p erio d of tim e, p erio d ically p rin tin g a s ta t u s m e ssa g e . O n e a c h ite ra tio n , it y ie ld s to o th e r th r e a d s to e n s u r e th a t th e p ro c e s s o r tim e is a p p o rtio n e d “fairly” a c ro s s all th e th re a d s . N otice t h a t in s te a d of callin g printf, th e fu n c tio n fo rm a ts a m e s s a g e w ith sprintf a n d th e n d is p la y s it o n stdout (file d e s c rip to r 1) b y c a llin g write. T h is illu s tr a te s o n e of th e p ro b le m s w ith u s in g s u s p e n d a n d re s u m e (thd_suspend a n d thd_continue) fo r s y n c h ro n iz a tio n . S u s p e n d a n d re s u m e a re s c h e d u lin g fu n c tio n s , n o t s y n c h ro n iz a tio n fu n c tio n s , a n d u s in g s c h e d u lin g a n d s y n c h ro n iz a tio n c o n tro ls to g e th e r c a n h a v e sev ere c o n s e q u e n c e s . I

In c a u tio u s u s e o f s u s p e n d a n d re s u m e c a n d e a d lo c k y o u r a p p lic a t io n .

In th is case, if a th re a d w ere s u s p e n d e d w hile m odifying a s td io s tre a m , all o th e r th r e a d s t h a t trie d to m odify th a t s td io s tre a m m ig h t block, w aitin g for a m u te x th a t is locked b y th e s u s p e n d e d th re a d . T h e w r i t e fu n ctio n , o n th e o th e r h a n d , is u s u ally a call to th e k e rn e l—th e k e rn e l is ato m ic w ith re s p e c t to sig n als, a n d th e re fo re c a n ’t b e s u s p e n d e d . U se o f w r i t e , th erefo re, c a n n o t c a u s e a dead lo ck .

225

Signals

In g e n e ra l, y o u c a n n o t s u s p e n d a th r e a d t h a t m a y p o s sib ly h o ld a n y re s o u rc e , if th a t re s o u rc e m a y b e re q u ire d b y so m e o th e r th r e a d b efo re th e s u s p e n d e d th r e a d is re s u m e d . In p a rtic u la r, th e r e s u lt is a d e a d lo ck if th e th r e a d t h a t w o u ld re s u m e th e s u s p e n d e d th r e a d firs t n e e d s to a c q u ire th e re s o u rc e . T h is p ro h ib itio n in c lu d e s , esp ecially , m u te x e s u s e d b y lib ra rie s y o u call— s u c h a s th e m u te x e s u s e d b y m a llo c a n d f r e e , o r th e m u te x e s u s e d b y s td io. 36-42 T h re a d s a re c re a te d w ith a n a ttr ib u te s o b je c t s e t to c re a te th r e a d s d e ta c h e d , r a th e r t h a n jo in a b le . T h e r e s u lt is t h a t th r e a d s w ill c e a s e to e x ist a s s o o n a s th e y te rm in a te , r a th e r th a n re m a in in g u n til m a in c a lls pthread_join. T h e pthread_ kill fu n c tio n d o e s n o t n e c e s s a rily fail if y o u a tte m p t to s e n d a sig n a l to a te rm in a te d th r e a d (th e s ta n d a r d is s ile n t o n th is po in t), a n d y o u m a y b e m e re ly s e ttin g a p e n d in g sig n a l in a th r e a d t h a t will n e v e r b e a b le to a c t o n it. If th is w ere to o ccu r, th e thd_suspend r o u tin e w o u ld h a n g w a itin g for th e th r e a d to re s p o n d . A lth o u g h pthread_kill m a y n o t fail w h e n s e n d in g to a te rm in a te d th r e a d , it will fail w h e n s e n d in g to a th r e a d t h a t d o e s n ’t e x ist—so th is a ttr ib u te c o n v e rts a p o ssib le h a n g , w h e n th e p ro g ra m is r u n w ith i t e r a t i o n s s e t to o low, in to a n a b o r t w ith a n e rro r m e ssa g e . 51-85 T h e m a in th r e a d s le e p s for tw o s e c o n d s a fte r c re a tin g th e th r e a d s to allow th e m to re a c h a “s te a d y s ta t e .” It th e n lo o p s th r o u g h th e firs t h a lf o f th e th r e a d s , s u s p e n d in g e a c h of th e m . It w a its a n a d d itio n a l tw o s e c o n d s a n d th e n re s u m e s e a c h of th e th r e a d s it h a d s u s p e n d e d . It w a its a n o th e r tw o se c o n d s, s u s p e n d s e a c h of th e re m a in in g th r e a d s (th e se c o n d h alf), a n d th e n a fte r a n o th e r tw o s e c o n d s r e s u m e s th e m . By w a tc h in g th e s t a t u s m e s s a g e s p r in te d b y th e in d iv id u a l th r e a d s , y o u c a n se e th e p a tte r n o f o u tp u t c h a n g e a s th e th r e a d s a r e s u s p e n d e d a n d re s u m e d . ■

susp.c

part 5

1 2

static void * thread_routine

3

{

4 5 6 7

sampleprogram

(void *arg)

int number = (int)arg; int status; int i; char b u f f e r [128];

8 9

for (i = 1; i

20

print

226

CHAPTER 6

sched_yield ();

21

}

22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

return (void *)0;

} int main (int argc, char *argv[])

{ pthread_t t h r e a d s [THREAD_COUNT]; pthread_attr_t detach; int status; void *result; int i; status = pthread_attr_init (&detach); if (status != 0) err_abort (status, "Init attributes object"); status = pthread_attr_setdetachstate ( Sdetach, PTHREAD_CREATE_DETACHED); if (status != 0) err_abort (status, "Set create-detached"); for (i = 0; i< THREAD_COUNT; i++) { status = pthread_create ( &threads[i], Sdetach, thread_routine, if (status 1= 0) err_abort (status, "Create thread");

> sleep

(2);

for (i = 0; i < THREAD_COUNT/2; i++) { printf ("Suspending thread %d.\n", i); status = thd_suspend (threads[i]); if (status 1= 0) err_abort (status, "Suspend thread");

> printf ("Sleeping ...\n"); sleep (2);

67

for (i = 0; i < THREAD_COUNT/2; i + + ) { printf ("Continuing thread %d.\n", i); status = thd__continue (t h r e a d s [i] ); if (status != 0) err_abort (status, "Suspend thread");

68

}

66

69

P O S I X adjusts to threads

(void *)i);

227

Signals

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

for (i = THREAD_C0UNT/2; i < THREAD_COUNT? i++) printf ("Suspending thread %d.\n", i); status = thd__suspend (threads [i ]); if (status != 0) err_abort (status, "Suspend thread"); }

{

printf ("Sleeping ...\n"); sleep (2); for (i = THREAD_C0UNT/2; i < THREAD_COUNT; i + + ) { printf ("Continuing thread %d.\n", i); status = thd_continue (t h r e a d s [i ]); if (status 1= 0) err_abort (status, "Continue thread"); }

86

87 88

pthread_exit (NULL);



6 .6 .4

/* Let threads finish */

} susp.c

part 5

sampleprogram

s ig w a it a n d sig w a itin fo

in t

s ig w a it

(c o n s t

s ig s e t_ t

*s e t,

in t

* s ig );

# i f d e f _ P O S IX _ R E A L T IM £ j5 lG N A L S in t

s ig w a itin fo

(

c o n s t s ig s e t_ t in t

s ig t ix n e d w a it const

s ig s e t^ t

const s tru c t

*s e t,

s ig in fo _ t

* in fo );

*s e t,

s ig in fo ^ t

* in fo ,

(

tim e s p e c

* tiia e o u t);

le n d if

I

A lw a y s u s e sigwait t o w o rk w ith a s y n c h ro n o u s s ig n a ls w ith in t h r e a d e d code.

P th r e a d s a d d s a fu n c tio n to allo w th r e a d e d p ro g ra m s to d e a l w ith “a s y n c h ro n o u s ” s ig n a ls sy n c h ro n o u s ly . T h a t is, in s te a d of allo w in g a sig n a l to in te r r u p t a th r e a d a t so m e a r b itr a r y p o in t, a th r e a d c a n c h o o se to receiv e a sig n a l sy n c h ro n o u sly . It d o e s th is b y c allin g sigwait, o r o n e of sigwait’s sib lin g s.

I

T he s ig n a ls fo r w h ic h y o u sigwait m u s t b e m a s k e d in t h e s ig w a itin g t h r e a d , a n d s h o u ld u s u a lly b e m a s k e d in a ll th re a d s .

T h e sigwait fu n c tio n ta k e s a sig n a l s e t a s its a rg u m e n t, a n d r e tu r n s a sig n a l n u m b e r w h e n a n y sig n a l in t h a t s e t o c c u rs . You c a n c re a te a th r e a d t h a t w a its for

228

23-41

61-65

P O S I X a d ju st s to t h r ea d s

so m e sig n a l, for e x am p le, s i g i n t , a n d c a u s e s so m e a p p lic a tio n a ctiv ity w h e n it o c c u rs . T h e n o n o b v io u s ru le is t h a t th e s ig n a ls for w h ic h y o u w a it m u s t b e m a s k e d b efo re callin g sigwait. In fa ct, y o u s h o u ld id eally m a s k th e s e s ig n a ls in main, a t th e s t a r t of th e p ro g ra m . B e c a u s e s ig n a l m a s k s a re in h e rite d b y th r e a d s y o u c re a te , all th r e a d s will (by d efau lt) h a v e th e sig n a l m a s k e d . T h is e n s u r e s t h a t th e sig n a l w ill n e v e r b e d eliv ered to a n y th r e a d e x c e p t th e o n e t h a t c a lls sigwait. S ig n a ls a re d eliv ered o n ly on ce. If tw o th r e a d s a re b lo c k e d in sigwait, only o n e o f th e m w ill receiv e a sig n a l t h a t ’s s e n t to th e p ro c e s s . T h is m e a n s y o u c a n ’t, for ex am p le, h a v e tw o in d e p e n d e n t s u b s y s te m s u s in g sigwait t h a t c a tc h SIGINT. It a lso m e a n s t h a t th e s ig n a l will n o t b e c a u g h t b y sigwait in o n e th r e a d a n d a lso d eliv ered to so m e s ig n a l-c a tc h in g fu n c tio n in a n o th e r th re a d . T h a t’s n o t so b a d , s in c e y o u c o u ld n ’t do t h a t in th e old n o n th r e a d e d m o d e l e ith e r—o n ly o n e sig n a l a c tio n c a n b e activ e a t a tim e. W hile sigwait, a P th re a d s fu n c tio n , re p o rts e rro rs b y re tu r n in g a n e rro r n u m ber, its sib lin g s, sigwaitinfo a n d sigtimedwait, w ere a d d e d to POSIX p rio r to P th re a d s , a n d u s e th e o ld e r errno m e c h a n is m . T h is is c o n fu sin g a n d aw k w ard , a n d th a t is u n fo rtu n a te . T h e p ro b le m is t h a t th e y d e a l w ith th e a d d itio n a l in fo rm atio n su p p lie d b y th e POSIX re a ltim e s ig n a ls o p tio n ( d efin e s th e sym bol _ p 0S1 x _ r e a l t i m e _ s i g n a l s ), a n d th e POSIX re a ltim e a m e n d m e n t, POSIX. lb , w as c o m p lete d b efo re th e P th re a d s a m e n d m e n t. B o th sigwaitinfo a n d sigtimedwait r e t u r n th e re a ltim e s ig n a l in fo rm a tio n , siginfo_t, for s ig n a ls receiv ed . In a d d itio n , sigtimedwait allo w s th e c a lle r to sp ecify t h a t sigtimedwait s h o u ld r e t u r n w ith th e e rro r EAGAIN in th e e v e n t th a t n o n e of th e s e le c te d s ig n a ls is receiv ed w ith in th e sp ecified in te rv a l. T h e sigwait.c p ro g ra m c r e a te s a ‘4sigwait th r e a d ” t h a t h a n d le s SIGINT. T h e signal__waiter th r e a d re p e a te d ly c a lls sigwait, w a itin g for a SIGINT sign a l. It c o u n ts five o c c u rre n c e s of s i g i n t (p rin tin g a m e s s a g e e a c h tim e), a n d th e n s ig n a ls a c o n d itio n v a ria b le o n w h ic h main is w aitin g . A t t h a t tim e, main w ill exit. T h e m a in p ro g ra m b e g in s b y m a s k in g s i g i n t . B e c a u s e all th r e a d s in h e rit th e ir in itia l sig n a l m a s k fro m th e ir c re a to r, SIGINT w ill b e m a s k e d in all th r e a d s . T h is p re v e n ts s i g i n t fro m b e in g d eliv ered a t a n y tim e e x c e p t w h e n th e signal^ waiter th r e a d is b lo c k e d in sigwait a n d re a d y to receiv e th e sig n al. ■

1 2 3 4 5

CH A P T E R 6

sigwait.c #include #include #include #include #include

< s y s/types.h>

< s i g n a l .h> "errors.h"

6 7 8 9 10 11

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; int interrupted = 0; sigset_t signal_set;

229

Signals

/* * Wait for the SIGINT signal. When it has occurred 5 times, set the * "interrupted" flag (the main thread's wait predicate) and signal a * condition variable. The main thread will exit. 16 17 18 19

*/ void *signal_waiter (void *arg)

{ int sig_number; int signal_count = 0; int status;

20

21 22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

while (1) { sigwait (&signal_set, &sig_number); if (sig_number == SIGINT) { printf ("Got SIGINT (%d of 5)\n", signal_count+l); if (++signal_count > = 5 ) { status = pthread_mutex_lock (&mutex); if (status != 0) err__abort (status, "Lock mutex"); interrupted = 1; status = pthread_cond_signal (&cond); if (status != 0) err_abort (status, "Signal condition"); status = pthread_mutex_unlock (&mutex); if (status != 0) err_abort (status, "Unlock mutex"); break;

} } > return NULL;

} int main

(int argc, char *argv[])

{ pthread_t signal_thread_id; int status;

/* * * * * * * * * *

*/

Start by masking the "interesting" signal, SIGINT in the initial thread. Because all threads inherit the signal mask from their creator, all threads in the process will have SIGINT masked unless one explicitly unmasks it. The semantics of sigwait requires that all threads (including the thread calling sigwait) have the signal masked, for reliable operation. Otherwise, a signal that arrives while the sigwaiter is not blocked in sigwait might be delivered to another thread.

230

61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92

P O S I X a d ju st s to t h r ea d s

sigemptyset (&signal set); sigaddset (&signal set, SIGINT); status = pthread sigmask (SIG BLOCK, &signal set, NULL); if (status 1= 0) err_abort (status, "Set signal mask"); /* * Create the sigwait thread. */ status = pthread create (&signal thread id, NULL, signal_waiter, NULL); if (status != 0) err_abort (status, "Create sigwaiter"); /* * Wait for the sigwait thread to receive SIGINT and signal * the condition variable*/ status = pthread mutex lock (&mutex); if (status != 0) err abort (status, "Lock mutex"); while (!interrupted) { status = pthread_cond wait (fccond, &mutex); if (status != 0) err abort (status, "Wait for interrupt"); } status = pthread mutex unlock (&mutex); if (status != 0) err_abort (status, "Unlock m u t e x ‫;) ״‬ printf ("Main terminating with SIGINT\n"); return 0; } ■

6 .6 .5

CH A P T E R 6

sigwait.c

SIG EV.THREAD S o m e of th e f u n c tio n s in th e POSIX. l b re a ltim e s ta n d a r d , w h ic h p ro v id e for a s y n c h r o n o u s n o tific a tio n , allo w th e p ro g ra m m e r to give specific in s tr u c tio n s a b o u t h o w t h a t n o tific a tio n is to b e a c c o m p lish e d . F o r e x am p le, w h e n in itia tin g a n a s y n c h r o n o u s device re a d o r w rite u s in g aio_read o r aio_write, th e p ro g ra m m e r sp ecifies a struct aiocb, w h ic h c o n ta in s , a m o n g o th e r m e m b e rs , a struct sigevent. O th e r fu n c tio n s t h a t a c c e p t a struct sigevent in c lu d e timer_ create (w hich c re a te s a p e r-p ro c e s s tim er) a n d sigqueue (w hich q u e u e s a sig n a l to a p ro c e s s ).

Signals

231

T h e s t r u c t s i g e v e n t s tr u c tu r e in POSIX. lb p ro v id e s a “n o tific a tio n m e c h a n is m ” t h a t allo w s th e p ro g ra m m e r to sp ecify w h e th e r a s ig n a l is to b e g e n e ra te d , a n d , if so, w h a t sig n a l n u m b e r s h o u ld b e u s e d . P th re a d s a d d s a n e w n o tific a tio n m e c h a n is m called SIGEV_THREAD. T h is n e w n o tific a tio n m e c h a n is m c a u s e s th e sig n a l n o tific a tio n fu n c tio n to b e r u n a s if it w ere th e s t a r t r o u tin e o f a th re a d . P th r e a d s a d d s se v e ra l m e m b e rs to th e POSIX. l b struct sigevent s tr u c tu r e . T h e n e w m e m b e rs a re sigev_notify_function, a p o in te r to a th r e a d s t a r t fu n c tio n ; a n d sigev_notify_attributes, a p o in te r to a th r e a d a ttr ib u te s o b je c t (pthread_attr_t) c o n ta in in g th e d e s ire d th r e a d c re a tio n a ttr ib u te s . If sigev_ notify_attributes is NULL, th e n o tify th r e a d is c re a te d a s if th e d e ta ch s ta te a ttr ib u te w a s s e t to p t h r e a d _ c r e a t e _ d e t a c h e d . T h is a v o id s a m e m o ry le a k —in g e n e ra l, th e n o tify th r e a d ’s id e n tifie r w o n ’t b e a v a ila b le to a n y o th e r th re a d . F u rth e rm o re , P th r e a d s s a y s t h a t th e r e s u lt of sp ecify in g a n a ttr ib u te s o b je c t t h a t h a s th e d e ta ch s ta te a ttr ib u te s e t to p t h r e a d _ c r e a t e _ j o i n a b l e is “u n d e fin e d .” (M ost likely, th e r e s u lt will b e a m e m o ry le a k b e c a u s e th e th r e a d c a n n o t b e jo in e d —if y o u a re lu ck y , th e s y s te m m a y o v errid e y o u r ch o ice a n d c re a te it d e ta c h e d an yw ay .) T h e s i g e v _ t h r e a d n o tific a tio n fu n c tio n m a y n o t a c tu a lly b e r u n in a n ew th re a d —P th re a d s carefu lly specifies th a t it b eh av e s a s if it w ere r u n in a n ew th re a d , j u s t a s I d id a few p a r a g r a p h s ago. T h e s y s te m m ay , for ex am p le, q u e u e s i g e v _ t h r e a d e v e n ts a n d call th e s t a r t r o u tin e s , seria lly , in so m e in te r n a l “s e rv e r th r e a d .” T h e d iffere n ce is effectively in d is tin g u is h a b le to th e a p p lic a tio n . A sy ste m t h a t u s e s a s e rv e r th r e a d m u s t b e v e ry c a re fu l a b o u t th e a ttr ib u te s specified fo r th e n o tific a tio n th r e a d —for ex am p le, s c h e d u lin g po licy a n d p rio rity , c o n te n tio n sco p e, a n d m in im u m s ta c k size m u s t all b e ta k e n in to c o n s id e ra tio n . T h e s i g e v __t h r e a d fe a tu re is n o t a v a ila b le to a n y of th e “tr a d itio n a l” sig n a l g e n e ra tio n m e c h a n is m s , s u c h a s s e t i t i m e r , o r for SIGCHLD, SIGINT, a n d so fo rth . T h o se w h o a re p ro g ra m m in g u s in g th e POSIX. l b “re a ltim e s ig n a l” in te rfa c e s , in c lu d in g tim e rs a n d a s y n c h r o n o u s I/O , m a y fin d th is n e w c a p a b ility u se fu l. T h e follow ing p ro g ra m , s i g e v _ t h r e a d .c , sh o w s h o w to u s e th e S I GEV_THREAD n o tific a tio n m e c h a n is m fo r a POSIX. l b tim er. 20-37 T h e fu n c tio n t i m e r _ t h r e a d is sp ecified a s th e “n o tific a tio n f u n c tio n ” (th re a d s t a r t ro u tin e ) fo r th e S1GEV_THREAD tim er. T h e fu n c tio n will b e ca lle d e a c h tim e th e tim e r e x p ire s. It c o u n ts e x p ira tio n s , a n d w a k e s th e m a in th r e a d a fte r five. N otice th a t, u n lik e a s ig n a l-c a tc h in g fu n c tio n , th e S1 g e v _ t h r e a d n o tific a tio n fu n c tio n c a n m a k e full u s e o f P th r e a d s s y n c h ro n iz a tio n o p e ra tio n s . T h is c a n b e a s u b s ta n tia l a d v a n ta g e in m a n y s itu a tio n s . 45-51 U n fo rtu n a te ly , n e ith e r S o la ris 2 .5 n o r D ig ital UNIX 4 .0 c o rre c tly im p le m e n te d SIGEV_THREAD . T h u s , u n lik e all o th e r e x a m p le s in th is b o o k , th is co d e w ill n o t co m p ile o n S o la ris 2 .5 . T h is # i f d e f b lo c k allo w s th e co d e to co m pile, a n d to fail g race fu lly if th e re s u ltin g p ro g ra m is r u n , w ith a n e rro r m e ssa g e . A lth o u g h th e p ro g ra m w ill co m p ile o n D igital UNIX 4 .0 , it w ill n o t r u n . T h e im p le m e n ta tio n of s i g e v _ t h r e a d h a s b e e n fixed in D ig ital UNIX 4 .0 D , w h ic h s h o u ld b e a v a ila b le b y th e tim e y o u re a d th is , a n d it s h o u ld a lso b e fixed in S o la ris 2.6.

232

CH A P T E R 6

P O S I X a d ju st s to t h r ea d s

T h e se s ta te m e n ts in itia lize th e sigevent s tr u c tu r e , w h ic h d e s c rib e s h o w th e s y s te m s h o u ld n o tify th e a p p lic a tio n w h e n a n e v e n t o c c u rs . In th is c a se , w e a re te llin g it to c all timer__thread w h e n th e tim e r e x p ire s, a n d to u s e d e fa u lt a ttr ib u te s . ■

4 5

sigev_thread.c #include #include #include #include

< s y s/signal.h>

,,errors.h"

6 timer_t timer_id; 7

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

8 pthread_cond_t cond = PTHREAD_C0ND_INITIALIZER; 9

int counter = 0;

10 11

/* * Thread start routine to notify the application when the * timer expires. This routine is run "as if" it were a new * thread, each time the timer expires.

12

13 14 15 16 17 18 19 20

21

* * When the timer has expired 5 times, the main thread will * be awakened, and will terminate the program.

*/ void timer_thread (void *arg)

{

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

int status; status = pthread_mutex_lock (Smutex); if (status 1= 0) err_abort (status, "Lock mutex"); if (++counter > = 5 ) { status = pthread_cond_signal (&cond); if (status != 0) err_abort (status, "Signal condition");

> status = pthread_mutex_unlock (&mutex); if (status != 0) err_abort (status, "Unlock mutex"); printf

} main()

("Timer % d \n", counter);

Signals

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

66 67

233

int status; struct itimerspec ts; struct sigevent se; #ifdef sun fprintf ( stderr, "This program cannot compile on Solaris 2.5.\n" "To build and run on Solaris 2.6, remove the\n" "\"#ifdef sun\" block in main().\n"); #else /* * Set the sigevent structure to cause the signal to be * delivered by creating a new thread. */ se.sigev_notify - SIGEV_THREAD; se.sigev__value.sival_ptr - &timer_id; se. sigev_notify__function = timer_thread; se. sigev_notify__attributes = NULL; /* * Specify a repeating timer that fires every 5 seconds. */ ts.it_value.tv_sec = 5; ts.it_value.tv_nsec = 0; ts.it_interval.tv_sec =5; ts.it_interval.tv_nsec = 0;

68

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

86 87

DPRINTF ((,,Creating timer\n‫;)) ״‬ status = timer_create(CLOCK_REALTIME, &se, &timer_id); if (status == -1) errno_abort ("Create timer"); DPRINTF (( "Setting timer %d for 5-second expiration...\n", timer_id)); status = timer_settime(timer_id, 0, &ts, 0); if (status == -1) errno_abort ("Set timer"); status = pthread__mutex_lock (&mutex); if (status != 0) err_abort (status, "Lock mutex"); while (counter < 5) { status = pthread_cond_wait (&cond, &mutex); if (status 1= 0) err_abort (status, "Wait on condition"); }

234

88 89 90

CHAPTER 6

P O S I X a d ju st s to t h r ea d s

status = pthread__mutex_unlock (&mutex); if (status i= 0) err_abort (status, "Unlock mutex");

91

92 93 94

#endif /* Sun */ return 0; > ■

6 .6 .6

sigev_thread.c

S e m a p h o re s : syn ch ro n izin g w ith a s ig n a l-c a tc h in g fu n c tio n

# i f d e f _PO S IX J3E M A P H O R E S in t

s e m ^ in it in t

m t

(s e m _ t

p s h a re d ,

s e m _ d e s tro y

m t

s e m _ w a it

in t

s e m _ try w a k e

in t

s e m j> o s t

in t

s e m _ g e tv a lu e

*s e m ,

u n s ig n e d (s e ir t

(s e m jt

in t

v a lu e );

*s e m );

*s e m );

(s e ra _ t *s e m );

(s e r n ^ t * s e m ) ; (s e m _ t

*s e m ,

in t

* s v a l);

# e n d if

A lth o u g h m u te x e s a n d c o n d itio n v a ria b le s p ro v id e a n id e a l s o lu tio n to m o s t s y n c h ro n iz a tio n n e e d s , th e y c a n n o t m e e t all n e e d s . O n e e x a m p le o f th is is a n e e d to c o m m u n ic a te b e tw e e n a POSIX s ig n a l-c a tc h in g fu n c tio n a n d a th r e a d w a itin g for so m e a s y n c h r o n o u s ev en t. In n e w co de, it is b e s t to u s e sigwait o r sigwaiti n f o r a th e r th a n re ly in g o n a s ig n a l-c a tc h in g fu n c tio n , a n d th is n e a tly av o id s th is p ro b le m . H owever, th e u s e of a s y n c h r o n o u s POSIX s ig n a l-c a tc h in g f u n c tio n s is w ell e s ta b lis h e d a n d w id e s p re a d , a n d m o s t p ro g ra m m e rs w o rk in g w ith th r e a d s a n d e x istin g co d e w ill p ro b a b ly e n c o u n te r th is s itu a tio n . To a w a k e n a th r e a d fro m a POSIX s ig n a l-c a tc h in g fu n c tio n , y o u n e e d a m e c h a n is m t h a t ’s r e e n tr a n t w ith r e s p e c t to POSIX s ig n a ls (a sy n c -sig n a l safe). POSIX p ro v id e s rela tiv e ly few of th e s e fu n c tio n s , a n d n o n e o f th e P th re a d s fu n c tio n s is in c lu d e d . T h a t’s p rim a rily b e c a u s e a n a s y n c -s ig n a l sa fe m u te x lo ck o p e ra tio n w o u ld b e m a n y tim e s slo w er t h a n o n e t h a t is n ’t a s y n c -s ig n a l safe. O u ts id e o f th e k e rn e l, m a k in g a fu n c tio n a s y n c -s ig n a l safe u s u a lly r e q u ire s t h a t th e fu n c tio n m a s k (block) s ig n a ls w h ile it r u n s — a n d t h a t is e x p e n siv e . In c a s e y o u ’re c u rio u s , h e re is th e full lis t o f POSIX 1 0 0 3 .1 -1 9 9 6 fu n c tio n s t h a t a re a s y n c -s ig n a l sa fe (som e o f th e s e f u n c tio n s e x ist o n ly w h e n c e rta in POSIX o p tio n s a re d efin ed , s u c h a s _ p o s i x _ a s y n c h r o n o u s _ i o o r _ p o s i x _ t i m e r s ):

235

Signals

access aio_error aio return aio_suspend alarm cfgetispeed cfgetospeed cfsetispeed cfsetospeed chdir chmod chown clock_gettime close creat dup2 dup execle execve exit fcntl fdatasync fork f stat f sync getegid geteuid getgid

getoverrun getgroups getpgrp getpid getppid getuid kill link lseek mkdir mkfifo open pathconf pause pipe read rename rmdir sem post setgid setpgid setsid setuid sigaction sigaddset sigdelset sigemptyset sigfillset

sigismember sigpending sigprocmask sigqueue sigsuspend sleep stat sysconf tcdrain tcflow tcflush tcgetattr tcgetpgrp tcsendbreak tcsetattr tcsetpgrp time timer_getoverrun timer_gettime timer settime times umask uname unlink utime wait waitpid write

POSIX. l b p ro v id e s c o u n tin g s e m a p h o re s , a n d m o s t s y s te m s th a t s u p p o r t P th r e a d s a lso s u p p o r t POSIX. l b s e m a p h o re s . You m a y n o tic e t h a t th e sem_j>ost fu n c tio n , w h ic h w a k e s th r e a d s w a itin g o n a s e m a p h o re , a p p e a r s in th e list of a s y n c -s ig n a l safe fu n c tio n s . If y o u r s y s te m s u p p o r ts POSIX s e m a p h o re s ( d e fin e s th e _ p o s i x _ s e m a p h o r e s o p tio n ), th e n P th r e a d s a d d s th e a b ility to u s e s e m a p h o re s b e tw e e n th r e a d s w ith in a p ro c e s s . T h a t m e a n s y o u c a n p o s t a s e m a p h o re , fro m w ith in a POSIX s ig n a l-c a tc h in g fu n c tio n , to w a k e a th r e a d in th e s a m e p ro c e s s o r in a n o th e r p ro c e ss. A s e m a p h o re is a d iffe re n t k in d o f s y n c h ro n iz a tio n o b je c t—it is a little lik e a m u te x , a little like a c o n d itio n v a ria b le . T h e d iffe re n c e s c a n m a k e s e m a p h o re s a little h a r d e r to u s e for m a n y c o m m o n ta s k s , b u t th e y m a k e s e m a p h o re s s u b s ta n tially e a s ie r to u s e for c e r ta in sp ec ia liz e d p u rp o s e s . In p a rtic u la r, s e m a p h o re s c a n b e p o s te d (u n lo c k e d o r sig n aled ) from a PO SIX s ig n a l-c a tc h in g fu n c tio n .

236

I

CHAPTER 6

P O S I X adjusts to threads

S e m a p h o re s a r e a g e n e r a l s y n c h ro n iz a tio n m e c h a n is m . W e ju s t h a v e n o re a s o n t o use t h e m t h a t w a y .

I a m e m p h a s iz in g th e u s e o f s e m a p h o re s to p a s s in fo rm a tio n fro m a sig n alc a tc h in g fu n c tio n , r a th e r t h a n for g e n e ra l u s e , fo r a c o u p le o f re a s o n s . O n e re a s o n is t h a t s e m a p h o re s a re p a r t of a d iffe re n t s ta n d a r d . A s I sa id , m o s t s y s te m s th a t s u p p o r t P th r e a d s w ill a lso s u p p o r t POSIX. lb , b u t th e re is n o s u c h re q u ire m e n t a n y w h e re in th e s ta n d a r d . So y o u m a y w ell fin d y o u rs e lf w ith o u t a c c e s s to s e m a p h o re s , a n d y o u s h o u ld n ’t feel d e p e n d e n t o n th e m . (Of c o u rs e , y o u m a y a lso fin d y o u rs e lf w ith s e m a p h o re s a n d w ith o u t th r e a d s —b u t in t h a t c a s e , y o u s h o u ld b e re a d in g a d iffe re n t book .) A n o th e r r e a s o n fo r k e e p in g s e m a p h o re s h e re w ith s ig n a ls is th a t, a lth o u g h s e m a p h o re s a re a c o m p lete ly g e n e ra l s y n c h ro n iz a tio n m e c h a n is m , it c a n b e m o re d ifficu lt to solve m a n y p ro b le m s u s in g s e m a p h o re s —m u te x e s a n d c o n d itio n v aria b le s a r e sim p ler. If y o u ’ve g o t P th re a d s , y o u on ly n e e d s e m a p h o re s to h a n d le th is o n e sp ecia liz ed fu n c tio n —w a k in g a w a itin g th r e a d fro m a s ig n a l-c a tc h in g fu n c tio n . J u s t re m e m b e r t h a t y o u ca n u s e th e m for o th e r th in g s w h e n th e y ’re c o n v e n ie n t a n d av ailab le. POSIX s e m a p h o re s c o n ta in a c o u n t, b u t n o “o w n er,” so a lth o u g h th e y c a n b e u s e d e s s e n tia lly a s a lock, th e y c a n a lso b e u s e d to w a it for e v e n ts. T h e te rm in o logy u s e d in th e POSIX s e m a p h o re o p e ra tio n s s tr e s s e s th e “w a it” b e h a v io r r a th e r t h a n th e “lo c k ” b eh av io r. D o n ’t b e c o n fu s e d b y th e n a m e s , th o u g h ; th e r e ’s n o diffe re n c e b e tw e e n “w a itin g ” o n a s e m a p h o re a n d “lo c k in g ” th e s e m a p h o re . A th r e a d w a its o n a s e m a p h o re (to lo ck a re s o u rc e , o r w a it for a n ev en t) b y c allin g sem_jvait. If th e s e m a p h o re c o u n te r is g re a te r t h a n zero, sem_wait d e c re m e n ts th e c o u n te r a n d r e t u r n s im m ed iately . O th e rw ise , th e th r e a d b lo c k s. A th r e a d c a n p o s t a s e m a p h o re (to u n lo c k a re s o u rc e , o r a w a k e n a w aiter) b y callin g semjpost. If o n e o r m o re th r e a d s a re w a itin g o n th e s e m a p h o re , sem_post will w a k e o n e w a ite r (th e h ig h e s t p rio rity , o r e a rlie s t, w aiter). If n o th r e a d s a re w aiting, th e s e m a p h o re c o u n te r is in c re m e n te d . T h e in itia l v a lu e of th e s e m a p h o re c o u n te r is th e d is tin c tio n b e tw e e n a “lo ck ” s e m a p h o re a n d a “w a it” se m a p h o re . By c re a tin g a s e m a p h o re w ith a n in itia l c o u n t o f 1, y o u allow o n e th re a d to co m p lete a sem_wait o p e ra tio n w ith o u t b lo ck in g — th is “lo c k s” th e s e m a p h o re . B y c re a tin g a s e m a p h o re w ith a n in itia l c o u n t of 0, y o u force all th r e a d s th a t call sem_wait to b lo c k u n til so m e th r e a d c alls sem__post. T h e d iffe re n c e s in h o w s e m a p h o re s w o rk give th e s e m a p h o re tw o im p o r ta n t a d v a n ta g e s o v er m u te x e s a n d c o n d itio n v a ria b le s t h a t m a y b e o f u s e in th re a d e d p ro g ra m s : 1. U n lik e m u te x e s , s e m a p h o re s h a v e n o c o n c e p t o f a n “o w n er.” T h is m e a n s t h a t a n y th r e a d m a y re le a s e th r e a d s b lo c k e d o n a s e m a p h o re , m u c h a s if a n y th r e a d c o u ld u n lo c k a m u te x t h a t so m e th r e a d h a d lo ck ed . (A lthough th is is u s u a lly n o t a good p ro g ra m m in g m o d el, th e re a re tim e s w h e n it is h a n d y .)

Signals

237

2. U n lik e c o n d itio n v a ria b le s , s e m a p h o re s c a n b e in d e p e n d e n t o f a n y e x te rn a l s ta te . C o n d itio n v a ria b le s d e p e n d o n a s h a r e d p re d ic a te a n d a m u te x for w aitin g —s e m a p h o re s do n o t. A s e m a p h o re is re p re s e n te d in y o u r p ro g ra m b y a v a ria b le of ty p e sem_t. You s h o u ld n e v e r m a k e a co p y o f a sem__t v a ria b le — th e r e s u lt of u s in g a co p y of a sem_t v a ria b le in th e sem_wait, sem_trywait, sem_post, a n d sem_destroy fu n ctio n s is u n d e fin e d . F o r o u r p u rp o s e s , a sem_t v a ria b le is in itia liz e d b y c a llin g th e sem_init fu n c tio n . POSIX. l b p ro v id e s o th e r w a y s to c re a te a “n a m e d ” s e m a p h o re t h a t c a n b e s h a r e d b e tw e e n p ro c e s s e s w ith o u t s h a r in g m em o ry , b u t th e re is n o n e e d for th is c a p a b ility w h e n u s in g a s e m a p h o re w ith in a sin g le p ro c e s s . U n lik e P th r e a d s fu n c tio n s , th e POSIX s e m a p h o re f u n c tio n s u s e errno to re p o r t e rro rs . T h a t is, s u c c e s s is d e s ig n a te d b y r e tu r n in g th e v a lu e 0, a n d e rro rs a re d e s ig n a te d b y r e tu r n in g th e v a lu e - 1 a n d s e ttin g th e v a ria b le errno to a n e rro r code. If y o u h a v e a s e c tio n o f co d e in w h ic h y o u w a n t u p to tw o th r e a d s to e x e c u te s im u lta n e o u s ly w h ile o th e rs w ait, y o u c a n u s e a s e m a p h o re w ith o u t a n y a d d itio n a l s ta te . In itialize th e s e m a p h o re to th e v a lu e 2; th e n p u t a sem_wait a t th e b e g in n in g of th e co d e a n d a sem_post a t th e e n d . Tw o th r e a d s c a n th e n w a it on th e s e m a p h o re w ith o u t b lo ck in g , b u t a th ird th r e a d will fin d th e s e m a p h o re s c o u n te r a t 0, a n d b lo ck. A s e a c h th r e a d e x its th e re g io n of co d e it p o s ts th e se m a p h o re , re le a s in g o n e w a ite r (if any) o r re s to rin g th e c o u n te r. T h e sem_getvalue fu n c tio n r e t u r n s th e c u r r e n t v a lu e of th e s e m a p h o re c o u n te r if th e re a re n o th r e a d s w aitin g . If th r e a d s a re w aitin g , sem_getvalue r e t u r n s a n eg a tiv e n u m b e r. T h e a b s o lu te v a lu e o f t h a t n u m b e r te lls h o w m a n y th r e a d s a re w a itin g o n th e s e m a p h o re . K eep in m in d t h a t th e v a lu e it r e tu r n s m a y a lre a d y b e in c o rre c t—it c a n c h a n g e a t a n y tim e d u e to th e a c tio n of so m e o th e r th re a d . T h e b e s t u s e for sem_getvalue is a s a w ay to w ak e m u ltip le w aiters, so m ew h at like a co n d itio n v aria b le b ro a d c a st. W ith o u t sem_getvalue, y o u h av e n o w ay of know in g how m a n y th re a d s m ig h t b e blo cked o n a se m a p h o re . To “b ro a d c a st" a se m a p h o re , y o u co u ld call sem_getvalue a n d sem_post in a loop u n til sem_getvalue re p o rts th a t th e re a re n o m o re w aiters. B u t re m e m b e r t h a t o th e r th r e a d s c a n call sem_post d u rin g th is loop, a n d th e re is n o s y n c h ro n iz a tio n b e tw e e n th e v a rio u s c o n c u r r e n t c a lls to sem_post a n d sem_getvalue. You c a n e a sily e n d u p is s u in g o n e o r m o re e x tra ca lls to sem_post, w h ic h will c a u s e th e n e x t th r e a d t h a t calls sem_wait to fin d a v a lu e g re a te r th a n 0, a n d r e tu r n im m ed iately w ith o u t blockin g. T h e p ro g ra m below , semaphore_signal.c, u s e s a s e m a p h o re to a w a k e n th r e a d s from w ith in a POSIX s ig n a l-c a tc h in g fu n c tio n . N otice t h a t th e sem_init call s e ts th e in itia l v a lu e to 0 so t h a t e a c h th re a d callin g sem_wait will b lo ck . T h e m a in p ro g ra m th e n r e q u e s ts a n in te rv a l tim er, w ith a POSIX s ig n a l-c a tc h in g fu n c tio n t h a t w ill w a k e o n e w a itin g th r e a d b y c a llin g sem__post. E a c h o c c u rre n c e o f th e POSIX tim e r sig n a l will a w a k e n o n e w a itin g th re a d . T h e p ro g ra m will ex it w h e n e a c h th r e a d h a s b e e n a w a k e n e d five tim e s.

238

CH A P T E R 6

P O S I X a d ju st s t o t h r ea ds

N otice th e co d e to c h e c k for e i n t r r e t u r n s t a t u s fro m th e sem wait call. T h e POSIX tim e r sig n a l in th is p ro g ra m will a lw ay s o c c u r w h ile o n e o r m o re th r e a d s a r e b lo c k e d in sem_wait. W h e n a sig n a l o c c u rs for a p ro c e s s (s u c h a s a tim e r signal), th e s y s te m m a y d eliv er t h a t sig n a l w ith in th e c o n te x t of a n y th r e a d w ith in th e p ro c e s s . Likely “v ic tim s ‫ ״ ״‬in c lu d e th r e a d s t h a t th e k e rn e l k n o w s to b e w aitin g , fo r e x a m p le , o n a s e m a p h o re . So th e re is a fairly good c h a n c e t h a t th e sem_wait th r e a d w ill b e c h o s e n , a t le a s t so m e tim e s. If t h a t o c c u rs , th e c a ll to sem_wait w ill r e t u r n w ith e i n t r .T h e th r e a d m u s t th e n re try th e call. T re a tin g a n e i n t r r e tu r n a s “s u c c e s s ” w o u ld m a k e it a p p e a r t h a t tw o th r e a d s h a d b e e n a w a k e n e d b y e a c h call to sem_j) 0 s t : th e th r e a d t h a t w a s in te r r u p te d , a n d th e th r e a d t h a t w a s aw ak e n e d b y th e se m _ p o st call.

32-35



semaphore's ignal.c

1 #include 2 #include 3 #include 4 #include < s e m aphore.h> 5 #include 6 #include 7 #include ‫ ״‬errors.h" 8 9 sem__t semaphore; 10 11 /* 12 * Signal-catching function. 13 */ 14 void signal catcher (int sig) 15 { 16 if (sem_post (&semaphore) == 1 ‫) ־‬ 17 errno abort ("Post semaphore ‫;( ״‬ 18 > 19 20 /* 21 * Thread start routine which waits on the semaphore. 22 */ 23 void *sem waiter (void *arg) 24 { 25 int number = (int)arg; 26 int counter; 27 28 /* 29 * Each thread waits 5 times. 30 */ 31 for (counter = 1; counter counter = = 0 ) { barrier->cycle = !barrier->cycle; barrier->counter = barrier->threshold; status = pthread_cond_broadcast (&barrier->cv);

/* * The last thread into the barrier will return status * -1 rather than 0, so that it can be used to perform * some special serial code following the barrier.

*/ if (status == 0) status = -1; } else {

/* * Wait with cancellation disabled, because barrier_wait * should not be a cancellation point.

*/ pthread_setcancelstate

(PTHREAD_CANCEL_DISABLE, & cancel);

/* * Wait until the barrier's cycle changes, which means * that it has been broadcast, and we don't want to wait * any m o r e .

*/ while (cycle == barrier->cycle) s ta tu s

= p th r e a d _ c o n d _ w a it

{ (

&barrier‫> ־‬cv, &barrier->mutex); if (status != 0) break;

}

251

E x t e n d e d syn c h r o n i z a t i o n

48 49 50 51 52 53 54 55 56 57 58 59 60

pthread setcancelstate

&tmp);

} ■

barrier.c

part 3

barrier_wait

F in ally , barrier_main.c is a s im p le p ro g ra m t h a t u s e s b a r r ie r s . E a c h th r e a d lo o p s o n c a lc u la tio n s w ith in a p riv a te a rra y . A t th e b e g in n in g a n d e n d o f e a c h ite ra tio n , th e th r e a d s , r u n n in g fu n c tio n thread_routine, all w a it o n a b a r r ie r to s y n c h ro n iz e th e o p e ra tio n . A t th e e n d of e a c h ite ra tio n , th e “le a d th r e a d ” (th e o n e receiv in g a -1 r e s u lt fro m b a r r i e r _ w a i t ) w ill m odify th e d a ta of all th r e a d s , p re p a rin g th e m for th e n e x t ite ra tio n . T h e o th e rs go d ire c tly to th e to p of th e loop a n d w a it o n th e b a r r ie r a t lin e 3 5 .

35,47 56-61



1 2 3 4 5 6 7 8

(cancel,

> /* * Ignore an error in unlocking. It shouldn't happen, and * reporting it here would be misleading — the barrier wait * completed, after all, whereas returning, for example. * EINVAL would imply the wait had failed. The next attempt * to use the barrier *will* return an error, or hang, due * to whatever happened to the mutex. */ pthread mutex unlock (&barrier->mutex); return status; /* error, -1 for waker, or 0 */

barrier_main.c

!include !include "barrier.h" !include "errors.h" !define !define !define !define

THREADS 5 ARRAY 6 INLOOPS 1000 OUTLOOPS 10

9

10 /* 11

* Keep track of each thread.

12

*/

13 typedef struct thread_tag { 14 pthread_t thread_id; 15 int number; 16 int increment; 17 int a r r a y [A R R A Y ]; 18 } thread_t; 19 20 barrier_t barrier; 21 thread_t t h r e a d [T H R E A D S ];

252

23

CH A P T E R 7

“R e a l c o d e ”

/*

24

* Start routine for threads.

25

*/

26

void *thread_routine

27

{

(void *arg)

thread_t *self = (thread_t*)arg; /* Thread's thread_t */ int in_loop, out_loop, count, status;

28 29 30

/*

31

* Loop through OUTLOOPS barrier cycles.

32

*/

33

for (out_loop = 0; out_loop < OUTLOOPS; out_loop++) status = barrier_wait (fcbarrier); if (status > 0) err_abort (status, "Wait on barrier");

34 35 36 37

{

38

/*

39

* This inner loop just adds a value to each element in * the working array.

40 41

*/

42

for (in_loop = 0; in_loop < INLOOPS; in_loop++) for (count = 0; count < ARRAY; count++) self->array[count] += self->increment;

43 44 45 46

status = barrier_wait (&barrier); if (status > 0) err__abort (status, "Wait on barrier");

47 48 49 50

/*

51

* The barrier causes one thread to return with the * special return status -1. The thread receiving this * value increments each element in the shared array.

52 53 54

*/

55

if (status == -1) { int thread_num;

56 57 58

for (thread__num = 0; thread_num < THREADS; thread_num++) t h r e a d [t hread_num].increment += 1;

59 60

>

61

}

62

return NULL;

63 64

}

65

66

int main

67

{

68 69

(int arg, char *argv[])

int thread_count, array_count; int s tatus;

70 71 72

barrier_init

(Sbarrier, THREADS);

2 S3

E x t e n d e d syn c h r o n i z a t i o n

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87

/* * Create a set of threads that will use the barrier. */ for (thread_count = 0; thread__count < THREADS; thread_count++) { thread[thread_count].increment = thread_count; thread[thread_count].number = thread_count; for (array_count = 0; array_count < ARRAY; array_count++) thread[thread_count].array[array_count] = array_count + 1; status = pthread_create (&thread [thread__count ]. thread_id, NULL, thread_routine, (v o i d * )&t h r e a d [thread__count]); if (status 1= 0) err_abort (status, "Create t hread” ); }

88 89 90 91 92 93 94 95 96 97 98

/* * Now join with each of the threads. */ for (thread_count = 0; thread_count < THREADS; thread_count++) { status = pthread_join (thread[thread_count].thread_id, NULL); if (status 1= 0) err_abort (status, "Join thread"); printf ("%02ds (%d) ", thread_count, t h r e a d [thread_count].increment);

99 100

for (array_count = 0; array_count < ARRAY; array_count++)

101

printf

102 103 104 105 106 107

printf

",

} /* * To be thorough, destroy the barrier. */

108

109 110

barrier_destroy (Sbarrier); return 0;

111

> ■

7.1.2

("%010u

thread[thread_count ].array [array__count ] ); (11\n" );

barrier_main.c

R e a d /w rite lo ck s A re a d /w r ite lock is a lo t lik e a m u te x . It is a n o th e r w ay to p re v e n t m o re th a n o n e th r e a d fro m m od ify in g s h a r e d d a ta a t th e s a m e tim e. B u t u n lik e a m u te x it d is tin g u is h e s b e tw e e n re a d in g d a ta a n d w ritin g d a ta . A m u te x e x c lu d e s all o th e r th r e a d s , w h ile a r e a d /w r ite lo c k allo w s m o re t h a n o n e th r e a d to re a d th e d a ta , a s lo n g a s n o n e of th e m n e e d s to c h a n g e it.

254

CH A P T E R

7

“R e a l c o d e ”

R e a d /w rite lo c k s a re u s e d to p ro te c t in fo rm a tio n t h a t y o u n e e d to re a d freq u e n tly b u t u s u a lly d o n ’t n e e d to m odify. F o r ex am p le, w h e n y o u b u ild a c a c h e o f re c e n tly a c c e s s e d in fo rm a tio n , m a n y th r e a d s m a y s im u lta n e o u s ly e x a m in e th e c a c h e w ith o u t co n flict. W h e n a th r e a d n e e d s to u p d a te th e c a c h e , it m u s t h a v e e x clu siv e a c c e s s. W h en a th r e a d lo ck s a r e a d /w r ite lock, it c h o o s e s s h a re d re a d a cce s s o r e xclu s iv e w rite a cce s s . A th r e a d th a t w a n ts re a d a c c e s s c a n ’t c o n tin u e w hile a n y th r e a d c u rre n tly h a s w rite a c c e s s. A th re a d try in g to g a in w rite a c c e s s c a n ’t c o n tin u e w h e n a n o th e r th r e a d c u rre n tly h a s e ith e r w rite a c c e s s o r re a d a c c e ss. W h e n b o th r e a d e rs a n d w rite rs a re w a itin g for a c c e s s a t th e s a m e tim e, th e re a d e rs a re given p re c e d e n c e w h e n th e w rite lo ck is re le a se d . R e a d p re c e d e n c e fav o rs c o n c u rre n c y b e c a u s e it p o te n tia lly allo w s m a n y th r e a d s to a c c o m p lish w o rk s im u lta n e o u s ly . W rite p re c e d e n c e o n th e o th e r h a n d w o u ld e n s u r e t h a t p e n d in g m o d ific a tio n s to th e s h a r e d d a ta a re c o m p le te d b efo re th e d a ta is u s e d . T h e re ’s n o a b s o lu te rig h t o r w ro n g policy, a n d if y o u d o n ’t fin d th e im p le m e n ta tio n h e re a p p ro p ria te for y o u , it is e a s y to c h a n g e . F ig u re 7 .3 s h o w s th e o p e ra tio n of a r e a d /w r ite lo c k b e in g u s e d to sy n c h ro n iz e th r e e th r e a d s , c a lled th r e a d 1, th r e a d 2, a n d th r e a d 3. T h e fig u re is a s o r t o f tim in g d ia g ra m , w ith tim e in c re a s in g fro m left to rig h t. E a c h of th e lin e s b e g in n in g a t th e la b e ls in th e u p p e r left d e s ig n a te s th e b e h a v io r o f a specific th r e a d —so lid for th r e a d 1, d o tte d for th r e a d 2, a n d d a s h e d for th r e a d 3. W h e n th e lin e s d ro p w ith in th e ro u n d e d re c ta n g le , th e y a re in te ra c tin g w ith th e r e a d /w r ite lock. If th e

FIGURE 7 .3

R e ad / w rite lock ope ration

255

E x t e n d e d syn c h r o n i z a t i o n

lin e d ro p s below th e c e n te r line, it sh o w s th a t th e th r e a d h a s th e r e a d /w r ite lo ck lo ck ed , e ith e r for e x clu siv e w rite o r fo r s h a r e d re a d . L in es t h a t h o v e r ab o v e th e c e n te r lin e r e p r e s e n t th r e a d s w a itin g for th e lock. In th is ex am p le, th r e a d 1 lo c k s th e r e a d /w r ite lock for ex clu siv e w rite. T h re a d 2 trie s to lo ck th e r e a d /w r ite lo ck fo r s h a r e d re a d a n d , fin d in g it a lre a d y lo ck ed fo r e x c lu siv e w rite, b lo c k s. W h e n th r e a d 1 re le a s e s th e lock, it a w a k e n s th r e a d 2, w h ic h th e n s u c c e e d s in lo c k in g th e r e a d /w r ite lo c k fo r s h a r e d re a d . T h re a d 3 th e n trie s to lo ck th e r e a d /w r ite lo c k fo r s h a r e d re a d a n d , b e c a u s e th e r e a d /w r ite lo ck is a lre a d y lo ck ed for s h a r e d re a d , it s u c c e e d s im m e d ia te ly . T h re a d 1 th e n trie s to lo ck th e r e a d /w r ite lo ck a g a in fo r e x clu siv e w rite a c c e s s , a n d b lo c k s b e c a u s e th e r e a d /w r ite lo c k is a lre a d y lo c k ed for re a d a c c e s s . W h e n th r e a d 3 u n lo c k s th e r e a d /w r ite lo ck, it c a n n o t a w a k e n th r e a d 1, b e c a u s e th e r e is a n o th e r re a d e r. O nly w h e n th r e a d 2 a lso u n lo c k s th e r e a d /w r ite lock, a n d th e lock b e c o m e s u n lo c k e d , c a n th r e a d 1 b e a w a k e n e d to lo c k th e r e a d /w r ite lo c k for ex c lu siv e w rite a c c e s s . T h e h e a d e r file rwlock.h a n d th e C s o u rc e file rwlock.c d e m o n s tr a te a n im plem e n ta tio n of re a d /w r ite lo c k s u s in g s ta n d a r d P th r e a d s m u te x e s a n d c o n d itio n v a ria b le s. T h is is a p o rta b le im p le m e n ta tio n t h a t is rela tiv ely e a s y to u n d e r s ta n d . O n e co u ld , of c o u rs e , c re a te a m u c h m o re effic ien t im p le m e n ta tio n fo r a n y specific s y s te m b a s e d o n k n o w led g e o f n o n p o rta b le h a rd w a re a n d o p e ra tin g s y ste m c h a ra c te ris tic s . T h e r e s t of th is s e c tio n sh o w s th e d e ta ils o f a r e a d /w r ite lo c k p a c k a g e . F irst, rwlo c k . h d e s c rib e s th e in te rfa c e s , a n d th e n rwlock • c p ro v id e s th e im p le m e n ta tio n . P a r t 1 s h o w s th e s tr u c t u r e o f a r e a d /w r ite lock, r e p r e s e n te d b y th e ty p e rwlock__t.

O f c o u rs e , th e r e ’s a m utex to se ria liz e a c c e s s to th e s tr u c tu r e . W e’ll u s e tw o s e p a r a te c o n d itio n v a ria b le s , o n e to w a it fo r re a d a c c e s s (called re a d ) a n d o n e to w a it fo r w rite a c c e s s (called, s u rp ris in g ly , w r ite ) . T h e rwlock_t s tr u c t u r e h a s a valid m e m b e r to e a sily d e te c t c o m m o n u s a g e e rro rs , s u c h a s try in g to lo ck a r e a d /w r ite lo ck t h a t h a s n ’t b e e n in itia lize d . T h e m e m b e r is s e t to a m a g ic n u m b e r w h e n th e r e a d /w r ite lo c k is in itia liz e d , j u s t a s in barrier_init. To e n a b le u s to d e te rm in e w h e th e r e ith e r c o n d itio n v a ria b le h a s w a ite rs, w e’ll k e e p a c o u n t o f activ e r e a d e rs ( r _ a c t iv e ) a n d a flag to in d ic a te a n a c tiv e w rite r (w _ a c tiv e ). We a lso k eep a c o u n t o f th e n u m b e r o f th r e a d s w a itin g for re a d a c c e s s (r_ w a it) a n d for w rite a c c e s s (w_wait). F in ally , w e n e e d a “m a g ic n u m b e r ” fo r o u r v alid m e m b er. (See th e fo o tn o te in S e c tio n 7 .1 .1 if y o u m is s e d th is p a r t of th e b a r r ie r ex am p le.)

7-9

10

11-12

13-14 17

■ 1

rwlock.h #include

2 3 4 5

/* * Structure describing a read/write lock. */

part 1

rwlock_t

256

CH A P T E R 7

“R e a l c o d e ‫״‬

6 typedef struct rwlock_tag { 7

8 9 10 11

12 13 14 15 16 17

pthread_mutex_t pthread_cond__t pthread_cond_t int int int int int } rwlock t;

mutex; read; write; valid; r_active; w_active; r_wait; w_wait;

!define RWLOCK VALID

Oxfacade

rwlock.h

/* /* /* /* /* /* /*

wait for read */ wait for write */ set when valid */ readers active */ writer active */ readers waiting */ writers waiting */

part 1

rwlock_t

We c o u ld h a v e s a v e d so m e s p a c e a n d sim p lifie d th e co d e b y u s in g a sin g le c o n d itio n v a ria b le , w ith re a d e rs a n d w rite rs w a itin g u s in g s e p a r a te p re d ic a te e x p re s s io n s . We w ill u s e o n e c o n d itio n v a ria b le for e a c h p re d ic a te , b e c a u s e it is m o re efficient. T h is is a c o m m o n trad e-o ff. T h e m a in c o n s id e ra tio n is t h a t w h e n tw o p re d ic a te s s h a r e a c o n d itio n v a ria b le , y o u m u s t a lw a y s w a k e th e m u s in g p th r e a d _ c o n d _ b r o a d c a s t, w h ic h w o u ld m e a n w a k in g all w a ite rs e a c h tim e th e r e a d /w r ite lo ck is u n lo c k e d . We k e e p tr a c k of a b o o le a n v a ria b le for “w rite r a c tiv e ,” s in c e th e re c a n o n ly b e one. T h e re a re a lso c o u n te r s for “re a d e rs a c tiv e ,” “re a d e rs w a itin g ,” a n d “w rite rs w a itin g .” We co u ld g et b y w ith o u t c o u n te r s for re a d e rs a n d w rite rs w aitin g . All re a d e rs a re a w a k e n e d s im u lta n e o u s ly u s in g a b ro a d c a s t, so it d o e s n ’t m a tte r h o w m a n y th e re a re . W rite rs a re a w a k e n e d on ly if th e re a re n o re a d e rs , so w e c o u ld d is p e n s e w ith k e e p in g tr a c k o f w h e th e r th e re a re a n y th r e a d s w a itin g to w rite (at th e c o s t o f a n o c c a sio n a l w a s te d c o n d itio n v a ria b le sig n a l w h e n th e re a re n o w a ite rs). We c o u n t th e n u m b e r of th r e a d s w a itin g for re a d a c c e s s b e c a u s e th e c o n d itio n v a ria b le w a its m ig h t b e c a n c e le d . W ith o u t c a n c e lla tio n , w e co u ld u s e a sim p le flag—“th r e a d s a re w a itin g for r e a d ” o r “n o th r e a d s a re w a itin g for r e a d .” E a c h th r e a d c o u ld s e t it befo re w aitin g , a n d w e co u ld c le a r it b efo re b ro a d c a s tin g to w a k e all w a itin g re a d e rs . H ow ever, b e c a u s e w e c a n ’t c o u n t th e th r e a d s w a itin g o n a c o n d itio n v a ria b le , w e w o u ld n ’t k n o w w h e th e r to c le a r t h a t flag w h e n a w a itin g r e a d e r w a s c a n c e le d . T h is in fo rm a tio n is critic a l, b e c a u s e if th e re a re n o r e a d e rs w a itin g w h e n th e re a d /w r ite lo ck is u n lo c k e d , w e m u s t w a k e a w rite r—b u t w e c a n n o t w a k e a w rite r if th e re a re w a itin g re a d e rs . A c o u n t of w a itin g re a d e rs , w h ic h w e c a n d e c re a s e w h e n a w a ite r is c a n c e le d , so lv es th e p ro b lem . T h e c o n s e q u e n c e s of “g e ttin g it w ro n g ” a re le s s im p o r ta n t fo r w rite rs t h a n for re a d e rs . B e c a u s e w e c h e c k for re a d e rs first, w e d o n ’t re a lly n e e d to k n o w w h e th e r th e re a re w rite rs . We c o u ld sig n a l a “p o te n tia l w rite r” a n y tim e th e re a d /w r ite lo ck w a s re le a s e d w ith n o w a itin g re a d e rs . B u t c o u n tin g w a itin g w rite rs allo w s u s to av oid a c o n d itio n v a ria b le sig n a l w h e n n o th r e a d s a re w aitin g . P a rt 2 sh o w s th e r e s t of th e d e fin itio n s a n d th e fu n c tio n p ro to ty p e s .

257

E x t e n d e d syn c h r o n i z a t i o n

T h e rwl0CK_iN 1 T 1ALIzer m a c ro allo w s y o u to s ta tic a lly in itia lize a r e a d /w r ite lock. O f c o u rs e , y o u m u s t a lso b e a b le to in itia lize a r e a d /w r ite lo ck t h a t y o u c a n n o t a llo c a te sta tic a lly , so w e p ro v id e rwl_init to in itia liz e d y n a m ic a lly , a n d rwl_ destroy to d e s tro y a r e a d /w r ite lo c k o n c e y o u ’re d o n e w ith it. In a d d itio n , th e re a r e f u n c tio n s to lo ck a n d u n lo c k th e r e a d /w r ite lo ck for e ith e r re a d o r w rite a c c e s s. You c a n “try to lo c k ” a r e a d /w r ite lock, e ith e r for re a d o r w rite a c c e s s, b y c a llin g rwl_readtrylock o r r w l _ w r i t e t r y l o c k . , j u s t a s y o u c a n try to lo ck a m u te x b y c a llin g pthread_mutex_trylock.

4-6 1 1 -1 8



1 2 3 4 5

rwlock.h

part 2

/* * Support static initialization of barriers. */ #define RWL_INITIALIZER \ {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER,

6

interfaces

\

PTHREAD_COND_INITIALIZER, RWLOCK_VALID, 0, 0, 0, 0}

7

8

/*

9

* Define read/write lock functions.

10

*/

11 12 13 14 15 16 17 18

extern extern extern extern extern extern extern extern ■

int int int int int int int int

rwl_init (rwlock_t *rwlock); rwl_destroy (rwlock__t *rwlock); rwl_readlock (rwlock_t *rwlock); rwl_readtrylock (rwlock_t *rwlock); rwl_readunlock (rwlock_jt *rwlock); rwl_writelock (rwlock_t *rwlock); rwl_writetrylock (rwlock_t *rwlock); rwl_writeunlock (rwlock_t *rwlock);

rwlock.h

part 2

interfaces

T h e file r w l o c k .c c o n ta in s th e im p le m e n ta tio n o f r e a d /w r ite lo c k s. T h e followin g e x a m p le s b r e a k d o w n e a c h o f th e fu n c tio n s u s e d to im p le m e n t th e rwlock.h in te rfa c e s . P a rt 1 sh o w s r w l _ i n i t , w h ic h in itia liz e s a r e a d /w r ite lock. It in itia liz e s th e P th r e a d s s y n c h ro n iz a tio n o b je cts, in itia liz e s th e c o u n te r s a n d flags, a n d fin ally s e ts th e v a l i d s e n tin e l to m a k e th e r e a d /w r ite lo c k rec o g n iz a b le to th e o th e r in te rfa c e s . If w e a re u n a b le to in itia liz e th e r e a d c o n d itio n v a ria b le , w e d e s tro y th e m u te x t h a t w e’d a lre a d y c re a te d . S im ilarly , if w e a re u n a b le to in itia lize th e w r i t e c o n d itio n v a ria b le , w e d e s tro y b o th th e m u te x a n d th e re a d c o n d itio n v a ria b le . ■

1 2

rwlock.c

#include #include ,,errors.h"

part 1

rwl__init

258

CH A P T E R 7

3 4 5 6 7 8

/* * Initialize a read/write lock. */ int rwl_init (rwlock_t *rwl)

9

{

“R e a l c o d e ”

#include "rwlock.h"

10

int status;

11

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

rwl->reactive = 0; rwl->r_wait = rwl->w_wait = 0; rwl->w_active = 0; status = pthread_mutex_init (&rwl->mutex, NULL); if (status != 0) return status; status = pthread_cond_init (&rwl->read, NULL); if (status 1= 0) { / * i f unable to create read CV, destroy mutex */ pthread_mutex_destroy (&rwl->mutex); return status; } status = pthread_cond_init (&rwl->write, NULL); if (status 1= 0) { / * i f unable to create write CV, destroy read CV and mutex */ pthread_cond__destroy (&rwl->read); pthread_mutex_destroy (&rwl->mutex); return status; } rwl->valid = RWLOCK_VALID; return 0; } ■

rwlock. c

part 1

rwl_init

P a rt 2 s h o w s th e r w l _ d e s tr o y fu n c tio n , w h ic h d e s tro y s a r e a d /w r ite lock. We firs t tr y to verify t h a t th e r e a d /w r ite lo c k w a s p ro p e rly in itia liz e d b y c h e c k in g th e v a l i d m e m b er. T h is is n o t a c o m p le te p ro te c tio n a g a in s t in c o rre c t u s a g e , b u t it is c h e a p , a n d it w ill c a tc h so m e of th e m o s t c o m m o n e rro rs . S ee th e a n n o ta tio n for b a r r i e r .c , p a r t 2, fo r m o re a b o u t h o w th e v a l i d m e m b e r is u s e d . 10-30 C h e c k w h e th e r th e r e a d /w r ite lock is in u s e . We lo o k for th r e a d s t h a t a re u s in g o r w a itin g fo r e ith e r re a d o r w rite a c c e s s. U sin g tw o s e p a r a te i f s ta te m e n ts m a k e s th e te s t slig h tly m o re re a d a b le , th o u g h th e r e ’s n o o th e r b en efit. 36-39 A s in barrier_destroy, w e d e s tro y all P th r e a d s s y n c h ro n iz a tio n o b je c ts, a n d s to re e a c h s t a t u s r e tu r n . If a n y of th e d e s tr u c tio n c a lls fails, r e tu r n in g a n o n z e ro v a lu e , rwl_destroy w ill r e t u r n t h a t s ta t u s , a n d if th e y all s u c c e e d it w ill r e tu r n 0 fo r s u c c e s s . 8-9

259

E x t e n d e d syn c h r o n i z a t i o n



rwlock.c

part 2

rwl_destroy

/* * Destroy a read/write lock.

*/ int rwl_destroy (rwlock_t *rwl)

{ 6

int status,

statusl, status2;

7

8

if (rwl->valid != RWLOCK__VALID) return EINVAL; status = pthread_mutex_lock (&rwl->mutex); if (status != 0) return status;

9 10 11 12

13 14 15 16 17 18 19

/* * Check whether any threads own the lock; report ,,BUSY" if * so.

*/

20

if {rwl->r_active > 0 || rwl->w_active) { pthread_mutex_unlock (&rwl->mutex); return EBUSY;

21

>

22

/*

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

* Check whether any threads are known to be waiting; report * EBUSY if so.

*/ if (rwl->r__wait ! - 0 | | rwl->w_wait ! = 0 ) pthread_mutex__unlock (&rwl->mutex); return EBUSY;

{

}



rwl->valid = 0; status = pthread_mutex_unlock (&rwl->mutex); if (status 1= 0) return status; status = pthread_mutex_destroy (&rwl->mutex); statusl = pthread_cond_destroy (&rwl->read); status2 = pthread_cond_destroy (&rwl->write); return (status == 0 ? status : (statusl == 0 ? statusl : status2)); rwlock.c

part 2

rwl_destroy

260

CH A P T E R 7

“R e a l c o d e ”

P a rt 3 sh o w s th e code for rwl_readcleanup a n d rwl_writecleanup, tw o c a n ce lla tio n c le a n u p h a n d le r s u s e d in lo ck in g th e re a d /w r ite lo ck for re a d a n d w rite a c c e s s, resp ectiv ely . A s y o u m a y in fe r from th is , r e a d /w r ite lo ck s, u n lik e b a rrie rs , a re c a n c e lla tio n p o in ts. W h e n a w a it is ca n c e le d , th e w a ite r n e e d s to d e c re a se th e c o u n t o f th r e a d s w a itin g for e ith e r a re a d o r w rite lock, a s a p p ro p ria te , a n d u n lo c k th e m u te x . ■

rwlock.c

part 3

1 2 3 4 5 6 7 8

/* * Handle cleanup when the read lock condition variable * wait is canceled. * * Simply record that the thread is no longer waiting, * and unlock the mutex. */ static void rwl_readcleanup (void *arg)

9

{

10

rwlock_t

cleanuphandlers

*rwl = (rwlock_t *)arg;

11

12 13 14 15 16 17 18 19 20 21

rwl‫> ־‬r__wait— ; pthread_mutex_unlock (&rwl->mutex); } /* * * * * *

22

Simply record that the thread is no longer waiting, and unlock the mutex.

*/

23 24 25 26 27 28 29

static void rwl_writecleanup (void *arg) { rwlock_t *rwl = (rwlock_t *)arg; rwl->w_wait— ; pthread_mutex_unlock (&rwl->mutex); } ■

10-26

Handle cleanup when the write lock condition variable wait is canceled.

rwlock.c

part 3

cleanuphandlers

P a rt 4 s h o w s rwl_readlock, w h ic h lo c k s a r e a d /w r ite lo ck fo r r e a d a c c e s s . If a w rite r is c u rre n tly activ e (w_active is n o n zero ), w e w a it fo r it to b r o a d c a s t th e read c o n d itio n v a ria b le . T h e r wait m e m b e r c o u n ts th e n u m b e r o f th r e a d s w aitin g to re a d . T h is co u ld b e a sim p le b o o le a n v a ria b le , e x c e p t for o n e p ro b le m — w h e n a w a ite r is c a n c e le d , w e n e e d to k n o w w h e th e r th e re a re a n y re m a in in g w a ite rs. M a in ta in in g a c o u n t m a k e s th is e asy , s in c e th e c le a n u p h a n d le r only n e e d s to d e c re a s e th e c o u n t.

261

E x t e n d e d syn c h r o n i z a t i o n

T h is is o n e of th e p la c e s w h e re th e co d e m u s t b e c h a n g e d to c o n v e rt o u r r e a d / w rite lo ck fro m “r e a d e r p re fe re n c e ” to “w rite r p re fe re n c e ,” s h o u ld y o u c h o o se to do th a t. To im p le m e n t w rite r p re fe re n c e , a r e a d e r m u s t b lo c k w h ile th e re a re w a itin g w rite rs (w _wait > 0), n o t m e re ly w h ile th e re a r e activ e w rite rs , a s w e do h e re . N otice th e u s e o f th e c le a n u p h a n d le r a ro u n d th e c o n d itio n w ait. A lso, n o tic e t h a t w e p a s s th e a r g u m e n t 0 to pthread_cleanup_pop so t h a t th e c le a n u p co d e is called o n ly if th e w a it is c a n c e le d . We n e e d to p e rfo rm slig h tly d iffe re n t a c tio n s w h e n th e w a it is n o t c a n c e le d . If th e w a it is n o t c a n c e le d , w e n e e d to in c re a s e th e c o u n t o f activ e re a d e rs b efo re u n lo c k in g th e m u te x .

15,21



1

rwlock.c

part 4

rwl_readlock

/*

2

* Lock a read/write lock for read access.

3

*/

4

int rwl_readlock (rwlock_t *rwl)

5

{

6 7 8 9 10 11 12 13 14 15 16 17 18 19

int s tatus; if (rwl->valid != RWLOCK_VALID) return EINVAL; status = pthread_mutex_lock (&rwl->mutex); if (status != 0) return status; if (rwl->w_active) { rwl->r_wait++; pthread_cleanup_push (rwl_readcleanup, (void*)rwl); while (rwl->w_active) { status = pthread_cond_wait (&rwl->read, &rwl->mutex); if (status 1= 0) break;

20

}

21

pthread_cleanup_pop rwl->r_wait— ;

22

23 24 25 26 27

(0);

> if (status == 0) rwl->r_active++; pthread_mutex_unlock (&rwl->mutex); return status;

28

} ■

rwlock.c

part 4

rwl_readlock

P a rt 5 s h o w s rwl_readtrylock. T h is fu n c tio n is n e a rly id e n tic a l to rwl_readlock, e x c e p t th a t, in s te a d o f w a itin g for a c c e s s if a w rite r is activ e, it r e tu r n s e b u s y . It d o e s n ’t n e e d a c le a n u p h a n d le r, a n d h a s n o n e e d to in c re a s e th e c o u n t o f w a itin g re a d e rs .

262

CH A P T E R 7

“R e a l c o d e ”

T h is fu n c tio n m u s t a lso b e m o d ifie d to im p le m e n t “w rite r p re fe re n c e ” r e a d / w rite lo ck s, b y r e tu r n in g e b u s y w h e n a w rite r is w aitin g , n o t j u s t w h e n a w rite r is activ e. ■

rwlock.c

part 5

1 2 3 4 5

/* * Attempt to lock a read/write lock for read access * block if unavailable). */ int rwl_readtrylock (rwlock__t *rwl)

6

{

7

int status,

rwl_readtrylock

(don't

status2;

8 9 10 11 12 13 14 15 16 17 18 19

if (rwl->valid != RWLOCK_VALID) return EINVAL; status = pthread_mutex_lock (&rwl->mutex); if (status != 0) return status; if (rwl->w_active) status = EBUSY; else rwl->r_active++; status2 = pthread_mutex_unlock (&rwl->mutex); return (status2 i= 0 ? status2 : status); >

20



13

rwlock.c

part 5

rwl_readtrylock

P a r t 6 s h o w s rwl_readunlock. T h is fu n c tio n e s s e n tia lly re v e rs e s th e effect o f rwl_readlock o r rwl_tryreadlock, b y d e c re a s in g th e c o u n t o f a c tiv e r e a d e r s (reactive).

14-15

If th e re a re n o m o re activ e re a d e rs , a n d a t le a s t o n e th r e a d is w a itin g for w rite a c c e s s, sig n a l th e w r i t e c o n d itio n v a ria b le to u n b lo c k one. N ote t h a t th e re is a ra c e h e re , a n d w h e th e r y o u s h o u ld b e c o n c e rn e d a b o u t it d e p e n d s o n y o u r n o tio n o f w h a t s h o u ld h a p p e n . If a n o th e r th r e a d t h a t is in te re s te d in re a d a c c e s s ca lls r w l_ r e a d lo c k o r r w l _ t r y r e a d l o c k b efo re th e a w a k e n e d w rite r c a n r u n , th e re a d e r m a y “w in ,” d e s p ite th e fa c t t h a t w e j u s t sele c te d a w riter. B e c a u se o u r v e rs io n o f re a d /w r ite lo ck s h a s “re a d e r p re fe re n c e ,” th is is w h a t w e u s u a lly w a n t to h a p p e n —th e w rite r will d e te rm in e t h a t it h a s failed a n d w ill r e s u m e w aitin g . (It receiv ed a s p u r io u s w a k e u p .) If th e im p le m e n ta tio n c h a n g e s to p re fe r w rite rs , th e s p u r io u s w a k e u p will n o t o ccu r, b e c a u s e th e p o te n tia l re a d e r w o u ld h a v e to blo ck . T h e w a ite r w e j u s t u n b lo c k e d c a n n o t d e c re a se w _ w ait u n til it a c tu a lly c la im s th e lock.

263

E x t e n d e d syn c h r o n i z a t i o n



1 2

rwlock.c

part 6

rwl_readunlock

/* * Unlock a read/write lock from read access.

*/

3 4

int rwl_readunlock (rwlock_t *rwl)

5

{

6

int status, status2;

7

8

if (rwl->valid != RWLOCK_VALID) return EINVAL; status = pthread_mutex_lock (&rwl->mutex); if (status != 0) return status; rwl->r_active— ; if (rwl->r_active == 0 && rwl->w_wait > 0) status = pthread_cond_signal (&rwl->write); status2 = pthread_mutex__unlock (&rwl->mutex); return (status2 == 0 ? status : status2);

9 10 11

12 13 14 15 16 17

}

18 ■

rwlock.c

25



3 4

rwl_readunlock

P a rt 7 sh o w s r w l_ w r ite l o c k . T h is fu n c tio n is m u c h like r w l_ r e a d lo c k . e x c e p t fo r th e p re d ic a te c o n d itio n o n th e c o n d itio n v a ria b le w ait. In p a r t 1, I ex p la in e d th a t, to c o n v e rt fro m “p re fe rre d r e a d ” to “p re fe rre d w rite .” a p o te n tia l r e a d e r w o u ld h a v e to w a it u n til th e re w ere n o activ e o r w a itin g w rite rs , w h e re a s c u rre n tly it w a its o n ly for activ e w rite rs. T h e p re d ic a te in r w l _ w r ite l o c k is th e c o n v e rse o f th a t c o n d itio n . B e c a u se w e s u p p o r t “p re fe rre d r e a d ,” in th e o ry , w e m u s t w a it h e re if th e re a re a n y activ e o r w a itin g re a d e rs . In fact, it is a b it sim p ler, b e c a u s e if th e re a r e a n y activ e re a d e rs , th e re c a n n o t b e a n y w a itin g re a d e rs —th e w h o le p o in t o f a r e a d /w r ite lock is th a t m u ltip le th r e a d s c a n h a v e re a d a c c e s s a t th e s a m e tim e. O n th e o th e r h a n d , w e d o h a v e to w a it if th e re a re a n y activ e w rite rs, b e c a u s e w e allow o n ly o n e w rite r a t a tim e. U n lik e r _ a c t i v e , w h ic h is a c o u n te r. w _ a c tiv e is tr e a te d a s a b o o le a n . O r is it a c o u n te r ? T h e re ’s re a lly n o s e m a n tic d iffere n ce, s in c e th e v a lu e o f 1 c a n b e co n s id e re d a b o o le a n t r u e o r a c o u n t o f 1—th e re c a n b e o n ly o n e ac tiv e w rite r a t a n y tim e.

13

1 2

part 6

rwlock.c

/* * Lock a read/write lock for write access.

*/ int rwl_writelock (rwlock_t *rwl)

part 7

rwl_writelock

264

CHA P T E R 7

“Real code”

5

6

int stat u s ;

7

8

if (rwl->valid != RWLOCK_VALID) return EINVAL; status = pthread_jnutex_lock (&rwl->mutex); if (status != 0) return status; if (rwl->w__active | | rwl->r__active > 0 ) { rwl->w_jwait++; pthread_cleanup_push (rwl_writecleanup, (void*)rwl); while (rwl->w_active | | rwl->r__active > 0 ) { status = pthread_cond_wait (&rwl->write, &rwl->mutex); if (status 1= 0) break;

9 10 11 12

13 14 15 16 17 18 19 20

}

21

pthread__cleanup__pop (0 ); rwl->w_wait— ;

22

23 24 25 26 27 28

> if (status == 0) rwl->w_active = 1; pthread__mutex_unlock (&rwl->mutex) ; return status; rwlock.c

part 7

rwl_writelock

P a rt 8 sh o w s rwl_writetrylock. T h is fu n c tio n is m u c h like rwl_writelock, ex c e p t t h a t it r e t u r n s e b u s y if th e r e a d /w r ite lo c k is c u rre n tly in u s e (e ith e r b y a r e a d e r o r b y a w riter) r a th e r th a n w a itin g fo r it to b e c o m e free. ■

1 2

rwlock.c

* Attempt to lock a read/write lock for write access. D o n ’t * block if unavailable. int rwl_writetrylock (rwlock_t *rwl)

6

{

*/

int status, status2;

8 9 10

11 12

13 14 15

rwl_writetrylock

/*

3 4 5 7

part 8

if (rwl->valid != RWLOCK_VALID) return EINVAL; status = pthread__mutex_lock (&rwl->mutex); if (status != 0) return status; if (rwl->w_active || rwl->r_active > 0) status = EBUSY;

265

E x t e n d e d syn c h r o n i z a t i o n

16 17 18 19

else rwl->w_active = 1; status2 = pthread_mutex_unlock (&rwl‫ > ־‬m u tex); return (status != 0 ? status : status2);

}

20



13-19

20-26

rwlock.c

part 8

rwl_writetrylock

F in ally , p a r t 9 s h o w s r w l_ w r ite u n lo c k . T h is fu n c tio n is called b y a th r e a d w ith a w rite lock, to re le a s e th e lock. W h e n a w rite r re le a s e s th e r e a d /w r ite lock, it is a lw ay s free; if th e re a re a n y th r e a d s w a itin g for a c c e s s , w e m u s t w a k e o n e. B e c a u s e w e im p le m e n t “p re fe rre d r e a d ” a c c e s s, w e firs t lo o k fo r th r e a d s t h a t a re w a itin g for r e a d a c c e s s. If th e re a re a n y t w e b r o a d c a s t th e r e a d c o n d itio n v a ria b le to w a k e th e m all. If th e re w ere n o w a itin g re a d e rs , b u t th e re a re o n e o r m o re w a itin g w rite rs , w a k e o n e o f th e m b y sig n a lin g th e w r i t e c o n d itio n v a ria b le . To im p le m e n t a "p re fe rre d w rite ” lock, y o u w o u ld re v e rse th e tw o te s ts , w a k in g a w a itin g w riter, if a n y , b efo re lo o k in g for w a itin g re a d e rs . ■

rwlock.c

part 9

1 /* 2 * Unlock a read/write lock from write access. 3 */ 4 int rwl writeunlock (rwlock t *rwl) 5 { 6 int status; ‫ד‬/ 8 if (rwl->valid != RWLOCK_VALID) 9 return E I N V A L ; 10 status = pthread__mutex_lock (&rwl->mutex); 11 if (status 1= 0) 12 return status; 13 rwl->w_active = 0; 14 if (rwl->r wait > 0 ) { 15 status = pthread_cond_broadcast (&rwl->read) 16 if (status 1= 0) { 17 pthread_mutex__unlock (&rwl->mutex); 18 return status; 19 } 20 } else if (rwl->w_wait > 0 ) { 21 status = pthread_cond_signal (&rwl->write); 22 if (status 1= 0) { 23 pthread_mutex__unlock (&rwl->mutex); 24 return status; 25 > 26 >

rwl_writeunlock

266

27 28 29

CH A P T E R 7

“R e a l c o d e ‫״ ״‬

part 9

writelock

status = pthread_mutex_unlock (&rwl->mutex); return status; > ■

rwlock.c

Now t h a t w e h a v e all th e p ie ces, rw lo c k _ m a in .c sh o w s a p ro g ra m t h a t u s e s r e a d /w r ite lo ck s. 11-17 E a c h th r e a d is d e s c rib e d b y a s tr u c tu r e of ty p e thread_t. T h e thread_num m e m b e r is th e th r e a d ’s in d e x w ith in th e a r r a y o f thread_t s tr u c tu r e s . T h e thread_id m e m b e r is th e pthread_t (th re a d id en tifier) r e tu r n e d b y pthread_ create w h e n th e th r e a d w a s c re a te d . T h e updates a n d reads m e m b e rs a re c o u n ts of th e n u m b e r of re a d lo ck a n d w rite lo c k o p e ra tio n s p e rfo rm e d b y th e th re a d . T h e interval m e m b e r is g e n e ra te d ra n d o m ly a s e a c h th r e a d is c re a te d , to d e te rm in e h o w m a n y ite ra tio n s th e th r e a d will re a d b efo re it p e rfo rm s a w rite. 22-26 T h e th r e a d s cycle th r o u g h a n a r r a y of d a t a _ t e le m e n ts. E a c h e le m e n t h a s a r e a d /w r ite lock, a d a t a e le m e n t, a n d a c o u n t o f h o w m a n y tim e s so m e th r e a d h a s u p d a te d th e ele m e n t. 48-58 T h e p ro g ra m c r e a te s a s e t of th r e a d s r u n n in g th e thread_routine fu n c tio n . E a c h th r e a d lo o p s i t e r a t i o n s tim e s, p ra c tic in g u s e of th e r e a d /w r ite lock. It cy cles th r o u g h th e a r r a y o f d a ta e le m e n ts in s e q u e n c e , r e s e ttin g th e in d e x (element) to 0 w h e n it re a c h e s th e e n d . A t in te rv a ls sp ecified b y e a c h th r e a d ’s interval m e m b er, th e th r e a d will m od ify th e c u r r e n t d a ta e le m e n t in s te a d o f re a d in g it. T h e th r e a d lo c k s th e r e a d /w r ite lo ck for w rite a c c e s s , s to re s its thread_num a s th e n e w data v a lu e , a n d in c re a s e s th e updates c o u n te r. 59-73 O n all o th e r ite ra tio n s , thread_routine r e a d s th e c u r r e n t d a t a e le m e n t, lockin g th e r e a d /w r ite lo ck for re a d a c c e s s . It c o m p a re s th e data v a lu e a g a in s t its thread_num to d e te rm in e w h e th e r it w a s th e m o s t re c e n t th r e a d to u p d a te t h a t d a ta e le m e n t, a n d , if so, it in c re m e n ts a c o u n te r. 95-103 O n S o la ris s y s te m s , in c re a s e th e th r e a d c o n c u rre n c y level to g e n e ra te m o re in te re s tin g activ ity . W ith o u t tim e slic in g of u s e r th r e a d s , e a c h th r e a d w o u ld te n d to e x e c u te s e q u e n tia lly o th e rw ise . ■

1 2 3 4 5 6 7

8 9

r w l o c k_main.c

#include "rwlock.h" #include "errors.h" #define THREADS #define DATASIZE #define ITERATIONS

5 15 10000

/* * Keep statistics for each thread.

10 */

11 12

typedef struct thread_tag { int thread num;

26 7

E x t e n d e d syn c h r o n i z a t i o n

pthread_t int int int } thread t ;

thread_id updates; reads; interval;

/* * Read/write lock and shared data.

*/

21 22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

typedef struct data_tag { rwlock t lock; int data; int updates > data t ; thread__t threads [THREADS ] data_t d a t a [D A T A S I Z E ];

/* * Thread start routine that uses read/write locks.

*/ void *thread_routine

(void *arg)

{ thread__t *self = (thread_t*)arg; int repeats = 0; int iteration; int element = 0 ; int status; for (iteration = 0; iteration < ITERATIONS; iteration++)

{

/* * Each "self->interval" iterations, perform an * update operation (write lock instead of read * lock).

*/ if ((iteration % self->interval) = = 0 ) { status = rwl_writelock (&data[element]•lock); if (status i= 0) err_abort (status, "Write lock"); data[element].data = self->thread_num; d a t a [e l e m e n t ].updates++; self->updates++; status = rwl__writeunlock (&data[element].l o ck); if (status != 0) err__abort (status, "Write unlock"); } else {

/* * Look at the current data element to see whether * the current thread last updated it. Count the

268

CH A P T E R 7

* times, to report later.

62 63 64 65

*/ status = rwl_readlock (&data[element].l o c k ) ; if (status != 0) err_abort (status, ‫ ״‬Read lock‫;) ״‬ self->reads++; if (data[element] .data == self‫> ־ ־‬thread__num) repeats++; status = rwl_readunlock (&data[element].l ock); if (status 1= 0) err_abort (status, "Read unlock'1);

66

67 68

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

} element++; if (element >= DA T A S I Z E ) element = 0;

} if (repeats > 0) printf ( "Thread %d found unchanged elements %d ti m e s \ n " , self->thread_num, repeats); return NULL;

>

86

int main (int argc, char *argv[])

87

{

88

89 90 91 92 93 94 95 96 97 98 99 100

101 102

103 104 105 106 107 108 109 110

“R e a l c o d e ‫״‬

int count; int data_count; int status; unsigned int seed = 1; int thread__updates = 0; int data_updates = 0; tifdef sun

/* * On Solaris 2.5, threads are not timesliced. To ensure * that our threads can run concurrently, we need to * increase the concurrency level to THREADS.

*/ DPRINTF (("Setting concurrency level to %d\n", THREADS)); thr_setconcurrency (T H R E A D S ); #endif

/* * Initialize the shared data.

*/ for (data_count = 0; data_count < DATASIZE; data_count++) { d a t a [data__count] .data = 0; data[data_count].updates = 0;

E x t e n d e d syn c h r o n i z a t i o n

113 114 115 116 117 118 119

status = rwl_init (&data[data_count].l o ck); if (status i= 0) err_abort (status, "Init rw lock");

> /* * Create THREADS threads to access shared data.

*/

120

for (count = 0; count < THREADS; count++) { threads[count].thread_num = count; threads[count].updates = 0; threads[count].reads = 0; t h r e a d s [c o u n t ].interval = rand__r (&seed) % 71; status = pthread_create (&threads[count].thread_id, N U L L , thread_routine, (v o i d * )&th r e a d s [c o u n t ]); if (status 1= 0) err_abort (status, "Create thread");

121 122

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158

> /* * Wait for all threads to complete, and collect * statistics.

*/ for (count = 0; count < THREADS; count++) { status = pthread_join (threads[count].thread_id, NULL); if (status i= 0) err_abort (status, *,Join t hread‫;) ״‬ thread_updates += threads[count].updates; printf ("%02d: interval %d, updates %d, reads % d\n", co u n t , t h r eads[c o u n t ].interval, t h r e a d s [c o u n t ].up d a t e s , thr e a d s [c o u n t ].r e a d s );

> /* * Collect statistics for the data.

*/ for (data_count = 0; data_count < DATA S I Z E ; data_count++) { data_updates += d a t a [d a t a _count].updates; printf (,,data %02d: value %d, %d updates\n", data__count, data [data_count ]. d a t a , d a t a [d a t a _count].upd a t e s ); rwl_destroy (fcdata[data_ c o u n t ].l o c k );

}



printf ("%d thread updates, %d data u p dates\n", thread_updates, data^updates); return 0; rwlock_main.c

269

270

CH A P T E R 7

“R e a l c o d e ”

7.2 W ork q u e u e m a n a g e r I’ve a lre a d y b riefly o u tlin e d th e v a rio u s m o d e ls o f th r e a d c o o p e ra tio n . T h e se in c lu d e p ip e lin e s, w o rk crew s, c lie n t/s e r v e r s , a n d so fo rth . In th is s e c tio n , I p r e s e n t th e d e v e lo p m e n t o f a “w o rk q u e u e / a s e t of th r e a d s t h a t a c c e p ts w o rk r e q u e s ts fro m a c o m m o n q u e u e , p ro c e s s in g th e m (potentially ) in p a ra lle l. T h e w o rk q u e u e m a n a g e r co u ld a lso b e c o n s id e re d a w o rk cre w m a n a g e r, d e p e n d in g o n y o u r re fe re n c e p o in t. If y o u th in k o f it a s a w ay to feed w o rk to a s e t o f th r e a d s , th e n “w o rk crew ” m ig h t b e m o re a p p ro p ria te . I p re fe r to th in k o f it a s a q u e u e t h a t m a g ically d o e s w o rk fo r y o u in th e b a c k g ro u n d , s in c e th e p re s e n c e o f th e w o rk c rew is a lm o s t c o m p le te ly in v isib le to th e caller. W h e n y o u c re a te th e w o rk q u e u e , y o u c a n sp ecify th e m a x im u m level of p a ra lle lism t h a t y o u n e e d . T h e w o rk q u e u e m a n a g e r in te r p r e ts t h a t a s th e m a x im u m n u m b e r o f “en g in e" th r e a d s t h a t it m a y c re a te to p ro c e s s y o u r re q u e s ts . T h re a d s w ill b e s ta r te d a n d s to p p e d a s re q u ire d b y th e a m o u n t o f w o rk . A th r e a d t h a t fin d s n o th in g to d o w ill w a it a s h o r t tim e a n d th e n te rm in a te . T h e o p tim a l “s h o r t tim e" d e p e n d s o n h o w e x p e n siv e it is to c re a te a n e w th r e a d o n y o u r s y ste m , th e c o s t in s y s te m re s o u rc e s to k e e p a th r e a d g o in g t h a t ’s n o t d o in g a n y th in g , a n d h o w likely it is t h a t y o u ’ll n e e d th e th r e a d a g a in so o n . I’ve c h o s e n tw o s e c o n d s , w h ic h is p ro b a b ly m u c h to o long. T h e h e a d e r file w o r k q .h a n d th e C s o u rc e file w o r k q . c d e m o n s tr a te a n im p lem e n ta tio n of a w o rk q u e u e m a n a g e r. P a rt 1 sh o w s th e tw o s tr u c t u r e ty p e s u s e d b y th e w o rk q u e u e p a c k a g e . T h e workq t ty p e is th e e x te rn a l r e p r e s e n ta tio n o f a w o rk q u e u e , a n d th e workq_ele_t is a n in te r n a l r e p r e s e n ta tio n of w o rk ite m s th a t have b een qu eu ed. 6-9 T h e w o r k q _ e le _ t s tr u c t u r e is u s e d to m a in ta in a lin k e d lis t o f w o rk ite m s . It h a s a lin k e le m e n t (called n e x t) a n d a d a t a v a lu e , w h ic h is s to re d w h e n th e w o rk ite m is q u e u e d a n d p a s s e d to th e c a lle r’s “e n g in e f u n c tio n ” w ith n o in te rp re ta tio n . 14-16 O f c o u rs e , th e r e ’s a m u te x to seria liz e a c c e s s to th e workq t, a n d a c o n d itio n v a ria b le (cv) o n w h ic h th e e n g in e th r e a d s w a it fo r w o rk to b e q u e u e d . 17 T h e attr m e m b e r is a th r e a d a t tr ib u t e s o b je ct, u s e d w h e n c re a tin g n ew e n g in e th r e a d s . T h e a ttr ib u te s o b je c t co u ld in s te a d h a v e b e e n a s ta tic v a ria b le w ith in workq. c, b u t I c h o s e to a d d a little m e m o ry o v e rh e a d to e a c h w o rk q u e u e , r a th e r th a n a d d th e m in o r c o m p lex ity o f o n e -tim e in itia liz a tio n o f a s ta tic d a ta item . 18 T h e f i r s t m e m b e r p o in ts to th e firs t ite m o n th e w o rk q u e u e . A s a n o p tim iz atio n to m a k e it e a s ie r to q u e u e n e w ite m s a t th e e n d o f th e q u e u e , th e l a s t m e m b e r p o in ts to th e la s t ite m o n th e q u e u e . 19-24 T h e s e m e m b e rs re c o rd a s s o r te d in fo rm a tio n a b o u t th e w o rk q u e u e . T h e valid m e m b e r is a m a g ic n u m b e r t h a t ’s s e t w h e n th e w o rk q u e u e is in itia lize d , a s w e’ve s e e n b e fo re in b a r r ie r s a n d r e a d /w r ite lo ck s. (In th is c a s e , th e m a g ic n u m b e r is th e m o n th a n d y e a r o f m y d a u g h te r ’s b irth d a y .) T h e quit m e m b e r is a flag t h a t allo w s th e “w o rk q u e u e m a n a g e r ” to te ll e n g in e th r e a d s to te r m in a te a s so o n a s th e q u e u e is e m p ty . T h e parallelism m e m b e r re c o rd s h o w m a n y th r e a d s th e c r e a to r c h o s e to allo w th e w o rk q u e u e to u tilize, counter r e c o rd s th e n u m b e r o f

271

W or k q u eu e m a n a g er

th r e a d s c re a te d , a n d i d l e re c o rd s th e c u r r e n t n u m b e r o f th r e a d s t h a t a re w a itin g for w o rk . T h e engine m e m b e r is th e u s e r ’s “e n g in e fu n c tio n ,” s u p p lie d w h e n th e w o rk q u e u e w a s c re a te d . A s y o u c a n see, th e e n g in e fu n c tio n ta k e s a n “u n ty p e d ” (v o id *) a rg u m e n t, a n d h a s n o r e t u r n v a lu e . w o r k q .h ■

part 1

workq_t

!include 3 4 5

/*

6

typedef struct workq_ele_tag { struct workq_ele_tag void } workq_e 1e _ t ;

* Structure to keep track of work queue requests-

*/

7 8

9

*next; *data;

10

/*

11 12

* Structure describing a work queue-

13 14 15 16 17 18 19

*/ typedef struct workq^tag { pthread mutex t mutex; /* control access to queue */ pthread cond t cv; /* wait for work */ pthread attr t attr; /* create detached threads */ *first, *last; workq ele t /* work queue */ int valid; /* valid */ int quit; /* workq should quit */ int parallelism; /* maximum threads */ int counter; /* current threads */ int idle; /* number of idle threads */ /* user engine */ void (* engine)(void *arg); } workq t;

20

21 22

23 24 25 26 27

!define WORKQ__VALID ■

w o r k q .h

0xdecl992 part 1

workq_t

P a r t 2 sh o w s th e in te rfa c e s w e’ll c re a te fo r o u r w o rk q u e u e . We n e e d to c re a te a n d d e s tro y w o rk q u e u e m a n a g e rs , so w e’ll defin e workq init a n d workq_destroy. B o th ta k e a p o in te r to a workq_t s tr u c tu r e . In a d d itio n , th e in itia liz e r n e e d s th e m a x im u m n u m b e r of th r e a d s th e m a n a g e r is allow ed to c re a te to s e n d e e th e q u e u e , a n d th e e n g in e fu n c tio n . Finally, th e p ro g ra m n e e d s to b e ab le to q u e u e w o rk ite m s fo r p ro c e s s in g —w e’ll call th e in te rfa c e fo r th is workq_add. It ta k e s a p o in te r to th e workq_t a n d th e a rg u m e n t th a t s h o u ld b e p a s s e d to th e e n g in e fu n c tio n .

272

CH A P T E R 7



1 2 3 4 5 6 7 8 9

34_40

interfaces

workq.h

part 2

interfaces

T h e file workq. c c o n ta in s th e im p le m e n ta tio n o f o u r w o rk q u e u e . T h e followin g e x a m p le s b r e a k d o w n e a c h o f th e f u n c tio n s u s e d to im p le m e n t th e w o r k q .h in te rfa c e s . P a rt 1 sh o w s th e w o r k q _ in it fu n c tio n , w h ic h in itia liz e s a w o rk q u e u e . We c re a te th e P th r e a d s s y n c h ro n iz a tio n o b je c ts t h a t w e n e e d , a n d fill in th e re m a in in g m e m b e rs . In itia liz e th e th r e a d a ttr ib u te s o b je c t a t t r so t h a t th e e n g in e th r e a d s w e c re a te w ill r u n d e ta c h e d . T h a t m e a n s w e do n o t n e e d to k e e p tr a c k of th e ir th r e a d id e n tifie r v a lu e s, o r w o riy a b o u t jo in in g w ith th e m . We’re n o t re a d y to q u it y e t (we’ve h a rd ly sta rte d !), so c le a r th e quit flag. T h e parallelism m e m b e r re c o rd s th e m a x im u m n u m b e r o f th r e a d s w e a re allo w ed to c re a te , w h ic h is th e workq_init p a r a m e te r threads. T h e counter m e m b e r will re c o rd th e c u r r e n t n u m b e r of activ e en g in e th re a d s , in itially 0, a n d idle will re c o rd th e n u m b e r of activ e th r e a d s w a itin g for m o re w ork. A nd of c o u rse , finally, w e s e t th e valid m em b er. ■

1 2 3 4 5

part 2

/* * Define work queue functions. */ extern int workq_init ( workq_t *wq, int threads, /* maximum threads */ void (*engine)(void *)); /* engine routine */ extern int workq_destroy (workq_t *wq ) ; extern int workq_add (workq_t *wq, void *data); ■

14-22

workq.h

“R e a l c o d e "

workq.c

#include #include #include #include #include

part 1

workq_init



"errors.h" "workq.h"

6

7 /* 8 * Initialize a work queue. 9 */ 10 int workq_init (workq_t *wq, int threads, void

n 12 13 14 15 16 17

{ int status; status = pthread_attr__init (&wq->attr); if (status 1= 0) return status; status = pthread_attr_setdetachstate (

(*engine)(void *arg))

273

W or k q u eu e m a n a g er

18 19 20 21

&wq->attr, PTHREAD_CREATE_DETACHED); if (status ! = 0 ) { pthread_attr_destroy (&wq->attr); return status; }

22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

status = pthread_jnutex__init (&wq->mutex, NULL); if (status != 0) { pthread_attr_destroy (&wq->attr); return status; > status = pthread_cond_init (&wq->cv, NULL); if (status != 0) { pthread_mutex_destroy (&wq->mutex); pthread_attr_destroy (&wq->attr); return status; } wq->quit = 0 ; /* not time to quit */ wq->first = wq->last = NULL; /* no queue entries */ wq->parallelism = threads; /* max servers */ wq->counter = 0 ; / * n o server threads yet */ wq->idle = 0 ; / * n o idle servers */ wq->engine = engine; wq->valid = WORKQ_VALID; return 0; } ■

24

25-33

44-50

workq.c

part 1

workq_init

P a rt 2 sh o w s th e workq_destroy fu n c tio n . T h e p ro c e d u re for s h u ttin g d o w n a w o rk q u e u e is a little d iffe re n t t h a n th e o th e rs w e’ve se e n . R e m e m b e r th a t th e P th r e a d s m u te x a n d c o n d itio n v a ria b le d e s tro y fu n c tio n fail, r e tu r n in g e b u s y , w h e n y o u try to d e s tro y a n o b je c t t h a t is in u s e . We u s e d th e s a m e m o d el for b a r r ie r s a n d r e a d /w r ite lo ck s. B u t w e c a n n o t do th e s a m e for w o rk q u e u e s —th e callin g p ro g ra m c a n n o t k n o w w h e th e r th e w o rk q u e u e is in u s e , b e c a u s e th e caller only q u e u e s re q u e s ts t h a t a re p ro c e s s e d a sy n c h ro n o u s ly . T h e w o rk q u e u e m a n a g e r w ill a c c e p t a re q u e s t to s h u t d o w n a t a n y tim e, b u t it w ill w a it for all e x istin g e n g in e th r e a d s to co m p le te th e ir w o rk a n d te rm in a te . O nly w h e n th e la s t w o rk q u e u e e le m e n t h a s b e e n p ro c e s s e d a n d th e la s t en g in e th r e a d h a s ex ited will w o r k q _ d e s tro y r e t u r n s u c c e ssfu lly . If th e w o rk q u e u e h a s n o th r e a d s , e ith e r it w a s n e v e r u s e d o r all th r e a d s h a v e tim e d o u t a n d s h u t d o w n s in c e it w a s la s t u s e d . T h a t m a k e s th in g s e a sy , a n d we c a n sk ip all th e s h u td o w n co m p lic a tio n . If th e re a re e n g in e th r e a d s , th e y a re a s k e d to s h u t d o w n b y s e ttin g th e quit flag in th e workq_t s tr u c t u r e a n d b ro a d c a s tin g th e c o n d itio n v a ria b le to a w a k e n a n y w a itin g (idle) e n g in e th r e a d s . E a c h e n g in e th r e a d will e v e n tu a lly r u n a n d se e th is flag. W h en th e y se e it a n d fin d n o m o re w ork , th e y ’ll s h u t th e m s e lv e s dow n. T h e la s t th r e a d to s h u t d o w n w ill w a k e u p th e th r e a d t h a t ’s w a itin g in workq_ destroy, a n d th e s h u td o w n will co m p lete . In s te a d of c re a tin g a c o n d itio n v a ria b le

274

CH A P T E R 7

“R e a l c o d e ”

t h a t ’s u s e d o n ly to w a k e u p workq_destroy, th e la s t th r e a d w ill sig n a l th e s a m e c o n d itio n v a ria b le u s e d to in fo rm idle e n g in e th r e a d s of n e w w o rk . A t th is p o in t, all w a ite rs h a v e a lre a d y b e e n a w a k e n e d b y a b r o a d c a s t, a n d th e y w o n ’t w a it a g a in b e c a u s e th e quit flag is se t. S h u td o w n o c c u rs o n ly o n c e d u r in g th e life of th e w o rk q u e u e m a n ag er, so th e re ’s little p o in t to c re a tin g a s e p a ra te co n d itio n v a ria b le for th is p u rp o s e . ■

workq.c

part 2

workq_destroy

/* 2

* Destroy a work queue.

3 4 5

*/

6

int workq_destroy (workq_t *wq)

{ int status,

statusl,

status2;

7

8 9 10 11 12

13 14 15 16 17 18 19 20 21 22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

if (wq->valid != WORKQ_VALID) return EINVAL; status = pthread_mutex_lock (&wq->mutex); if (status 1= 0) return status; wq->valid = 0 ; /* prevent any other operations */

/* * Check whether any threads are active,

and run them down:

* * 1. * 2. * 4. * *

set the quit flag broadcast to wake any servers that may be asleep wait for all threads to quit (counter goes to 0) Because we don't use join, we d o n ’t need to worry about tracking thread IDs.

*/ if (wq->counter > 0 ) { wq->quit = 1; /* if any threads are idling, wake them. */ if (wq->idle > 0 ) { status = pthread_cond_broadcast (&wq->cv); if (status i= 0) { pthread_mutex_unlock (&wq->mutex); return s tatus;

> } /* * * * * * *

Just to prove that every rule has an exception. I'm using the "cv" condition for two separate predicates here. That's OK, since the case used here applies only once during the life of a work queue — during rundown. The overhead is minimal and it's not worth creating a separate condition variable that would

275

Work queue manager

42 43 44 45 46 47 48 49 50

* wait and be signaled exactly once! */ while (wq->counter > 0 ) { status = pthread_cond_wait (&wq->cv, &wq->mutex); if (status 1= 0) { pthread_mutex_unlock (&wq->mutex); return status; } >

51

}

52 53 54 55 56 57 58 59

status = pthread_mutex_unlock (&wq->mutex); if (status != 0) return status; status = pthread_mutex_destroy (&wq->mutex); status1 = pthread_cond_destroy (&wq->cv); status2 = pthread_attr_destroy (&wq->attr); return (status ? status : (statusl ? statusl : status2)); } ■

16-35 40-45 46-59

workq.c

workq.c

1 2 3 4

/* * Add an item to a work queue. */ int workq_add (workq__t *wq, void *element)

5

{

part 3

workq_ele_t *item; pthread_t id; int status; if (wq->valid != W O R KQ_VALID) return E I N V A L ;

12

13 14 15 16

workg_destroy

P a rt 3 sh o w s w orkq_ad d, w h ic h a c c e p ts w o rk for th e q u e u e m a n a g e r sy ste m . It a llo c a te s a n e w w o rk q u e u e e le m e n t a n d in itia liz e s it from th e p a ra m e te rs . It q u e u e s th e e le m e n t, u p d a tin g th e f i r s t a n d l a s t p o in te rs a s n e c e s s a ry . If th e re a r e idle e n g in e th r e a d s , w h ic h w ere c re a te d b u t r a n o u t of w o rk , sig n a l th e c o n d itio n v a ria b le to w a k e one. If th e re a re n o idle e n g in e th r e a d s , a n d th e v a lu e o f parallelism allo w s for m o re, c re a te a n e w e n g in e th re a d . If th e re a r e n o id le th r e a d s a n d it c a n ’t c re a te a n e w e n g in e th r e a d , workq_add r e tu r n s , le av in g th e n e w e le m e n t for th e n e x t th r e a d th a t fin ish e s its c u r r e n t a s s ig n m e n t. ■

6 7 8 9 10 11

part 2

/* * Create and initialize a request structure. */ item = (workq__ele_t *)malloc (sizeof (workq_ele_t));

workq_add

276

CH A P T E R 7

“R e a l c o d e *

if (item == NULL) return ENOMEM; item->data = element; item->next = NULL; status = pthread_mutex__lock (&wq->mutex); if (status != 0) { free (item); return status;

19 20 21 22

23 24 25 26

/*

27

* Add the request to the end of the queue, updating the * first and last pointers.

28 29

*/

30

if (wq->first == NULL) wq->first = item; else wq->last->next = item; wq->last = item;

31 32 33 34 35 36

/*

37 38

* if any threads are idling, wake one.

39

*/ if (wq->idle > 0 ) { status = pthread_cond_signal (&wq->cv); if (status ! = 0 ) { pthread_mutex_unlock (&wq‫ > ־‬m u t e x ); return status;

40 41 42 43 44

>

45

} else if (wq->counter < wq->parallelism)

46

{

/*

47

* If there were no idling threads, * create a new thread, do so.

48 49

and we're allowed to

*/

50

DPRINTF (("Creating new w o r k e r \ n " )); status = pthread_create ( &id, &wq->attr, w o rkq_server, (void*)wq); if (status 1= 0) { pthread_mutex_unlock (&wq->mutex); return status;

51 52 53 54 55 56 57

>

58

wq->counter++;

59

}

60

pthread_mutex__unlock (&wq->mutex); return 0;

61 62 ■

} workq.c

part 3

workq_add

277

W or k q u eu e m a n a g er

T h a t ta k e s c a re of all th e e x te rn a l in te rfa c e s , b u t w e will n e e d o n e m o re fu n c tio n , th e s t a r t fu n c tio n for th e e n g in e th r e a d s . T h e fu n c tio n , s h o w n in p a r t 4, is c a lle d workq_server. A lth o u g h w e co u ld s t a r t a th r e a d r u n n in g th e c a lle r’s e n g in e w ith th e a p p ro p ria te a r g u m e n t for e a c h re q u e s t, th is is m o re effic ient. T h e workq_server fu n c tio n w ill d e q u e u e th e n e x t r e q u e s t a n d p a s s it to th e e n g in e fu n c tio n , th e n lo ok for n e w w o rk . It w ill w a it if n e c e s s a r y a n d s h u t d o w n o n ly w h e n a c e rta in p erio d o f tim e p a s s e s w ith o u t a n y n e w w o rk a p p e a rin g , o r w h e n to ld to s h u t d o w n b y workq_destroy. N otice th a t th e s e rv e r b e g in s b y lo c k in g th e w o rk q u e u e m u te x , a n d th e “m a tc h in g ” u n lo c k d o e s n o t o c c u r u n til th e e n g in e th r e a d is re a d y to te rm in a te . D e sp ite th is , th e th r e a d s p e n d s m o s t of its life w ith th e m u te x u n lo c k e d , e ith e r w a itin g for w o rk in th e c o n d itio n v a ria b le w a it o r w ith in th e c a lle r’s en g in e fu n c tio n . 29-62 W h e n a th r e a d c o m p le te s th e c o n d itio n w a it loop, e ith e r th e re is w o rk to b e d o n e o r th e w o rk q u e u e is s h u ttin g d o w n (wq->quit is n o n zero ). 67-80 F irs t, w e c h e c k for w o rk a n d p ro c e s s th e w o rk q u e u e e le m e n t if th e re is o n e. T h e re c o u ld still b e w o rk q u e u e d w h e n workq_destroy is called , a n d it m u s t all b e p ro c e s s e d b efo re a n y e n g in e th r e a d te rm in a te s . T h e u s e r ’s e n g in e fu n c tio n is c a lled w ith th e m u te x u n lo c k e d , so th a t th e u s e r ’s e n g in e c a n r u n a lo n g tim e, o r b lo ck , w ith o u t affectin g th e e x e c u tio n of o th e r en g in e th r e a d s . T h a t d o e s n o t n e c e s s a rily m e a n t h a t e n g in e f u n c tio n s c a n r u n in p a ra lle l—th e c a lle r-s u p p lie d e n g in e fu n c tio n is re s p o n s ib le fo r e n s u r in g w h a te v e r s y n c h ro n iz a tio n is n e e d e d to allo w th e d e s ire d level o f c o n c u rre n c y o r p a ra lle lis m . Id eal e n g in e fu n c tio n s w o u ld re q u ire little o r n o s y n c h ro n iz a tio n a n d w o u ld r u n in p a ra lle l. 86-104 W h e n th e re is n o m o re w o rk a n d th e q u e u e is b e in g s h u t d ow n, th e th r e a d te rm in a te s , a w a k e n in g workq_destroy if th is w a s th e la s t e n g in e th r e a d to s h u t dow n. 110-114 F in ally we c h e c k w h e th e r th e e n g in e th r e a d tim e d o u t lo o k in g for w ork , w h ic h w o u ld m e a n th e e n g in e h a s w a ite d lo n g e n o u g h . If th e r e ’s still n o w o rk to b e fo u n d , th e e n g in e th r e a d ex its. ■

workq.c

1

/*

2 3 4

* Thread start routine to serve the work queue. */ static void *workq_server (void *arg)

5

{

6 7 8 9

part 4

workq_server

struct timespec timeout; workq_t *wq = (workq_t *)arg; workq_ele_t *we; int status, timedout;

10 11

12

/*

* We don't need to validate the workq_t here... we don't

278

13 14 15 16 17 18 19 20 21

CH A P T E R 7

* * * *

“R e a l c o d e ”

create server threads until requests are queued (the queue has been initialized by t h e n l ) and we wait for all server threads to terminate before destroying a work queue.

*/ DPRINTF (("A worker is starting\n")); status = pthread_mutex_lock (&wq->mutex); if (status 1= 0) return NULL;

22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

while (1) { timedout = 0; DPRINTF (("Worker waiting for w o r k \ n " )); clock_gettime (CLOCK_REALTIME, Stimeout); timeout.tv_sec += 2; while (wq->first == NULL && !wq->quit)

{

/* * Server threads time out after spending 2 seconds * waiting for new work, and exit.

*/ status = pthread__cond_timedwait ( &wq->cv, &wq->mutex, &timeout); if (status == ETIMEDOUT) { DPRINTF (("Worker wait timed o u t \ n " )); timedout = 1; break; } else if (status 1 = 0 ) {

/* * * * * * * * * * * * *

This shouldn't happen, so the work queue package should fail. Because the work queue API is asynchronous, that would add complication. Because the chances of failure are slim, I choose to avoid that complication. The server thread will return, and allow another server thread to pick up the work later. Note that if this were the only server thread, the queue wouldn't be serviced until a new work item is queued. That could be fixed by creating a new server h e r e .

*/ DPRINTF (( "Worker wait failed, %d (%s)\n", status, strerror (status))); wq->counter— ; pthread__mutex_unlock (&wq->mutex); return NULL;

} }

279

W ork q u eu e m a n a g er

63 64 65 66 67 68

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

87 88

DPRINTF ((,,Work queue: %#lx, quit: wq->first, wq->quit)); we = wq->first;

if (we != NULL) { wq->first = we->next; if (wq->last == we) wq->last ® NULL; status = pthread_mutex_unlock (&wq->mutex); if (status != 0) return NULL; DPRINTF ( (,,Worker calling engineXn" ) ); wq->engine (we->data); free (we); status = pthread_mutex_lock (&wq->mutex); if (status != 0) return NULL;

> /* * If there are no more work requests, and the servers * have been asked to quit, then shut down.

*/ if (wq->first == NULL && wq->quit) { DPRINTF (("Worker shutting d o w n \ n " )); wq->counter— ;

89 90 91 92 93 94 95 96 97 98 99

/* * * * * * * * *

*/

101

102

110 111

NOTE: Just to prove that every rule has an exception. I'm using the "cv" condition for two separate predicates here. That's OK, since the case used here applies only once during the life of a work queue — during rundown. The overhead is minimal and it's not worth creating a separate condition variable that would wait and be signaled exactly once!

if (wq->counter == 0) pthread_cond_broadcast (&wq->cv); pthread_mutex_unlock (&wq->mutex); return NULL;

100

103 104 105 106 107 108 109

%d\n‫ ״‬,

} /* * If there's no more work, and we wait for as long as * we're allowed, then terminate this server thread.

*/ if (wq->first == NULL && timedout) { DPRINTF ((,,engine terminating due to timeout. \n" ));

280

112 113 114 115 116 117 118 119

CHA P T E R 7

“R e a l c o d e ”

wq->counter— ; break; } } pthread_mutex_unlock (&wq->mutex); DPRINTF ((,,Worker e xiting\n")); return NULL; }

120



workq.c

part 4

workq__server

F in ally , w o r k q _ m a i n .c is a s a m p le p ro g ra m t h a t u s e s o u r w o rk q u e u e m a n ag er. Two th r e a d s q u e u e w o rk e le m e n ts to th e w o rk q u e u e in p a ra lle l. T h e engine fu n c tio n is d e s ig n e d to g a th e r so m e s ta tis tic s a b o u t e n g in e u s a g e . To a c c o m p lish th is , it u s e s th re a d -s p e c ific d a ta . W h e n th e s a m p le r u n c o m p le te s, main c o llects all o f th e th re a d -s p e c ific d a t a a n d r e p o r ts so m e s ta tis tic s . 15-19 E a c h e n g in e th r e a d h a s a n engine_t s tr u c t u r e a s s o c ia te d w ith th e th re a d sp ecific d a ta k ey engine_key. T h e e n g in e fu n c tio n g e ts th e c a llin g th r e a d ’s v a lu e of th is key, a n d if th e c u r r e n t v a lu e is n u l l , c re a te s a n e w engine_t s tr u c tu r e a n d a s s ig n s it to th e key. T h e c a l l s m e m b e r o f engine_t s tr u c t u r e re c o rd s th e n u m b e r o f c a lls to th e e n g in e fu n c tio n w ith in e a c h th re a d . 29-37 T h e th re a d -s p e c ific d a ta k e y ’s d e s tr u c to r fu n c tio n , destructor, a d d s th e te rm in a tin g th r e a d ’s engine_t to a list (engine_list_head), w h e re main c a n fin d it la te r to g e n e ra te th e fin al re p o rt. 43-68 T h e e n g in e fu n c tio n ’s w o rk is rela tiv e ly b o rin g . T h e a r g u m e n t is a p o in te r to a p o w e r_ t s tr u c tu r e , c o n ta in in g th e m e m b e rs v a l u e a n d power. It u s e s a triv ial loop to m u ltip ly v a l u e b y its e lf pow er tim e s. T h e r e s u lt is d is c a rd e d in th is ex am pie, a n d th e power__t s tr u c t u r e is freed. 73-98 A th r e a d is s ta r te d , b y main, r u n n in g th e thread_routine fu n c tio n . In a d d itio n , main c a lls thread_routine. T h e thread_routine fu n c tio n lo o p s for so m e n u m b e r o f ite ra tio n s , d e te rm in e d b y th e m a c ro i t e r a t i o n s , c re a tin g a n d q u e u in g w o rk q u e u e e le m e n ts. T h e value a n d power m e m b e rs o f th e power_t s tr u c t u r e a r e d e te rm in e d s e m ira n d o m ly u s in g rand_r. T h e fu n c tio n sle e p s fo r a ra n d o m p e rio d o f tim e, fro m zero to fo u r s e c o n d s , to o c c a sio n a lly allo w e n g in e th r e a d s to tim e o u t a n d te rm in a te . T ypically w h e n y o u r u n th is p ro g ra m y o u w o u ld e x p e c t to se e s u m m a ry m e s s a g e s re p o rtin g so m e sm a ll n u m b e r o f en g in e th r e a d s , e a c h o f w h ic h p ro c e s s e d so m e n u m b e r of ca lls—w h ic h to ta l 5 0 c a lls (25 e a c h fro m th e tw o th re a d s ). ■

1 2 3 4 5

w o r k q _ m a i n .c

#include #include #include #include #include



"workq.h"

281

W or k q u eu e m a n a g er

#include "errors.h" *define ITERATIONS

11

12

13 14 15 16 17 18 19

25

typedef struct power_tag { int value; int power; } power_t; typedef struct engine_jtag { struct engine_tag *link; pthread_t thread__id; int calls; } engine_t;

20 21 22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

pthread_key_t engine_key; /* Keep track of active engines */ pthread_mutex_t engine_list_mutex = PTHREAD_MUTEX_INITIALIZER; engine_t *engine_list__head = NULL; workq__t workq;

/* * Thread-specific data destructor routine for engine__key.

*/ void destructor

(void *value_ptr)

{ engine_t *engine = (engine_t*)v a l u e_ptr; pthread_mutex__lock (&engine_list_mutex); engine->link = engine_list_head; engine_list_head = engine; pthread__mutex__unlock (&engine_list__mutex);

> /* * This is the routine called by the work queue servers to * perform operations in parallel.

*/ void engine_routine (void *arg)

{ engine_t *engine; power__t *power = (power_t*)arg; int result, count; int status; engine « pthread_getspecific (engine_key); if (engine ‫ ־ ־‬NULL) { engine = (engine_t*)malloc (sizeof (engine_t)); status = pthread_setspecific ( engine_key, (v o i d * )e n g i n e );

282

if (status 1= 0) err_abort (status, "Set t s d " ); engine->thread_id = pthread_self (); engine->calls = 1; > else engine->calls++; result = 1; printf ( "Engine: computing %d~%d\n", power->value, power->power); for (count = 1; count power; count++) result *= power->value; free (arg);

58 59 60 61 62 63 64 65 66

67 68

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

} /* * Thread start routine that issues work queue requests-

*/ void *thread_routine

(void *arg)

{ power_t *el e m e n t ; int count; unsigned int seed = (unsigned int)time (NULL); int status;

/* * Loop, making requests.

*/ for (count = 0; count < ITERATIONS; count++) { element = (power_t*)malloc (sizeof (power_t)); if (element ‫ ־ ־ ־‬NULL) errno_abort ("Allocate e l e m e n t " ); element->value = rand_r (&seed) % 20; element‫> ־‬power = rand_r (&seed) % 7; DPRINTF (( "Request: % d A%d\n", element->value, element->power)); status = workq__add (fcworkq, (void* )element) ; if (status != 0) err_abort (status, ,,Add to work queue"); sleep (rand_r (&seed) % 5);

86

87 88

89 90 91 92 93 94 95 96 97 98 99

CH A P T E R 7

} return NULL;

}

100

int main (int argc, char *argv[])

1 0 1

{

102

103

pthread_t thread__id; engine_jt *engine;

“R e a l c o d e *

283

B u t w h a t a b o u t e x i st i n g l i br a r i e s?

int count = 0, calls = 0; int status; status = pthread_key_create (&engine_key, destructor); if (status != 0) err_abort (status, "Create k e y ” ); status = workq_init (&workq, 4, eng ine__rou t i n e ); if (status 1= 0) err_abort (status, "Init work queue"); status = pthread_create (&thread__id, NULL, thread_routine, NULL); if (status != 0) err_abort (status, "Create thread"); (v o i d )thread_routine (N U L L ); status = pthread_join (thread_id, NULL); if (status != 0) err_abort (status, "Join thread"); status = workq__destroy (&workq); if (status 1= 0) err_abort (status, "Destroy work queue");

110 111 112

113 114 115 116 117 118 119 120

121 1 2 2

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

/* * By now, all of the engine_t structures have been placed * on the list (by the engine thread destructors), so we * can count and summarize them.

*/ engine = engine_list_head; while (engine != NULL) { count++; calls += engine->calls; printf (,,engine %d: %d calls\n", engine = engine->link;

> printf ("%d engine threads processed %d call s \ n " , count, calls); return 0;

} ■

‫ ז‬.3

count, engine->calls);

workq_main.c

But w h a t a b o u t e xistin g lib rarie s? “The g r e a t a r t o f riding, as I w as s a y in g is— to k e e p y o u r b a la n c e p ro p erly. Like this, y o u k n o w H e le t g o th e b rid le , a n d s tre tc h e d o u t b o th his a rm s to sh o w A lic e w h a t h e m e a n t, a n d this tim e h e fe ll fla t o n his b a c k , rig h t u n d e r th e horse's fee t. — L e w is C a r r o l T h r o u g h t h e L o o k in g - G la s s

284

CH A P T E R 7

“R e a l c o d e ”

W h e n y o u c re a te a n e w lib ra ry , all it ta k e s is c a re fu l d e s ig n to e n s u r e t h a t th e lib ra ry w ill b e th re a d -s a fe . A s y o u d e c id e w h a t s ta te is n e e d e d for th e fu n c tio n , y o u c a n d e te rm in e w h ic h s ta te n e e d s to b e s h a r e d b e tw e e n th r e a d s , w h ic h s ta te s h o u ld b e m a n a g e d b y th e ca lle r th ro u g h e x te rn a l c o n te x t h a n d le s , w h ic h s ta te c a n b e k e p t in local v a ria b le s w ith in a fu n c tio n , a n d so fo rth . You c a n defin e th e in te rfa ce s to th e fu n c tio n s to s u p p o rt th a t s ta te in th e m o s t efficient m a n n e r. B u t w h e n y o u ’re m odifying a n ex istin g lib ra ry to w o rk w ith th re a d s , y o u u s u a lly d o n ’t h av e th a t lu x u ry . A nd w h e n y o u a re u s in g so m eo n e e lse ’s lib rary , y o u m a y n e e d sim ply to “m a k e do."

7.3.1

M o d ify in g lib ra ries to b e th re a d -s a fe M an y f u n c tio n s rely o n s ta tic s to ra g e a c ro s s a s e q u e n c e of calls, for e x am p le, strtok o r getpwd. O th e rs d e p e n d o n r e tu r n in g a p o in te r to s ta tic s to ra g e , for

e x am p le, asctime. T h is s e c tio n p o in ts o u t so m e te c h n iq u e s t h a t c a n h e lp w h e n y o u n e e d to m a k e “leg acy ” lib ra rie s th re a d -s a fe , u s in g so m e w ell-k n o w n ex am p ie s in th e ANSI C r u n - tim e lib rary . T h e s im p le s t te c h n iq u e is to a s s ig n a m u te x to e a c h s u b s y s te m . A t a n y call in to th e s u b s y s te m y o u lo ck th e m u te x ; a t a n y ex it from th e s u b s y s te m y o u u n lo c k th e m u te x . B e c a u s e th is sin g le m u te x co v ers th e e n tire s u b s y s te m , w e o ften refer to s u c h a m e c h a n is m a s a “big m u te x ” (see S e c tio n 3 .2 .4 ). T h e m u te x p re v e n ts m o re th a n o n e th r e a d from e x e c u tin g w ith in th e s u b s y s te m a t a tim e. N ote t h a t th is fixes only s y n ch ro n iz a tio n ra ce s , n o t s e q u e n ce ra ce s (S ectio n 8 .1 .2 d e s c rib e s th e d is tin c tio n b e tw e e n th e two). T h e b e s t c a n d id a te s for th is a p p ro a c h a re fu n c tio n s t h a t do little e x c e p t m a in ta in so m e in te r n a l d a ta b a s e . T h a t in c lu d e s fu n c tio n s s u c h a s m a llo c a n d f r e e t h a t m a n a g e a n in te r n a l re s o u rc e pool b u t g r a n t lim ited (or no) e x te rn a l v isib ility in to th a t pool. O n e p ro b le m w ith u s in g th e “b ig m u te x ” a p p r o a c h is t h a t y o u h a v e to b e c a re fu l a b o u t y o u r d efin itio n of “s u b s y s te m .” You n e e d to in c lu d e all f u n c tio n s t h a t s h a r e d a ta o r t h a t call e a c h o th er. Ifmalloc a n d free h a v e o n e m u te x w h ile realloc u s e s a n o th e r, th e n y o u ’ve got a ra c e a s s o o n a s o n e th r e a d c a lls realloc w h ile a n o th e r th r e a d is in malloc o r free. A nd w h a t if realloc is im p le m e n te d to call malloc, co p y d a ta , a n d th e n call free on th e old p o in te r? T h e realloc fu n c tio n w o u ld lock th e h e a p m u te x a n d call malloc. T h e malloc fu n c tio n w o u ld im m e d ia te ly try to lo ck th e h e a p m u te x itself, re s u ltin g in a d e a d lo c k . T h e re a re se v e ra l w ay s to solve th is . O n e is to ca re fully s e p a r a te e a c h of th e e x te rn a l in te rfa c e s in to a n in te r n a l “e n g in e ” fu n c tio n t h a t d o e s th e a c tu a l w o rk a n d a n e x te rn a l e n try p o in t th a t lo c k s th e s u b s y s te m m u te x a n d c a lls th e en g in e. O th e r e n try p o in ts w ith in th e s u b s y s te m t h a t n e e d th e s a m e e n g in e f u n c tio n w o u ld call it d irec tly r a th e r th a n u s in g th e n o rm a l e n try p o in t. T h a t’s o ften th e m o s t effic ien t so lu tio n , b u t it is a lso h a r d e r to do. A n o th e r p o ssib ility is to c o n s tr u c t a “re c u rs iv e ” m u te x t h a t allo w s th e s u b s y s te m to relo c k

B u t w h a t a b o u t e x i st i n g l i br a r i e s?

285

its ow n m u te x w ith o u t deadlock.* Now malloc a n d free a r e allo w ed to re lo c k th e m u te x h e ld b y realloc, b u t a n o th e r th r e a d try in g to call a n y of th e m will b e b lo c k e d u n til realloc c o m p lete ly u n lo c k s th e re c u rs iv e m u te x . M o st fu n c tio n s w ith p e r s is te n t s ta te re q u ire m o re s u b s ta n tia l c h a n g e s th a n j u s t a “b ig m u te x ,” esp e c ia lly to avoid a lte rin g th e in te rfa c e . T h e a s c tim e fu n c tio n , for e x am p le, r e tu r n s a p o in te r to th e c h a r a c te r s tr in g re p r e s e n ta tio n of a b in a ry tim e. T ra d itio n a lly , th e s trin g is fo rm a tte d in to a s ta tic b u ffe r d e c la re d w ith in th e a s c tim e fu n c tio n , a n d th e fu n c tio n r e tu r n s a p o in te r to t h a t bu ffer. L ocking a m u te x w ith in asctime is n ’t e n o u g h to p ro te c t th e d a ta . In fact, it is n o t ev en p a rtic u la rly u s e fu l. A fter asctime r e tu r n s , th e m u te x h a s b e e n u n lo c k e d . T h e c a lle r n e e d s to re a d th e bu ffer, a n d th e re is n o th in g to p re v e n t a n o th e r th r e a d fro m c a llin g asctime (an d “c o r ru p tin g ” th e firs t th r e a d ’s re s u lt) b efo re th e firs t th r e a d h a s fin ish e d re a d in g o r co p y in g it. To solve th is p ro b le m u s in g a m u te x , th e c a lle r w o u ld n e e d to lo c k a m u te x b efo re c a llin g asctime, a n d th e n u n lo c k it on ly a fte r it h a d fin ish e d w ith th e d a t a o r co p ied th e r e tu r n e d b u ffe r so m e w h e re “sa fe .” T h e p ro b le m c a n in s te a d b e fixed b y re c o d in g asctime to a llo c a te a h e a p b u ffe r u s in g malloc, fo rm a ttin g th e tim e s tr in g in to t h a t bu ffer, a n d r e tu r n in g its a d d re s s . T h e fu n c tio n c a n u s e a th re a d -s p e c ific d a ta k ey to k e e p tr a c k o f th e h e a p a d d r e s s so t h a t it c a n b e re u s e d o n th e n e x t call w ith in th a t th re a d . W h e n th e th r e a d te rm in a te s , a d e s tr u c to r fu n c tio n c a n free th e s to ra g e . It w o u ld b e m o re efficien t to av oid u s in g malloc a n d th re a d -s p e c ific d a ta , b u t th a t re q u ire s c h a n g in g th e in te rfa c e to asctime. P th r e a d s a d d s a n e w th re a d -s a fe a lte rn a tiv e to asctime, ca lle d asctime_r, w h ic h re q u ire s th e c a lle r to p a s s th e a d d r e s s a n d le n g th of a bu ffer. T h e asctime_r fu n c tio n fo rm a ts th e tim e s trin g in to th e c a lle r’s b u ffer. T h is allo w s th e c a lle r to m a n a g e th e b u ffe r in a n y w ay t h a t ’s c o n v e n ie n t. It c a n b e o n th e th r e a d ’s s ta c k , in h e a p , o r c a n ev en b e s h a re d b e tw e e n th r e a d s . A lth o u g h in a w ay th is is “giving u p ” o n th e e x istin g fu n c tio n a n d d efin in g a n ew fu n c tio n , it is o fte n th e b e s t w ay (an d s o m e tim e s th e o n ly p ra c tic a l way) to m a k e a fu n c tio n th re a d -s a fe .

7 .3 .2

Living w ith le g a c y lib ra rie s S o m e tim e s y o u h a v e to w o rk w ith co d e y o u d id n ’t w rite, a n d c a n ’t c h a n g e . A lo t of co d e is n o w b e in g m a d e th re a d -s a fe , a n d m o s t o p e ra tin g s y s te m s t h a t s u p p o rt th r e a d s c a n b e e x p e c te d to s u p p ly th r e a d - s a fe im p le m e n ta tio n s o f th e

*

I t i s e a s y t o c o n s t r u c t a “r e c u r s i v e ” m u t e x u s i n g a m u t e x , a c o n d i t i o n v a r i a b l e , t h e p t h r e a d _

t v a l u e o f t h e c u r r e n t o w n e r ( i f a n y ) , a n d a c o u n t o f t h e o w n e r ’s “r e c u r s i o n d e p t h . ” T h e d e p t h i s 0 w h e n t h e r e c u r s iv e m u t e x i s n o t lo c k e d , a n d g r e a t e r t h a n 0 w h e n it i s lo c k e d . T h e m u t e x p r o t e c t s a c c e s s to t h e d e p t h a n d o w n e r m e m b e r s , a n d t h e c o n d it io n v a r ia b le i s u s e d to w a it fo r t h e d e p t h to b e c o m e 0 , s h o u ld a t h r e a d w is h to lo c k t h e r e c u r s iv e m u t e x w h ile a n o t h e r t h r e a d h a s it lo c k e d .

286

CHA R IE R 7

“R e a l c o d e n

c o m m o n b u n d le d lib ra ry p a c k a g e s . T h e “in n e r c irc le ” o f th r e a d - s a fe lib ra rie s will g ra d u a lly in c re a s e to b e c o m e th e ru le r a th e r t h a n th e e x c e p tio n a s m o re a p p lic a tio n a n d lib ra ry d e v e lo p e rs d e m a n d th re a d -s a fe ty . B u t in e v ita b ly y o u ’ll fin d t h a t a lib ra ry y o u n e e d h a s n ’t b e e n m a d e th re a d safe, for e x am p le, a n o ld e r v e rs io n o f th e X W in d o w s w in d o w in g sy ste m , o r a d a ta b a s e e n g in e , o r a s im u la tio n p a c k a g e . A n d y o u w o n ’t h a v e s o u rc e code. O f c o u rs e y o u ’ll im m e d ia te ly c o m p la in to th e s u p p lie r o f th e lib ra iy a n d co n v in ce th e m to m a k e th e n e x t v e rs io n fully th re a d -s a fe . B u t w h a t c a n y o u d o u n til th e n e w v e rs io n a rriv e s ? If y o u re a lly n e e d th e lib ra iy , th e a n s w e r is “u s e it a n y w a y .” T h e re a r e a n u m b e r o f te c h n iq u e s y o u c a n u s e , from sim p le to co m p lex . T h e a p p r o p r ia te level of co m p lex ity re q u ire d d e p e n d s e n tire ly o n th e lib ra ry ’s in te rfa c e a n d h o w (as w ell a s h o w m u c h ) y o u u s e th e lib ra ry in y o u r code. I

M a k e t h e u n s a fe lib ra ry in to a s e rv e r th r e a d .

In so m e c a s e s , y o u m a y fin d it c o n v e n ie n t to r e s tr ic t u s e o f th e lib ra ry to o n e th re a d , m a k in g t h a t th r e a d a “s e rv e r” fo r th e c a p a b ilitie s p ro v id ed b y th e u n s a f e lib ra ry . T h is te c h n iq u e is c o m m o n ly a p p lie d , fo r e x a m p le , w h e n u s in g v e rs io n s o f th e X I 1 p ro to c o l c lie n t lib r a iy t h a t a re n o t th re a d -s a fe . T h e m a in th r e a d o r s o m e o th e r th r e a d c re a te d fo r th e p u r p o s e p ro c e s s e s q u e u e d X I 1 r e q u e s ts o n b e h a lf of o th e r th r e a d s . O nly th e s e rv e r th r e a d m a k e s c a lls in to th e X I 1 lib ra ry , so it d o e s n o t m a tte r w h e th e r X I 1 is th re a d -s a fe . I W rite y o u r o w n " b ig m u t e x ‫ ״‬w r a p p e r s a r o u n d t h e in te rfa c e s .

If th e fu n c tio n y o u n e e d h a s a “th r e a d - s a fe in te rfa c e ” b u t n o t a “th re a d -s a fe im p le m e n ta tio n ,” t h e n y o u m a y b e a b le to e n c a p s u la te e a c h ca ll in s id e a w ra p p e r fu n c tio n (or a m a cro ) t h a t lo c k s a m u te x , c a lls th e fu n c tio n , a n d th e n u n lo c k s th e m u te x . T h is is j u s t a n e x te rn a l v e rs io n o f th e “b ig m u te x ” a p p ro a c h . B y “th r e a d safe in te rfa c e ” I m e a n t h a t th e fu n c tio n re lie s o n th e s ta tic s ta te , b u t t h a t a n y d a t a r e tu r n e d to th e c a lle r is n ’t s u b je c t to a lte r a tio n b y la te r c alls. F o r e x am p le, m a llo c fits t h a t categ o ry . T h e a llo c a tio n o f m e m o ry in volves s ta tic d a t a t h a t n e e d s to b e p ro te c te d , b u t o n c e a b lo c k h a s b e e n a llo c a te d a n d r e tu r n e d to a caller, th a t a d d r e s s (an d th e m e m o ry to w h ic h it p o in ts) will n o t b e affected b y la te r c a lls to m a llo c . T h e e x te rn a l “b ig m u te x ” is n o t a good s o lu tio n fo r lib ra rie s t h a t m a y b lo c k fo r s u b s t a n ti a l p e rio d s o f tim e —like X I 1 o r a n y o th e r n e tw o rk p ro to co l. W hile th e r e s u lt m a y b e safe, it w ill b e v e ry in e fficie n t u n le s s y o u ra re ly u s e th e lib ra ry , b e c a u s e o th e r th r e a d s m a y b e lo c k ed o u t for lo n g p e rio d s o f tim e w h ile re m o te o p e ra tio n s a re ta k in g p la ce. I

E x te n d t h e im p le m e n t a t io n w ith e x te r n a l s ta te .

A big m u te x w o n ’t fix a fu n c tio n like a s c ti m e t h a t w rite s d a t a in to a s ta tic b u ffe r a n d r e t u r n s th e a d d re s s : T h e r e tu r n e d d a t a m u s t b e p ro te c te d u n til th e

B u t w h a t a b o u t e x i st i n g l i br a r i e s?

28 7

c a lle r is fin ish e d u s in g it, a n d th e d a ta is u s e d o u ts id e th e w ra p p e r. F o r a fu n c tio n lik e s t r t o k th e d a ta is in u s e u n til th e e n tire s e q u e n ce of to k e n s h a s b e e n p a rs e d . In g e n e ra l, fu n c tio n s t h a t h a v e p e r s is te n t s ta tic d a ta a re m o re d ifficu lt to e n c a p s u la te . A fu n c tio n like asctime c a n b e e n c a p s u la te d b y c re a tin g a w ra p p e r fu n c tio n t h a t lo c k s a m u te x , c a lls th e fu n c tio n , co p ie s th e r e tu r n v a lu e in to a th re a d -s a fe bu ffer, u n lo c k s th e m u te x , a n d th e n r e tu r n s . T h e th re a d -s a fe b u ffe r c a n b e d y n a m ic a lly a llo c a te d b y th e w ra p p e r fu n c tio n u s in g malloc, for in s ta n c e . You c a n re q u ire th e c a lle r to free th e b u ffe r w h e n d o n e , w h ic h c h a n g e s th e in te rfa c e , o r y o u c a n m a k e th e w ra p p e r k e e p tr a c k o f a p e r - th r e a d b u ffe r u s in g th re a d sp ecific d a ta . A lte rn a tiv e ly , y o u co u ld in v e n t a n e w in te rfa c e t h a t re q u ire s th e c a lle r to s u p p ly a bu ffer. T h e c a lle r c a n u s e a s ta c k b u ffer, o r a b u ffe r in h e a p , or, if p ro p e rly sy n c h ro n iz e d (by th e caller), it c a n s h a r e th e b u ffe r b e tw e e n th r e a d s . R e m e m b e r t h a t if th e w ra p p e r u s e s th re a d -sp e c ific d a ta to k e e p tr a c k of a p e r - th r e a d h e a p buffer, th e w ra p p e r c a n b e m a d e c o m p a tib le w ith th e o rig in al in te rfa c e . T h e o th e r v a r ia n ts re q u ire in te rfa c e c h a n g e s: T h e c a lle r m u s t s u p p ly d iffe re n t in p u ts o r it m u s t b e a w a re o f th e n e e d to free th e r e tu r n e d b u ffer. A fu n c tio n t h a t k e e p s p e r s is te n t s ta te a c ro s s a s e q u e n c e o f c a lls is m o re diffic u lt to e n c a p s u la te n e a tly . T h e s ta tic d a ta m u s t b e p ro te c te d th ro u g h o u t. T h e e a s ie s t w ay to do th is is sim p ly to c h a n g e th e c a lle r to lo ck a m u te x b efo re th e firs t call a n d k e e p it lo ck ed u n til a fte r th e fin al call o f a s e q u e n c e . B u t re m e m b e r th a t n o o th e r th re a d c a n u s e th e fu n c tio n u n til th e m u te x is u n lo c k e d . If th e c a lle r d o e s a s u b s ta n tia l a m o u n t o f p ro c e s s in g b e tw e e n calls, a m a jo r p ro c e s s in g b o ttle n e c k c a n o ccu r. O f c o u rs e , th is m a y a lso b e d ifficu lt o r im p o ss ib le to in te g ra te in to a sim p le w ra p p e r—th e w ra p p e r w o u ld h a v e to b e ab le to reco g n ize th e firs t a n d la s t of a n y s e rie s of calls. A b e tte r, b u t h a rd e r, w a y is to fin d so m e w ay to e n c a p s u la te th e f u n c tio n (or a s e t o f re la te d fu n c tio n s) in to a n e w th re a d -s a fe in te rfa c e . T h e re is n o g e n e ra l m o d e l for th is tra n s fo rm a tio n , a n d in m a n y c a s e s it m a y b e im p o ssib le . B u t o fte n y o u j u s t n e e d to b e c re a tiv e , a n d p o s sib ly ap p ly so m e c o n s tr a in ts . W hile th e lib ra ry fu n c tio n m a y n o t b e e a s y to e n c a p s u la te , y o u m a y b e a b le to e n c a p s u la te "sp e c ia l c a s e s ” t h a t y o u u s e . W hile strtok, for e x am p le, allo w s y o u to a lte r th e to k e n d e lim ite rs a t e a c h call, m o s t co d e d o e s n o t ta k e a d v a n ta g e of th is flexibility. W ith o u t th e c o m p lic a tio n of v a ry in g d e lim ite rs, y o u co u ld d efin e a n e w to k e n p a r s in g m o d el o n to p o f strtok w h e re all to k e n s in a s tr in g a re fo u n d b y a th re a d sa fe s e tu p fu n c tio n a n d s to re d w h e re th e y c a n b e re trie v e d o n e b y o n e w ith o u t callin g strtok a g a in . T h u s , w hile th e s e tu p fu n c tio n w o u ld lo ck a c o m m o n m u te x a n d seria liz e a c c e s s a c ro s s all th r e a d s , th e in fo rm a tio n re trie v a l fu n c tio n c o u ld r u n w ith o u t a n y s e ria liz a tio n .

8 Hints to a v o id d e b u g g in g

“O th e r m a p s a r e s uch s h a p es , with th e ir islands a n d c a p e s I But w e ’v e g o t o u r b ra v e C a p ta in to th a n k ” (So th e c r e w w o u ld p ro te s t) ,,th a t h e ’s b o u g h t us th e b e s t— A p e r fe c t a n d a b s o lu te b la n k !” — L e w is C a r r o ll, T h e H u n t in g o f t h e S n a r k

W ritin g a c o m p lic a te d th r e a d e d p ro g ra m is a lo t h a r d e r th a n w ritin g a sim p le s y n c h ro n o u s p ro g ra m , b u t o n c e y o u le a r n th e ru le s it is n o t m u c h h a r d e r t h a n w ritin g a c o m p lic a te d s y n c h ro n o u s p ro g ra m . W ritin g a th r e a d e d p ro g ra m to per* fo rm a c o m p lic a te d a s y n ch ro n ou s fu n c tio n w ill u s u a lly b e e a s ie r th a n w ritin g th e s a m e p ro g ra m u s in g m o re tra d itio n a l a s y n c h r o n o u s p ro g ra m m in g te c h n iq u e s . T h e c o m p lic a tio n s b e g in w h e n y o u n e e d to d e b u g o r a n a ly z e y o u r th re a d e d p ro g ra m . T h a t’s n o t so m u c h b e c a u s e u s in g th r e a d s is h a r d , b u t r a th e r b e c a u s e th e to o ls for d e b u g g in g a n d a n a ly z in g th r e a d e d co d e a re le ss w ell d ev elo p ed a n d u n d e r s to o d t h a n th e p ro g ra m m in g in te rfa c e s . You m a y feel a s if y o u a re n a v ig a tin g fro m a b la n k m a p . T h a t d o e s n ’t m e a n y o u c a n ’t u tiliz e th e p o w er o f th re a d e d p ro g ra m m in g rig h t now , b u t it d o e s m e a n t h a t y o u n e e d to b e c a re fu l, a n d m a y b e a little m o re c rea tiv e, in av o id in g th e ro c k s a n d s h o a ls o f th e u n c h a r te d w a te rs . A lth o u g h th is c h a p te r m e n tio n s so m e th r e a d d e b u g g in g a n d a n a ly s is to o ls a n d s u g g e s ts w h a t y o u c a n a c c o m p lish w ith th e m , m y g o al is n ’t to te ll y o u a b o u t to o ls y o u c a n u s e to solve p ro b le m s. In s te a d , I w ill d e s c rib e so m e of th e c o m m o n p ro b le m s t h a t y o u m a y e n c o u n te r a n d im p a r t s o m e th in g re s e m b lin g *4sa g e a d v ic e ” o n av o id in g th o s e p ro b le m s b efo re y o u h a v e to d e b u g th e m — or, p e r h a p s m o re re a listic a lly , h o w to reco g n ize w h ic h p ro b le m s y o u m a y b e e n c o u n te rin g . I C h e c k y o u r a s s u m p tio n s a t t h e d o o r.

T h re a d e d p ro g ra m m in g is p ro b a b ly n e w to y o u . A s y n c h ro n o u s p ro g ra m m in g m a y b e n ew to y o u . If so, y o u ’ll n e e d to b e c a re fu l a b o u t y o u r a s s u m p tio n s . Y ou’ve c ro s s e d a b rid g e, a n d b e h a v io r t h a t ’s a c c e p ta b le —o r ev en re q u ire d —in S y n c h ro n o u s L an d c a n b e d a n g e ro u s a c ro s s th e riv er in A s y n c h ro n o u s L an d . You c a n le a r n th e n ew ru le s w ith o u t a lo t o f tro u b le , a n d w ith p ra c tic e y o u ’ll p ro b a b ly ev en feel co m fo rta b le w ith th e m . B u t y o u h a v e to s t a r t b y b e in g c o n s ta n tly a w are t h a t s o m e th in g ’s c h a n g e d .

290

CHAPTER 8

H i n t s t o a vo i d d e bu g g i n g

8.1 A v o id in g in c o rre c t c o d e ‫ ״‬For in s ta n c e , n o w ,” she w e n t on, stic kin g a la rg e p ie c e o f p la s te r o n h e r fin ‫־‬ g e r as she s p o k e, “th e r e ’s th e K in g ’s M essen ger. H e ’s in prison now, b e in g p u n ish e d : a n d th e tria l d o e s n ’t e v e n b e g in till n e x t W e d n e s d a y : a n d o f c o u rs e th e c r im e c o m e s last o f a ll.” “S u p p o se h e n e v e r c o m m its th e c r im e ? ” s a id A lic e . ‫ ״‬That w o u ld b e a ll th e better, w o u ld n ’t it? ” th e Q u e e n said , a s she b o u n d th e p la s te r ro u n d h e r fin g e r with a b it o f rib b o n.

—Lewis Carroll, Through the Looking-Glass

P th r e a d s d o e s n ’t p ro v id e m u c h a s s is ta n c e in d e b u g g in g y o u r th r e a d e d code. T h a t is n o t s u rp ris in g , s in c e POSIX d o e s n o t reco g n ize th e c o n c e p t o f d e b u g g in g a t all, ev en in e x p la in in g w h y th e n e a rly u n iv e rs a l s i g t r a p s ig n a l is n o t in c lu d e d in th e s ta n d a r d . T h e re is n o s ta n d a r d w ay to in te r a c t w ith y o u r p ro g ra m o r o b se rv e its b e h a v io r a s it r u n s , a lth o u g h every th r e a d e d s y s te m w ill p ro v id e so m e fo rm of d e b u g g in g to ol. E v e n in th e u n lik e ly e v e n t t h a t th e d ev e lo p e rs of th e sy ste m h a d n o c o n c e rn for y o u , th e p o o r p ro g ra m m e r, th e y n e e d e d to d e b u g th e ir o w n code. A v e n d o r t h a t p ro v id e s th r e a d s w ith a n o p e ra tin g s y s te m w ill p ro v id e a t le a s t a b a s ic th r e a d “o b s e rv a tio n w in d o w ” in a d e b u g g in g u tility . You s h o u ld e x p e c t a t m in im u m th e a b ility to d is p la y a list of th e r u n n in g th r e a d s a n d th e ir c u r r e n t s ta te , th e s ta te o f m u te x e s a n d c o n d itio n v a ria b le s , a n d th e s ta c k tra c e of all th r e a d s . You s h o u ld a lso b e a b le to s e t b re a k p o in ts in sp ecified th r e a d s a n d sp ecify a “c u r r e n t th r e a d ” to e x a m in e re g is te rs, v a ria b le s , a n d s ta c k tra c e s . B e c a u se im p le m e n ta tio n s of P th re a d s a re likely to m a in ta in a lot of s ta te in u s e r m o d e, w ith in th e p ro c e s s , d e b u g g in g u s in g tra d itio n a l UNIX m e c h a n is m s s u c h a s ptrace o r th e proc file s y ste m c a n b e difficult. A c o m m o n s o lu tio n is to p ro v id e a s p e c ia l lib ra iy th a t is called b y th e d eb u g g er, w h ic h k n o w s h o w to s e a rc h th r o u g h th e a d d r e s s s p a c e o f th e p ro c e s s b e in g d e b u g g e d to find th e s ta te o f th r e a d s a n d s y n c h ro n iz a tio n o b je cts. S o la ris, for ex am p le, p ro v id es th e libthread_db. so s h a r e d lib rary , a n d D igital UNIX p ro v id e s libpthreaddebug. so. A th r e a d p a c k a g e p la c e d o n to p of a n o p e ra tin g s y s te m b y a th ird p a r ty will n o t b e ab le to p ro v id e m u c h in te g ra tio n w ith a d eb u g g er. F o r e x am p le, th e p o rta b le “D C E t h r e a d s ” lib ra ry p ro v id e s a b u ilt-in d e b u g c o m m a n d p a r s e r th a t y o u c a n in v o k e fro m th e d e b u g g e r u s in g th e p ri n t o r c all c o m m a n d to re p o rt th e s ta te of th r e a d s a n d s y n c h ro n iz a tio n o b je c ts w ith in th e p ro c e ss. T h is lim ite d d e b u g g in g s u p p o r t is a t b e s t in c o n v e n ie n t—y o u c a n ’t a n a ly z e th r e a d s ta te w ith in a co re file a fte r a p ro g ra m h a s failed, a n d it c a n n o t u n d e r s ta n d (or rep o rt) th e sy m b o lic n a m e s o f p ro g ra m v a ria b le s .

* w ith

F o r h i s t o r i c a l r e a s o n s , t h e f u n c t i o n i s c a l l e d c m a _ d e b u g . S h o u l d y o u f in d y o u r s e l f s t u c k DCE

t h r e a d s c o d e , tr y c a l l i n g it, a n d

com m an d s.

e n te r th e h e lp

com m and

fo r a lis t o f a d d it io n a l

A vo i d i n g i n c o r r ec t c o d e

291

T h e follow ing s e c tio n s d e s c rib e so m e o f th e m o s t c o m m o n c la s s e s of th re a d e d p ro g ra m m in g e rro rs , w ith th e in te n tio n o f h e lp in g y o u to av oid th e s e p ro b le m s w h ile d e sig n in g , a s w ell a s p o s sib ly m a k in g it e a s ie r to reco g n ize th e m w hile d eb u g g in g .

8.1.1

A vo id re ly in g o n “th re a d in e rtia ”

A lw ays, a lw a y s , re m e m b e r t h a t th r e a d s a re a s y n c h ro n o u s . T h a t’s esp e c ia lly im p o rta n t to k e e p in m in d w h e n y o u develop co d e o n u n ip ro c e s s o r s y s te m s w h e re th r e a d s m a y b e “slig h tly s y n c h ro n o u s ." N o th in g h a p p e n s s im u lta n e o u s ly o n a u n ip ro c e s s o r, w h e re re a d y th r e a d s a re se ria lly tim e slic e d a t rela tiv e ly p re d ic ta b le in te rv a ls . W h e n y o u c re a te a n e w th r e a d o n a u n ip ro c e s s o r o r u n b lo c k a th r e a d w a itin g for a m u te x o r c o n d itio n v a ria b le , it c a n n o t r u n im m e d ia te ly u n le s s it h a s a h ig h e r p rio rity t h a n th e c re a to r o r w ak er. T h e s a m e p h e n o m e n o n m a y o c c u r ev en o n a m u ltip ro c e ss o r, if y o u h a v e re a c h e d th e “c o n c u rre n c y lim it" o f th e p ro c e s s , fo r ex am p le, w h e n y o u h a v e m o re re a d y th r e a d s th a n th e r e a re p ro c e s s o rs . T h e c re a to r, o r th e th r e a d w a k in g a n o th e r th re a d , given e q u a l p rio rity , will c o n tin u e r u n n in g u n til it b lo c k s o r u n til th e n e x t tim e slic e (w hich m a y b e m a n y n a n o s e c o n d s aw ay). T h is m e a n s th a t th e th r e a d t h a t c u rre n tly h a s a p ro c e s s o r h a s a n a d v a n ta g e . It te n d s to re m a in in m o tio n , e x h ib itin g b e h a v io r v a g u e ly a k in to p h y s ic a l in e rtia . A s a re s u lt, y o u m a y g e t aw ay w ith e rro rs t h a t w ill c a u s e y o u r co d e to b r e a k in m y s te rio u s w a y s w h e n th e n ew ly c re a te d o r a w a k e n e d th r e a d is a b le to r u n im m e d ia te ly —w h e n th e re a re free p ro c e s s o rs . T h e follow ing p ro g ra m , i n e r t i a . c , d e m o n s tr a te s h o w th is p h e n o m e n o n c a n d is r u p t y o u r p ro g ra m . 27-41 T h e q u e s tio n is o n e of w h e th e r th e th r e a d fu n c tio n printer_thread w ill see th e v a lu e o f stringPtr th a t w a s s e t b efo re th e call to pthread_create, o r th e v a lu e s e t a fte r th e call to pthread_create. T h e d e s ire d v a lu e is “A fter v a lu e .’’ T h is is a v ery co m m o n c la s s of p ro g ra m m in g erro r. O f c o u rse , in m o s t c a s e s th e p ro b lem is le s s o b v io u s th a n in th is sim p le ex am p le. O ften, th e v a ria b le is u n in itia liz e d , n o t s e t to so m e b e n ig n v alu e, a n d th e r e s u lt m a y b e d a ta c o rru p tio n o r a seg m en ta tio n fau lt. 39 Now, n o tic e th e d e la y loop. E v en o n a m u ltip ro c e ss o r, th is p ro g ra m w o n ’t b r e a k all th e tim e . T h e p ro g ra m will u s u a lly b e a b le to c h a n g e stringPtr b efo re th e n e w th r e a d c a n b e g in e x e c u tin g —it ta k e s tim e for a n ew ly c re a te d th r e a d to g et in to y o u r code, a fte r all, a n d th e “w in d o w o f o p p o rtu n ity ” in th is p a r tic u la r p ro g ra m is only a few in s tr u c tio n s . T h e loop allo w s m e to d e m o n s tr a te th e p ro b lem b y d e la y in g th e main th r e a d lo n g e n o u g h to give th e printer th r e a d tim e to s ta r t. If y o u m a k e th i s loop lo n g e n o u g h , y o u w ill se e th e p ro b le m e v e n o n a u n ip ro c e sso r, if main is e v e n tu a lly tim e slic e d . ■ 1 2

inertia.c *include *include "errors.h"

292

4 5

CHAPTER 8

Hints to avoid debugging

void *printer_thread (void *arg)

{ char *string = * (char**)arg;

6

7

8

printf ("%s\n", return NULL;

9

string);

}

10 11 12

int main

13 14 15 16 17 18 19

{

(int argc, char *argv[])

pthread_t printer_id; char *string_ptr; int i, status; #ifdef sun

/* * On Solaris 2.5, threads are not timesliced. To ensure * that our two threads can run concurrently, we need to * increase the concurrency level to 2.

20 21 22

*/

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

DPRINTF (("Setting concurrency level to 2\n")); thr_j3etconcurrency (2 ); #endif string_ptr = "Before value"; status = pthread_create ( &printer_id, NULL, printer_thread, (v o i d * )&string_ptr); if (status 1= 0) err_abort (status, "Create thread");

/* * * * *

Give the thread a chance to get started if i t ’s going to run in parallel, but not enough that the current thread is likely to be timesliced. (This is a tricky balance, and the loop may need to be adjusted on your system before you can see the b u g . )

*/ for (i = 0; i < 10000000;

i++);

string_ptr = "After value"; status = pthread_join (printer_id, NULL); if (status 1= 0) err__abort (status, "Join thread"); return 0;

} ■

inertia.c

T h e w ay to fix i n e r t i a . c is to s e t th e “A fter v a lu e ,” th e o n e y o u w a n t th e th r e a d s to see, b efo re c re a tin g th e th re a d . T h a t’s n o t so h a rd , is it? T h e re m a y

A v o i d i n g i n c o r r ec t c o d e

293

still b e a “B efore v a lu e .” w h e th e r it is u n in itia liz e d s to ra g e o r a v a lu e t h a t w a s p re v io u sly u s e d for so m e o th e r p u rp o s e , b u t th e th r e a d y o u c re a te c a n ’t se e it. By th e m e m o ry v isib ility ru le s giv en in S e c tio n 3 .4 , th e n e w th r e a d s e e s all m e m o ry w rite s th a t o c c u rre d p rio r to th e call in to p t h r e a d _ c r e a t e . A lw ays d e s ig n y o u r co d e so t h a t th r e a d s a r e n ’t s ta r te d u n til a fte r all th e re s o u rc e s th e y n e e d h a v e b e e n c re a te d a n d in itia liz e d e x ac tly th e w ay y o u w a n t th e th r e a d to se e th e m . I

N e v e r a s s u m e t h a t a t h r e a d y o u c r e a t e w ill w a it fo r y o u .

You c a n c a u s e y o u rs e lf a s m a n y p ro b le m s b y a s s u m in g a th r e a d will r u n “s o o n ” a s by a s s u m in g it w o n ’t r u n “too s o o n .” C re a tin g a th r e a d t h a t re lie s o n “te m p o ra ry s to ra g e ” in th e c re a to r th r e a d is a lm o s t alw ay s a b a d id e a. I h a v e s e e n co d e t h a t c re a te s a s e rie s of th r e a d s , p a s s in g a p o in te r to th e s a m e lo cal s tr u c tu r e to e a c h , c h a n g in g th e s tr u c tu r e m e m b e r v a lu e s e a c h tim e. T h e p ro b le m is t h a t y o u c a n ’t a s s u m e th r e a d s w ill s t a r t in a n y sp ecific o rd er. All of th o s e th r e a d s m a y s t a r t a fte r y o u r la s t c re a tio n call, in w h ic h c a s e th e y all g et th e la s t v a lu e of th e d a ta . O r th e th r e a d s m ig h t s ta r t a little b it o u t of order, so t h a t th e firs t a n d s e c o n d th re a d g et th e s a m e d a ta , b u t th e o th e rs g et w h a t y o u in te n d e d th e m to get. T h re a d in e rtia is a s p e c ia l c a s e o f th r e a d ra c e s. A lth o u g h th r e a d r a c e s a re cove re d m u c h m o re e x te n siv e ly in S e c tio n 8 .1 .2 , th r e a d in e rtia is a s u b tle effect, a n d m a n y p eo p le do n o t reco g n ize it a s a ra c e . So te s t y o u r co d e th o ro u g h ly o n a m u ltip ro c e sso r, if a t all p o ssib le . Do th is a s e a rly a s p o ssib le d u rin g d e v e lo p m e n t, a n d c o n tin u o u s ly th r o u g h o u t d ev e lo p m e n t. D o th is d e s p ite th e fa c t th a t, e sp e cially w ith o u t a p e rfe c t th r e a d e d d e b u g g er, te s tin g o n a m u ltip ro c e s s o r w ill b e m o re d ifficu lt th a n d e b u g g in g o n a u n ip ro c e ss o r. A nd, of c o u rs e , y o u s h o u ld c a re fully re a d th e follow ing se c tio n .

8 .1 .2

N e v e r b e t yo u r m o rtg a g e o n a th re a d r a c e A ra c e o c c u rs w h e n tw o o r m o re th r e a d s try to g et s o m e p la c e o r do s o m e th in g a t th e s a m e tim e. O n ly o n e c a n w in. W h ich th r e a d w in s is d e te rm in e d b y a lo t o f fa c to rs, n o t all o f w h ic h a re u n d e r y o u r c o n tro l. T h e o u tc o m e m a y b e affected b y h o w m a n y p ro c e s s o rs a re o n th e s y ste m , h o w m a n y o th e r p ro c e s s e s a re r u n n in g , h o w m u c h n e tw o rk o v e rh e a d th e s y s te m is h a n d lin g , a n d o th e r th in g s like th a t. T h a t’s a n o n d e te rm in is tic ra c e . It p ro b a b ly w o n ’t co m e o u t th e s a m e if y o u r u n th e s a m e p ro g ra m tw ice in a row . You d o n ’t w a n t to b e t o n r a c e s like th at.* W h e n y o u w r ite t h r e a d e d c o d e , a s s u m e t h a t a t a n y a r b itr a r y p o in t, w ith in a n y s t a t e m e n t o f y o u r p r o g r a m , e a c h th r e a d m a y g o t o s le e p fo r a n u n b o u n d e d p e r io d o f tim e .

*

M y d a u g h t e r h a d t h is f ig u r e d o u t b y t h e t im e s h e w a s t h r e e — w h e n s h e w a n t e d to r a c e , s h e

t o l d m e a h e a d o f t i m e w h e t h e r m y j o b w a s t o w i n o r l o s e . T h e r e ’s r e a l l y n o p o i n t t o l e a v i n g t h e s e im p o r ta n t t h in g s to c h a n c e !

294

CH A P T E R 8

H i n t s to a vo i d d ebu g g i n g

P ro c e s s o rs m a y e x e c u te y o u r th r e a d s a t differin g r a te s , d e p e n d in g o n p ro c e ss o r lo a d , in te r r u p ts , a n d so fo rth . T im e slic in g o n a p ro c e s s o r m a y in t e r r u p t a th r e a d a t a n y p o in t for a n u n sp e c ifie d d u ra tio n . D u rin g th e tim e t h a t a th r e a d is n ’t r u n n in g , a n y o th e r th r e a d m a y r u n a n d d o a n y th in g th a t s y n c h ro n iz a tio n p ro to c o ls in y o u r co d e d o n ’t sp ecifically p re v e n t it fro m do in g , w h ic h m e a n s t h a t b e tw e e n a n y tw o in s tr u c tio n s a th r e a d m a y fin d a n e n tire ly d iffe re n t p ic tu re of m em o ry , w ith a n e n tire ly d iffe re n t s e t of th r e a d s activ e. T h e w ay to p ro te c t a th r e a d ’s view of th e w o rld fro m s u r p r is e s is to rely o n ly o n ex p licit s y n c h ro n iz a tio n b e tw e e n th r e a d s . M o st s y n c h ro n iz a tio n p ro b le m s w ill p ro b a b ly sh o w u p p re tty q u ic k ly if y o u ’re d e b u g g in g o n a m u ltip ro c e ss o r. T h re a d s w ith in s u ffic ie n t s y n c h ro n iz a tio n will c o m p e te fo r th e h o n o r of re a c h in g m e m o ry la s t. It is a m in o r iro n y of th r e a d r a c e s t h a t th e “lo s e r” g e n e ra lly w in s b e c a u s e th e m e m o ry s y s te m will k e e p th e la s t v a lu e w ritte n to a n a d d r e s s . S o m e tim e s, y o u w o n ’t n o tic e a ra c e a t all. B u t so m etim e s y o u ’ll g e t a m y stify in g w ro n g re s u lt, a n d so m e tim e s y o u ’ll g e t a s e g m e n ta tio n fau lt. R a c e s a re u s u a lly d ifficu lt to d ia g n o se . T h e p ro b le m o ften w o n ’t o c c u r a t all o n a u n ip ro c e s s o r s y s te m b e c a u s e ra c e s re q u ire c o n c u r r e n t e x e c u tio n . T h e level of c o n c u rre n c y o n a u n ip ro c e s s o r, ev en w ith tim eslicin g , is fairly low, a n d o fte n a n u n s y n c h ro n iz e d s e q u e n c e of w rite s will c o m p le te b efo re a n o th e r th r e a d g e ts a c h a n c e to re a d th e in c o n s is te n t d a ta . E v en o n a m u ltip ro c e ss o r, r a c e s m a y b e diffic u lt to re p ro d u c e , a n d th e y o ften re fu s e to rev ea l th e m s e lv e s to a d eb u g g er. R a c e s d e p e n d o n th e re la tiv e tim in g o f th r e a d e x e c u tio n —s o m e th in g a d e b u g g e r is likely to c h a n g e . S o m e r a c e s h a v e m o re to do w ith m e m o ry visib ility th a n w ith s y n c h ro n iz a tio n of m u ltip le w rite s. R e m e m b e r th e b a s ic ru le s of m e m o ry v isib ility (see S e c tio n 3.4): A th r e a d c a n alw ay s se e c h a n g e s to m e m o ry t h a t w ere p e rfo rm e d b y a th r e a d p re v io u sly ru n n in g o n th e s a m e p ro c e sso r. O n a u n ip ro c e s s o r all th r e a d s r u n o n th e s a m e p ro c e sso r, w h ic h m a k e s it d ifficu lt to d e te c t m e m o ry v isib ility p ro b le m s d u r in g d eb u g g in g . O n a m u ltip ro c e sso r, y o u m a y see v isib ility ra c e s only w h e n th e th r e a d s a re s c h e d u le d o n d iffe re n t p ro c e s s o rs w hile e x e c u tin g specific v u ln e ra b le s e c tio n s of code. N o o r d e r in g exists b e t w e e n th r e a d s unless y o u c a u s e o rd e r in g . Bill G a llm e is te r's c o ro lla ry : "T h re a d s w ill ru n in t h e m o s t e v il o r d e r p o s s ib le .‫״‬

You d o n ’t w a n t to fin d y o u rs e lf d e b u g g in g th r e a d ra c e s . You m a y n e v e r se e th e s a m e o u tc o m e tw ice. T h e s y m p to m s will c h a n g e w h e n y o u try to d e b u g th e co d e— p o s sib ly b y m a s q u e ra d in g a s a n e n tire ly d iffe re n t k in d o f p ro b le m , n o t j u s t a s th e s a m e p ro b le m in a d iffe re n t p la ce. E v en w o rse , th e p ro b le m m a y n e v e r o c c u r a t all u n til a c u s to m e r r u n s th e code, a n d th e n it m a y fail ev ery tim e, b u t o n ly in th e c u s to m e r ’s im m e n s e , m o n o lith ic a p p lic a tio n , a n d o n ly a fte r it h a s b e e n r u n n in g

A v o i d i n g i n c o r r ec t c o d e

295

for d a y s. It will b e r u n n in g o n a s e c u re d s y s te m w ith n o n e tw o rk a c c e s s , th e y will b e u n a b le to sh o w y o u th e p ro p rie ta ry code, a n d w ill b e u n a b le to re p ro d u c e th e p ro b le m w ith a sim p le te s t p ro g ra m . I

" S c h e d u lin g ‫ ״‬is n o t t h e s a m e a s " s y n c h r o n iz a tio n /‫׳‬

It m a y a p p e a r a t firs t th a t s e ttin g a th r e a d to th e SCHED_ f i f o s c h e d u lin g policy a n d m a x im u m p rio rity w o u ld allow y o u to avoid u s in g ex p en siv e sy n c h ro n iz a tio n m e c h a n is m s b y g u a ra n te e in g th a t n o o th e r th re a d c a n r u n u n til th e th r e a d b lo c k s itse lf o r lo w ers its prio rity . T h ere a re sev eral p ro b le m s w ith th is , b u t th e m a in p ro b le m is t h a t it w o n ’t w o rk o n a m u ltip ro c e sso r. T h e SCHED_ f i f o policy p re v e n ts p re e m p tio n b y a n o th e r th re a d , b u t o n a m u ltip ro c e s s o r o th e r th r e a d s c a n r u n w ith o u t a n y fo rm of p re e m p tio n . S c h e d u lin g e x ists to te ll th e s y s te m h o w im p o r ta n t a sp ecific jo b (th read ) is to y o u r a p p lic a tio n so it c a n s c h e d u le th e jo b y o u n e e d th e m o st. S y n c h ro n iz a tio n e x ists to tell th e s y s te m t h a t n o o th e r th r e a d c a n b e allo w ed in to th e c ritic a l sectio n u n til th e c a llin g th r e a d is d o n e. In re a l life, a d e te rm in is tic ra c e , w h e re th e w in n e r is g u a r a n te e d from th e b e g in n in g , is n ’t v ery ex citin g (ex cep t to a th re e y e a r old). B u t a d e te rm in is tic ra c e re p r e s e n ts a s u b s ta n tia lly s a fe r b e t, a n d t h a t ’s th e k in d o f ra c e y o u w a n t to d e sig n in to y o u r p ro g ra m s . A d e te rm in is tic ra c e , a s y o u c a n g u e s s , is n ’t m u c h of a ra c e a t all. It is m o re like w a itin g in lin e—n ic e, o rg an iz ed , a n d p re d ic ta b le . E x c ite m e n t is o v e rra te d , esp e c ia lly w h e n it c o m e s to d e b u g g in g c o m p lic a te d th r e a d e d a p p lic a tio n s . T h e s im p le s t fo rm o f ra c e is w h e n m o re th a n o n e th r e a d trie s to w rite s h a r e d s ta te w ith o u t p ro p e r s y n c h ro n iz a tio n , fo r e x a m p le , w h e n tw o th r e a d s in c re m e n t a s h a r e d c o u n te r. T h e tw o th r e a d s m a y fe tc h th e s a m e v a lu e fro m m em o ry , in c re m e n t it in d e p e n d e n tly , a n d s to re th e s a m e r e s u lt in to m em o ry ; th e c o u n te r h a s b e e n in c re m e n te d b y o n e r a th e r th a n b y tw o, a n d b o th th r e a d s h a v e th e s a m e r e s u lt v alu e. A slig h tly m o re s u b tle ra c e o c c u rs w h e n o n e th r e a d is w ritin g so m e s e t of s h a r e d d a ta w h ile a n o th e r th r e a d r e a d s t h a t d a ta . If th e r e a d s o c c u r in a d iffe re n t o rd er, o r if th e r e a d e r c a tc h e s u p to th e w riter, th e n th e r e a d e r m a y g e t in c o n s is te n t r e s u lts . F o r e x am p le, o n e th r e a d in c re m e n ts a s h a r e d a r r a y in d e x a n d th e n w rite s d a ta in to th e a r r a y e le m e n t a t t h a t in d e x . A n o th e r th r e a d fe tc h e s th e s h a r e d in d e x b efo re th e w rite r h a s filled in th e e n tire e le m e n t a n d r e a d s t h a t elem e n t. T h e r e a d e r fin d s in c o n s is te n t d a ta b e c a u s e th e e le m e n t h a s n ’t b e e n co m p lete ly s e t u p yet. It m a y ta k e a n u n e x p e c te d co d e p a th b e c a u s e of so m e th in g it s e e s th e re o r it m a y follow a b a d p o in ter. A lw ays d e sig n a n d co d e a s s u m in g th a t th r e a d s a re m o re a s y n c h r o n o u s t h a n y o u c a n im ag in e. A n y o n e w h o ’s w ritte n a lo t of co d e k n o w s t h a t c o m p u te rs h a v e little c r e a tu r e s th a t en jo y a n n o y in g y o u . R e m e m b e r t h a t w h e n y o u co d e w ith th r e a d s th e re a r e lo ts o f th e m lo o se a t th e s a m e tim e. T a k e n o c h a n c e s , m a k e n o a s s u m p tio n s . M ak e s u r e a n y s h a r e d s ta te is s e t u p a n d v isib le b efo re c re a tin g th e th r e a d th a t w ill u s e it; o r c re a te it u s in g s ta tic m u te x e s o r p th r e a d _ o n c e . U se a

296

CHAPTER 8

Hints to avoid debugging

m u te x to e n s u r e t h a t th r e a d s c a n ’t re a d in c o n s is te n t d a ta . If y o u m u s t s h a r e s ta c k d a ta b e tw e e n th r e a d s , b e s u r e all th r e a d s t h a t u s e th e d a ta h a v e te rm in a te d b efo re r e tu r n in g fro m th e fu n c tio n t h a t a llo c a te d th e sto ra g e . “S e q u e n c e r a c e s ” m a y o c c u r w h e n y o u a s s u m e so m e o rd e rin g o f e v e n ts, b u t t h a t o rd e rin g is n ’t c o d e d in to th e a p p lic a tio n . S e q u e n c e r a c e s c a n o c c u r ev en w h e n y o u c a re fu lly a p p ly s y n c h ro n iz a tio n c o n tro l to e n s u r e d a t a c o n s is te n c y . You c a n o n ly av o id th is k in d o f ra c e b y e n s u r in g t h a t o rd e rin g i s n ’t im p o rta n t, o r b y a d d in g co d e t h a t fo rces e v e ry th in g to h a p p e n in th e o rd e r it n e e d s to h a p p e n . F o r e x a m p le , im a g in e t h a t th r e e th r e a d s s h a r e a c o u n te r v a ria b le . E a c h w ill s to re a p riv a te co p y of th e c u r r e n t v a lu e a n d in c re m e n t th e s h a r e d c o u n te r. If th e th r e e th r e a d s a re p e rfo rm in g th e s a m e fu n c tio n , a n d n o n e of th e m c a re s w h ic h v a lu e of th e c o u n te r th e y get, th e n it is e n o u g h to lo ck a m u te x a r o u n d th e fe tc h a n d in c re m e n t o p e ra tio n . T h e m u te x g u a r a n te e s t h a t e a c h th r e a d g e ts a d is tin c t v a lu e , a n d n o v a lu e s a re s k ip p e d . T h e re ’s n o ra c e b e c a u s e n o n e o f th e th r e a d s c a r e s w h o w in s. B u t if it m a tte r s w h ic h v a lu e e a c h th r e a d rece iv es, t h a t sim p le co d e w ill n o t do th e jo b . F o r ex am p le, y o u m ig h t im a g in e t h a t th r e a d s a r e g u a r a n te e d to s t a r t in th e o rd e r in w h ic h th e y a re c re a te d , so t h a t th e firs t th r e a d g e ts th e v a lu e 1, th e s e c o n d g e ts th e v a lu e 2, a n d so fo rth . O n ce in a w h ile (p ro b ab ly w h ile y o u ’re d eb u g g in g ), th e th r e a d s w ill g et th e v a lu e y o u ex p ec t, a n d e v e ry th in g will w ork, a n d a t o th e r tim e s, th e th r e a d s w ill h a p p e n to r u n in a d iffe re n t ord er. T h e re a re se v e ra l w a y s to solve th is . F o r ex am p le, y o u c o u ld a s s ig n e a c h of th e th r e a d s th e p ro p e r v a lu e to b e g in w ith , b y in c re m e n tin g th e c o u n te r in th e th r e a d t h a t c r e a te s th e m a n d p a s s in g th e a p p ro p ria te v a lu e to e a c h th r e a d in a d a ta s tr u c tu r e . T h e b e s t so lu tio n , th o u g h , is to avoid th e p ro b le m b y d e s ig n in g th e co d e so t h a t s t a r t u p o rd e r d o e s n ’t m a tte r. T h e m o re s y m m e tric a l y o u r th r e a d s a re , a n d th e few er a s s u m p tio n s th e y m a k e a b o u t th e ir e n v iro n m e n t, th e le s s c h a n c e t h a t th is k in d o f ra c e will h a p p e n . R a c e s a r e n ’t a lw ay s w ay d o w n th e re a t th e level of m e m o ry a d d r e s s re fe re n c e s, th o u g h . T h ey c a n b e a n y w h e re . T h e tra d itio n a l ANSI C lib ra ry , for e x am p le, allo w s a n u m b e r of s e q u e n c e r a c e s w h e n y o u u s e c e rta in fu n c tio n s in a n a p p lic a tio n w ith m u ltip le th r e a d s . T h e readdir fu n c tio n , for e x am p le, re lie s o n s ta tic s to ra g e w ith in th e fu n c tio n to m a in ta in c o n te x t a c ro s s a s e rie s o f id e n tic a l c a lls to readdir. If o n e th r e a d c a lls readdir w h ile a n o th e r th r e a d is in th e m id d le of a s e q u e n c e o f its ow n c a lls to readdir, th e s ta tic s to ra g e will b e o v e rw ritte n w ith a n e w c o n te x t.

I

" S e q u e n c e r a c e s " c a n o c c u r e v e n w h e n a ll y o u r c o d e uses m u te x e s t o p r o t e c t s h a re d d a t a !

T h is ra c e o c c u rs ev en if readdir is “th r e a d a w a re ” a n d lo c k s a m u te x to p ro te c t th e s ta tic s to ra g e . It is n o t a s y n c h ro n iz a tio n ra c e , it is a s e q u e n c e ra c e . T h re a d A m ig h t call readdir to s c a n d ire c to ry /usr/bin, fo r e x am p le, w h ic h lo c k s th e m u te x , r e t u r n s th e firs t e n try , a n d th e n u n lo c k s th e m u te x . T h re a d B m ig h t th e n call readdir to s c a n d ire c to ry /usr/include, w h ic h a lso lo c k s th e m u te x ,

A vo i d i n g i n c o r r ec t c o d e

297

r e t u r n s th e firs t e n try , a n d th e n u n lo c k s th e m u te x . Now th r e a d A c a lls readdir a g a in e x p e c tin g th e s e c o n d e n try in /usr/bin; b u t in s te a d it g e ts th e se c o n d e n try in /usr/include. No in te rfa c e h a s b e h a v e d im p ro p erly , b u t th e e n d re s u lt is w ro n g . T h e in te rfa c e to readdir sim p ly is n o t a p p ro p ria te fo r u s e b y th re a d s . T h a t’s w h y P th r e a d s sp ecifies a s e t o f n e w re e n tra n t fu n c tio n s , in c lu d in g readdir_r, w h ic h h a s a n a d d itio n a l a r g u m e n t t h a t is u s e d to m a in ta in c o n te x t a c ro s s calls. T h e a d d itio n a l a r g u m e n t so lv es th e s e q u e n c e ra c e b y av o id in g an y n e e d for s h a r e d d a ta . T h e call to readdir_r in th r e a d A r e t u r n s th e firs t e n try fro m /usr/bin in th r e a d A’s b u ffer, a n d th e call to readdir_r in th r e a d B r e tu r n s th e firs t e n try fro m /usr/include in th r e a d B ’s b u ffe r . . . a n d th e s e c o n d call in th r e a d A r e tu r n s th e se c o n d e n try fro m /usr/bin in th r e a d A’s b u ffer. R efer to p i p e .c, in S e c tio n 4 .1 , fo r a p ro g ra m t h a t u s e s readdir_r. S e q u e n c e r a c e s c a n a lso b e fo u n d a t h ig h e r levels o f co d in g . File d e s c rip to rs in a p ro c e s s , for ex a m p le , a re s h a r e d a c ro s s all th r e a d s . If tw o th r e a d s a tte m p t to getc fro m th e s a m e file, e a c h c h a r a c te r in th e file c a n go to o n ly o n e th re a d . E v en th o u g h getc itse lf is th re a d -s a fe , th e s e q u e n c e o f c h a r a c te r s s e e n b y e a c h th re a d is n o t d e te rm in is tic —it d e p e n d s o n th e o rd e rin g o f e a c h th r e a d ’s in d e p e n d e n t c a lls to getc. T h ey m a y a lte rn a te , e a c h g e ttin g every s e c o n d c h a r a c te r th ro u g h o u t th e file. O r o n e m a y g e t 2 o r 100 c h a r a c te r s in a row a n d th e n th e o th e r m ig h t g e t 1 c h a r a c te r b efo re b e in g p re e m p te d fo r so m e re a s o n . T h e re a re a n u m b e r of w ay s y o u c a n reso lv e th e g e t c ra c e . You c a n o p e n th e file u n d e r tw o s e p a r a te file d e s c rip to rs a n d a s s ig n o n e to e a c h th re a d . In th a t w ay, e a c h th r e a d s e e s ev ery c h a ra c te r, in o rd er. T h a t so lv es th e ra c e b y rem o v in g th e d e p e n d e n c y o n o rd e rin g . O r y o u c a n lo c k th e file a c ro s s th e e n tire s e q u e n c e of g e t s o p e ra tio n s in e a c h th re a d , w h ic h so lv es th e ra c e b y e n fo rcin g th e d e s ire d o rd er. T h e p ro g ra m p u t c h a r . c , b a c k in S e c tio n 6 .4 .2 , sh o w s a s im ila r s itu a tio n . U su a lly a p ro g ra m t h a t d o e s n ’t ca re a b o u t o rd e rin g will r u n m o re effic iently t h a n a p ro g ra m th a t e n fo rc e s so m e p a r tic u la r o rd e rin g , first, b e c a u s e e n fo rcin g th e o rd e rin g will a lw ay s in tro d u c e c o m p u ta tio n a l o v e rh e a d t h a t ’s n o t d irec tly re la te d to g e ttin g th e jo b d o n e . R e m e m b e r A m d a h l’s law . “U n o rd e re d ” p ro g ra m s a re m o re efficien t b e c a u s e th e g r e a te s t p o w er of th r e a d e d p ro g ra m m in g is t h a t th in g s c a n h a p p e n c o n c u rre n tly , a n d s y n c h ro n iz a tio n p re v e n ts c o n c u rre n c y . R u n n in g a n a p p lic a tio n o n a m u ltip ro c e s s o r s y s te m d o e s n ’t h e lp m u c h if m o s t p ro c e s s o rs s p e n d th e ir tim e w a itin g for o n e to fin ish so m e th in g .

8 .1 .3

C o o p e ra te to a v o id d e a d lo c k s Like ra c e s, d e a d lo c k s a re th e r e s u lt o f s y n c h ro n iz a tio n p ro b le m s in a p ro g ra m . W hile r a c e s a re re s o u rc e c o n flicts c a u s e d b y in s u ffic ie n t s y n c h ro n iz a tio n , d e a d lo c k s a re u s u a lly c o n flic ts in th e u s e o f s y n c h ro n iz a tio n . A d e a d lo c k c a n h a p p e n w h e n a n y tw o th r e a d s s h a r e re s o u rc e s . E s s e n tia lly a d e a d lo c k o c c u rs w h e n th r e a d A h a s r e s o u rc e 1 a n d c a n ’t c o n tin u e u n til it h a s re s o u rc e 2, w h ile th r e a d B h a s re s o u rc e 2 a n d c a n ’t c o n tin u e u n til it h a s re s o u rc e 1.

298

CHAPTER 8

Hints to avoid debugging

T h e m o s t c o m m o n ty p e o f d e a d lo c k in a P th r e a d s p ro g ra m is m u te x d e a d lo ck , w h e re b o th re s o u rc e s a re m u te x e s . T h e re is o n e re a lly im p o r ta n t a d v a n ta g e o f a d e a d lo c k o v er a ra c e : It is m u c h e a s ie r to d e b u g th e p ro b le m . In a ra c e , th e th r e a d s do s o m e th in g in c o rre c tly a n d m ove on. T h e p ro b le m sh o w s u p so m e tim e la ter, u s u a lly a s a sid e effect. B u t in a d e a d lo c k th e th r e a d s axe s till th e re w aitin g , a n d a lw ay s will b e —if th e y co u ld go a n y w h e re , it w o u ld n ’t b e a d ea d lo c k . So w h e n y o u a t ta c h to th e p ro c e s s w ith th e d e b u g g e r o r lo o k a t a c r a s h d u m p , y o u c a n see w h a t r e s o u r c e s a re involved. W ith a little d ete c tiv e w o rk y o u c a n o fte n d e te rm in e w h y it h a p p e n e d . T h e m o s t likely c a u s e is a re s o u rc e o rd e rin g in c o n siste n c y . T h e s tu d y o f d e a d lo c k s g o es w ay b a c k to th e e arly d a y s of o p e ra tin g s y ste m d e sig n . A n y o n e w h o ’s ta k e n c o m p u te r sc ie n c e c o u rs e s h a s p ro b a b ly r u n in to th e c la s s ic d in in g p h ilo s o p h e rs p ro b le m . S o m e p h ilo s o p h e rs s it a t a r o u n d ta b le w ith p la te s of s p a g h e tti; e a c h a lte rn a te ly e a ts a n d d is c u s s e s p h ilo so p h y . A lth o u g h n o u te n s ils a re re q u ire d to d is c u s s p h ilo so p h y , e a c h p h ilo s o p h e r re q u ire s tw o fo rk s to e a t. T h e ta b le is s e t w ith a sin g le fo rk b e tw e e n e a c h pair. T h e p h ilo s o p h e rs n e e d to s y n c h ro n iz e th e ir e a tin g a n d d is c u s s io n to p re v e n t d ead lo ck . T h e m o s t o b v io u s fo rm o f d e a d lo c k is w h e n all p h ilo s o p h e rs s im u lta n e o u s ly p ic k u p o n e fo rk e a c h a n d re fu s e to p u t it do w n. T h e re ’s a lw ay s a w ay to m a k e s u r e t h a t y o u r p h ilo s o p h e rs c a n all e a t, e v e n tu ally. F o r e x am p le, a p h ilo s o p h e r c a n ta k e th e fo rk to h e r rig h t, a n d th e n lo o k to h e r left. If th e fo rk is a v ailab le, s h e c a n ta k e it a n d e a t. If n o t, s h e s h o u ld r e tu r n th e fo rk s h e ’s h o ld in g to th e ta b le a n d c h a t aw h ile. (T h at is th e m u te x b a c k o ff stra te g y d is c u s s e d in S e c tio n 3 .2 .5 .1 .) S in c e th e p h ilo s o p h e rs a re all in a good m o o d a n d n o n e h a s re c e n tly p u b lis h e d p a p e r s sev erely c ritic a l of a d jo in in g colle a g u e s, th o s e w h o g e t to e a t will in r e a s o n a b ly s h o r t o rd e r r e t u r n b o th o f th e ir fo rk s to th e ta b le so t h a t th e ir co lle a g u e s o n e a c h sid e c a n p ro ceed . A m o re re lia b le (an d m o re s a n ita ry ) s o lu tio n is to s k ip th e s p a g h e tti a n d serv e a d is h th a t c a n b e e a te n w ith o n e fork. M u te x d e a d lo c k s c a n ’t h a p p e n if e a c h th r e a d h a s o n ly o n e m u te x lo c k ed a t a tim e. It is a good id e a to av oid callin g fu n c tio n s w ith a m u te x locked. F irst, if t h a t fu n c tio n (or s o m e th in g it calls) lo c k s a n o th e r m u te x , y o u c o u ld e n d u p w ith a d e a d lo c k . S e c o n d , it is a goo d id e a to lo ck m u te x e s for a s s h o r t a tim e a s p o ssib le (rem em b er, lo c k in g a m u te x p re v e n ts a n o th e r th r e a d fro m “e a tin g ”—t h a t is, e x e c u tin g —c o n c u rre n tly ). C allin g p r i n t f , th o u g h , is n ’t likely to c a u s e a d e a d lo c k in y o u r code, b e c a u s e y o u d o n ’t lo c k a n y ANSI C lib ra ry m u te x e s , a n d th e ANSI C lib ra ry d o e s n ’t lo ck a n y of y o u r m u te x e s . If th e call is in to y o u r ow n code, o r if y o u call a lib ra ry t h a t m a y call b a c k in to y o u r co de, b e c a re fu l. If y o u n e e d to lo ck m o re th a n o n e m u te x a t a tim e, av o id d e a d lo c k s b y u s in g a s tr ic t h ie ra rc h y o r a b a c k o ff a lg o rith m . T h e m a in d is a d v a n ta g e of m u te x b a c k o ff is t h a t th e b a c k o ff loop c a n r u n a lo ng tim e if th e re a re lo ts o f o th e r th r e a d s lockin g th e m u te x e s , ev en if th e y do so w ith o u t a n y p o ssib ility of a d ea d lo c k . T h e b a c k o ff a lg o rith m a s s u m e s t h a t o th e r th r e a d s m a y lo ck th e firs t m u te x a fte r h av in g lo ck ed o n e o r m o re of th e o th e r m u te x e s . If all th r e a d s a lw a y s lo ck m u te x e s in th e o rd e r th e y ’re lo ck ed b y th e b a c k o ff loop, th e n y o u ’ve g o t a fixed lo c k in g h ie ra r c h y a n d y o u d o n ’t n e e d th e b a c k o ff alg o rith m .

A v o i d i n g i n c o r r ec t c o d e

299

W h e n a p ro g ra m h a s h u n g b e c a u s e o f a d e a d lo c k , y o u re q u ire tw o im p o r ta n t c a p a b ilitie s of y o u r th re a d e d d eb u g g er. F irs t, it allo w s y o u to r u n y o u r p ro g ra m in a m o d e w h e re m u te x o w n e rs h ip is re c o rd e d , a n d m a y b e d is p la y e d u s in g d e b u g g e r c o m m a n d s . F in d in g a th r e a d th a t is b lo c k e d o n so m e m u te x w h ile it o w n s o th e r m u te x e s is a good in d ic a tio n t h a t y o u m a y h a v e a d e a d lo c k . S e c o n d , y o u w o u ld lik e to b e a b le to e x a m in e th e call s ta c k o f th r e a d s t h a t o w n m u te x e s to d e te rm in e w hy th e m u te x e s h a v e re m a in e d lo ck ed . T h e call s ta c k m a y n o t alw ay s b e su fficie n t, th o u g h . O n e c o m m o n c a u s e of a d e a d lo c k is th a t so m e th r e a d h a s r e tu r n e d fro m a fu n c tio n w ith o u t u n lo c k in g a m u te x . In th is c a s e , y o u m a y n e e d a m o re s o p h is tic a te d too l to tra c e th e sy n c h ro n iz a tio n b e h a v io r of th e p ro g ra m . S u c h a tool w o u ld allow y o u to e x a m in e th e d a ta a n d d e te rm in e , for ex am p le, t h a t fu n c tio n b a d _ lo c k lo ck ed a m u te x a n d failed to u n lo c k t h a t m u te x .

8 .1 .4

B e w a re o f p rio rity inversion “P rio rity in v e rs io n ” is a p ro b le m u n iq u e to a p p lic a tio n s (or lib ra rie s) th a t rely o n re a ltim e p rio rity s c h e d u lin g . P rio rity in v e rsio n involves a t le a s t th re e th r e a d s o f differin g p rio rity . T h e d ifferin g p rio ritie s a re im p o r ta n t—p rio rity in v e rsio n is a co n flict b e tw e e n s y n c h ro n iz a tio n a n d s c h e d u lin g r e q u ire m e n ts . P rio rity in v e rsio n allo w s a lo w -p rio rity th r e a d to in d e fin itely p re v e n t a h ig h e r-p rio rity th r e a d from ru n n in g . T h e r e s u lt u s u a lly is n o t a d e a d lo c k (th o u g h it c a n be), b u t it is a lw ay s a se v e re p ro b le m . S ee S e c tio n 5 .5 .4 for m o re a b o u t p rio rity in v e rsio n . M o st co m m o n ly , a p rio rity in v e rs io n r e s u lts fro m th r e e th r e a d s o f differin g p rio rity s h a r in g re s o u rc e s . O n e e x a m p le of a p rio rity in v e rsio n is w h e n a low ‫ ־‬p rio rity th r e a d lo c k s a m u te x , a n d is p re e m p te d b y a h ig h -p rio rity th re a d , w h ic h th e n b lo c k s o n th e m u te x c u rre n tly lo ck ed b y th e lo w -p rio rity th re a d . N orm ally, th e lo w -p rio rity th r e a d w o u ld re s u m e , allo w in g it to u n lo c k th e m u te x , w h ic h w o u ld u n b lo c k th e h ig h -p rio rity th r e a d to c o n tin u e . H ow ever, if a m e d iu m -p rio rity th r e a d w a s a w a k e n e d (p o ssib ly b y so m e a c tio n of th e h ig h -p rio rity th re a d ), it m ig h t p re v e n t th e lo w e r-p rio rity th r e a d fro m r u n n in g . T h e m e d iu m -p rio rity th r e a d (or o th e r th r e a d s it a w a k e n s) m a y in d e fin itely p re v e n t th e lo w -p rio rity th r e a d fro m re le a s in g th e m u te x , so a h ig h -p rio rity th r e a d is b lo c k e d b y th e a c tio n of a lo w e r-p rio rity th re a d . If th e m e d iu m -p rio rity th r e a d b lo c k s, th e lo w -p rio rity th r e a d will b e allow ed to re s u m e a n d re le a s e th e m u te x , a t w h ic h p o in t o p e ra tio n re s u m e s . B e c a u s e of th is , m a n y p rio rity in v e rs io n d e a d lo c k s reso lv e th e m s e lv e s a fte r a s h o r t tim e. If all p rio rity in v e rs io n p ro b le m s in a p ro g ra m re lia b ly reso lv e th e m s e lv e s w ith in a s h o r t tim e, th e p rio rity in v e rs io n m a y b e c o m e a p e rfo rm a n c e is s u e r a th e r th a n a c o rre c tn e s s is s u e . In e ith e r c a se , p rio rity in v e rsio n c a n b e a sev ere p ro b lem . H ere a re a few id e a s to av oid p rio rity in v e rsio n : •

Avoid re a ltim e s c h e d u lin g e n tirely . T h a t cle a rly is n o t p ra c tic a l in m a n y re a ltim e a p p lic a tio n s , how ever.

300







8 .1 .5

CHAPTER 8

Hints to avoid debugging

D e sig n y o u r th r e a d s so th a t th r e a d s of d ifferin g p rio rity do n o t n e e d to u s e th e s a m e m u te x e s . T h is m a y b e im p ra c tic a l, too; m a n y ANSI C fu n c tio n s , fo r e x am p le, u s e m u te x e s . U se p rio rity ceiling m u te x e s (S ectio n 5 .5 .5 .1 ) o r p rio rity in h e rita n c e (Sectio n 5 .5 .5 .2 ). T h e se a re o p tio n a l f e a tu re s of P th r e a d s a n d w ill n o t b e av a ila b le ev ery w h ere. Also, y o u c a n n o t s e t th e m u te x p rio rity p ro to co l fo r m u te x e s y o u do n o t c re a te , in c lu d in g th o s e u s e d b y ANSI C fu n c tio n s . Avoid c a llin g fu n c tio n s t h a t m a y lock m u te x e s y o u d id n ’t c re a te in a n y th r e a d w ith ele v a te d p rio rity .

N e v e r s h a re c o n d itio n v a ria b le s b e tw e e n p re d ic a te s Y our co d e will u s u a lly b e c le a n e r a n d m o re effic ien t if y o u av oid u s in g a sin g le c o n d itio n v a ria b le to m a n a g e m o re t h a n o n e p re d ic a te c o n d itio n . You s h o u ld n o t, for ex am p le, d efin e a sin g le “q u e u e ” c o n d itio n v a ria b le t h a t is u s e d to a w a k e n th r e a d s w a itin g for th e q u e u e to b eco m e e m p ty a n d a lso th r e a d s w a itin g for a n e le m e n t to b e a d d e d to th e q u e u e . B u t th is is n ’t j u s t a p e rfo rm a n c e is s u e (or it w o u ld b e in a n o th e r sectio n ). If y o u u s e pthread__cond_signal to w a k e th r e a d s w a itin g o n th e s e s h a r e d c o n d itio n v a ria b le s , th e p ro g ra m m a y h a n g w ith th r e a d s w a itin g o n th e c o n d itio n v a ria b le a n d n o b o d y left to w a k e th e m u p . W hy? B e c a u s e y o u c a n only s ig n a l a c o n d itio n v a ria b le w h e n y o u k n o w t h a t a sin g le th r e a d n e e d s to b e a w a k e n e d , a n d th a t a n y th r e a d w a itin g o n th e c o n d itio n v a ria b le m a y b e c h o s e n . W h e n m u ltip le p re d ic a te s s h a r e a c o n d itio n v a ria b le , y o u c a n n e v e r b e s u r e t h a t th e a w a k e n e d th r e a d w a s w a itin g fo r th e p re d ic a te y o u set. If it w a s n o t, th e n it w ill se e a s p u rio u s w a ke u p a n d w a it a g a in . Y our s ig n a l h a s b e e n lo st, b e c a u s e n o th r e a d w a itin g for y o u r p re d ic a te h a d a c h a n c e to s e e t h a t it h a d c h a n g e d . It is n o t e n o u g h for a th r e a d to re sig n a l th e co n d itio n v a ria b le w h e n it g e ts a s p u rio u s w a k e u p , eith er. T h re a d s m a y n o t w a k e u p in th e o rd e r th e y w aited , esp ecially w h e n y o u u s e p rio rity s c h e d u lin g . “R esig n a lin g ” m ig h t r e s u lt in a n in fin ite loop w ith a few h ig h -p rio rity th r e a d s (all w ith th e w ro n g p red ic ate) a lte rn a te ly w a k ‫־‬ in g e a c h o th e r u p . T h e b e s t so lu tio n , w h e n y o u really w a n t to s h a r e a c o n d itio n v a ria b le b e tw e e n p re d ic a te s , is a lw ay s to u s e pthread_cond__broadcast. B u t w h e n y o u b r o a d c a s t, all w a itin g th r e a d s w a k e u p to re e v a lu a te th e ir p re d ic a te s . You a lw ay s k n o w t h a t o n e s e t o r th e o th e r c a n n o t p ro c e e d —so w h y m a k e th e m all w a k e u p to fin d o u t? If 1 th r e a d is w a itin g for w rite a c c e s s, for e x am p le, a n d 100 a re w a itin g for re a d a c c e s s, all 101 th r e a d s m u s t w a k e u p w h e n th e b r o a d c a s t m e a n s t h a t it is n o w OK to w rite, b u t o n ly th e o n e w rite r c a n p ro c e e d —th e o th e r 100 th r e a d s m u s t w a it ag a in . T h e r e s u lt of th is im p re c is io n is a lo t of w a s te d c o n te x t sw itc h e s, a n d th e re a re m o re u s e fu l w ay s to k e e p y o u r c o m p u te r b u sy .

A vo i d i n g i n c o r r ec t c o d e

8 .1 .6

301

S h arin g stack s a n d re la te d m e m o ry c o rru p te rs T h e re ’s n o th in g w ro n g w ith s h a r in g s ta c k m e m o ry b e tw e e n th r e a d s . T h a t is, it is legal a n d so m e tim e s re a s o n a b le fo r a th r e a d to a llo c a te so m e v a ria b le o n its ow n s ta c k a n d c o m m u n ic a te t h a t a d d r e s s to o n e o r m o re o th e r th r e a d s . A co rre c tly w ritte n p ro g ra m c a n s h a r e s ta c k a d d r e s s e s w ith n o r is k a t all; h o w ev er (th is m a y co m e a s a s u rp ris e ), n o t ev ery p ro g ra m is w ritte n co rrectly , ev en w h e n y o u w a n t it to b e c o rre c t. S h a rin g s ta c k a d d r e s s e s c a n m a k e sm a ll p ro g ra m m in g e rro rs c a ta s tro p h ic , a n d th e s e e rro rs c a n b e v ery d ifficu lt to iso la te .

I

R e tu rn in g fro m t h e f u n c t io n t h a t a llo c a t e s s h a re d s ta c k m e m o ry , w h e n o t h e r th r e a d s m a y still u s e t h a t d a t a , w ill re s u lt in u n d e s ir a b le b e h a v io r.

If y o u s h a r e s ta c k m em o ry , y o u m u s t e n s u r e t h a t it is n e v e r p o s sib le for th e th r e a d t h a t o w n s th e s ta c k to “p o p ” t h a t s h a r e d m e m o ry fro m th e s ta c k u n til all o th e r th r e a d s h a v e fo rev er c e a s e d to m a k e u s e o f th e s h a r e d d a ta . S h o u ld th e o w n in g th r e a d r e t u r n fro m a s ta c k fra m e c o n ta in in g th e d a ta , for ex am p le, th e o w n in g th r e a d m a y call a n o th e r fu n c tio n a n d th e re b y re a llo c a te th e s p a c e o ccu p ie d b y th e s h a r e d v a ria b le . O n e o r b o th o f th e follow ing p o ssib le o u tc o m e s will e v e n tu a lly b e o b serv ed : 1. D a ta w ritte n b y a n o th e r th r e a d will b e o v e rw ritte n w ith sa v e d re g is te r valu e s , a r e tu r n PC, o r w h atev e r. T h e s h a r e d d a t a h a s b e e n c o rru p te d . 2. S av ed re g is te r v a lu e s, r e t u r n PC, o r w h a te v e r will b e o v e rw ritte n b y a n o th e r th r e a d m o d ify in g th e s h a r e d d a ta . T h e o w n in g th r e a d ’s call fra m e h a s b e e n c o rru p te d . H av in g ca re fu lly e n s u r e d t h a t th e re is n o p o s sib le w ay fo r th e o w n in g th r e a d to p o p th e s ta c k d a ta w h ile o th e r th r e a d s a r e u s in g th e s h a r e d d a ta , a r e y o u sa fe ? M ay be n o t. We’re s tr e tc h in g th e p o in t a little, b u t re m e m b e r, w e’re ta lk in g a b o u t a p ro g ra m m in g e rro r—m a y b e a silly th in g like failin g to in itia lize a p o in te r v a ria b le d e c la re d w ith a u to s to ra g e c la ss , for ex am p le. A p o in te r to th e s h a r e d d a ta m u s t b e s to re d so m e w h e re to b e u s e fu l—o th e r th r e a d s h a v e n o o th e r w ay to fin d th e p ro p e r s ta c k a d d re s s . A t so m e p o in t, th e p o in te r is likely to a p p e a r in v a rio u s lo c a tio n s o n th e s ta c k of every th r e a d t h a t u s e s th e d a ta . N on e of th e s e p o in te rs will n e c e s s a rily b e e ra s e d w h e n th e th r e a d c e a s e s to m a k e u s e of th e s ta c k . W rites th r o u g h u n in itia liz e d p o in te rs a re a c o m m o n p ro g ra m m in g erro r, re g a rd le s s of th r e a d s , so to so m e e x te n t th is is n o th in g n e w o r d iffere n t. However, in th e p re s e n c e of th r e a d s a n d s h a r e d s ta c k d a ta , e a c h th r e a d h a s sin o p p o rtu n ity to c o r r u p t d a ta u s e d b y so m e o th e r th r e a d a s y n c h ro n o u s ly . T h e s y m p to m s of th a t c o rru p tio n m a y n o t a p p e a r u n til so m e tim e later, w h ic h c a n p o se a p a rtic u la rly d ifficu lt d e b u g g in g ta s k . If, in y o u r p ro g ra m , s h a r in g s ta c k d a ta s e e m s c o n v e n ie n t, th e n b y all m e a n s ta k e a d v a n ta g e of th e cap a b ility . B u t if s o m e th in g u n e x p e c te d h a p p e n s d u rin g d eb u g g in g , s t a r t b y e x a m in in g th e co d e t h a t s h a r e s s ta c k d a ta p a rtic u la rly c a re fully. If y o u ro u tin e ly u s e a n a n a ly s is to ol t h a t re p o rts u s e of u n in itia liz e d v a ria b le s (su c h a s T h ird D egree o n D ig ital UNIX), y o u m a y n o t n e e d to w o rry a b o u t th is c la s s of p ro b le m —o r m a n y o th e rs .

302

CH A P T E R 8

H i n t s to a vo i d d ebu g g i n g

8.2 A v o id in g p e rfo rm a n c e p ro b le m s ‘,Well, in our c o u n t r y ” s a id A lic e , still p a n tin g a little, ,,y o u ’d g e n e r a lly g e t to s o m e w h e re e ls e — if y o u ra n v e ry fast for a lo n g tim e a s w e ’v e b e e n d o in g ” ,,A slow sort o f c o u n try !” s a id th e Q u e e n . ,,Now, here, y o u s e e , it ta k e s a ll th e ru n n in g you c a n d o , to k e e p in th e s a m e p la c e . If y o u w a n t to g e t s o m e w h e re else, y o u m ust run a t le a s t tw ic e a s fast as th a tI” — L e w is C a r r o il, T h r o u g h t h e L o o k in g -G la s s

S o m e tim e s, o n c e a p ro g ra m w o rk s, it is “d o n e .” A t le a st, u n til y o u w a n t to m a k e it d o s o m e th in g else. In m a n y c a s e s , th o u g h , “w o rk in g ” is n ’t good e n o u g h . T h e p ro g ra m n e e d s to m e e t p e rfo rm a n c e g o als. S o m e tim e s th e p e rfo rm a n c e g o als a r e clear: “m u s t p e rfo rm so m a n y tr a n s a c tio n s in th is p e rio d o f tim e .” O th e r tim e s , th e g o als a re looser: “m u s t b e v ery f a s t.” T h is s e c tio n gives p o in te rs o n d e te rm in in g h o w fa s t y o u ’re going, w h a t’s slow in g y o u u p , a n d h o w to te ll (m aybe) w h e n y o u ’re g o in g a s fa s t a s y o u c a n go. T h e re a r e so m e v ery good to o ls to h e lp y o u , a n d th e re w ill b e a lo t m o re a s th e in d u s tr y a d ju s ts to s u p p o rtin g e a g e r a n d o u ts p o k e n th r e a d p ro g ra m m e rs . B u t th e re a re n o p o rta b le s ta n d a r d s for th r e a d e d a n a ly s is to o ls. If y o u r v e n d o r s u p p o r ts th r e a d s , y o u ’ll p ro b a b ly find a t le a s t a th re a d -s a fe v e rs io n of p r o f , w h ic h is a n e a rly u n iv e rs a l UNIX tool. E a c h s y s te m will p ro b a b ly re q u ire d iffe re n t s w itc h e s a n d e n v iro n m e n ts to u s e it safely fo r th r e a d s , a n d th e o u tp u t will differ. P e rfo rm a n c e tu n in g r e q u ire s m o re t h a n j u s t a n s w e rin g th e tra d itio n a l q u e s tio n , “H ow m u c h tim e d o e s th e a p p lic a tio n s p e n d in e a c h fu n c tio n ? ” You h a v e to a n a ly z e c o n te n tio n o n m u te x e s , for e x am p le. M u te x e s w ith h ig h c o n te n tio n m a y n e e d to b e s p lit in to se v e ra l m u te x e s c o n tro llin g m o re sp ec ia liz e d d a t a (finerg ra in c o n c u rre n c y ), w h ic h c a n im p ro v e p e rfo rm a n c e b y in c re a s in g c o n c u rre n c y . If fin e r g ra in m u te x e s h a v e low c o n te n tio n , c o m b in in g th e m m a y im p ro v e p e rfo rm a n c e b y re d u c in g lo c k in g o v erh ea d .

8.2.1

B ew are o f c o n c u rre n t s e ria liza tio n T h e id e a l p a ra lle l co d e is a s e t of ta s k s t h a t is co m p lete ly c o m p u te -b o u n d . T h ey n e v e r s y n c h ro n iz e , th e y n e v e r b lo c k —th e y j u s t “th in k .” If y o u s t a r t w ith a p ro g ra m t h a t c a lls th r e e c o m p u te -b o u n d f u n c tio n s in s e rie s , a n d c h a n g e it to c re a te th re e th r e a d s e a c h r u n n in g o n e o f th o s e fu n c tio n s , th e p ro g ra m will r u n (nearly) th r e e tim e s faster. A t le a st, it s h o u ld do so if y o u ’re r u n n in g o n a m u ltip ro c e s s o r w ith a t le a s t th r e e C PU s t h a t a re , a t th a t m o m e n t, a llo c a te d for y o u r u se. T h e id e al c o n c u r r e n t co d e is a s e t o f ta s k s t h a t is c o m p le te ly I /O - b o u n d . T h ey n e v e r s y n c h ro n iz e , a n d do little c o m p u ta tio n —th e y j u s t is s u e I /O r e q u e s ts a n d w a it for th e m . If y o u s t a r t w ith a p ro g ra m t h a t w rite s c h u n k s o f d a ta to th re e

A vo i d i n g p er f o r m a n c e p r o bl em s

303

s e p a r a te files (ideally, o n th r e e s e p a r a te d is k s , w ith s e p a r a te co n tro llers), a n d c h a n g e it to c re a te th r e e th r e a d s , e a c h w ritin g o n e o f th o s e c h u n k s of d a ta , all th r e e I /O o p e ra tio n s c a n p ro g re s s s im u lta n e o u s ly . B u t w h a t if y o u ’ve g o n e to all t h a t tro u b le to w rite a s e t o f c o m p u te -b o u n d p a rallel o r I /O - b o u n d c o n c u r r e n t th r e a d s a n d it t u r n s o u t t h a t y o u ’ve j u s t c o n v e rte d a s tr a ig h t-lin e s e ria liz e d p ro g ra m in to a m u ltith r e a d e d se ria liz e d p ro g ra m ? T h e r e s u lt will b e a slo w er p ro g ra m t h a t a c c o m p lis h e s th e s a m e r e s u lt w ith s u b s ta n tially m o re o v e rh e a d . M o st likely, t h a t is n o t w h a t y o u in te n d e d . H ow co u ld t h a t have h ap p en ed ? L et’s s a y th a t y o u r c o m p u te -b o u n d o p e ra tio n s call m a llo c a n d f r e e in th e ir w ork. T h o se f u n c tio n s m odify th e s ta tic p ro c e s s s ta te , so th e y n e e d to p e rfo rm so m e ty p e of sy n c h ro n iz a tio n . M o st likely, th e y lo c k a m u te x . If y o u r th r e a d s r u n in a lo op callin g m a llo c a n d f r e e , s u c h t h a t a s u b s t a n ti a l a m o u n t o f th e ir to ta l tim e m a y b e s p e n t w ith in th o s e fu n c tio n s , y o u m a y fin d t h a t th e r e ’s v e iy little re a l p a ra lle lis m . T h e th r e a d s w ill s p e n d a lo t of tim e b lo c k e d o n th e m u te x w h ile o n e th r e a d o r a n o th e r a llo c a te s o r frees m e m o ry . S im ila rly , th e c o n c u r r e n t I /O th r e a d s m a y b e u s in g se ria liz e d re s o u rc e s . If th e th r e a d s p e rfo rm “c o n c u r r e n t” I /O u s in g th e s a m e s td io f i l e s tre a m , for ex am p le, th e y will b e lo c k in g m u te x e s to u p d a te th e s tr e a m ’s s h a r e d bu ffer. E v en if th e th r e a d s a re u s in g s e p a r a te files, if th e y a re o n th e s a m e d is k th e re w ill b e lo ck in g w ith in th e file s y s te m to s y n c h ro n iz e th e file c a c h e a n d so fo rth . E v en w h e n u s in g s e p a r a te d is k s , tr u e c o n c u rre n c y m a y b e s u b je c t to lim ita tio n s in th e I /O b u s o r d is k c o n tro lle r s u b s y s te m s . T h e p o in t o f all th is is t h a t w ritin g a p ro g ra m t h a t u s e s th r e a d s d o e s n ’t m ag ically g r a n t p a ra lle lis m o r ev en c o n c u rre n c y to y o u r a p p lic a tio n . W h e n y o u ’re a n a ly z in g p e rfo rm a n c e , b e a w a re th a t y o u r p ro g ra m c a n b e affected b y fa c to rs th a t a r e n ’t w ith in y o u r co n tro l. You m a y n o t ev en b e ab le to se e w h a t’s h a p p e n in g in th e file s y ste m , b u t w h a t y o u c a n ’t see c a n h u r t y o u .

8 .2 .2

Use th e righ t n u m b e r o f m u te x e s T h e firs t s te p in m a k in g a lib ra ry th re a d -s a fe m a y b e to c re a te a “b ig m u te x ” t h a t p ro te c ts all e n trie s in to th e lib rary . If on ly o n e th r e a d c a n e x e c u te w ith in th e lib ra ry a t a tim e, th e n m o s t f u n c tio n s will b e th re a d -s a fe . A t le a st, n o s ta tic d a ta will b e c o rru p te d . If th e lib ra ry h a s n o p e r s is te n t s ta te t h a t n e e d s to re m a in co n s is te n t a c ro s s a s e rie s of c alls, th e big m u te x m a y se e m to b e e n o u g h . M an y lib ra rie s a re left in th is s ta te . T h e s ta n d a r d X I 1 c lie n t lib ra ry (Xlib) p ro v id e s lim ite d s u p p o r t for th is b ig m u te x a p p ro a c h to th re a d -s a fe ty , a n d h a s for y e a rs . B u t th re a d -s a fe ty is n ’t e n o u g h a n y m o re —n o w y o u w a n t th e lib ra ry to p e rfo rm w ell w ith th r e a d s . In m o s t c a s e s , t h a t w ill re q u ire re d e s ig n in g th e lib ra ry so t h a t m u ltip le th r e a d s c a n u s e it a t th e s a m e tim e. T h e b ig m u te x se ria liz e s all o p e ra tio n s in th e lib ra ry , so y o u a re g e ttin g n o c o n c u rre n c y o r p a ra lle liz a tio n w ith in th e lib ra iy . If u s e of th a t lib ra iy is th e p rim a ry fu n c tio n of y o u r th r e a d s , th e p ro g ra m w o u ld r u n fa s te r w ith a sin g le th r e a d a n d n o s y n c h ro n iz a tio n . T h a t big

304

CHAPTER 8

Hints to avoid debugging

m u te x in X lib, re m e m b e r, k e e p s all o th e r th r e a d s fro m u s in g a n y X lib fu n c tio n u n til th e firs t th r e a d h a s receiv ed its re s p o n s e from th e serv er, a n d t h a t m ig h t ta k e q u ite a w hile. M ap o u t y o u r lib ra ry fu n c tio n s , a n d d e te rm in e w h a t o p e ra tio n s c a n re a s o n ab ly r u n in p a ra lle l. A c o m m o n s tra te g y is to c re a te a s e p a r a te m u te x for e a c h d a t a s tr u c tu r e , a n d u s e th o s e m u te x e s to se ria liz e a c c e s s to th e s h a r e d d a ta , r a th e r th a n u s in g th e “b ig m u te x ” to se ria liz e a c c e s s to th e lib ra ry . W ith a p ro filer t h a t s u p p o r ts th r e a d s , y o u c a n d e te rm in e t h a t y o u h a v e too m u c h m u te x activ ity, b y lo o k in g for h o t s p o ts w ith in c a lls to pthread_mutex_ lock, pthread_mutex_unlock, a n d pthread_mutex_trylock. H owever, th is d a ta w ill n o t b e co n c lu siv e , a n d it m a y b e v ery d ifficu lt to d e te rm in e w h e th e r th e h ig h activ ity is d u e to to o m u c h m u te x c o n te n tio n o r to o m u c h lo c k in g w ith o u t c o n te n tio n . You n e e d m o re sp ecific in fo rm a tio n o n m u te x c o n te n tio n a n d t h a t r e q u ire s sp e c ia l to o ls. S o m e th r e a d d e v e lo p m e n t s y s te m s p ro v id e d e ta ile d v is u a l tra c in g in fo rm a tio n t h a t s h o w s s y n c h ro n iz a tio n c o s ts . O th e rs p ro v id e “m e te rin g ” in fo rm a tio n o n in d iv id u a l m u te x e s to tell h o w m a n y tim e s th e m u te x w a s lo ck ed , a n d h o w o ften th r e a d s fo u n d th e m u te x a lre a d y lo ck ed .

8 .2.2 .1 Too m a n y m u te x e s w ill n o t h e lp B ew are, too, of e x c h a n g in g a “b ig ” m u te x for lo ts of “tin y ” m u te x e s . You m a y m a k e m a tte r s w o rse . R em em b er, it ta k e s tim e to lo ck a m u te x , a n d m o re tim e to u n lo c k t h a t m u te x . E v en if y o u in c re a s e p a ra lle lis m b y d e s ig n in g a lo c k in g h ie ra rc h y t h a t h a s v ery little c o n te n tio n , y o u r th r e a d s m a y s p e n d so m u c h tim e lo c k in g a n d u n lo c k in g all th o s e m u te x e s t h a t th e y g et le s s re a l w o rk d o n e. Lo ck ing a m u te x a lso a ffe c ts th e m e m o ry s u b s y s te m . In a d d itio n to th e tim e y o u s p e n d lo c k in g a n d u n lo c k in g , y o u m a y d e c re a s e th e efficiency of th e m e m o ry s y s te m b y ex ce ssiv e lo ck in g . Lo ck ing a m u te x , for ex am p le, m ig h t in v a lid a te a b lo c k of c a c h e o n all p ro c e s s o rs . It m ig h t s ta ll all b u s a ctiv ity w ith in so m e ra n g e of p h y s ic a l a d d re s s e s . So fin d o u t w h e re y o u re a lly n e e d m u te x e s . F o r e x am p le, in th e p re v io u s sectio n I s u g g e s te d c re a tin g a s e p a r a te m u te x for e a c h d a ta s tr u c tu r e . Yet, if tw o d a t a s tr u c t u r e s a re u s u a lly u s e d to g e th e r, o r if o n e th r e a d w ill h a rd ly ev er n e e d to u s e o n e d a t a s tr u c t u r e w h ile a n o th e r th r e a d is u s in g th e se c o n d d a ta s tr u c tu r e , th e e x tra m u te x m a y d e c re a s e y o u r o verall p e rfo rm a n c e .

8 .2 .3

N e v e r fig h t o v e r c a c h e lines No m o d e rn c o m p u te r r e a d s d a ta d ire c tly from m a in m em o ry . M em ory th a t is f a s t e n o u g h to k e e p u p w ith th e c o m p u te r is to o ex p e n siv e for t h a t to b e p ra c tical. In s te a d , d a ta is fe tc h e d b y th e m e m o ry m a n a g e m e n t u n it in to a f a s t lo cal c a c h e a rra y . W h e n th e c o m p u te r w rite s d a ta , th a t, too, g o es in to th e lo cal c a c h e a rra y . T h e m odified d a ta m a y a lso b e w ritte n to m a in m e m o ry im m e d ia te ly o r m a y b e “f lu s h e d ” to m e m o ry only w h e n n e e d e d .

A vo i d i n g p er f o r m a n c e p r o bl em s

305

So if o n e p ro c e s s o r in a m u ltip ro c e s s o r s y s te m n e e d s to re a d a v a lu e th a t a n o th e r p ro c e s s o r h a s in its c a c h e , th e re m u s t b e so m e ‘4c a c h e c o h e re n c y ” m e c h a n is m to e n s u r e th a t it c a n fin d th e c o rre c t d a ta . M ore im p o rta n tly , w h e n o n e p ro c e s s o r w rite s d a ta to so m e lo c a tio n , all o th e r p ro c e s s o rs t h a t h a v e o ld e r co p ies o f t h a t lo c a tio n in c a c h e n e e d to co p y th e n e w d a ta , o r re c o rd t h a t th e old d a ta is in v alid . C o m p u te r s y s te m s c o m m o n ly c a c h e d a ta in rela tiv e ly la rg e b lo c k s o f 6 4 o r 128 b y te s. T h a t c a n im p ro v e efficiency b y o p tim iz in g th e re fe re n c e s to slow m a in m em o ry . It a lso m e a n s th a t, w h e n th e s a m e 6 4 ‫ ־‬o r 1 2 8 -b y te b lo c k is c a c h e d b y m u ltip le p ro c e s s o rs , a n d o n e p ro c e s s o r w rite s to a n y p a r t o f t h a t b lo c k , all pro c e s s o rs c a c h in g th e b lo c k m u s t th ro w a w a y th e e n tire block. T h is h a s s e rio u s im p lic a tio n s for h ig h -p e rfo rm a n c e p a ra lle l c o m p u ta tio n . If tw o th r e a d s a c c e s s d iffe re n t d a ta w ith in th e s a m e c a c h e b lo c k , n o th r e a d will b e a b le to ta k e a d v a n ta g e o f th e (fast) c a c h e d co p y o n th e p ro c e s s o r it is u sin g . E a c h re a d w ill re q u ire a n e w c a c h e fill fro m m a in m e m o ry , slo w in g d o w n th e p ro g ra m . C a c h e b e h a v io r m a y v a ry w id ely ev en o n d iffe re n t c o m p u te r s y s te m s u s in g th e s a m e m ic ro p ro c e s s o r c h ip . It is n o t p o s sib le to w rite co d e t h a t is g u a r a n te e d to b e o p tim a l o n all p o ssib le s y s te m s . You c a n s u b s ta n tia lly im p ro v e y o u r c h a n c e s , how ever, b y b e in g v ery c a re fu l to alig n a n d s e p a ra te a n y p e rfo rm a n c e -c ritic a l d a ta u s e d b y m u ltip le th re a d s . You c a n o p tim ize y o u r co d e fo r a p a r tic u la r c o m p u te r s y s te m b y d e te rm in in g th e c a c h e c h a r a c te r is tic s of t h a t sy ste m , a n d d e sig n in g y o u r co d e so t h a t n o tw o th r e a d s w ill e v er n e e d to w rite to th e s a m e c a c h e b lo c k w ith in p e rfo rm a n c e c ritic a l p a ra lle l lo o p s. A b o u t th e b e s t y o u c a n h o p e to do w ith o u t o p tim iz in g for a p a r tic u la r s y s te m w o u ld b e to e n s u r e t h a t e a c h th r e a d h a s a p riv a te , p ag ea lig n ed , s e g m e n t of d a ta . It is h ig h ly u n lik e ly t h a t a n y s y s te m w o u ld u s e a c a c h e b lo c k a s la rg e a s a p ag e, b e c a u s e a p a g e in c lu d e s fa r to o m u c h v a rie d d a ta to p ro v id e a n y p e rfo rm a n c e a d v a n ta g e in th e m e m o ry m a n a g e m e n t u n it.

9 PO SIX th re a d s m in i-re fe re n c e

T h is c h a p te r is a c o m p a c t re fe re n c e to th e POSIX. l c s ta n d a r d .

9.1 POSIX ‫ ו‬003 . ‫ ו‬c - 1 995 o p tio n s P th re a d s is in te n d e d to a d d r e s s a w ide v a rie ty o f a u d ie n c e s . H ig h -p e rfo rm a n c e c o m p u ta tio n a l p ro g ra m s c a n u s e it to s u p p o r t p a ra lle l d eco m p o sitio n o f loops. R ealtim e p ro g ra m s c a n u s e it to s u p p o r t c o n c u rre n t re a ltim e I/O . D a ta b a s e a n d n e tw o rk s e rv e rs c a n u s e it to e a sily s u p p o r t c o n c u rre n t c lien ts. B u s in e s s o r softw are d ev elo p m en t p ro g ra m s c a n u s e it to ta k e a d v a n ta g e of p arallel a n d c o n c u rre n t o p e ra tio n s o n tim e -s h a rin g sy ste m s. T h e P th r e a d s s ta n d a r d allo w s y o u to d e te rm in e w h ic h o p tio n a l c a p a b ilitie s a re p ro v id ed by th e s y ste m , b y d efin in g a s e t o f f e a tu r e - te s t m a c ro s, w h ic h a re sh o w n in T a b le 9 .1 . A ny im p le m e n ta tio n o f P th r e a d s m u s t in fo rm y o u w h e th e r e a c h o p tio n is s u p p o rte d , b y th r e e m e a n s : •





By m a k in g a fo rm a l s ta te m e n t o f s u p p o r t in th e PO SIX C o n fo rm a n c e D ocu m e n t. You c a n u s e th is in fo rm a tio n to h e lp d e s ig n y o u r a p p lic a tio n to w o rk o n sp ecific s y s te m s . By d e fin in g co m p ile -tim e sy m b o lic c o n s ta n ts in th e < u n i s t d . h> h e a d e r file. You c a n te s t for th e s e sy m b o lic c o n s ta n ts u s in g # i f d e f o r #i f n d e f p re p ro c e s s o r c o n d itio n a ls to s u p p o r t a v a rie ty o f P th r e a d s s y ste m s . By r e tu r n in g a p o sitiv e n o n z e ro v a lu e w h e n th e s y s c o n f fu n c tio n is called w ith th e a s s o c ia te d s y s c o n f sy m b o l. (This is n o t u s u a lly u s e fu l fo r th e “f e a tu r e - te s t” m a c ro s t h a t sp ecify w h e th e r o p tio n s a re p r e s e n t—if th e y a re n o t, th e a s s o c ia te d in te rfa c e s u s u a lly a r e n o t su p p lie d , a n d y o u r co d e will n o t lin k , a n d m a y n o t ev en co m pile.)

You m ig h t, for e x am p le, c h o o se to av o id rely in g o n p rio rity s c h e d u lin g b e c a u s e a fte r re a d in g th e c o n fo rm a n c e d o c u m e n ts y o u d isc o v e re d th a t th r e e o u t of th e fo u r s y s te m s y o u w ish to s u p p o r t do n o t p ro v id e th e fe a tu re . O r y o u m ig h t p re fe r to u s e p rio rity in h e rita n c e fo r y o u r m u te x e s o n s y s te m s t h a t p ro v id e th e fe a tu re , b u t w rite th e co d e so t h a t it will n o t txy to a c c e s s th e m u te x p ro to co l a ttr ib u te o n s y s te m s t h a t do n o t p ro v id e t h a t o p tio n .

307

308

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

Sy m bo lic const ant , sy sc o nf sy m bo l nam e

De sc ript io n

_P0SIX THREADS _J5C_THREADS

You c a n u s e th r e a d s (if y o u r s y s te m d o e s n ’t d efin e th is , y o u ’re o u t o f lu ck).

_P0SIX THREAD ATTR STACKSIZE _SC_THREAD_ATTR_STACKSI z e

You c a n c o n tro l th e size o f a th r e a d ’s s ta c k .

_P0SIX THREAD ATTR STACKADDR _SC_THREAD_ATTR_STACKADDR

You c a n a llo c a te a n d c o n tro l a th r e a d ’s s ta c k .

_P0SIX THREAD PRIORITY_SCHEDULING _SC_THREAD_PRIORITY_SCHEDULING

You c a n u s e re a ltim e s c h e d u lin g .

_P0SIX THREAD PRIO INHERIT _SCJTHREAD_PRI0_INHERIT

You c a n c re a te p rio rity in h e rita n c e m u te x e s .

POSIX THREAD PRIO PROTECT _SC_THREAD_PRI0JPR0TECT

You c a n c re a te p rio rity ceiling m u te x e s.

_P0SIX THREAD PROCESSESHARED JSC_THREAD_PR0CESS_SHARED

You c a n c re a te m u te x e s a n d co n d itio n v a ria b le s t h a t c a n b e s h a r e d w ith a n o th e r p ro c e s s .

_P0SIX THREAD SAFE FUNCTIONS _SC_THREAD_SAFE_FUNCTIONS

You c a n u s e th e s p e c ia l “_ r” lib ra ry f u n c tio n s t h a t p ro v id e th re a d -s a fe b eh av io r.

TABLE 9.1

P O S IX 1003.1 c~ l 995 options

9.2 POSIX 003.1 ‫ ו‬c - 1 995 lim its T h e P th r e a d s s ta n d a r d allo w s y o u to d e te rm in e th e r u n - tim e lim its of th e sy ste m th a t m a y affect y o u r a p p lic a tio n , for ex am p le, h o w m a n y th r e a d s y o u c a n c re a te , b y d e fin in g a s e t of m a c ro s, w h ic h a re s h o w n in T a b le 9 .2 . A ny im p le m e n ta tio n o f P th r e a d s m u s t in fo rm y o u o f its lim its, b y th re e m e a n s : •





By m a k in g a fo rm a l s ta te m e n t in th e POSIX C o n fo rm a n c e D o c u m e n t. You c a n u s e th is in fo rm a tio n to h e lp d e s ig n y o u r a p p lic a tio n to w o rk o n specific s y ste m s . B y d e fin in g co m p ile -tim e sy m b o lic c o n s ta n ts in th e c l i m i t s . h> h e a d e r file. T h e sy m b o lic c o n s ta n t m a y b e o m itte d fro m c l i m i t s . h > w h e n th e lim it is a t le a s t a s la rg e a s th e re q u ire d m in im u m , b u t c a n n o t b e d e te rm in e d a t co m p ile tim e, for ex am p le, if it d e p e n d s o n a v a ila b le m e m o ry s p a c e . You c a n t e s t for th e s e sy m b o lic c o n s ta n ts u s in g # i f d e f o r t i f n d e f p re p ro c e s s o r c o n d itio n a ls . B y r e tu r n in g a p o sitiv e n o n z e ro v a lu e w h e n th e sysconf fu n c tio n is calle d w ith th e a s s o c ia te d s y s c o n f sym bol.

You m ig h t, fo r ex am p le, d e s ig n y o u r a p p lic a tio n to rely o n n o m o re th a n 6 4 th r e a d s , if th e c o n fo rm a n c e d o c u m e n ts sh o w e d t h a t th r e e o u t o f th e fo u r s y s te m s

309

P O S I X 1 0 0 3 . 1 c -1 9 9 5 i n t e r f a c e s

R un-t im e inv ariant v alues, sy sc o nf sy m bo l nam e

De sc ript io n

PTHREAD DESTRUCTOR ITERATIONS _SC_THREAD_DESTRUCT0R_ITERATI0NS

M ax im u m n u m b e r o f a tte m p ts to d e s tro y a th r e a d ’s th re a d -s p e c ific d a ta o n te rm in a tio n (m u s t b e a t le a s t 4).

PTHREAD KEYS MAX _SC_THREAD_KEYS_MAX

M a x im u m n u m b e r o f th re a d -sp e c ific d a ta k e y s av a ila b le p e r p ro c e s s (m u s t b e a t le a s t 128).

PTHREAD STACK MIN _SCJTHREAD_STACK_MIN

M in im u m s u p p o r te d s ta c k size for a th r e a d .

PTHREAD THREADS MAX _SC_THREAD_JTHREADS_MAX

M a x im u m n u m b e r o f th r e a d s s u p p o rted p e r p ro c e s s (m u s t b e a t le a s t 64).

TABLE 9.2

P O S IX 1003.1c - 1 995 lim its

y o u w is h to s u p p o r t d o n o t s u p p o r t a d d itio n a l th r e a d s . O r y o u m ig h t p re fe r to w rite c o n d itio n a l co d e t h a t re lie s o n th e v a lu e o f th e pt h r e a d _ t h r e a d s _ ma x sy m bo lic c o n s ta n t (if defined) o r call s y s c o n f to d e te rm in e th e lim it a t r u n tim e.

9 .3

POSIX 1 0 0 3 .1 C - 1 9 9 5 in t e r f a c e s T h e in te rfa c e s a re s o rte d b y fu n c tio n a l ca te g o rie s: th r e a d s , m u te x e s , a n d so fo rth . W ith in e a c h categ o ry , th e in te rfa c e s a r e liste d in a lp h a b e tic a l o rd er. F ig u re 9.1 d e s c rib e s th e fo rm a t o f th e e n trie s . F irs t, th e h e a d e r e n try (1) sh o w s th e n a m e of th e in te rfa c e . If th e in te rfa c e is a n o p tio n a l fe a tu re of P th re a d s , th e n th e n a m e o f th e f e a tu r e - te s t m a c ro for t h a t

| pthread_mutexattr getpshared....... ............ j j >osixjthr eadj >rocess _shared ]

©

®

int pthread_mutexattr_getpshared ( const pthread^utexattr_t int

*attr, *pshared);

D e te r m in e w h e th e r m u te x e s c r ea te d w ith a t t r c a n b e s h a r e d b y m u ltip le p r o ce s s es ,

pshared

® ©

PTHREAD PROCESS SHARED ~ ~ PTHREAD PROCESS PRIVATE R e fe r e n c es :

’© ® ‫י‬ FIGURE 9.1

May be shared if in shared memory. Cannot be shared.

3 .2 , 5 .2 .1

H e a d er s :

< p th r e a d . h >

E rr o rs :

[EINVAL]

H in t:

p s h a re d m u te x e s m u s t b e a llo c a te d in s h a r e d m e m o r y.

M ini- re fe re nce fo rm a t

a t t r in va lid .

310

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

o p tio n is s h o w n a t th e e n d of th e line, in b ra c k e ts . T h e in te rfa c e pthread_ mutexattr_getpshared, for ex am p le, is a n o p tio n u n d e r th e _P0SIX_THREAD_ fe a tu re . T h e p ro to ty p e e n tiy (2) sh o w s th e full C la n g u a g e p ro to ty p e for th e in te rfa c e , d e s c rib in g h o w to call th e fu n c tio n , w ith all a r g u m e n t ty p e s. T h e d e s crip tio n e n try (3) gives a b rie f s y n o p s is o f th e in te rfa c e . In th is c a se , th e p u r p o s e o f th e in te rfa c e is to sp ecify w h e th e r m u te x e s c re a te d u s in g th e a ttr ib u te s o b je c t c a n b e s h a r e d b e tw e e n m u ltip le p ro c e s s e s . F u n c tio n s w ith a r g u m e n ts t h a t h a v e sy m b o lic v a lu e s , like p s h a r e d in th is e x am p le, will in c lu d e a ta b le (4) t h a t d e s c rib e s e a c h p o ssib le v a lu e . T h e d e fa u lt v a lu e of th e a r g u m e n t (the s ta te of a n ew th re a d , o r th e d e fa u lt v a lu e of a n a ttr ib u te in a n e w a ttr ib u te s ob je ct, in th is c a s e p t h r e a d _ p r o c e s s _ p r i v a t e ) is in d ic a te d b y s h o w in g th e n a m e in b old . T h e re fe re n ce s e n try (5) gives c ro s s -re fe re n c e s to th e p rim a ry s e c tio n s of th is b o o k t h a t d is c u s s th e in te rfa c e , o r o th e r clo sely re la te d in te rfa c e s . T h e h e a d e rs e n try (6) s h o w s th e h e a d e r files n e e d e d to co m p ile co d e u s in g th e fu n c tio n . If m o re th a n o n e h e a d e r is sh o w n , y o u n e e d all o f th e m . T h e e rrors e n try (7) d e s c rib e s e a c h of th e p o s sib le e rro r n u m b e r s r e tu r n e d b y th e in te rfa c e ; B e c a u s e P th r e a d s d is tin g u is h e s b e tw e e n m a n d a to ry e rro r d e te c tio n (“if o c c u r s ” in POSIX te rm s) a n d o p tio n a l e rro r d e te c tio n (“if d e te c te d ” in POSIX te rm s), th e e rro rs t h a t a n in te rfa c e m u s t re p o r t (if th e y o ccu r) a re s h o w n in bo ld (see S e c tio n 9 .3 .1 for d e ta ils o n P th r e a d s erro rs). T h e h in t e n try (8) gives a sin g le , a n d in e v ita b ly ov ersim p lified , p h ilo so p h ic a l c o m m e n t re g a rd in g th e in te rfa c e . S o m e h in ts p o in t o u t c o m m o n e rro rs in u s in g th e in te rfa c e ; o th e rs d e s c rib e s o m e th in g a b o u t th e d e s ig n e rs ’ in te n d e d u s e o f th e in te rfa c e , o r so m e fu n d a m e n ta l re s tric tio n o f th e in terface. In pthread_mutexattr_ getpshared, for ex am p le, th e h in t p o in ts o u t t h a t a m u te x c re a te d to b e “p ro c e s s s h a r e d ” m u s t b e allo cated in s h a re d m e m o ry t h a t ’s a c c e ssib le b y all p a rtic ip a tin g p ro c e sse s. processes hared

9.3.1

Error d e te c tio n a n d re p o rtin g T h e POSIX s ta n d a r d d is tin g u is h e s c a re fu lly b e tw e e n tw o c a te g o rie s o f erro r: 1. M a n d a to ry (“if o c c u r s ”) e rro rs involve c irc u m s ta n c e s b e y o n d th e c o n tro l of th e p ro g ra m m e r. T h e s e e rro rs m u s t a lw ay s b e d e te c te d a n d re p o rte d b y th e s y s te m u s in g a p a r tic u la r e rro r co de. If y o u c a n n o t c re a te a n e w th r e a d b e c a u s e y o u r p ro c e s s la c k s s u ffic ie n t v irtu a l m em o ry , th e n th e im p le m e n ta tio n m u s t alw ay s te ll y o u . You c a n ’t p o s sib ly b e e x p e c te d to c h e c k w h e th e r th e r e ’s e n o u g h m e m o ry b efo re c re a tin g th e th r e a d —for o n e th in g , y o u h a v e n o w ay to k n o w h o w m u c h m e m o ry w o u ld b e re q u ire d . 2. O p tio n a l (“if d e te c te d ”) e rro rs a re p ro b le m s t h a t a re u s u a lly y o u r m is ta k e . You m ig h t try to lo ck a m u te x t h a t h a d n ’t b e e n in itia lize d , for ex a m p le , o r try to u n lo c k a m u te x t h a t ’s lo c k ed b y a n o th e r th re a d . S o m e s y s te m s m a y

P O S I X 1 0 0 3 . l c -1 9 9 5 i n t e r f a c e s

311

n o t d e te c t th e s e e rro rs , b u t th e y ’re still e rro rs in y o u r co de, a n d y o u o u g h t to b e ab le to av oid th e m w ith o u t h e lp from th e sy ste m . W hile it w o u ld b e “n ic e ” for th e s y s te m to d e te c t o p tio n a l e rro rs a n d r e tu r n th e a p p ro p ria te e rro r n u m b e r, s o m e tim e s it ta k e s a lo t o f tim e to c h e c k o r is d ifficu lt to c h e c k reliab ly . It m a y b e ex p en siv e , fo r ex am p le, fo r th e s y s te m to d e te rm in e th e id e n tity o f th e c u r r e n t th re a d . S y s te m s m a y th e re fo re n o t re m e m b e r w h ic h th r e a d lo ck ed a m u te x , a n d w o u ld b e u n a b le to d e te c t t h a t th e u n lo c k w a s erro n e o u s . It m a y n o t m a k e s e n s e to slow d o w n th e b a s ic s y n c h ro n iz a tio n o p e ra tio n s for c o rre c t p ro g ra m s j u s t to m a k e it a little e a s ie r to d e b u g in c o rre c t p ro g ra m s . S y s te m s m a y p ro v id e d e b u g g in g m o d e s w h e re so m e o r all of th e o p tio n a l e rro rs a re d e te c te d . D ig ital UNIX, for ex am p le, p ro v id es “e rro r c h e c k ” m u te x e s a n d a “m e te re d ” e x e c u tio n m o d e, w h e re th e o w n e rs h ip of m u te x e s is alw ay s tra c k e d a n d o p tio n a l e rro rs in lo c k in g a n d u n lo c k in g m u te x e s a re re p o rte d . T h e UNIX98 s p e c ific a tio n in c lu d e s “e rro r c h e c k ” m u te x e s (S ectio n 10.1 .2), so th e y w ill so o n b e a v a ila b le o n m o s t UNIX s y ste m s .

9 .3 .2

Use o f v o i d * ty p e ANSI C r e q u ire s t h a t y o u b e allo w ed to c o n v e rt a n y p o in te r ty p e to v o id * a n d b a c k , w ith th e r e s u lt b e in g id e n tic a l to th e o rig in a l v a lu e . However, ANSI C d o e s n o t re q u ire th a t all p o in te r ty p e s h a v e th e s a m e b in a ry r e p re s e n ta tio n . T h u s , a lo n g * th a t y o u c o n v e rt to v o id * in o rd e r to p a s s in to a th r e a d ’s s t a r t ro u tin e m u s t a lw a y s b e u s e d a s a lo n g * , n o t a s , for e x a m p le , a c h a r* . In a d d itio n , th e r e s u lt o f c o n v e rtin g b e tw e e n p o in te r a n d in te g e r ty p e s is “im p le m e n ta tio n d e fin e d .” M ost s y s te m s s u p p o r tin g UNIX w ill allo w y o u to c a s t a n in te g e r v a lu e to v o id * a n d b a c k , a n d to m ix p o in te r ty p e s —b u t b e a w a re t h a t th e co d e m a y n o t w o rk o n all s y ste m s . S o m e o th e r s ta n d a r d s , n o ta b ly th e POSIX. l b re a ltim e s ta n d a r d , h a v e solv ed th e s a m e p ro b le m (th e n e e d for a n a r g u m e n t o r s tr u c t u r e m e m b e r t h a t c a n ta k e a n y ty p e value) in d iffe re n t w ay s. T h e sigevent s tr u c t u r e in POSIX. l b , for ex am pie, in c lu d e s a m e m b e r t h a t c o n ta in s a v a lu e to b e p a s s e d in to a s ig n a l-c a tc h in g fu n c tio n , called sigev_value. In s te a d o f d efin in g sigev_value a s a void*, how ever, a n d rely in g o n th e p ro g ra m m e r to p ro v id e p ro p e r ty p e c a s tin g , th e sigev_ value m e m b e r is a union sigval, c o n ta in in g o v erlay ed int a n d void* m e m b e rs. T h is m e c h a n is m av o id s th e p ro b le m of c o n v e rtin g b e tw e e n in te g e r a n d p o in te r ty p e s, e lim in a tin g o n e of th e c o n flic ts w ith ANSI C g u a r a n te e s .

9 .3 .3

T hread s T h re a d s p ro v id e co n cu rre n cy , th e a b ility to h a v e m o re t h a n o n e “s tr e a m of e x e c u tio n ” w ith in a p ro c e s s a t th e s a m e tim e . E a c h th r e a d h a s its o w n h a rd w a re re g is te rs a n d s ta c k . All th r e a d s in a p ro c e s s s h a r e th e full v irtu a l a d d r e s s s p a c e , p lu s all file d e s c rip to rs , sig n a l a c tio n s , a n d o th e r p ro c e s s re s o u rc e s .

312

|

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

p th re a d _ a ttr _ d e s tr o y

int pthread_attr_destroy ( pthread_attr_t *attr);

D estroy a th re a d a ttrib u te s object. The object c a n no longer be u sed . R eferences: H eaders: Errors: Hint:

|

2, 5.2.3 < p th re a d .h > [EINVAL] a t t r is invalid. Does n o t affect th re a d s created u sin g a t t r .

p t h r e a d _ a tt r _ g e t d e t a c h s t a t e

i n t p th re a d _ a ttr_ g e td e ta c h s ta te ( co n st p th re a d _ a ttr_ t * a ttr, in t * d e ta c h s ta te ); D eterm ine w h eth er th re a d s crea ted w ith a t t r will r u n d etached. d a t& e h s ta td

pthread_create__j0inable

T hread ID is valid, m ust be joined.

PTHREAD j:reate_dbtached

H ire ad ID is invalid, cannot be joined, canceled, or modified.

R eferences: H eaders: Errors: Hint:

|

2, 5.2.3 < p th re a d .h > [EINVAL] a t t r is invalid. You c a n ’t jo in or cancel d etach ed th re a d s.

p t h r e a d _ a t t r _ g e t s t a c k a d d r ...........

...................................... [ _ p o s 1x j THREAD ATTR_STACKADDR]

i n t p th re a d _ a ttr_ g e ts ta c k a d d r ( c o n s t p th r e a d _ a tt r _ _ t * a ttr, v o id * * s ta c k a d d r); D eterm in e th e a d d re ss of th e s ta c k on w hich th re a d s crea ted w ith a t t r will ru n . R eferences: H eaders: E rrors:

2, 5.2.3 < p th re a d .h >

Hint:

C reate only one th re a d for each sta c k ad d ress!

[EINVAL] attr is invalid. [ENOSYS] stacksize n o t su p p o rted .

313

P O S I X 1 0 0 3 . 1 c -1 9 9 5 i n t e r f a c e s

| ^ th r e a d ^ a tt r ^ g e t s t a c k s iz © ............................ [_posixjTHREAD ATTR STACKSIZE]

int pthread_attr_getstacksize const pthread__attr_t size_t

( *attr, *stacksize);

D eterm ine th e size of th e sta c k on w hich th re a d s created w ith a t t r will ru n .

|

References: H eaders: Errors:

2, 5.2 .3 < p th re a d .h >

Hint:

Use on newly created a ttrib u te s object to find th e defau lt sta c k size.

[EINVAL] attr invalid. [ENOSYS] stacksize not supported.

p th r e a d _ a ttr _ in it

in t p th re a d _ a ttr_ in it ( p th r e a d _ a ttr _ _ t

* a ttr);

Initialize a th re a d a ttrib u te s object w ith defau lt a ttrib u te s. R eferences: H eaders: Errors: H int:

|

2, 5.2.3 < p th re a d .h > [ENOMEM] insufficien t m em ory for a t t r . Use to define th re a d types.

p t h r e a d _ a ttr _ s e td e ta c h s ta te

int pthread_attr_setdetachstate ( pthread_attr_t *attr, int detachstate); Specify whether threads created with attr will run d e t a c h e d . datachstate

pt h wba d _c h e a t e _ j o in a b l e

T h read ID is valid* m u s t b e join ed .

p t h r e a d _c r e a t e _ d b t a c h e d

T h re a d ID is invalid, c a n n o t be join ed , canceled, o r modified.

R eferences: H eaders: E rrors: Hint:

2, 5.2.3 < p th re a d .h > [e i n v a l ] a t t r invalid. [EINVAL] d e t a c h s ta t e invalid. You c a n ’t jo in or cancel d etach ed th rea d s.

314

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

p t h r e a d _ a tt r _ s e ts t a c k a d d r ........................... [_posix_thread_attr_stackaddr]

in t p th re a d _ a ttr_ s e ts ta c k a d d r ( p th re a d _ a ttr_ t * a ttr , v o id * s ta c k a d d r); T h re a d s crea ted w ith a t t r will ru n on th e s ta c k sta rtin g a t s ta c k a d d r. M u st be a t le a st p t h r e a d _ s t a c k _ m i n bytes. R eferences: H eaders: E rrors: Hint:

|

2, 5.2.3 < p th r e a d . h> [EINVAL] a t t r invalid. [ENOSYS] s ta c k a d d r n o t su p p o rted . C reate only one th re a d for eac h sta c k a d d re ss, a n d be care fu l of sta c k alignm en t.

p t h r e a d _ a tt r _ $ e ts ta c k s iz e ...............................................

[_POSIX_THREAD_ATTR_STACKSIZE]

in t p th re a d _ a ttr_ s e ts ta c k s iz e ( p t h r e a d _ a t t r _ t *a t t r , s iz e _ t s ta c k s iz e ); T h rea d s crea ted w ith a t t r will r u n on a s ta c k of a t le a st s t a c k s i z e by tes. M ust be a t le a st p t h r e a d __s t a c k _ m i n bytes. R eferences: H eaders: E rro rs:

Hint:

2, 5.2.3 < p th re a d .h > [EINVAL] a t t r or s t a c k s i z e invalid. [EINVAL] s t a c k s i z e too sm all or too big. [ENOSYS] s t a c k s i z e n o t su p p o rted . F ind th e d efau lt first ( p th r e a d _ a ttr _ g e ts ta c k s iz e ) , th e n in c re ase by m ultiplying. Use only if a th re a d n e e d s m ore th a n th e default.

p t h r e a d _ c r e a te

i n t p th re a d _ c re a te ( p th re a d _ t c o n st p th re a d _ a ttr_ t v o id v o id

* tid , * a ttr, * (* s ta rt) * arg );

( v o id * ) ,

C reate a th re a d ru n n in g th e s ta rt functio n, essen tially a n a sy n c h ro n o u s call to th e fu n ctio n s ta r t w ith a rg u m e n t v alue arg . The a t t r a rg u m e n t specifies optio nal creatio n a ttrib u te s, a n d th e id entification of th e new th re a d is re tu rn e d in t i d . R eferences: H eaders: E rrors: Hint:

2, 5.2.3 < p th r e a d . h> [EINVAL] a t t r invalid. [EA6AIN] in su fficien t reso u rces. All re so u rc e s needed by th re a d m u s t alread y be initialized.

315

P O S I X 1 0 0 3 .1 c -1 9 9 5 i n t e r f a c e s

p th re a d _ d e ta c h

int pthread_detach pthread_t

( t h r e a d );

D etach th e th re a d . Use th is to d e ta c h th e m a in th re a d or to “ch an g e y o u r m in d ” afte r crea tin g a jo in ab le th re a d in w hich you are no longer in terested . R eferences: H eaders: E rrors: H int:

|

2, 5.2 .3 < p th re a d .h > [EINVAL] th r e a d is n o t a jo in ab le th rea d . [ESRCH] no th re a d could be found for ID th re a d . D etached th re a d s c a n n o t be jo in ed or canceled; sto rag e is freed im m ediately on te rm in atio n .

p th r e a d .e q u a l

int pthread_equal ( pthread__t pthread_t

tl, t 2 );

R e tu rn value 0 if t l a n d t2 a re equal, otherw ise re tu r n nonzero. R eferences: H eaders: H int:

|

2, 5.2.3 < p th re a d .h > C om pare p th r e a d _ s e lf a g a in st sto red th re a d identifier.

p t h r e a d .e x it

int pthread_exit ( void

*value_ptr);

T erm in ate th e calling th r e a d , re tu rn in g th e value v a lu e _ p tr to an y jo in in g th rea d . R eferences: H eaders: H int:

I

2, 5.2.3 < p th re a d .h > v a lu e _ p tr is tre a te d a s a value, n o t th e a d d re s s of a value.

p th r e a d J o i n

i n t p th re a d _ jo in ( p th re a d _ t v o id

th re a d , * * v a lu e _ p tr);

W ait for th r e a d to te rm in ate, a n d r e tu r n th re a d ’s exit v alu e if v a lu e _ p tr is n o t n u l l .This also d e ta c h e s th r e a d on su ccessfu l com pletion. R eferences: H eaders: E rrors:

H int:

2, 5.2 .3 < p th re a d .h > [EINVAL] th r e a d is n o t a jo in ab le th rea d . [ESRCH] no thread could be found for ID thread. [e d e a d l k ] a tte m p t to jo in w ith self. D etached th re a d s c a n n o t be jo in ed or canceled.

316

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

p th re a d _ s e lf

pthread_t pthread_self

(void);

R e tu rn th e calling th re a d ’s ID. R eferences: H eaders: Hint:

2, 5.2.3 < p th re a d .h > Use to se t th re a d ’s sch ed u lin g p a ra m e te rs.

s c h e d _ y ie ld

int sched_yield (void);

M ake th e calling th re a d ready , afte r o th e r re ad y th re a d s of th e sam e priority, an d select a new th re a d to ru n . This c a n allow co o p eratin g th re a d s of th e sam e priority to s h a re p ro cesso r re so u rc e s m ore equ itab ly, especially on a un ip ro cesso r. This fu n ctio n is from POSIX. lb (realtim e ex tensio ns), a n d is declared in < sched.h > . It re p o rts erro rs by settin g th e re tu rn value to -1 a n d sto rin g a n erro r code in e rrn o . R eferences: H eaders: E rrors: Hint:

9 .3 .4

2, 5.2.3 < sch ed .h > [ENOSYS] sched_yieId n o t su p p o rted . U se before locking m u tex to red u ce c h a n c e s of a tim eslice w hile m u tex is locked.

M u te x e s M u te x e s p ro v id e s y n ch ro n iz a tio n , th e ab ility to c o n tro l h o w th r e a d s s h a r e r e s o u rc e s . You u s e m u te x e s to p re v e n t m u ltip le th r e a d s fro m m o d ify in g s h a r e d d a ta a t th e s a m e tim e, a n d to e n s u r e t h a t a th r e a d c a n re a d c o n s is te n t v a lu e s for a s e t of r e s o u r c e s (for e x am p le, m em ory) t h a t m a y b e m odified b y o th e r th r e a d s .

p th r e a d _ m u te x a ttr _ d e s tr o y

i n t p th r e a d _ _ m u te x a ttr _ d e s tr o y ( p th re a d _ m u te x a ttr_ t * a ttr); D estroy a m u tex a ttrib u te s object. The object c a n no longer b e u sed . References: H eaders: E rrors: Hint:

3.2, 5.2.1 < p th re a d .h > [EINVAL] attr invalid.

D oes n o t affect m u tex es crea ted u sin g a t t r .

317

P O S I X 1 0 0 3 .1 c - 1 9 9 5 i n t e r f a c e s

p t h r e a d j n u t e x a t t r _ g e t p s h a r e d ....................... [__posix_threadj?rocess jshared ] in t

p th r e a d _ m u te x a ttr _ g e tp sh a r e d co n st

(

p th r e a d _ m u te x a ttr _ t

in t

* a ttr , * p sh a r e d );

D e te r m in e w h e th e r m u te x e s c r e a te d w ith a t t r c a n b e s h a r e d b y m u ltip le p r o c e s s e s .

pshared PTHREAD_PROCESS_SHARED

M ay b e s h a re d if in s h a re d m em ory.

PTHREAD_PROCESS_PRIVATE

C an n o t be sh a re d .

R eferences: H eaders: E rrors: Hint:

3.2, 5.2.1 < p th r e a d . h> [e i n v a l ] a t t r invalid. p s ha re d m u tex es m u s t be allocated in s h a re d m em ory.

p t h r e a d _ m u t e x a t t r jn it

int pthread_mutexattr_init ( pthread_mutexattr_t

*attr);

Initialize a m u tex a ttrib u te s object w ith d efau lt a ttrib u te s. R eferences: H eaders: E rro rs: H int:

3.2, 5.2.1 < p th re a d .h > [EN0MEM] in sufficient m em ory for attr. Use to define m u tex types.

p t h r e a d _ m u te x a t tr _ $ e t p s h a r e d ........................ [_posix_thread_process_shared ]

int pthread_mutexattr_setpshared ( pthread_mutexattr_t *attr, int pshared);

M utexes created w ith a t t r c an be sh ared betw een processes if th e p th read _ m u tex _ t variable is allocated in m em ory sh ared by th e processes. pshared PTHREAD_PR0CESSJ5 HARED

May be s h a re d if in sh a re d m em ory.

PTHREAD_PROCESS_PRIVATE

C a n n o t b e sh a re d .

R eferences: H eaders: Errors: Hint:

3.2, 5.2.1 < p th re a d .h > [EINVAL] attr or detachstate invalid. ps ha re d

m u tex es m u s t be allo cated in s h a re d m em ory.

318

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

1 p th r e a d _ m u te x _ d e s tr o y

i n t p t h r e a d m utex d e s t r o y p th r e a d _ m u te x _ t

(

* m u tex ) ;

D estroy a mutex th a t you no longer need. R eferences: H eaders: E rrors: Hint:

3.2, 5.2.1 < p th re a d .h > [EBUSY] mutex is in u se. [EINVAL] mutex is invalid. S afest afte r u n lo ck in g mutex, w h en no o th e r th re a d s will lock.

1 p th r e a d _ m u te x _ in it

i n t p t h r e a d m utex i n i t ( p t h r e a d m utex t c o n s t p th re a d m u te x a ttr t

*m utex. * a ttr);

Initialize a mutex. Th e a t t r arg u m e n t specifies optional crea tio n a ttrib u te s. R eferences: H eaders: E rrors:

Hint:

3.2, 5.2.1 < p th r e a d . h> [EAGA1N] in sufficient re so u rc e s (other th a n memory). [EN0MEM] in su fficien t m em ory. [EPERM] no privilege to perfo rm operatio n. [EBUSY] mutex is alread y initialized. [EINVAL] a t t r is invalid. U se sta tic initialization in ste ad , if possible.

p th r e a c l_ m u te x J o c k

int pthread_mutex_lock ( pthread_mutex_t

*mutex);

Lock a mutex. If th e mutex is c u rre n tly locked, th e calling th re a d is blo ck ed u n til m u tex is un lo cked . O n re tu rn , th e th re a d ow ns th e m u te x u n til it calls p th re a d _ mutex__unlock.

R eferences: H eaders: E rrors:

Hint:

3.2, 5.2.1

[EINVAL] th re a d prio rity exceeds m u tex priority ceiling. [EINVAL] mutex is invalid. [e d e a d l k ] calling thread already ow n s mutex.

Always u n lo c k w ith in th e sam e th re a d .

319

P O S I X 1 0 0 3 . 1 c -1 9 9 5 i n t e r f a c e s

J p t h r e a c L m u t e x J r y lo c k

int pthread_mutex_trylock ( pthread_mutex_t

* mutex);

Lock a mutex. If th e mutex is cu rre n tly locked, r e tu r n s im m ed iately w ith e b u s y .O th ‫׳‬ erwise, calling th re a d becom es ow ner u n til it u n lo ck s. R eferences: H eaders: E rrors:

3.2, 5.2.1 < p th re a d .h > [ E I N V A L ] th re a d priority exceeds m u tex priority ceiling. [e b u s y ] m u t e x i s a l r e a d y lo c k [EINVAL] mutex is invalid. [ e d e a d lk

H int:

] c a llin g

th r e a d

ed .

a lr e a d y

o w n s m u te x .

Always u n lo c k w ith in th e sam e th re a d .

p t h r e a d _ m u te x _ u n lo c k

i n t p th re a d _ m u te x _ u n lo c k ( pthread__mutex_t

*mutex);

U nlock a mutex. The m u te x becom es unow ned . If any th re a d s are w aiting for th e m utex, one is aw ak en ed (sch ed uling policy s c h e d _ f i f o a n d s c h e d _ r r policy w aite rs are ch o sen in priority order, th e n an y o th e rs a re ch o sen in unspecified order). References: H eaders: E rro rs:

3.2, 5.2.1 < p th r e a d . h> [EINVAL] m utex is invalid. [EPERM] calling th re a d does n o t own mutex. Always u n lo ck w ith in th e sam e th re a d .

H int:

9 .3 .5

C o n d itio n v a ria b le s C o n d itio n v a ria b le s p ro v id e co m m u n ica tio n , th e a b ility to w a it fo r so m e s h a r e d r e s o u rc e to r e a c h so m e d e s ire d s ta te , o r to sig n a l t h a t it h a s re a c h e d so m e s ta te in w h ic h a n o th e r th r e a d m a y b e in te re s te d . E a c h c o n d itio n v a ria b le is clo sely a s s o c ia te d w ith a m u te x t h a t p r o te c ts th e s ta te o f th e re s o u rc e .

p th r e a d _ c o n d a ttr _ d e $ tr o y

i n t p th re a d _ c o n d a ttr_ d e s tro y p th r e a d _ c o n d a ttr _ _ t

( * a ttr);

D estroy a co n d itio n v ariab le a ttrib u te s object. The object can n o longer be u sed . R eferences: H eaders: E rro rs: Hint:

3.3, 5 .2 .2 < p th r e a d . h> [EINVAL] a t t r invalid. Does n o t affect co ndition v aria b les c rea ted u sin g a t t r .

320

|

CH A P T E R 9

p th r e a d _ c o n d a t t r _ g e t p s h a r e d ...............................

P O S I X t h r e a d s m i n i -r e f e r e n c e

[_POSIX_THREAD_PROCESS_SHARED]

int pthread_condattr_getpshared ( const pthread_condattr_t int

*attr, *pshared);

D eterm in e w h e th e r co ndition variables crea ted w ith a t t r c a n be sh a re d by m ultip le pro cesses. pshared PTHREAD_PROCESS_SHARED

May b e s h a re d if in s h a re d m em ory.

PTHREAD__PROCESS_PRIVATE

C a n n o t b e sh a re d .

References: H eaders: E rrors: Hint:

3.3, 5.2.2 < p th re a d .h > [EINVAL] a t t r invalid. p s ha re d condition v aria b les m u s t be allocated in sh a re d m em ory a n d u s e d w ith p s ha re d m utexes.

p th r e a d _ c o n d a ttr _ in it

int pthread_condattr_init ( pthread_condattr_t

*attr);

Initialize a condition variable a ttrib u te s object w ith d efau lt a ttrib u te s. R eferences: H eaders: E rrors: Hint:

3.3, 5.2.2 < p th re a d .h > [ENOMEM] insufficient m em ory for a t t r . Use to define condition variable types.

p t h r e a d _ c o n d a t tr _ $ e tp s h a r e d ............................................... [_posix_thread_process_shared ]

i n t p th r e a d _ _ c o n d a ttr _ s e tp s h a r e d ( p th re a d _ c o n d a ttr_ t * a ttr, in t p sh ared ); C ond ition v aria b les created w ith a t t r c a n be sh a re d betw een p ro cesses if th e p th re a d _ c o n d _ t varia ble is allocated in m em ory sh a re d by th e pro cesses. pshared pthread_process_shared

M ay b e s h a re d if in s h a re d m em ory.

PT&R&AI) PROCESS PRIVATE

C an n o t be sh a re d .

321

P O S I X 1 0 0 3 . 1 c -1 9 9 5 i n t e r f a c e s

References: H eaders: E rrors: Hint:

I

3.3, 5.2.2 < p th re a d .h > [EINVAL] a t t r or d e t a c h s t a t e invalid. p s ha re d condition v aria b le s m u s t be allocated in sh a re d m em ory a n d u se d w ith p s ha re d m utexes.

p t h r e a d _ c o n d _ d e s tr o y

i n t p t h r e a d co n d d e s t r o y p t h r e a d co n d t

(

* c o n d );

D estroy co ndition variable cond th a t you no lon ger need. R eferences: H eaders: E rrors: H int:

3.3, 5.2.2 < p th re a d .h > [EBUSY] cond is in u se. [EINVAL] cond is invalid. S afest afte r w ak eu p from cond, w h en no o th e r th re a d s will w ait.

1 p th r e a d _ c o n d J n it

i n t p t h r e a d co n d i n i t ( p t h r e a d co n d t c o n s t p th re a d c o n d a ttr t

* co n d , * a ttr);

Initialize a co ndition variable cond. The a t t r a rg u m e n t specifies op tional creatio n a ttrib u te s. R eferences: H eaders: Errors:

H int:

3.3, 5.2 .2 < p th re a d .h > [EAGA1N] in su fficien t re so u rc e s (other th a n m emory). [enomem] in su fficien t m em ory. [EBUSY ] cond is alread y initialized. [EINVAL] a t t r is invalid. U se s ta tic in itializatio n in ste ad , if possible.

p th r e a d _ c o n d _ b r o a d c a s t

int pthread__cond_broadcast ( pthread__cond_t

*cond);

B ro ad ca st condition v aria ble cond, w aking all c u rre n t w aiters. R eferences: H eaders: E rrors: Hint:

3.3, 5.2.2 < p th re a d .h > [EINVAL] cond is invalid. Use w h en m ore th a n one w aiter m ay resp o n d to p red ic ate ch an g e or if an y w aiting th re a d m ay n o t be able to resp o n d .

322

|

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

p th r e a d _ c o n d _ s ig n a l

i n t p th r e a d _ c o n d _ s ig n a l ( p th r e a d _ c o n d _ t

* c o n d );

Signal condition variable cond, w aking one w aiting th read . If s c h e d _ f i f o or s c h e d _ r r policy th re a d s a re w aiting, th e h ig h est-p rio rity w aiter is aw akened. O therw ise, a n u nspecified w aiter is aw ak en ed. R eferences: H eaders: E rro rs: H int:

3.3, 5.2.2 < p th re a d .h > [EINVAL] cond is invalid. U se w h en an y w aiter c a n resp o n d , a n d only one need resp o n d . (All w aiters a re equal.)

p t h r e a d _ c o n d J im e d w a it

i n t p th r e a d _ c o n d _ tim e d w a it ( p th r e a d _ c o n d _ t p th r e a d _ m u te x _ t c o n s t s t r u c t tim e s p e c

* co n d , * m utex , * a b s ti m e ) ;

W ait on co ndition variable cond, u n til aw ak en ed by a sig nal or b ro a d c a st, or u n til th e a b so lu te tim e a b stim e is reach ed .

|

R eferences: H eaders: E rrors:

3.3, 5.2.2 < p th re a d .h >

Hint:

M utex is alw ays un lo ck ed (before wait) a n d relocked (after wait) in sid e p th re a d _ c o n d _ tim e d w a it, even if th e w ait fails, tim es out, or is canceled .

[ETIMEDOUT] tim e specified by a b stim e h a s p assed . [EINVAL] cond, mutex, or a b stim e is invalid. [e i n v a l ] different m u tex es for c o n c u rre n t w aits. [e i n v a l ] m u tex is n o t ow ned by calling th re a d .

p t h r e a d _ c o n d _ w a it

i n t p th r e a d _ c o n d _ w a it ( p th r e a d _ c o n d _ t p t h r e a d m utex t

* co n d , * m u tex ) ;

W ait on condition varia ble cond, u n til aw ak en ed by a signal or b ro a d c a st. R eferences: H eaders: E rrors:

Hint:

3.3, 5.2.2 < p th re a d .h > [EINVAL] cond or mutex is invalid. [EINVAL] d ifferent m u tex es for c o n c u rre n t w aits. [EINVAL] m u tex is n o t ow ned by calling th re a d . M utex is alw ays un lo ck ed (before wait) a n d relocked (after wait) inside p th r e a d cond w a it, even if th e w ait fails or is canceled.

P O S I X 1 0 0 3 . 1 c -1 9 9 5 i n t e r f a c e s

9 .3 .6

323

C a n c e lla tio n C a n c e lla tio n p ro v id e s a w ay to r e q u e s t t h a t a th r e a d te rm in a te “g ra c e fu lly ” w h e n y o u n o lo n g e r n e e d it to co m p le te its n o rm a l e x e c u tio n . E a c h th r e a d c a n c o n tro l h o w a n d w h e th e r c a n c e lla tio n a ffects it, a n d c a n r e p a ir th e s h a r e d s ta te a s it te rm in a te s d u e to c a n c e lla tio n .

p th re a c L c a n c e l

i n t p th r e a d _ c a n c e l ( p th re a d _ _ t

th re a d );

R eq u ests th a t th r e a d be canceled. R eferences: H eaders: E rro rs: H int:

5.3 < p th re a d .h > [ESRCH] no th r e a d found co rresp o n d in g to th r e a d . C an ce llation is a sy n ch ro n o u s. Use pthread_join to w ait for term in a tio n of th r e a d if necessary .

p t h r e a d _ c le a n u p _ p o p

v o id p th re a d _ c le a n u p _ _ p o p ( i n t e x e c u t e ) ; Pop th e m o st recently p u s h e d clean u p handler. Invoke th e clean u p h a n d le r if exec u te is nonzero. References: H eaders: Hint:

5.3 < p th re a d .h > Specify e x e c u te a s non zero to avoid d u p licatio n of com m o n clean u p code.

p th r e a d _ c le a n u p _ p u s h

v o id p th re a d _ _ c le a n u p _ p u sh ( v o id ( * r o u t i n e ) ( v o id * ) , v o id * a rg ); P u sh a new clean u p h a n d le r on to th e th re a d ’s s ta c k of c le a n u p h a n d le rs. Invoke th e clean u p h a n d le r if execute is nonzero . E ac h clean u p h a n d le r p u s h e d onto th e s ta c k is pop ped a n d invoked w ith th e a rg u m e n t arg w h en th e th re a d exits by calling pthread_exit, w h en th e th re a d a c ts on a can cellatio n req u est, or w h en th e th re a d calls pthread_cleanup_pop w ith a non zero execute arg u m e n t. R eferences: H eaders: H int:

5.3 < p th re a d .h > pthread_cleanup_push a n d pthread_cleanup_pop m u s t be p aired

in th e sam e lexical scope.

324

|

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

p t h r e a d .s e t c a n c e ls t a t e

int pthread_setcancelstate ( int state, int *oldstate);

A tom ically se t th e calling th re a d ’s cancelability sta te to s t a t e a n d r e tu r n th e previous cancelab ility s ta te a t th e location referen ced by o l d s t a t e . state, oldstate FTHREAD_CANCEL_EHABl>E

Cancellation is enabled.

PTHREAD_CAHCEL_DISABLE

Cancellation is disabled.

R eferences: H eaders: E rro rs: Hint:

5.3 < p th re a d .h > [EINVAL] state is invalid. Use to disable can cellatio n a ro u n d “ato m ic” code th a t in clu d es can* cellation poin ts.

p t h r e a d .s e t c a n c e lt y p e

int pthread_setcanceltype ( int type, int *oldtype);

A tom ically se t th e calling th re a d ’s cancelability type to ty p e an d re tu r n th e previo u s cancelab ility type a t th e location referen ced by o ld ty p e . type, oldtype pthrbad_canccXi_jd&fer&ed

Only deferred cancellation is allowed.

pthread_cancel^astochkonous Asynchronous cancellation is allowed.

R eferences: H eaders: E rrors: Hint:

5.3 < p th re a d .h > [EINVAL] ty p e is invalid. U se w ith c au tio n —m o st code is n o t safe for u s e w ith a sy n c h ro n o u s cancelab ility type.

P O S I X 1 0 0 3 . l c -1 9 9 5 i n t er f a c es

325

p th r e a d J e s t c a n c e l

void pthread_testcancel

(void);

C reates a deferred can cellatio n p o in t in th e calling th rea d . The call h a s no effect if th e c u rre n t cancelability s ta te is p t h r e a d _ c a n c e l __d Is a b l e . R eferences: H eaders: Hint:

9 .3 .7

5.3 < p th re a d .h > C an cellation is a sy n c h ro n o u s. U se p th r e a d _ jo in to w ait for term in a tio n of th re a d if n ecessary .

T h re a d -s p e c ific d a ta T h re a d -sp e c ific d a ta p ro v id e s a w ay to d e c la re v a ria b le s th a t h a v e a c o m m o n “n a m e ” in all th r e a d s , b u t a u n iq u e v a lu e in e a c h th re a d . You s h o u ld c o n s id e r u s in g th re a d -s p e c ific d a t a in a th r e a d e d p ro g ra m in m a n y c a s e s w h e re a n o n th r e a d e d p ro g ra m w o u ld u s e “s ta tic ” d a ta . W h e n th e s ta tic d a ta m a in ta in s co n te x t a c ro s s a s e rie s of c a lls to so m e fu n c tio n , for ex am p le, th e c o n te x t s h o u ld g e n e ra lly be th re a d -sp e c ific . (If n o t, th e s ta tic d a t a m u s t b e p ro te c te d b y a m u tex .)

|

p th r e a d _ g e t s p e c if ic

v o id * p th r e a d _ _ g e ts p e c if ic ( p th r e a d _ k e y _ t k ey ); R e tu rn th e c u rre n t v alu e of key in th e calling th re a d . If no value h a s b een se t for key in th e th re a d , n u l l is re tu rn e d . R eferences: H eaders: E rro rs: H int:

5.4, 7.2, 7.3.1 < p th re a d .h > The effect of calling p th r e a d _ g e ts p e c if i c w ith a n invalid key is u n defined. No e rro rs a re detected. C alling p th r e a d _ g e ts p e c if i c in a d e s tru c to r fu n ctio n will re tu rn n u l l . U se d e s tru c to r’s a rg u m e n t in ste ad .

p th re a d _ k e y _ c re a te

i n t p th r e a d _ k e y _ c r e a t e ( p th r e a d _ k e y _ t *key, v o id ( * d e s t r u c t o r ) ( v o id * ) ) ; C reate a th read -sp ecific d a ta key visible to all th re a d s. All existing a n d new th re a d s have value n u l l for key u n til s e t u sin g p th re a d _ _ s e ts p e c if ic . W hen an y th re a d w ith a non-NULL value for key te rm in a te s, d e s t r u c t o r is called w ith key’s c u rre n t v alue for th a t th rea d .

326

R eferences: H eaders: Errors: Hint:

|

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

5 .4 , 7 .2 , 7 .3 .1

[EAGA1N] in su fficien t re so u rc e s or p t h r e a d _ k e y s _ m a x exceeded. [EN0MEM] insufficient m em ory to crea te th e key. E ach key (pthread_key_t variable) m u s t be c rea ted only once; u se a m u te x or pthread_once.

p t h r e a d _ k e y .d e le t e

int pthread_ key_delete pthread_key_t

( k e y );

Delete a th read -sp ecific d a ta key. T his do es n o t ch an g e th e value of th e th re a d specific d a ta key for an y th re a d an d does n o t r u n th e key’s d e s tru c to r in an y th re a d , so it sh o u ld be u se d w ith g reat cau tio n . R eferences: H eaders: E rrors: Hint:

|

5 .4

[EINVAL] key is invalid.

U se only w h en you know all th re a d s hav e

null

value.

p t h r e a d _ $ e t$ p e c iflc

int pthread_ setspecific ( pthread_key_t key, const void *value);

A ssociate a th read -sp ecific value w ith in th e calling th re a d for th e specified key. R eferences: H eaders:

Errors:

[ENOMEM] insufficient m em ory.

Hint:

If yo u se t a value of n u l l , th e key’s d e s tru c to r will n o t be called a t th re a d te rm in atio n .

5 .4 , 7 .2 , 7 .3 .1

[EINVAL] key is invalid.

9 .3 .8

R e a ltim e s c h e d u lin g R ealtim e s c h e d u lin g p ro v id e s a p re d ic ta b le re s p o n s e tim e to im p o r ta n t e v e n ts w ith in th e p ro c e s s . N ote t h a t “p re d ic ta b le ” d o e s n o t alw a y s m e a n “f a s t,” a n d in m a n y c a s e s re a ltim e s c h e d u lin g m a y im p o se o v e rh e a d t h a t r e s u lts in slo w er exec u tio n . R e a ltim e s c h e d u lin g is a lso s u b je c t to s y n c h ro n iz a tio n p ro b le m s s u c h a s p rio rity in v e rs io n (S ectio n s 5 .5 .4 a n d 8 .1 .4 ), a lth o u g h P th re a d s p ro v id e s o p tio n a l facilities to a d d r e s s so m e of th e s e p ro b le m s.

327

P O S I X 1 0 0 3 .1 c -1995 i nt er faces

|

p t h r e a d _ a t tr _ g e t in h e r it s c h e d .................... [_posix_thread_priority_scheduling] THREAD PRIORITY SCHEDULING]

in t p th re a d _ a ttr_ g e tin h e rits c h e d ( co n st p th re a d _ a ttr_ t * a ttr, in t * in h e rits c h e d ); D eterm ine w h eth er th re a d s created w ith a t t r will ru n u sin g th e sch ed u lin g policy a n d p a ra m e te rs of th e creato r or th o se specified in th e a ttrib u te s object. The d efau lt in h e r i ts c h e d is im plem en tation-defined. inheritsched PTHREAD_INHBRIT_SCHED

Use c re a to r's sch ed u lin g policy a n d p aram eters.

PTHREADJSXPLICITJ5CHED

U se sch ed u lin g policy a n d p a ra m e te rs in a ttrib u te s object.

References: H eaders: Errors:

5.2.3, 5.5 < p th re a d .h > [ENOSYS] priority sch ed u lin g is n o t su p p o rted . [EINVAL] a t t r invalid.

p th r e a d _ a tt r _ g e ts c h e d p a r a m ................... [_posix_thread_priority__scheduling ]

i n t p th re a d _ a ttr_ g e ts c h e d p a ra m c o n st p th re a d _ a ttr_ t s t r u c t sc h e d _ p a ra m

( * a ttr, * p a ra m );

D eterm ine th e scheduling p a ram eters u se d by th re a d s created w ith a t t r . The defau lt param is im plem en tation defined. R eferences: H eaders: E rrors:

5.2.3, 5.5 < p th re a d .h > [ENOSYS] priority sch ed u lin g is n o t su p p o rted . [EINVAL] a t t r invalid.

p t h r e a d _ a tt r _ g e t s c h e d p o lic y .................... [_posix_thread_priority^scheduling ]

i n t p th re a d _ a ttr_ g e ts c h e d p o lic y ( co n st p th re a d _ a ttr_ t * a ttr, in t * p o lic y ); D eterm ine th e sch ed u lin g policy u se d by th re a d s created w ith a t t r . The default p o lic y is im plem en tatio n defined.

328

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

policy SCHED_FIF0

R u n th re a d u n til it blocks; p reem p t low er' prio rity th re a d s w h e n read y

SCHED_RR

Like SCHED J 1 F O , b u t s u b je c t to periodic tim eslicing.

SCHED_0THER

Im p lem en tatio n defined (may be SCHED_FIFO, SCHED_RR, o r so m eth in g else).

R eferences: H eaders: E rro rs:

5.2.3, 5.5 < p th r e a d . h> [ENOSYS] priority sch ed u lin g is n o t su p p o rted . [EINVAL] a t t r invalid.

p t h r e a d _ a t t r _ g e t $ c o p e .............................[ _ p o s i x _ t h r e a d _ p r i o r i t y _ s c h e d u l i n g ]

int pthread_attr_getscope ( const pthread_attr_t int

*attr, *contentionscope);

D eterm in e th e co n ten tio n scope u se d by th re a d s crea ted w ith a t t r . The d efau lt is im p le m en ta tio n defined. contentionscope

T h re a d c o n te n d s w ith o th e r th re a d s in th e p ro c e ss for proc e sso r reso u rces.

PTHREAD_SCOPE_PROCESS

PTHREAD_SCOPE_SYSTEM

‫׳‬

R eferences: H eaders: E rrors: Hint:

T h rea d co n te n d s w ith th re a d s in all p ro cesses for p ro cesso r reso u rces.

5.2 .3, 5.5 < p th r e a d . h> [ENOSYS] prio rity sch ed u lin g is n o t su p p o rted . [EINVAL] a t t r invalid. Im p lem en tatio n m u s t su p p o rt one or b o th of th e se, b u t need n o t su p p o rt both.

329

P O S I X 1 0 0 3 .l c -1 9 9 5 i n t e r f a c e s

p th r e a d _ a t tr _ s e tin h e r its c h e d .............. ...... [_posix_thread_priority_scheduling]

i n t p th re a d _ a ttr_ s e tin h e rits c h e d ( p th re a d _ a ttr_ t * a ttr, in t in h e rits c h e d ); Specify w h eth er th re a d s created w ith a t t r will ru n u sin g th e scheduling policy an d p aram eters of th e crea to r or th o se specified in th e a ttrib u te s object. W hen you change th e scheduling policy or p a ra m e te rs in a th re a d a ttrib u te s object, you m u s t ch ange th e inherits che d attrib u te from p t h r e a d _ i n h e r i t _ s c h e d to p t h r e a d __ e x p l i c i t _ s c h e d .The defau lt is im plem entation-defined. inheritsched PTHREADJENHERIT^SCHEP

U se c re a to r’s sch ed u lin g policy a n d p a ra m e te rs.

PTHREAD JSXPLICIT_SCHED

U se sc h ed u lin g policy a n d p a ra m e te rs in a ttrib u te s object.

References: H eaders: E rro rs:

|

5.2.3, 5.5 < p th re a d .h > [EN0SYS] priority sch ed u lin g is n o t su p p o rted . [EINVAL] a t t r or in h e r i ts c h e d invalid.

p t h r e a d _ a t t r _ s e ts c h e d p a r a m ................... [_posix_thread_priority_scheduling]

i n t p th r e a d _ a ttr _ _ s e ts c h e d p a r a m ( p th re a d _ a ttr_ t c o n s t s t r u c t s c h e d _ p a ra m

* a ttr, * p a ra m );

Specify th e sch ed u lin g p a ra m e te rs u se d by th re a d s created w ith a t t r . The defau lt param is im p lem en tatio n defined. R eferences: H eaders: E rro rs:

5.2.3, 5.5 < p th re a d .h > [ENOSYS] priority sch ed u lin g is n o t su p p o rted . [EINVAL] a t t r or param invalid. [e n o t s u p ] param se t to su p p o rte d value.

p t h r e a d _ a t t r _ $ e t$ c h e d p o lic y .................... [_posix_thread_priority_scheduling]

in t p th re a d _ a ttr_ s e ts c h e d p o lic y ( p th re a d _ a ttr_ t * a ttr , in t p o lic y ); Specify th e sch ed u lin g policy u se d by th re a d s create d w ith a t t r . The d efau lt p o lic y is im p lem en ta tio n defined.

330

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

policy SCHED_FIFO

R u n th re a d u n til it blo cks; p re e m p t lo w er‫ ־‬p rio rity th re a d s w h en ready.

SCHED_RR

lik e SCHEDJTOFO, b u t su b je c t to periodic tim eslid n g .

SCHEDjOTHER

Im p lem en tatio n defin ed (m ay be SCHEDJFIFO, SCHEDJflR, o r so m eth in g else).

References: H eaders: E rrors:

5.2.3 . 5.5 < p th r e a d . h> [ENOSYS] priority sch ed u lin g is n o t su p p o rted . [EINVAL] a t t r or p o li c y invalid. [EN0TSUP] param set to supported value.

p th r e a d _ a t t r _ $ e t$ c o p e ......................... [_posixjthread_priority_scheduling]

i n t p th re a d _ a ttr_ s e ts c o p e ( p th re a d _ a ttr_ t * a ttr , in t c o n te n tio n s c o p e ); Specify th e co n ten tio n scope u se d by th re a d s crea ted w ith a t t r . The d efau lt is im p lem en ta tio n defined. contentionscope PTHREAD_SCOPE ^PROCESS

T h rea d co n te n d s w ith o th e r th re a d s in th e p ro cess for proc e sso r reso u rces.

PTHRBAD_SCOPE_SYSTEM

T h read c o n te n d s w ith th re a d s in all p ro c e sse s for p ro cesso r reso u rces.

R eferences: H eaders: E rrors:

Hint:

5.2 .3, 5.5 < p th r e a d . h> [ENOSYS] priority sch ed u lin g is n o t su p p o rted . [EINVAL] a t t r or c o n te n tio n s c o p e invalid. [ENOTSUP] c o n te n tio n s c o p e se t to su p p o rte d value. Im p lem en tatio n m u s t su p p o rt one or b o th of th ese, b u t n eed n o t s u p p o rt b oth .

331

P O S I X 1 0 0 3 . 1 c -1 9 9 5 i n t e r f a c e s

p t h r e a d _ g e t $ c h e d p a r a m .......................... [ _ p o s i x _ t h r e a d _ p r i o r i t y _ s c h e d u l i n g ]

i n t p th re a d _ _ g e ts c h e d p a ra m ( p th re a d _ t in t s t r u c t s c h e d _ p a ra m

th re a d , * p o li c y * p a ra m );

D eterm ine th e sch ed u lin g p o lic y an d p a ra m e te rs (param) cu rren tly u se d by th rea d . policy SCHED_FIF0

R u n th re a d u n til it blocks; p re e m p t low er-prio rity th re a d s w h en ready .

SCHED_RR

Like SCHED_FIFO, b u t su b je c t to periodic tim eslicing.

SCHEDJDTHER

Im p lem en tatio n defined (may b e SCHEDJFIFO, SCHED_RR. o r so m eth in g else).

R eferences: H eaders: E rro rs: H int:

I

5.2 .3, 5.5 < p th re a d .h > [ e n o s y s j priority sch ed u lin g is n o t su p p o rted . [ESRCH] th r e a d do es n o t refer to a n existing th re a d . Try to avoid dynam ically m odifying th re a d sch ed u lin g policy an d p a ra m e te rs, if possible.

p t h r e a d _ m u t e x _ g e t p r io c e il in g .............................. [ _ p o s i x j T H R E A D P R I O PROTECT]

i n t p th r e a d _ _ m u te x _ g e tp r io c e ilin g ( c o n s t p th r e a d _ m u te x _ t * m u tex , in t * p rio c e ilin g ); D eterm in e th e priority ceiling a t w hich th re a d s will ru n w hile ow ning mutex. R eferences: H eaders: E rrors: H int:

3.2, 5.2.1, 5.5 .5 < p th r e a d . h> [e n o s y s j priority sc h ed u lin g is n o t su p p o rted . [EINVAL] m u t e x invalid. P rote ct protocol is in a p p ro p riate u n le ss th e c rea to r of th e m u tex also cre a te s a n d co n tro ls all th re a d s th a t m ight lock th e m u tex.

332

|

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

p t h r e a d _ m u te x _ $ e t p r io c e ilin g ...........................[_pos 1 xj THREAD_PRI0 JPROTECT]

int pthread_mutex_getprioceiling ( pthread__mutex_t *mutex, int prioceiling, int *old_ceiling);

Specify th e prio rity ceiling a t w hich th re a d s will r u n w hile ow ning mutex. R e tu rn s previo us priority ceiling for m utex . References: H eaders: E rrors:

3.2, 5.2.1, 5.5 .5 < p th re a d .h > [ENOSYS] priority sch ed u lin g is n o t su p p o rted . [EINVAL] mutex invalid, or prioceiling out of range. [EPERM] no privilege to se t prioceiling.

Hint:

P rote ct protocol is in a p p ro p ria te u n le ss th e c re a to r of th e m u tex also cre a te s a n d co n tro ls all th re a d s th a t m ight lock th e m utex .

p t h r e a d ‫ ״‬m u t e x a t t r _ g e t p r io c e ili n g ....................... [_posix_thread_prio_protect ]

i n t p th re a d _ m u te x a ttr_ _ g e tp rio c e ilin g ( c o n s t p th re a d _ m u te x a ttr_ t in t

* a ttr, * p rio c e ilin g );

D eterm in e th e priority ceiling a t w hich th re a d s will r u n while ow ning a m u te x ereated w ith a t t r . References: H eaders: E rrors: Hint:

3.2, 5.2.1, 5.5 .5 < p th re a d .h > [ENOSYS] priority sch ed u lin g is n o t su p p o rted . [EINVAL] a t t r invalid. P rote ct protocol is in a p p ro p ria te u n le ss th e c re a to r of th e m u tex also c re a te s a n d contro ls all th re a d s th a t m ight lock th e m utex.

p t h r e a d _ m u t e x a ft r _ g e tp r o t o c o l... [_posix_thread_prio_inherit_posix_thread_prio_protect]

i n t p th re a d _ m u te x a ttr_ g e tp ro to c o l ( c o n s t p th re a d _ m u te x a ttr_ t in t

* a ttr, * p r o to c o l);

D eterm in e w h e th e r m u tex es crea ted w ith a t t r hav e priority ceiling protocol (protect), priority in h e rita n c e protocol (inherit), or no priority protocol (none).

P O S I X 1 0 0 3 .l c -1 9 9 5 i n t e r f a c e s

333

protocol PTHREADJ»1H0__1I0NE

No p rio rity in h e rita n c e protocol.

PTHREAD_PRIO_INHERIT

W hile ow ning m u tex , th re a d in h e rits h ig h e st prio rity of a n y th re a d w aitin g for th e m u tex .

p t h r e a d _p r i o _ p r o t e c t

W hile ow ning m u tex , th re a d in h e rits m u te x priority ceiling.

R eferences: H eaders: E rrors:

3.2, 5.2.1, 5.5.5 < p th re a d .h > [e n o s y s ] prio rity sch ed u lin g is n o t su p p o rted .

Hint:

In he rit

[EINVAL] attr invalid.

|

protocol is expensive, a n d p rote ct protocol is in a p p ro p riate u n le ss th e c re a to r of th e m u te x also c re a te s a n d co n tro ls all th re a d s th a t m ig h t lock th e m utex.

p t h r e a d _ m u te x a t tr _ $ e tp r io c e ilin g ......... ..................................... [_pos1x

THREAD PRI0 PROTECT]

int pthread_mutexattr_jsetprioceiling ( pthread_mutexattr_t *attr, int prioceiling);

Specify th e priority ceiling a t w hich th re a d s will ru n w hile ow ning a m u tex created w ith attr. The value of prioceiling m u s t be a valid priority p a ra m e te r for th e SCHED_FIFO policy. References: H eaders: Errors:

Hint:

|

3.2, 5.2.1, 5.5.5

[e n o s y s ] priority sch ed u lin g is n o t su p p o rted . [EINVAL] attr or prioceiling invalid. [EPERM] no permission to set prioceiling. P rote ct protocol is in a p p ro p riate u n le ss th e crea to r of th e m u tex also c rea tes a n d contro ls all th re a d s th a t m ig ht lock th e m utex.

p th r e a d _ m u te x a ttr _ s e tp ro to c o l ‫״ ״‬

(_posix_thread_prio_inherit_posix_thread_prio_protect‫נ‬ int pthread_mutexattr_setprotocol ( pthread_mutexattr_t *attr, int protocol);

Specify w h eth er m u tex es create d w ith a t t r have priority ceiling protocol priority in h e rita n c e protocol (inherit), o r n o priority protocol (none).

(prote ct),

334

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

protocol PTHREAD_PRIOJRONE

No p rio rity in h e rita n c e protocol.

PTHKEAD_PRIO_INHERIT

W hile ow ning m utex, th re a d in h e rits h ig h e st prio rity of an y th re a d w aitin g for th e m utex.

PTHREAD_ PRI0_PR0TECT

W hile ow ning m u tex , th re a d in h e rits m u te x priority ceiling.

R eferences: H eaders: E rrors:

3.2, 5.2.1, 5.5.5 < p th re a d .h > [ENOSYS] priority sch ed u lin g is n o t su p p o rted . [EINVAL] attr or protocol invalid. [ENOTSUP] p r o to c o l value is n o t su p p o rted .

Hint:

In he rit protocol is expensive, a n d p rote ct protocol is in a p p ro p riate u n le ss th e cre a to r of th e m u te x also c re a te s an d co n tro ls all th re a d s th a t m ight lock th e m u tex.

p t h r e a d _ s e t $ c h e d p a r a m ........................[_posix_thread_priority_scheduling]

i n t p th re a d _ _ s e ts c h e d p a ra m ( p th re a d _ t in t c o n s t s t r u c t sc h e d _ p a ra m

th re a d , p o lic y * p a ra m );

Specify th e sch ed u lin g p o lic y a n d p a ra m e te rs (param) to be u se d by th rea d . policy SCHED_FIFO

R u n th re a d u n til it block s; p re e m p t low er-priority th re a d s w h en ready.

SCHED_RR

Like SCHED_FIFO. b u t s u b ‫־‬ je c t to periodic tim eslicing.

SCHED_OTHER

Im p lem en tatio n defined (may be SCHED_FIFO. SCHED_RR, o r so m eth in g else).

R eferences: H eaders: E rrors:

Hint:

5.5 < p th re a d .h > [ENOSYS] priority sch ed u lin g is n o t su p p o rted . [ESRCH] th r e a d do es n o t refer to a n ex isting th re a d . [EINVAL] policy or param is invalid. [ENOTSUP] p o lic y o r param is u n su p p o rte d value. [EPERM] n o p erm issio n to se t p o lic y or param. Try to avoid dynam ically m odifying th re a d sch ed u lin g policy an d p a ra m e te rs, if possible.

335

P O S I X 1 0 0 3 . l c -1 9 9 5 i n t er f a c es

s c h e d _ g e t _ p r io r it y _ m a x ................................ [_posix_priority_scheduling]

i n t s c h e d _ g e t_ p r io r ity _ m a x ( in t p o lic y ); R e tu rn th e m axim um integer priority allowed for th e specified sch ed u lin g p o lic y . policy SCHED_FIF0

R u n th re a d u n til it blocks; p re e m p t low er-priority th re a d s w h en ready.

SCHED_RR

Like s c h e d _ f i f o »b u t su b je c t to periodic tim eslicing.

SCHED_0THER

Im plem entation defined (may b e SCHEDJFIFO. SCHED_RR, o r so m eth in g else) .

R eferences: H eaders: E rrors: Hint:

5.5.2 < s c h e d .h >

[EN0SYS] priority sch ed u lin g is n o t su p p o rted . [EINVAL] p o lic y is invalid.

Priority m in a n d m ax a re integ er v alu es—you can com pute relative valu es, for exam ple, h a lf a n d q u a rte r p o in ts in range.

$ c h e d _ g e t_ p r io r ity _ m in ................................. [ p o s i x p r i o r i t y s c h e d u l i n g ]

i n t s c h e d _ g e t_ p rio r ity _ _ m in ( in t p o lic y ); R etu rn th e m inim um in teg er priority allowed for th e specified sch ed u lin g p o lic y . policy SCHED_FIF0

R u n th re a d u n til it blocks; p reem p t low er-priority th re a d s w h en ready.

SCHED_RR

Like SCHED_FIFO, b u t su b je c t to periodic tim eslicing.

SCHED_OTHER

Im p lem en tatio n defined (may be SCHED _FIFO, SCHED_RR, o r som ethin g else).

R eferences: H eaders: E rrors: Hint:

5.5.2 < sched.h > [ENOSYS] priority sch ed u lin g is n o t su p p o rted . [EINVAL] p o li c y is invalid. Priority m in a n d m ax are in teg er v alu es—you can co m p u te relative values, for exam ple, h a lf an d q u a rte r p o in ts in range.

336

9 .3 .9

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

Fork h a n d le rs P th r e a d s p ro v id e s so m e n e w fu n c tio n s to h e lp th e n e w th r e a d e d e n v iro n m e n t to c o e x ist w ith th e tra d itio n a l p ro c e s s -b a s e d UNIX e n v iro n m e n t. C re a tio n o f a c h ild p ro c e s s b y co p y in g th e full a d d r e s s sp a c e , fo r e x a m p le , c a u s e s p ro b le m s for th re a d e d a p p lic a tio n s b e c a u s e th e f o r k call is a s y n c h r o n o u s w ith re s p e c t to o th e r th r e a d s in th e p ro c e s s .

|

p t h r e a d .a t f o r k

int pthread_atfork ( v o id v o id v o id

( *prepare ) ( v o i d ) , ( *parent ) ( v o i d ) , ( * c h ild ) ( v o id ) );

Define “fork h a n d le rs ” th a t are ru n w hen th e p ro cess c re a te s a child p ro cess. Allows p ro tectio n of sy n ch ro n izatio n objects a n d s h a re d d a ta in th e child p ro cess (which is o therw ise difficult to control). References: H eaders: E rrors: Hint:

9 .3 .1 0

6.1.1 < u n istd .h > * [ENOMEM] in su fficien t sp ace to reco rd th e h a n d lers. All re so u rc e s need ed by child m u s t be protected.

S td io P th r e a d s p ro v id e s so m e n e w fu n c tio n s , a n d n e w v e rs io n s o f old fu n c tio n s , to a c c e s s ANSI C s td io f e a tu re s safely fro m a th r e a d e d p ro c e s s . F o r sa fe ty r e a s o n s , th e old fo rm s o f s in g le -c h a ra c te r a c c e s s to s td io b u ffe rs h a v e b e e n a lte re d to lo c k th e file s tre a m , w h ic h c a n d e c re a s e p e rfo rm a n c e . You c a n c h a n g e old co d e to in s te a d lo ck th e file s tr e a m m a n u a lly a n d , w ith in th a t lo ck ed reg io n , u s e n ew c h a r a c te r a c c e s s o p e ra tio n s t h a t do n o t lo ck th e file s tre a m .

|

flo c k file

void flockfile ( FILE

*file);

In crease th e lock c o u n t for a s td io file stre a m to gain exclusive access to th e file stream . If th e file stre a m is c u rren tly locked by a n o th e r th re a d , th e calling th re a d is blocked u n til th e lock c o u n t for th e file s tre a m becom es zero. If th e calling th re a d alread y ow ns th e file s tre a m lock, th e lock co u n t is in crem en ted —a n id en tical n u m b e r of calls to f u n l o c k f i l e is req u ire d to rele ase th e file s tre a m lock.

*

D ig it a l U N IX a n d S o la r is b o th (in c o r r e c tly ) p la c e t h e d e f in itio n in < p t h r e a d . h > . T h e U N IX 9 8

b r a n d w ill r e q u ir e t h a t t h e y b e fix e d .

P O S I X 1 0 0 3 . l c -1 9 9 5 i n t er f a c es

337

A lthou gh m o st s td io fu n ctio n s, s u c h as p r i n t f a n d f g e ts , a re th rea d -sa fe , you m ay som etim es find th a t it is im p o rta n t th a t a seq u en ce of p r i n t f calls, for exam pie, from one th re a d c a n n o t be se p a ra te d by calls m ad e from a n o th e r th re a d . Also, a few s td io fu n ctio n s a re n o t th re a d -sa fe a n d c a n only be u se d w hile th e file s tre a m is locked by th e caller. R eferences: H eaders: H int:

|

6.4.1 < s td io .h > U se to p ro tect a seq u en ce of s td io op eratio ns.

ftry lo c k file

int ftrylockfile ( FILE

*file);

If th e file stre a m is c u rren tly locked by a n o th e r th re a d , r e tu r n a nonzero value. O therwise, in c re ase th e lock c o u n t for th e file stream , a n d r e tu r n th e value zero. R eferences: H eaders: Hint:

|

6.4.1 < s td io .h > U se to p ro tec t a seq u en ce of s td io op eratio n s.

fu n lo c k file

v o id f u n l o c k f i l e FILE

( * file );

D ecrease th e lock c o u n t for a s td io file stre a m th a t w as previously locked by a corresp o n d in g call to f u n l o c k f i l e . If th e lock c o u n t becom es 0, rele ase th e lock so th a t a n o th e r th re a d c a n lock it. R eferences: H eaders: Hint:

J

6.4.1 < s td io .h > U se to p ro tec t a seq u en ce of s td io op eratio n s.

g e tc _ u n lo c k e d

i n t g e tc _ u n lo c k e d ( FILE

* file );

R e tu rn a single c h a ra c te r from th e s td io stre a m file, w ith o u t locking th e file stream . T his o p eratio n m u s t only be u se d w hile th e file s tre a m h a s b een locked by calling f l o c k f i l e , or w hen you know th a t no o th e r th re a d m ay acc ess th e file s tre a m concu rren tly . R e tu rn s EOF for re a d erro rs or end-of-file condition. R eferences: H eaders: H int:

6 .4 .2 < s td io .h > R eplace old calls to g e tc to re ta in fa ste st access.

338

CHAPTER 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

g e tc h a r jjn lo c k e d

i n t g e tc _ u n lo c k e d ( v o i d ) ; R e tu rn a single c h a ra c te r from th e s td io stre a m s t d i n w ith o u t locking th e file stream . T his o p eratio n m u s t only be u se d w hile th e file stre a m h a s been locked by calling f l o c k f i l e , or w h en you know th a t no o th e r th re a d m ay access th e file s tre a m co n cu rren tly . R e tu rn s EOF for read erro rs or end-of-file condition. R eferences: H eaders: Hint:

6.4 .2 < s td io .h > R eplace old calls to g e t c h a r to re ta in fa ste st access.

p u tc _ u n lo c k e d

i n t p u tc _ u n lo c k e d ( in t FILE

c, * file );

W rite a single c h a ra c te r c (interpreted a s a n unsigned char) to th e s td io s tre a m file w ith o u t locking th e file stream . T his o p eratio n m u s t only be u se d w hile th e file s tre a m h a s b een locked by calling flockfile, or w hen you know th a t no o th e r th re a d m ay access th e file stre a m con cu rren tly . R e tu rn s th e c h a ra c te r or th e valu e EOF if a n erro r occurred. R eferences: H eaders: Hint:

‫ן‬

6.4 .2 < s td io .h > R eplace old calls to p u tc to re ta in fa s te s t access.

p u t c h a r .u n lo c k e d

i n t p u tc h a r _ u n lo c k e d ( in t

c );

Write a single c h a ra c te r c (in terp reted as a n u n sig n e d char) to th e s td io stre a m s td o u t w ith o u t locking th e file stream . This op eratio n m u s t only be u se d w hile th e file stre a m h a s b e e n locked by calling f l o c k f i l e , or w hen you know th a t no o th e r th re a d m ay a cc ess th e file s tre a m co n cu rren tly . R e tu rn s th e c h a ra c te r or th e valu e EOF if a n e rro r o ccurred. R eferences: H eaders: H int:

9.3.11

6 .4 .2 < s td io .h > R eplace old calls to putchar to re ta in fa ste st access.

T h re a d -s a fe fu n ctio n s T h re a d -s a fe fu n c tio n s p ro v id e im p ro v ed a c c e s s to tra d itio n a l f e a tu r e s of ANSI C a n d POSIX t h a t c a n n o t b e effectively m a d e th r e a d - s a fe w ith o u t in te rfa c e c h a n g e s . T h e s e r o u tin e s a re d e s ig n a te d b y th e “_ r ” su ffix a d d e d to th e tra d itio n a l fu n c tio n n a m e th e y re p la c e , for e x am p le, g e t l o g i n _ r for g e t l o g i n .

P O S I X 1 0 0 3 .1 c -1 9 9 5 i n t e r f a c e s

339

g e tlo g ir w

int getlogin_r ( char size_t

*name, namesize);

W rite th e u s e r n am e asso ciated w ith th e c u rre n t p ro cess in to th e buffer po in ted to by n am e. The b u ffer is nam esize byte s long, a n d sh o u ld hav e sp ace for th e n am e a n d a te rm in atin g n u ll ch ara cter. The m ax im u m size of th e login n am e is L0G1N_ NAME_MAX. R eferences: H eaders:

|

6.5.1 < u n is td .h >

r e a d d lr_ r

int readdir__r ( DIR struct dirent struct dirent

*dirp, *entry, **result);

R e tu rn a p o in ter (result) to th e directory en try a t th e c u rre n t position in th e directory s tre a m to w hich dirp refers. W hereas readdir re ta in s th e c u rre n t position us* in g a s ta tic variable, readdir_r u s e s th e entry p aram eter, su p p lied by th e caller. R eferences: H eaders: E rrors:

|

6 .5 .2 , [EBADF] dirp is n o t a n op en directory stream .

strtok_r

char *strtok_r ( char const char char

*s, *sep, **lasts);

R etu rn a po inter to th e n ex t to k en in th e strin g s.W hereas strtok reta in s th e c u rre n t position w ithin a strin g u sin g a static variable, strtok_r u se s th e lasts param eter, su pplied by th e caller. R eferences: H eaders:

6 .5 .3

a s c tim e _ r

c h a r * a s c tim e _ r ( c o n s t s t r u c t tm *tm , char * b u f); C onvert th e “b ro k en -d o w n ” tim e in th e s tru c tu re p o in ted to by tm into a string, w hich is sto red in th e b u ffer p o in ted to by b u f . The b u ffer poin ted to by b u f m u s t

340

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

co n tain a t le a st 26 bytes. The fu n ctio n re tu rn s a p o in ter to th e bu ffer on su ccess, or n u l l on failure. R eferences: H e a d e rs:

I

6 .5 .4

c tim e _ r

c h a r * c tim e _ r ( c o n s t tim e _ t char

* c lo c k , * b u f );

C onvert th e c a le n d a r tim e pointed to by c lo c k into a strin g re p re se n tin g th e local tim e, w hich is sto red in th e b u ffer pointed to by buf. The bu ffer p oin ted to by buf m u s t c o n ta in a t le a st 26 byte s. The fu n ctio n r e tu r n s a p o in ter to th e bu ffer o n su ecess, or n u l l on failure. R eferences: H eaders:

6.5 .4 < tim e .h >

g m t im e _ r

s t r u c t tm *gm tim e_r ( c o n s t tim e _ t s t r u c t tm

* c lo c k , * re s u lt);

C onvert th e ca le n d a r tim e p oin ted to by c lo c k into a “bro k en -d o w n tim e” ex p ressed a s C oord in ated U niversal Tim e (UTC), w hich is sto red in th e s tru c tu re p oin ted to by r e s u l t . The fu n ctio n re tu rn s a p o in ter to th e s tru c tu re on su ccess, or n u l l on failure. R eferences: H eaders:

6 .5 .4 < tim e . h>

lo c a lt im e .r

s t r u c t tm * l o c a l t i m e _ r ( c o n s t tim e _ t * c lo c k , s t r u c t tm * re s u lt); C onvert th e c a le n d a r tim e po in ted to by c lo c k into a “bro k en -d o w n tim e” expressed a s local tim e, w hich is sto red in th e s tru c tu re p o in ted to by r e s u l t . The fu n ctio n re tu rn s a p o in ter to th e s tru c tu re on su ccess, or n u l l o n failure. R eferences: H eaders:

6 .5 .4 < tim e . h>

341

P O S I X 1 0 0 3 . l c -1 9 9 5 i n t e r f a c e s

ra n d r

int rand_r ( unsigned int

*seed);

R e tu rn th e n ex t value in a seq u en ce of p se u d o ra n d o m in teg ers in th e ran g e of 0 to rand _max .W h ereas rand u s e s a static variable to m a in ta in th e co n tex t betw een a series of calls, rand_r u s e s th e value p o in ted to by seed, w hich is su p p lied by th e caller. R eferences: H eaders:

|

6 .5 .5

g e t g r g id _ r

i n t g e tg rg id _ r ( g id _ t s t r u c t g ro u p char s iz e _ t s t r u c t g ro u p

g id , * g ro u p , * b u ffer, b u fs iz e , * * re s u lt);

Locate a n en try from th e gro u p d a ta b a s e w ith a gro u p id m a tch in g th e gid argum en t. The group en try is sto red in th e m em ory p o in ted to by buffer, w hich conta in s bufsize bytes, a n d a p o in ter to th e en try is sto red a t th e a d d re ss poin ted to by result. The m ax im u m bu ffer size req u ired c a n be d eterm in e d by calling sysconf w ith th e _SC_GETGR_R_SIZE_MAX param ete r. R eferences: H eaders: E rrors:

6 .5 .6 < s y s / t y p e s . h>, < g rp .h > [ erange ] th e specified bu ffer is too sm all.

g e tg rn a rrw

i n t g e tg rn a m _ r ( co nst char s t r u c t g ro u p char s iz e _ t s t r u c t g ro u p

*name, * g ro u p , * b u ffe r, b u fs iz e , * * re s u lt);

Locate a n en try from th e gro up d a ta b a s e w ith a gro u p n am e m a tch in g th e name arg u m e n t. The g ro u p e n try is sto red in th e m em ory p oin ted to by b u f f e r , w hich co n ta in s b u f s iz e bytes, an d a p o in ter to th e en try is sto red a t th e a d d re ss po in ted to by r e s u l t . The m ax im u m b u ffer size req u ired c a n be d eterm in e d by calling s y sc o n f w ith th e _SC_GETGR_R_S1ZE_MAX p aram eter. R eferences: H eaders: E rrors:

6 .5 .6 < s y s /ty p e s .h > , < g rp .h > [e r a n g e ] th e specified bu ffer is too sm all.

342

|

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

g e tp w u id _ r

i n t g e tp w u id r ( u id _ t s t r u c t p assw d char s iz e _ t s t r u c t passw d

u id , *pwd, * b u ffe r, b u fs iz e , * * re s u lt);

Locate a n en try from th e u s e r d a ta b a s e w ith a u s e r id m a tc h in g th e u id arg u m en t. The u s e r en try is sto red in th e m em ory poin ted to by b u f f e r , w hich co n tain s b u f s iz e bytes, a n d a p o in ter to th e e n try is sto red a t th e a d d re s s p oin ted to by r e s u l t . The m ax im u m buffer size req u ire d c a n be d eterm in e d by calling s y sc o n f w ith th e _SC_getpw _r_ size _max param ete r. R eferences: H eaders: E rrors:

6 .5 .6 < s y s / t y p e s . h>, [ERANGE ] th e specified bu ffer is too sm all.

g e tp w n a m ^ r

i n t getpw nam _r ( const char s t r u c t p assw d char s iz e _ t s t r u c t p assw d

*name, *pwd, * b u ffe r, b u fs iz e , * * re s u lt);

Locate a n en try from th e u s e r d a ta b a s e w ith a u s e r n am e m a tch in g th e name argum ent. The u s e r en try is sto red in th e m em ory poin ted to by b u f f e r , w hich co n tain s b u f s iz e bytes, a n d a p o in ter to th e e n try is sto red a t th e a d d re s s poin ted to by r e s u l t . The m ax im u m buffer size req u ired c a n be d eterm in e d by calling sy sc o n f w ith th e _sc_getpw _r_ s 1 z e_max param ete r. R eferences: H eaders: Errors:

9 .3 .1 2

6 .5 .6 < s y s / ty p e s .h > , [ERANGE ] th e specified buffer is too sm all.

Signals P th r e a d s p ro v id e s fu n c tio n s t h a t e x te n d th e POSIX sig n a l m o d el to s u p p o r t m u ltith r e a d e d p ro c e s s e s . All th r e a d s in a p ro c e s s s h a r e th e s a m e sig n a l a c tio n s . E a c h th r e a d h a s its ow n p e n d in g a n d b lo c k e d sig n a l m a s k s . T h e p ro c e s s a lso h a s a p e n d in g sig n a l m a s k so t h a t a s y n c h r o n o u s s ig n a ls c a n p e n d a g a in s t th e p ro c e s s w h e n all th r e a d s h a v e th e sig n a l b lo c k ed . In a m u ltith re a d e d p ro c e s s , th e b e h a v io r of s ig p ro c m a s k is u n d e fin e d .

343

P O S I X 1 0 0 3 . 1 c -1 9 9 5 i n t e r f a c e s

|

p th r e a d _ k ill

in t p th re a d _ k ill ( p th re a d _ t in t

th re a d , s ig );

R eq u est th a t th e signal s i g be delivered to th re a d . If s i g is 0, no signal is sen t, b u t e rro r checkin g is perform ed. If th e actio n of th e sig nal is to te rm in ate, stop, or contin u e, th e n th e en tire p ro cess is affected. References: H ead ers: E rrors:

6.6.3 < s ig n a l.h > [ E S R C H ] n o th re a d co rresp o n d in g to th rea d .

H int:

To te rm in a te a th re a d , u s e can cellatio n.

[E IN V A L ]

s ig

is a n

in v a lid

s ig n a l n u m b e r .

p th r e a c L s ig m a s k

i n t p th r e a d _ s ig m a s k ( in t const s ig s e t_ t s ig s e t_ _ t

how, * s e t, * o s e t);

C o ntrol th e m ask in g of sig nals w ith in th e calling th rea d . !low S IG _ B L 0 C K

R e s u ltin g s e t is t h e u n io n o f t h e cu rren t s e t a n d th e a rg u m en t s e t .

S IG _U N B L O C K

R e s u lt in g s e t is th e in t e r s e c tio n o f th e cu rren t se t a n d th e a rg u m en t se t.

S IG _ S E T M A S K

R e s u ltin g s e t is th e

e t p o in te d to

b y th e a rg u m en t s e t

R eferences: H eaders: E rrors: H int:

6.6 .2 < s ig n a l.h >

[ e i n v a l ] h o w is n o t one of th e defined values. You c a n n o t p rev en t delivery of a sy n c h ro n o u s sig nals to th e p ro cess u n le ss th e signal is blocked in all th re a d s.

s ig tim e d w a it

i n t s i g ti m e d w a i t ( const s ig s e t_ t * s e t, s ig in fo _ t * in fo , c o n s t s t r u c t tim e s p e c * ti m e o u t ) ; If a signal in s e t is pending, atom ically clear it from th e se t of p en d in g sig nals a n d re tu rn th e sig nal n u m b e r in th e s i_ s ig n o m em b er of info. The c a u se of th e signal

344

CHA P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

sh all be sto red in th e si_code m em ber. If an y value is q u eu ed to th e selected signal, re tu r n th e first q u eu ed v alu e in th e si_value m em ber. If no sig nal in set is p en d ing, su sp e n d th e calling th re a d u n til one or m ore becom e pend ing. If th e tim e interval specified by timeout p a sse s, sigtimedwait will r e tu r n w ith th e erro r eagain . This fu n ctio n r e tu r n s th e signal n u m b e r—on error, it r e tu r n s -l a n d se ts errno to th e a p p ro p ria te e rro r code. R eferences: H eaders: E rrors:

Hint:

|

6 .6 .4 < s ig n a l.h > [EINVAL] set c o n ta in s a n invalid sig nal nu m b er. [e a g a i n ] th e tim eo u t interval p assed . [ENOSYS] realtim e sig n als a re n o t su p p o rted . U se only for a sy n c h ro n o u s signal delivery. All sig nals in s e t m u s t b e m a sk e d in th e calling th re a d , a n d sh o u ld u su a lly b e m a sk e d in all th re a d s.

s ig w a it

i n t s ig w a it ( co n st s ig s e t_ t in t

* s e t, * s ig );

If a sig nal in set is pen ding , atom ically clear it from th e se t of p en d in g sig n als an d r e tu r n th e sig nal n u m b e r in th e lo cation referenced by sig. If no signal in set is pend ing, su sp e n d th e calling th re a d u n til one or m ore becom e pending. References: H eaders: E rro rs: Hint:

6 .6 .4

[EINVAL] set c o n ta in s a n invalid sig nal nu m b er. U se only for a sy n c h ro n o u s sig nal delivery. All sig n als in set m u s t be m a sk ed in th e calling th re a d , a n d sh o u ld u su a lly be m a sk e d in all th re a d s.

s ig w a itin fo

i n t s ig w a itin fo ( c o n s t s ig s e t_ _ t s ig in fo _ t

* s e t, * in fo );

If a signal in s e t is pending, atom ically clear it from th e se t of p en d in g sig n als a n d re tu r n th e sig n al n u m b e r in th e s i_ s ig n o m em b er of info. The c a u se of th e signal sh all be sto red in th e s i_ c o d e m em ber. If an y value is q u eu ed to th e selected signal, r e tu r n th e first q u eu ed v alue in th e s i_ v a lu e m em ber. If no sig nal in s e t is pending, su sp e n d th e calling th re a d u n til one or m ore becom e pending. This fu nction retu r n s th e signal n u m b e r—on error, it re tu rn s -1 a n d se ts e rrn o to th e ap p ro p ria te erro r code.

34 5

P O S I X 1 0 0 3 . 1 c -1 9 9 5 i n t e r f a c e s

R eferences: H eaders: E rro rs: Hint:

9 .3 .1 3

6 .6 .4 < s ig n a l.h > [EINVAL] s e t c o n tain s a n invalid signal n u m ber. [ENOSYS] realtime signals are not supported. Use only for a sy n c h ro n o u s signal delivery. All sig n als in s e t m u s t be m a sk e d in th e calling th re a d , a n d sh o u ld u su a lly be m a sk ed in all th re a d s.

S e m a p h o re s S e m a p h o re s co m e fro m POSIX. l b (POSIX 10 03 . l b - 1993) r a th e r t h a n from P th re a d s . T h ey follow th e o ld e r UNIX c o n v e n tio n fo r re p o rtin g e rro rs . T h a t is, o n fa ilu re th e y r e t u r n a v a lu e of -1 a n d s to re th e a p p ro p ria te e rro r n u m b e r in to errno. All of th e s e m a p h o re f u n c tio n s re q u ire th e h e a d e r file .

[ POSIX SEMAPHORES]

s e m _ d e $ tr o y ...........................

int sem_destroy ( sem t

*sem);

D estroy a n u n n a m e d sem ap h o re. R eferences: H eaders: Errors:

6 .6 .6

[EINVAL] value ex ceeds sem _value _m a x . [ENOSYS] sem ap h o re s a re n o t su p p o rted . [ebusy ] th re a d s (or processes) are c u rre n tly blocked on sem.

s e m j n i t ...............................................

int sem_init ( sem_t int unsigned int

[_posix_semaphores]

*sem, pshared. value);

Initialize a n u n n a m e d sem aphore. The initial v alue of th e sem ap h o re c o u n ter is value. If th e p sh a re d a rg u m e n t h a s a n on zero value, th e sem ap h o re can be sh a re d betw een p rocesses. W ith a zero value, it ca n be sh a re d only betw een th re a d s in th e sam e process. R eferences: H ead ers: E rrors:

Hint:

6.6 .6 < semaphore.h> [EINVAL] sem is n o t a valid sem ap hore. [ENOSPC] a req u ired reso u rce h a s b een ex h au ste d . [ENOSYS] sem ap h o res are n o t su p p o rted . [EPERM] th e p ro cess lack s a p p ro p ria te privilege. Use a value of 1 for a lock, a value of 0 for w aiting.

346

CH A P T E R 9

P O S I X t h r e a d s m i n i -r e f e r e n c e

1 s e m t r y w a i t ......................

i n t sem t r y w a i t ( sem t

* s e m );

Try to w ait on a sem ap h o re (or “tiy to lock” th e sem ap hore). If th e sem ap h o re value is g re a te r th a n zero, d ecre ase th e value by one. If th e sem ap h o re value is 0, th e n r e tu r n im m ediately w ith th e e rro r e a g a i n . R eferences: H eaders: Errors:

H int:

|

6 .6 .6

[EAGAIN] th e sem ap h o re w as alread y locked. [EINVAL] sem is n o t a valid sem ap h o re. [EINTR] th e fu n ctio n w as in te rru p te d by a signal. [ENOSYS] sem ap h o re s a re n o t su p p o rted . [EDEADLK] a deadlock co ndition w as detected. W hen th e sem ap h o re’s in itial value w as 1, th is is a lock operation ; w hen th e in itial value w as 0, th is is a w ait operation.

s e m p o s t...........................

i n t sem p o s t ( sem _t

* s e m )?

P ost a w ak eu p to a sem ap h o re. If th e re axe w aiting th re a d s (or processes), one is aw ak en ed . O therw ise th e sem ap h o re value is in crem en ted by one. R eferences: H eaders: Errors: Hint:

6 .6 .6

[EINVAL] sem is n o t a valid sem ap h o re. [ENOSYS] sem ap h o re s are n o t su p p o rted . May be u se d from w ithin a sig n al-h an d lin g function.

$ e m _ w a it . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

int sem_wait ( sem_t

[_ p o s ix _ s e m a p h o r e s ]

*sem);

Wait on a sem ap h o re (or lock th e sem aphore). If th e sem ap h o re value is g reater th a n zero, d ecrease th e value by one. If th e sem ap h o re value is 0, th e n th e calling th re a d (or process) is blocked u n til it c an su ccessfu lly d ecrease th e value or u n til in te rru p te d by a signal. R eferences: H eaders: E rrors:

6 .6 .6

[EINVAL] sem is n o t a valid sem ap h o re. [E IN T R ]

th e

fu n c tio n

w a s in t e r r u p te d

b y

a

s ig n a l.

[ENOSYS] sem ap h o re s are n o t su p p o rted . [ e d e a d l k ] a dead lock condition w as detected.

Hint:

W hen th e se m a p h o re ’s in itial v alu e w as 1, th is is a lock o peration; w h en th e initial value w as 0, th is is a w ait operation.

10 Future s ta n d a rd iz a tio n

T h re e p rim a ry s ta n d a r d iz a tio n effo rts a ffect P th r e a d s p ro g ra m m e rs . X /O p e n ’s X SH 5 is a n ew in te rfa c e sp e c ific a tio n t h a t in c lu d e s POSIX. lb , P th re a d s , a n d a s e t of a d d itio n a l th r e a d f u n c tio n s (p a rt of th e A sp e n f a s t- tr a c k su b m is s io n ). T h e POSIX. lj d ra ft s ta n d a r d p ro p o s e s to a d d b a r r ie r s , r e a d /w r ite lo ck s, s p in lo c k s, a n d im p ro v ed s u p p o r t for “rela tiv e tim e ” w a its o n c o n d itio n v a ria b le s . T h e POSIX. 14 d ra ft s ta n d a r d (a “POSIX S ta n d a r d P rofile”) gives d ire c tio n for m a n a g in g th e v a rio u s o p tio n s o f P th r e a d s in a m u ltip ro c e s s o r e n v iro n m e n t.

10.1 X /O p e n XSH5 (UNIX98) M ut e x t y p e at t ri but e : int pthread_mutexattr_gettype ( const pthread__mutexattr_t *attr, int *type); int pthread_mutexattr_settype ( pthread_mutexattr__t *attr, int type);

R e ad/w ri t e lo c k s: int pthread_rwlock_init (pthread__rwlock_t *rwlock, const pthread_rwlockattr_t *attr); int pthread_rwlock_destroy (pthread_rwlock_t *rwlock); pthread_rwlock_t rwlock - PTHREAD_RWLOCKJCNITIALIZER; int pthread__rwlock__rdlock (pthread_rwlock_t *rwlock); int pthread_rwlock_tryrdlock ( pthreadjrwlock_t *rwlock); int pthread_rwlock_unlock (pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock (pthread_rwlock_t *rwlock); int pthread_rwlock_trywrlock ( pthread_rwlock_t *rwlock); int pthread_rwlockattr_init ( pthread_rwlockattr_t * a t t r ); int pthread_rwlockattr_destroy ( pthread_rwlockattr_t *attr); int pthread_rwlockattr_getpshared ( const pthread__rwlockattr__t *attr, int *pshared) ? int pthread_rwlockattr_setpshared ( pthread__rwlockattr_t *attr, int pshar e d ) ;

347

348

CH A P T E R 10

Future standardization

P aralle l I/O: size_t pread (int fildes, void *buf, size_t nbyte, o£f_t offset); size_t pwrite (int fildes, const void *b u f , size_t nbyte, off_t offset);

M i sc e llan e o us: int pthread_attr^getguards ize ( const pthread_attr_t *attr, siz©_t *guardsize); int pthread_attr_setguardsize ( pthread_attr_t *attr, size_t guardsize); int pthread_getconcurrency (); int pthread_setconcurrency (int new_level);

X /O p e n , w h ic h is p a r t of T h e O p en G ro u p , o w n s th e UNIX tr a d e m a r k a n d d ev elo p s UNIX in d u s tr y p o rta b ility sp ecificatio n s a n d b r a n d s . T h e X /O p e n b r a n d s in c lu d e X PG 3, X PG4, UNIX93, a n d UNIX95. UNIX95 is a lso k n o w n a s “SP EC 1 1 7 0 ” o r th e “S in gle UNIX S p ecificatio n .” X /O p e n re c e n tly p u b lis h e d th e X / O p e n C A E S p e cifica tion , S y s te m In te rfa ce s a n d H e a d e rs , Is s u e 5 (also k n o w n a s X SH 5), w h ic h is p a r t of th e n e w UNIX98 b ra n d . X SH 5 re q u ire s c o n fo rm a n c e to th e POSIX. 1 -1 9 9 6 s ta n d a r d , w h ic h in e lu d e s th e P O S IX .lb a n d P O S IX .lc a m e n d m e n ts . T h e X SH 5 sp ec ific a tio n a lso a d d s a s e t of e x te n s io n s to POSIX. T h is s e c tio n d is c u s s e s th e X SH 5 e x te n s io n s t h a t sp ecifically a ffect th r e a d e d p ro g ra m s . You c a n re co g n ize a s y s te m co n fo rm in g to X SH 5 b y a d e fin itio n for th e _X0PEN_VERSI0N sy m b o l, in , to th e v a lu e 5 0 0 o r h ig h er. T h e m o s t v a lu a b le c o n trib u tio n of UNIX98 to th e th r e a d e d p ro g ra m m in g in d u s try , how ev er, is p o ssib ly th e d e v e lo p m e n t of a s ta n d a rd iz e d , p o rta b le te s tin g s y ste m . A n u m b e r o f c o m p lic a te d is s u e s a ris e w h e n d ev elo p in g a n im p le m e n ta tio n of P th re a d s , a n d so m e s u b tle a s p e c ts of th e s ta n d a r d a re a m b ig u o u s . S u c h a n in d u s try -w id e te s tin g s y s te m w ill re q u ire all v e n d o rs im p le m e n tin g UNIX98 b r a n d e d s y s te m s to a g re e o n in te r p r e ta tio n s o f P th re a d s .

‫ ו‬0.‫ ו‬.‫ו‬

POSIX o p tio n s for XSH5 S o m e o f th e f e a tu re s t h a t a re o p tio n s in th e P th r e a d s s ta n d a r d a re re q u ire d b y X SH 5. If y o u r co d e re lie s o n th e s e P th r e a d s o p tio n s, it w ill w o rk o n a n y sy ste m co n fo rm in g to X SH 5: • • •

_P0S1X_THREADS: T h re a d s a re s u p p o rte d . _ p o s i x _ t h r e a d _ a t t r _ s t a c k a d d r :T h e s ta c k a d d r a ttr ib u te is s u p p o rte d . _ p o s i x _ t h r e a d _ a t t r __s t a c k s i z e :T h e s ta ck s iz e a ttr ib u te is s u p p o rte d .



_P0S1X_THREAD_PR0CESS_SHARED: M u tex es, c o n d itio n v a ria b le s , a n d X SH 5

re a d /w r ite lo c k s c a n b e s h a r e d b e tw e e n p ro c e s s e s .

349

X /O p e n X S H 5 [U N I X 9 8 ]



_ p o s i x _ t h r e a d __s a f e _ f u n c t i o n s : T h e P th r e a d s th re a d -s a fe fu n c tio n s a re

s u p p o rte d . S ev eral a d d itio n a l P th re a d s o p tio n s a re “b u n d le d ” in to th e X SH 5 re a ltim e th r e a d s o p tio n g ro u p . If y o u r s y ste m c o n fo rm s to X SH 5 a n d s u p p o r ts th e _ x o p e n _ r e a l t i m e _ t h r e a d s o p tio n , th e n th e s e P th re a d s o p tio n s a re a lso s u p p o rte d : •

_ p o s i x _ t h r e a d _ p r i o r i t y _ s c h e d u l i n g : R e a ltim e

p rio rity s c h e d u lin g is

s u p p o rte d . • •

10.1.2

_ p o s i x _ t h r e a d _ p r i o _ p r o t e c t : P rio rity ceilin g m u te x e s a re s u p p o rte d . _ p o s i x _ t h r e a d _ p r i o _ i n h e r i t : P rio rity in h e rita n c e m u te x e s a re s u p p o rte d .

M u te x ty p e T h e D C E th r e a d s p a c k a g e p ro v id ed a n e x te n s io n t h a t allo w ed th e p ro g ra m m e r to sp ecify th e “k in d ” o f m u te x to b e c re a te d . D C E th r e a d s s u p p lie d fa s t, re cu rs iv e , a n d n on re cu rs iv e m u te x k in d s . T h e X SH 5 sp e c ific a tio n c h a n g e s th e a ttr ib u te n a m e fro m “k in d ” to “ty p e ,” re n a m e s fa s t to d e fa u lt, r e n a m e s n o n re cu r‫־‬ s iv e to e rro rch e cK a n d a d d s a n e w ty p e, n o rm a l (Table 10.1). A n o rm a l m u te x is n o t allo w ed to d e te c t d e a d lo c k e rro rs —t h a t is, a th r e a d w ill h a n g if it trie s to lo ck a n o rm a l m u te x t h a t it a lre a d y o w n s. T h e d e fa u lt m u te x ty p e, like th e D C E fa s t m utex ,* p ro v id e s im p le m e n ta tio n -d e fin e d e rro r c h e c k in g . T h a t is, d e fa u lt m a y b e m a p p e d to o n e of th e o th e r s ta n d a r d ty p e s o r m a y b e s o m e th in g e n tire ly d iffere n t. M u te x ty p e

D e fin itio n

PTHREAD_MUTEX_NORMAL

B a sic m u te x w ith n o sp ecific e rro r c h e c k in g b u ilt in. D oes n o t re p o rt a d e a d lo c k error.

PTHREAD_MUTEX_RECURSIVE

Allows a n y th re a d to lock th e m u te x “rec u rsiv e ly ” —it m u s t u n lo c k a n e q u a l n u m b e r of tim e s to re le a se th e m u tex .

PTHREAD_MUTEX_ERRORCHECK

D e te c ts a n d re p o rts sim p le u s a g e e rro rs —a n a tte m p t to u n lo c k a m u te x t h a t ’s n o t lo c k ed b y th e c a llin g th r e a d (or th a t is n ’t lo c k ed a t all), o r a n a tte m p t to re lo c k a m u te x th e th r e a d a lre a d y o w n s.

PTHREAD_MUTEX DEFAULT

T h e d e fa u lt m u te x ty p e, w ith v ery lo o se s e m a n tic s to allow u n fe tte re d in n o v a tio n a n d e x p e rim e n ta tio n . M ay b e m a p p e d to a n y of th e o th e r th re e defin ed ty p e s, o r m a y b e s o m e th in g else en tirely .

TABLE 10.1

X S H 5 m u te x ty pes

* D C E threads implemented f a s t mutexes much like the definition of X S H 5 nor m al mutexes, with no error checking. This was not, however, specification of intent.

350

CH A P T E R 10

Future standardization

A s a n a p p lic a tio n developer, y o u c a n u s e a n y o f th e m u te x ty p e s a lm o s t in te rc h a n g e a b ly a s lo n g a s y o u r co d e d o e s n o t d e p e n d o n th e im p le m e n ta tio n to d e te c t (or fail to d etect) a n y p a r tic u la r e rro rs . N ever w rite co d e t h a t c o u n ts o n a n im p le m e n ta tio n fa ilin g to d e te c t a n y erro r. Do n o t lo ck a m u te x in o n e th r e a d a n d u n lo c k it in a n o th e r th re a d , for e x am p le, ev en if y o u a re s u r e t h a t th e e rro r w o n ’t b e re p o rte d —u s e a s e m a p h o re in s te a d , w h ic h h a s n o “o w n e rs h ip ” s e m a n tic s . All m u te x e s , re g a rd le s s o f ty p e, a re c re a te d u s in g pthread_mutex_init, des tro y e d u s in g pthread_mutex_destroy, a n d m a n ip u la te d u s in g pthread_mutex_ lock, pthread_mutex_unlock, a n d pthread_mutex_trylock. N o rm a l m u te x e s w ill u s u a lly b e th e f a s te s t im p le m e n ta tio n p o s sib le for th e m a c h in e , b u t will p ro v id e th e le a s t e rro r c h e c k in g . R e cu rs iv e m u te x e s a re p rim a rily u s e fu l for c o n v e rtin g old co d e w h e re it is diffic u lt to e s ta b lis h c le a r b o u n d a r ie s of s y n c h ro n iz a tio n , for e x am p le, w h e n y o u m u s t call a fu n c tio n w ith a m u te x lo ck ed a n d th e fu n c tio n y o u call— o r so m e fu n c tio n it c a lls—m a y n e e d to lock th e s a m e m u te x . I h a v e n e v e r s e e n a s itu a tio n w h e re re c u rs iv e m u te x e s w ere re qu ire d to solve a p ro b le m , b u t I h a v e s e e n m a n y c a s e s w h e re th e a lte r n a te (a n d u s u a lly “b e tte r ”) s o lu tio n s w ere im p ra c tic a l. S u c h s itu a tio n s fre q u e n tly le a d d e v e lo p e rs to c re a te re c u rs iv e m u te x e s , a n d it m a k e s m o re s e n s e to h a v e a sin g le im p le m e n ta tio n a v a ila b le to ev ery o n e. (B u t y o u r co d e w ill u s u a lly b e e a s ie r to follow, a n d p e rfo rm b e tte r, if y o u avoid re c u rs iv e m u te x e s.) E rro rch e ck m u te x e s w ere d evised a s a d eb u g g in g tool, a lth o u g h le ss in tru siv e d eb u g g in g to o ls (w here available) c a n b e m o re pow erful. To u s e e rro rc h e c k m u te x e s y o u m u s t reco m p ile co d e to t u r n th e d eb u g g in g fe a tu re o n a n d off. It is fa r m o re u s e fu l to h av e a n e x te rn a l o p tio n to force all m u te x e s to re c o rd d eb u g g in g d a ta . You m a y w a n t to u s e e rro rc h e c k m u te x e s in fin al “p ro d u c tio n ” code, of c o u rs e , to d e te c t s e rio u s p ro b le m s early , b u t b e a w a re th a t e rro rc h e c k m u te x e s will a lm o s t alw ay s b e m u c h slo w er th a n n o rm a l m u te x e s d u e to th e e x tra s ta te a n d ch eck in g . D e fa u lt m u te x e s allo w e a c h im p le m e n ta tio n to p ro v id e th e m u te x s e m a n tic s th e v e n d o r feels will b e m o s t u s e fu l to th e ta rg e t a u d ie n c e . It m a y b e u s e fu l to m a k e e rro rch e ck m u te x e s th e d e fa u lt, for e x am p le, to im p ro v e th e th r e a d e d d e b u g g in g e n v iro n m e n t of a s y ste m . O r th e v e n d o r m a y c h o o se to m a k e n o rm a l m u te x e s th e d e fa u lt to give m o s t p ro g ra m s th e b e n e fit o f a n y e x tra sp e e d .

|

p th r e a d _ m u t e x a t tr _ g e tty p e

int pthread_mutexattr_gettype ( const pthread_mutexattr_t int

*attr, *type);

Specify th e type of m u tex es created w ith a t t r .

351

X /O p e n X S H 5 [U N I X 9 8 ]

type PTHREAD MUTEX DEFAULT

U nspecified type.

PTHREAD MUTEX NORMAL

B asic m utex, w ith n o erro r checking.

PTHREAD_MUTEX_RE CURSI VE

T h re a d c a n relo ck a m u te x it ow ns.

PTHREAD_MUTEX_ERRORCHECK

C h eck s for u sa g e erro rs.

R eferences: E rrors:

3.2, 5.2.1, 10.1.2 [EINVAL] ty p e invalid.

Hint:

N orm a l m u tex es

[EINVAL] attr invalid.

will u su a lly be fastest; e rrorche ck m u tex es a re u seful for debugging; re curs iv e m u tex es c a n be u sefu l for m ak in g old in terfaces th rea d -sa fe .

p t h r e a d _ m u t e x a ttr _ $ e tty p e

int pthread__mutexattr_settype ( pthread_mutexattr_t int

*attr, type);

D eterm in e th e type of m u tex es crea ted w ith a t t r . typo PTHREAD_MUTEX_DEFAULT

U nspecified type.

PTHREAD MUTEX NORMAL

B asic m utex, w ith n o erro r checking.

PTHREAD_MUTEX_RECURSIVE

T h rea d c a n relock a m u te x it ow ns.

PTHREAD_MUTEX_ERRORCHECK

C hecks for u sag e erro rs.

R eferences: Errors: Hint:

3.2, 5.2.1, 10.1.2 [EINVAL] ty p e invalid. [EINVAL] a t t r invalid. N orm a l m u tex es will u su a lly be fastest; e rrorche ck m u tex es are u seful for debugging; re curs iv e m u tex es c a n b e u sefu l for m ak in g old in terfaces th read -safe.

10.1.3 Set c o n c u r r e n c y le v e l W h en y o u u s e P th r e a d s im p le m e n ta tio n s th a t s c h e d u le u s e r th r e a d s o n to so m e s m a lle r s e t o f k e rn e l e n titie s (see S e c tio n 5 .6 .3 ), it m a y b e p o s sib le to h a v e re a d y u s e r th r e a d s w h ile all k e rn e l e n titie s a llo c a te d to th e p ro c e s s a re b u s y .

35 2

CH A P T E R 10

F u t u r e st a n d a r d i z a t i o n

S o m e im p le m e n ta tio n s , for ex am p le, “lo c k ” a k e rn e l e n tity to a u s e r th r e a d th a t b lo c k s in th e k e rn e l, u n til th e b lo c k in g c o n d itio n , for ex a m p le a n I /O re q u e s t, is co m p le te d . T h e s y s te m will c re a te so m e r e a s o n a b le n u m b e r of k e rn e l e x e c u tio n e n titie s fo r th e p ro c e s s , b u t e v e n tu a lly th e poo l of k e rn e l e n titie s m a y b eco m e e x h a u s te d . T h e p ro c e s s m a y b e left w ith th r e a d s c a p a b le o f p e rfo rm in g u s e fu l w o rk for th e a p p lic a tio n , b u t n o w ay to s c h e d u le th e m . T h e pthread_setconcurrency fu n c tio n a d d r e s s e s th is lim ita tio n b y allo w ing th e a p p lic a tio n to a s k for m o re k e rn e l e n titie s . If th e a p p lic a tio n d e s ig n e r rea liz e s th a t 10 o u t of 15 th r e a d s m a y a t a n y tim e b e c o m e b lo c k e d in th e k e rn e l, a n d it is im p o r ta n t for th o s e o th e r 5 th r e a d s to b e a b le to c o n tin u e p ro c e s s in g , th e n th e a p p lic a tio n m a y r e q u e s t t h a t th e k e rn e l s u p p ly 15 k e rn e l e n titie s . If it is im p o rt a n t th a t a t le a s t 1 o f th o s e 5 c o n tin u e , b u t n o t t h a t all c o n tin u e , th e n th e a p p lic a tio n co u ld r e q u e s t th e m o re c o n se rv a tiv e n u m b e r o f 11 k e rn e l e n titie s . O r if it is OK for all th r e a d s to b lo c k o n c e in a w hile, b u t n o t o ften , a n d y o u k n o w t h a t o n ly ra re ly will m o re th a n 6 th r e a d s b lo c k a t a n y tim e, th e a p p lic a tio n c o u ld r e q u e s t 7 k e rn e l e n titie s . T h e pthread_setconcurrency fu n c tio n is a h in t, a n d im p le m e n ta tio n s m a y ig n o re it o r m odify th e ad vice. You m a y u s e it freely o n a n y s y s te m t h a t co n fo rm s to th e UNIX98 b r a n d , b u t m a n y s y s te m s will d o n o th in g m o re t h a n s e t a v a lu e t h a t is r e tu r n e d b y pthread_getconcurrency. O n D ig ital UNIX, for ex am p le, th e re is n o n e e d to s e t a fixed c o n c u rre n c y level, b e c a u s e th e k e rn e l m o d e a n d u s e r m o d e s c h e d u le r s c o o p e ra te to e n s u r e t h a t re a d y u s e r th r e a d s c a n n o t b e p rev e n te d fro m r u n n in g b y o th e r th r e a d s b lo c k e d in th e k e rn e l.

p th re a d _ g e tc o n c u rre n c y

int pthread_getconcurrency

();

R e tu rn s th e v alue se t by a previous p th re a d _ s e tc o n c u rre n c y call. If th e re have b een no previo us calls to p th re a d _ s e tc o n c u rre n c y , r e tu r n s 0 to in d icate th a t th e im p le m en ta tio n is m a in tain in g th e c o n cu rren c y level au to m atically . R eferences: E rrors: Hint:

5.6.3, 10.1.3 none. C o n cu rren cy level is a hin t. It m ay be ignored by an y im plem en tation, a n d w ill be ignored by a n im p lem en tatio n th a t does n o t need it to e n s u re co n cu rren cy .

p th r e a d _ s e t c o n c u r r e n c y

int pthread_getconcurrency

(int new_level);

Allows th e ap p licatio n to inform th e th re a d s im p le m en ta tio n of its d esired m inim u m co n cu rren cy level. The a c tu a l level of co n cu rren cy re su ltin g from th is call is unspecified.

353

X /O p e n X S H 5 [U N I X 9 8 ]

R eferences: E rro rs:

5.6.3, 10.1.3

Hint:

C on cu rren cy level is a h in t. It m ay be ignored by an y im plem entation, a n d w ill be ignored by a n im p le m en tatio n th a t do es n o t need it to e n s u re co n cu rren cy .

[EINVAL] new_level is negative. [EAGAIN] new_level exceeds a sy stem reso u rce.

10.1.4 S ta c k g u a r d size G u a rd size c o m e s fro m D C E th r e a d s . M o st th r e a d im p le m e n ta tio n s a d d to th e th r e a d ’s s ta c k a “g u a r d ” reg io n , a p a g e o r m o re o f p ro te c te d m em o ry . T h is pro te c te d p ag e is a sa fe ty zo n e, to p re v e n t a s ta c k overflow in o n e th r e a d fro m c o rru p tin g a n o th e r th r e a d ’s s ta c k . T h e re a r e tw o good r e a s o n s fo r w a n tin g to c o n tro l a th r e a d ’s g u a rd size: 1. It allo w s a n a p p lic a tio n o r lib ra ry t h a t a llo c a te s la rg e d a ta a r r a y s o n th e s ta c k to in c re a s e th e d e fa u lt g u a r d size. F o r e x a m p le , if a th r e a d a llo c a te s tw o p a g e s a t o n ce, a sin g le g u a rd p a g e p ro v id e s little p ro te c tio n a g a in s t s ta c k overflow s—th e th r e a d c a n c o r r u p t a d jo in in g m e m o ry w ith o u t to u c h in g th e p ro te c te d p ag e. 2. W h e n c re a tin g a la rg e n u m b e r of th r e a d s , it m a y b e t h a t th e e x tra p a g e for e a c h s ta c k c a n b e c o m e a sev ere b u r d e n . In a d d itio n to th e e x tra p ag e, th e k e r n e l’s m e m o ry m a n a g e r h a s to k e e p tr a c k o f th e differin g p ro te c tio n o n a d jo in in g p a g e s, w h ic h m a y s tr a in s y s te m re s o u rc e s . T h ere fo re , y o u m a y s o m e tim e s n e e d to a s k th e s y s te m to “t r u s t y o u ” a n d avo id a llo c a tin g a n y g u a r d p a g e s a t all fo r y o u r th r e a d s . You c a n d o th is b y re q u e s tin g a g u a rd size of 0 b y te s.

p th r e a d _ a ttr _ g e tg u a r d $ iz e

int pthread_attr_getguardsize const pthread_attr_t size_t

( *attr, *guardsize);

D eterm in e th e size of th e g u a rd region for th e s ta c k on w hich th re a d s created w ith a t t r will ru n . References: E rrors: H int:

2, 5.2.3 [EINVAL] a t t r invalid. Specify 0 to fit lots of s ta c k s in a n a d d re ss sp ace, or in c re ase d efau lt guardsize for th re a d s th a t allocate large b u ffers on th e stack.

354

CHAPTER 10

Future standardization

p th r e a d _ a ttr _ s e tg u a r d s iz e

i n t p th re a d _ a ttr_ s e tg u a rd s iz e p th re a d _ a ttr_ t s iz e _ t

( *a t t r , g u a rd s iz e );

T h re a d s crea ted w ith a t t r will ru n on a s ta c k w ith g u a r d s iz e b y tes p ro tecte d a g a in st s ta c k overflow. The im p le m en ta tio n m ay ro u n d g u a r d s iz e u p to th e n ex t m ultiple of p a g e s i z e . Specifying a v alu e of 0 for g u a r d s iz e will c a u se th re a d s c rea ted u sin g th e a ttrib u te s ob ject to r u n w ith o u t s ta c k overflow protection. R eferences: Errors: Hint:

10.1.5

2, 5.2 .3 [EINVAL] g u a r d s iz e or a t t r invalid. Specify 0 to fit lots of sta c k s in a n a d d re ss space, or in c re ase default g u a r d s iz e for th re a d s th a t allocate large b u ffers on th e sta ck .

P a ra lle l I / O M an y h ig h -p e rfo rm a n c e s y s te m s , s u c h a s d a ta b a s e e n g in e s, u s e th r e a d s , a t le a s t in p a rt, to g a in p e rfo rm a n c e th r o u g h p a ra lle l I/O . U n fo rtu n a te ly , P th re a d s d o e s n ’t d ire c tly s u p p o r t p a ra lle l I/O . T h a t is, tw o th r e a d s c a n in d e p e n d e n tly is s u e I /O o p e ra tio n s for files, o r ev en for th e s a m e file, b u t th e POSIX file I /O m o d e l p la c e s so m e r e s tric tio n s o n th e level o f p a ra lle lism . O n e b o ttle n e c k is t h a t th e c u r r e n t file p o sitio n is a n a ttr ib u te of th e file d e sc rip to r. To re a d o r w rite d a t a fro m o r to a sp ecific p o sitio n w ith in a file, a th r e a d m u s t call ls e e k to se e k to th e p ro p e r b y te offset in th e file, a n d th e n r e a d o r w r i t e . If m o re th a n o n e th r e a d d o e s th is a t th e s a m e tim e, th e firs t th r e a d m ig h t seek , a n d th e n th e s e c o n d th r e a d s e e k to a d iffere n t p la c e b efo re th e firs t th re a d c a n is s u e th e r e a d o r w r i t e o p e ra tio n . T h e X /O p e n p r e a d a n d p w r i t e fu n c tio n s offer a so lu tio n , b y m a k in g th e s e e k a n d re a d o r w rite c o m b in a tio n ato m ic. T h re a d s c a n is s u e p r e a d o r p w r i t e o p e ra tio n s in p a ra lle l, a n d , in p rin c ip le , th e s y s te m c a n p ro c e s s th o s e I /O r e q u e s ts c o m p lete ly in p a ra lle l w ith o u t lo c k in g th e file d e sc rip to r.

|

p re a d

s iz e _ t p re a d ( in t v o id s iz e _ t off_ _ t

fild e s , * b u f, n b y te , o ffs e t);

Read n b y te b y te s from offset o f f s e t in th e file open ed on file d escrip to r f i l d e s , placing th e re s u lt in to bu f. The file d escrip to r’s c u rre n t offset is n o t affected, allowing m u ltip le p re a d a n d / o r p w r ite o p eratio n s to pro ceed in parallel.

355

X /O p e n X S H 5 [U N I X 9 8 ]

R eferences: E rrors:

none

H int:

Allows h ig h -p erfo rm an ce p arallel I/O .

[EINVAL] offset is negative. [E0VERFL0W] attempt to read beyond m a x i m u m . [ENX10] request outside capabilities of device. [ESP1PE] file is pipe.

p w r ite

size_jt pwrite ( int const void size__t off t

fildes, *b u f , nbyte, o f f s e t );

W rite nbyte b y te s to offset offset in th e file open ed on file d escrip to r fildes. from buf. The file d escrip to r’s c u rre n t offset is n o t affected, allowing m ultip le pread a n d / or pwrite op eratio n s to proceed in parallel. R eferences: Errors:

none

Hint:

Allows h ig h -p erfo rm an ce parallel I/O .

[EINVAL] offset is negative. [ESP1PE] file is pipe.

10.1.6 C a n c e lla tio n points M o st UNIX s y s te m s s u p p o r t a s u b s ta n tia l n u m b e r of in te rfa c e s t h a t d o n o t co m e fro m POSIX. T h e s e l e c t a n d p o l l in te rfa c e s , for ex am p le, s h o u ld b e d e fe rre d c a n c e lla tio n p o in ts . P th r e a d s d id n o t re q u ire th e s e f u n c tio n s to b e c a n c e lla tio n p o in ts , how ever, b e c a u s e th e y d o n o t e x ist w ith in POSIX. 1. T h e s e l e c t a n d p o l l fu n c tio n s , ho w ever, a lo n g w ith m a n y o th e rs , e x is t in X /O p e n . T h e X SH 5 s ta n d a r d in c lu d e s a n e x p a n d e d lis t of c a n c e lla tio n p o in ts co v erin g X /O p e n in te rfa c e s . A d d itio n a l f u n c tio n s t h a t m u s t b e c a n c e lla tio n p o in ts in X SH 5: getmsg getpmsg lockf msgrcv msgsnd poll

pread putmsg putpmsg pwrite readv select

sigpause usleep wait3 waitid writev

356

CHAPTER 10

Future standardization

A d d itio n a l fu n c tio n s t h a t m a y b e c a n c e lla tio n p o in ts in X SH 5: catclose catgets catopen closelog dbm close dbm delete dbm fetch dbm nextkey dbm open dbm store diclose dlopen endgrent endpwent endutxent fgetwc fgetws fputwc fputws fseeko

fsetpos ftello ftw fwprintf fwscanf getgrent getpwent getutxent getutxid getutxline getw getwc getwchar iconv close iconv open ioctl mkstemp nf tw openlog pclose

popen pututxline putw putwc putwchar readdir r seekdir semop setgrent setpwent setutxent syslog ungetwc vfprintf vfwprintf vprintf vwprintf wprintf wscanf

10.2 POSIX 1003.1J_ _ _ _ _ _ _ _ _ _ _ _ _ C o n d itio n v a r ia b le w a it c lo c k : int pthread_condattr_getclock ( const pthread_condattr_t *attr, clockid_t *clock_id); int pthread_condattr_setclock ( pthread_condattr__t *attr, clockid_t clock_id);

B a rr ie rs : int barrier_attr_init (barrier_attr_t *attr); int barrier^attr__destroy (barrier_attr__t *attr); int barrier_attr_getpshared ( const barrier_attr_t *attr, int *pshared); int barrier_attr_setpshared ( barrier_attr_t *attr, int pshared); int barrier_init (barrier_t *barrier, const barrier^attr_t *attr, int count); int barrier_destroy (barrier_t *barrier); int barrier_wait (barrier_t *barrier);

P O S IX 1003. I j

357

R e a d e r / w r i t e r lo c k s : int rwlock_attr_init (rwlock_attr_t *attr); int rwlock_attr_destroy (rwlock_attr_t *attr); int rwlock_attr_getpshared ( const rwlock_attr_t *attr, int *pshared); int rwlock_attr__setps hared ( rwlock__attr_t *attr, int pshared); int rwlock^init ( rwlock_t *lock, const rwlock_attr_t *attr); int rwlock_destroy (rwlock_t *lock); int rwlock_rlock (rwlock__t *lock); int rwlock_timedrlock (rwlock_t *lock, const struct timespec *timeout); int rwlock_tryrlock (rwlock_t *lock); int rwlock_wlock (rwlock_t *lock); int rwlock_timedwlock (rwlock_t *lock, const struct timespec *timeout); int rwlock__trywlock (rwlock__t *lock); int rwlock^unlock (rwlock_t *lock);

Spin lo c k s: int int int int int int int int int int

spin_init (spinlock^t *lock); spin__destroy (spinlock^t *lock); spin_lock (spinlock_t *lock); spin_trylock (spinlock_t *lock); spin__unlock (spinlock_t *lock); pthread_spin_init (pthread_spinlock_t *lock); pthread_spin__destroy (pthread_spinlock_t *lock); pthread_spin_lock (pthread_j3pinlock_t *lock); pthread_spin_trylock (pthread_spinlock__t *lock); pthread_spin_unlock (pthread_spinlock_t *lock);

T h r e a d a b o r t: int pthread_abort (pthread_t t h r ead);

T h e s a m e POSIX w o rk in g g ro u p t h a t d ev elo p ed POSIX. l b a n d P th r e a d s h a s d ev elo p ed a n e w s e t o f e x te n s io n s for re a ltim e a n d th r e a d e d p ro g ra m m in g . M ost of th e e x te n s io n s re le v a n t to th r e a d s (an d to th is book) a re th e r e s u lt o f p ro p o s a ls d ev elo p ed by th e POSIX 1 0 0 3 .1 4 profile g ro u p , w h ic h sp ec ia liz e d in “tu n in g ” th e e x istin g POSIX s ta n d a r d s fo r m u ltip ro c e s s o r s y ste m s . POSIX. lj a d d s so m e th re a d sy n c h ro n iz a tio n m e c h a n is m s th a t h av e b e e n com m o n in a w ide ra n g e of m u ltip ro c e ss o r a n d th re a d p ro g ra m m in g , b u t th a t h a d b e e n o m itte d from th e o rig in al P th re a d s s ta n d a r d . B a rrie rs a n d sp in lo c k s a re p rim a rily u s e fu l for fin e-g ra in ed p a ra lle lism , for ex am p le , in s y ste m s t h a t a u to m a tic a lly

358

CHA P T E R 10

F u t u r e st a n d a r d i z a t i o n

g e n e ra te p a ra lle l code from p ro g ra m loops. R e a d /w rite lo ck s a re u s e fu l in s h a re d d a ta a lg o rith m s w h e re m a n y th r e a d s a re allow ed to re a d s im u lta n e o u sly , b u t only o n e th re a d c a n b e allow ed to u p d a te d a ta .

10.2.1

Barriers “B a rrie rs ” a re a fo rm of s y n c h ro n iz a tio n m o s t c o m m o n ly u s e d in p a ra lle l d e c o m p o sitio n of lo o p s. T h e y ’re a lm o s t n e v e r u s e d e x c e p t in co d e d e s ig n e d to r u n o n ly o n m u ltip ro c e s s o r s y s te m s . A b a r r ie r is a “m e e tin g p la c e ” for a g ro u p of a s s o c ia te d th r e a d s , w h e re e a c h w ill w a it u n til all h a v e re a c h e d th e b a rrie r. W h e n th e la s t o n e w a its o n th e b a rrie r, all th e p a rtic ip a tin g th r e a d s a re re le a s e d . S ee S e c tio n 7 .1 .1 for d e ta ils of b a r r ie r b e h a v io r a n d fo r a n ex a m p le sh o w in g h o w to im p le m e n t a b a r r ie r u s in g s ta n d a r d P th r e a d s s y n c h ro n iz a tio n . (Note t h a t th e b e h a v io r of th is e x a m p le is n o t p re c ise ly th e s a m e a s t h a t p ro p o s e d b y POSIX. lj.)

10.2.2

R e a d /w r ite lo cks A r e a d /w r ite lo ck (also so m e tim e s k n o w n a s “r e a d e r /w r ite r lo c k ”) allo w s o n e th r e a d to ex clu siv ely lo ck so m e s h a r e d d a ta to w rite o r m odify t h a t d a ta , b u t a lso allo w s m u ltip le th r e a d s to s im u lta n e o u s ly lo ck th e d a ta for re a d a c c e s s . UNIX98 sp ecifies “r e a d /w r ite lo c k s” v ery sim ila r to POSIX. lj r e a d e r/w r ite r lo cks. A lth o u g h X /O p e n in te n d s t h a t th e tw o sp e cificatio n s w ill b e fu n c tio n a lly id e n tica l, th e n a m e s a re d iffere n t to avoid co nflict s h o u ld th e POSIX s ta n d a r d c h a n g e before ap p ro v al. If y o u r co d e re lie s o n a d a ta s tr u c tu r e t h a t is fre q u e n tly re fe re n c e d , b u t on ly o c c a sio n a lly u p d a te d , y o u s h o u ld c o n s id e r u s in g a r e a d /w r ite lo ck r a th e r th a n a m u te x to a c c e s s t h a t d a ta . M o st th r e a d s w ill b e a b le to re a d th e d a ta w ith o u t w aitin g ; th e y ’ll n e e d to b lo c k only w h e n so m e th r e a d is in th e p ro c e s s of m odifyin g th e d a ta . (S im ilarly, a th r e a d t h a t d e s ire s to w rite th e d a ta will b e b lo c k e d if a n y th r e a d s a re r e a d in g th e d a ta .) S ee S e c tio n 7 .1 .2 fo r d e ta ils of r e a d /w r ite lo c k b e h a v io r a n d fo r a n e x am p le sh o w in g h o w to im p le m e n t a re a d /w r ite lo ck u s in g s ta n d a r d P th r e a d s s y n c h ro n iz a tio n . (Note t h a t th e b e h a v io r of th is ex a m p le is n o t p re c ise ly th e s a m e a s th a t p ro p o s e d b y POSIX. lj.)

* T h e P O S IX w o r k in g g r o u p i s c o n s id e r in g t h e p o s s ib ilit y o f a d a p t in g t h e X S H 5 r e a d / w r it e l o c k d e f i n i t i o n a n d a b a n d o n i n g t h e o r i g i n a l P O S I X . l j n a m e s , b u t t h e d e c i s i o n h a s n ’t y e t b e e n m ade.

P O S IX 1003. l j

359

10.2.3 S pinlocks S p in lo c k s a re m u c h like m u te x e s . T h e re ’s b e e n a lo t of d is c u s s io n a b o u t w h e th e r it ev en m a k e s s e n s e to s ta n d a rd iz e o n a s p in lo c k in te rfa c e — sin c e POSIX sp ecifies on ly a s o u rc e level API, th e r e ’s v ery little POSIX. lj s a y s a b o u t th e m t h a t d is tin g u is h e s th e m fro m m u te x e s . T h e e s s e n tia l id e a is th a t a s p in lo c k is th e m o s t p rim itiv e a n d f a s te s t s y n c h ro n iz a tio n m e c h a n is m av a ila b le o n a given h a rd w a re a r c h ite c tu re . O n so m e s y s te m s , t h a t m a y b e a sin g le “te s t a n d s e t” in s tr u c tio n — o n o th e rs , it m a y b e a s u b s ta n tia l s e q u e n c e o f “lo a d lo ck ed , te s t, s to re c o n d itio n a l, m e m o ry b a r r ie r ” in s tr u c tio n s . T h e c ritic a l d is tin c tio n is t h a t a th r e a d try in g to lo c k a s p in lo c k d o e s n o t n e ce s s a rily b lo c k w h e n th e s p in lo c k is a lre a d y h e ld b y a n o th e r th re a d . T h e in te n t is t h a t th e th r e a d will “s p in ,” re try in g th e lo ck ra p id ly u n til it s u c c e e d s in lo ck in g th e sp in lo c k . (This is o n e of th e “iffy” s p o ts —o n a u n ip ro c e s s o r it h a d b e tte r b lo ck , o r it’ll do n o th in g b u t s p in o u t th e r e s t o f its tim e slic e . . . o r s p in to e te rn ity if it is n ’t tim esliced .) S p in lo c k s a re g re a t for fin e -g ra in e d p a ra lle lis m , w h e n th e co d e is in te n d e d to r u n o n ly o n a m u ltip ro c e ss o r, c a re fu lly tu n e d to h o ld th e sp in lo c k for o n ly a few in s tr u c tio n s , a n d g e ttin g u ltim a te p e rfo rm a n c e is m o re im p o r ta n t th a n s h a r in g th e s y ste m re s o u rc e s c o rd ia lly w ith o th e r p ro c e s s e s . To b e effective, a s p in lo c k m u s t n e v e r b e lo c k ed for a s lo n g a s it ta k e s to “c o n te x t s w itc h ” fro m o n e th r e a d to a n o th e r. If it d o e s ta k e a s lo n g o r longer, y o u ’ll g e t b e tte r o v erall p e rfo rm a n c e b y b lo c k in g a n d allo w in g so m e o th e r th r e a d to do u s e fu l w ork . POSIX. lj c o n ta in s tw o s e ts of s p in lo c k fu n c tio n s : o n e s e t w ith a s p in _ prefix , w h ic h allo w s sp in lo c k s y n c h ro n iz a tio n b e tw e e n p ro c e s s e s ; a n d th e o th e r s e t w ith a p th r e a d _ prefix , allo w in g s p in lo c k s y n c h ro n iz a tio n b e tw e e n th r e a d s w ith in a p ro c e s s . T h is, y o u will n o tic e , is v ery d iffe re n t fro m th e m o d e l u s e d fo r m u te x e s , c o n d itio n v a ria b le s , a n d r e a d /w r ite lo ck s, w h e re th e s a m e f u n c tio n s w ere u s e d a n d th e p s h a re d a ttr ib u te sp ecifies w h e th e r th e re s u ltin g s y n c h ro n iz a tio n o b je ct c a n b e s h a r e d b e tw e e n p ro c e s s e s . T h e ra tio n a le for th is is th a t sp in lo c k s a re in te n d e d to b e v ery fa st, a n d s h o u ld n o t b e s u b je c t to a n y p o s sib le o v e rh e a d a s a r e s u lt o f n e e d in g to d ecid e, a t r u n tim e, h o w to b e h a v e . It is, in fact, u n lik e ly t h a t th e im p le m e n ta tio n o f spin_lock a n d pthread_spin_lock w ill d iffer o n m o s t s y s te m s , b u t th e s ta n d a r d allo w s th e m to b e d iffere n t.

10.2.4 C o n d itio n v a r ia b le w a it c lo c k P th r e a d s c o n d itio n v a ria b le s s u p p o r t o n ly “a b s o lu te tim e ” tim e o u ts . T h a t is, th e th r e a d sp ecifies t h a t it is w illin g to w a it u n til “J a n 1 0 0 :0 0 :0 0 GMT 2 0 0 1 ,” r a th e r t h a n b e in g a b le to sp ecify t h a t it w a n ts to w a it fo r “ 1 h o u r, 10 m in u te s .” T h e re a s o n for th is is t h a t a c o n d itio n v a ria b le w a it is s u b je c t to w a k e u p s for v a rio u s r e a s o n s t h a t a re b e y o n d y o u r c o n tro l o r n o t e a s y to co n tro l. W h e n y o u w ak e e a rly fro m a “ 1 h o u r, 10 m in u te ” w a it it is d ifficu lt to d e te rm in e h o w m u c h of th a t

360

CH A P T E R 10

F u t u r e st a n d a r d i z a t i o n

tim e is left. B u t w h e n y o u w a k e e a rly from th e a b s o lu te w ait, y o u r ta rg e t tim e is still “J a n 1 0 0 :0 0 :0 0 GMT 2 0 0 1 .” (The r e a s o n s for e arly w a k e u p a re d is c u s s e d in S e c tio n 3 .3 .2 .) D e sp ite all th is e x c e lle n t re a s o n in g , “re la tiv e tim e ” w a its a re u s e fu l. O n e im p o r ta n t a d v a n ta g e is th a t a b s o lu te s y s te m tim e is s u b je c t to e x te rn a l c h a n g e s . It m ig h t b e m o dified to c o rre c t fo r a n in a c c u r a te clo ck ch ip , o r b r o u g h t u p -to -d a te w ith a n e tw o rk tim e serv er, o r a d ju s te d for a n y n u m b e r o f o th e r re a s o n s . B o th re la tiv e tim e w a its a n d a b s o lu te tim e w a its re m a in c o rre c t a c r o s s t h a t a d ju s tm e n t, b u t a rela tiv e tim e w a it e x p re s s e d a s if it w ere a n a b s o lu te tim e w a it c a n n o t. T h a t is, w h e n y o u w a n t to w a it for “ 1 h o u r, 10 m in u te s ,” b u t th e b e s t y o u c a n do is a d d th a t in te rv a l to th e c u r r e n t clo ck a n d w a it until t h a t clo ck tim e, th e s y s te m c a n ’t a d ju s t th e a b s o lu te tim e o u t for y o u w h e n th e s y s te m tim e is changed. POSIX. lj a d d r e s s e s th is is s u e a s p a r t o f a s u b s ta n tia l a n d p e rv a siv e “c le a n u p ” o f POSIX tim e serv ice s. T h e s ta n d a r d (b u ild in g o n to p o f POSIX. lb , w h ic h in tro d u c e d th e re a ltim e clo ck fu n c tio n s , a n d th e CL0CK_REALTIME clock) in tro d u c e s a n e w s y s te m clo ck c a lled c l o c k _ m o n o t o n i c . T h is n e w clo ck is n ’t a “re la tiv e tim e r” in th e tra d itio n a l s e n s e , b u t it is n e v e r d e c re a se d , a n d it is n e v e r m odified b y d a te o r tim e c h a n g e s o n th e s y ste m . It in c re a s e s a t a c o n s ta n t ra te . A “re la tiv e tim e ” w ait is n o th in g m o re th a n ta k in g th e c u r r e n t a b s o lu te v a lu e of th e c l o c k _ m o n o t o n i c clock, a d d in g so m e fixed offset (4200 se c o n d s for a w ait of 1 h o u r a n d 10 m in u tes), a n d w aitin g u n til th a t v a lu e of th e clock is re a c h e d . T h is is a c c o m p lish e d b y a d d in g th e c o n d itio n v a ria b le a ttr ib u te clock. You s e t th e clock a ttr ib u te in a th re a d a ttr ib u te s o b je ct u s in g pthread_condattr_setclock a n d re q u e s t th e c u r r e n t v a lu e b y callin g pthread_condattr_getclock. T h e d e fa u lt v a lu e is clock_monotonic, o n th e a s s u m p tio n t h a t m o s t c o n d itio n w a its a re in te rv a ls. W hile th is a s s u m p tio n m a y b e in c o rre c t, a n d it m a y s e e m to b e a n in c o m p a tib le c h a n g e fro m P th r e a d s (an d it is, in a way), th is w a s s w e p t u n d e r th e ru g d u e to th e fa c t t h a t th e tim e d c o n d itio n w a it fu n c tio n su ffe re d fro m a p ro b le m t h a t POSIX. lj fo u n d to b e ex tre m e ly c o m m o n th r o u g h th e e x istin g b o d y of POSIX s ta n d a r d s . ‘T im e ” in g e n e ra l w a s o n ly v ery loosely d efin ed . A tim e d c o n d itio n w ait, for ex am p le, d o e s n o t s a y p recisely w h a t th e tim e o u t a rg u m e n t m e a n s . O nly t h a t “a n e rro r is r e tu r n e d if th e a b s o lu te tim e specified b y a b s tim e p a s s e s (th a t is, s y ste m tim e e q u a ls o r ex ceed s a b s tim e ).” T h e in te n t is c le a r—b u t th e re a re n o sp ecific im p le m e n ta tio n o r u s a g e directiv es. O ne m ig h t re a s o n a b ly a s s u m e t h a t o n e s h o u ld a c q u ire th e c u r r e n t tim e u s in g clock_gettime (CL0CK_REALT1ME , &now), a s su g g e ste d in th e a s s o c ia te d ra tio n a le . However, POSIX “ra tio n a le ” is little m o re th a n h isto ric a l co m m e n ta ry , a n d is n o t p a r t of th e fo rm al s ta n d a r d . F u rth e rm o re , clock_gettime is a p a r t of th e o p tio n al _P0SIXJT1MERS s u b s e t of POSIX. lb , a n d th e re fo re m a y n o t e x ist o n m a n y s y ste m s s u p p o rtin g th re a d s . POSIX. lj is a tte m p tin g to “ratio n a liz e ” all of th e s e loose e n d s, a t le a s t for sy ste m s th a t im p le m e n t th e e v e n tu a l POSIX. lj s ta n d a rd . O f c o u rse , th e CL 0 CK_M 0 N 0 T 0 N 1 C fe a tu re is u n d e r a n o p tio n of its ow n, a n d ad d itio n ally relies o n th e _posix__timers

P O S I X 1 0 0 3 .1 4

361

option , so it is n ’t a cu re-all. In th e a b s e n c e of th e s e o p tio n s, th e re is n o clo ck a ttr ib u te , a n d n o w ay to b e s u r e of rela tiv e tim e o u t b e h a v io r—o r ev en co m p lete ly p o rta b le beh av io r.

10.2.5 T h re a d a b o r t T h e pthread_abort fu n c tio n is e s s e n tia lly fail-safe c a n c e lla tio n . It is u s e d only w h e n y o u w a n t to b e s u r e th e th re a d will te rm in a te im m ed iately . T h e d a n g e ro u s a s p e c t of pthread_abort is th a t th e th r e a d d o e s n o t r u n c le a n u p h a n d le r s o r h a v e a n y o th e r o p p o rtu n ity to c le a n u p a fte r itself. T h a t is, if th e ta rg e t th r e a d h a s a m u te x lo cked , th e th r e a d will te rm in a te w ith th e m u te x still lo cked. B e c a u se y o u c a n n o t u n lo c k th e m u te x from a n o th e r th re a d , th e a p p lic a tio n m u s t b e p re p a re d to a b a n d o n th a t m u te x en tirely . F u rth e r, it m e a n s th a t a n y o th e r th r e a d s t h a t m ig h t b e w a itin g fo r th e a b a n d o n e d m u te x will c o n tin u e to w a it for th e m u te x forev er u n le s s th e y a re a lso te rm in a te d b y c allin g pthread_abort. In g en era l, re a l a p p lic a tio n s c a n n o t reco v er from a b o rtin g a th re a d , a n d y o u s h o u ld never, ever, u s e p th r e a d _ a b o r t. However, for a c e rta in c la ss of a p p lic a tio n s th is cap a b ility is re q u ire d . Im agine, for ex am p le, a re a ltim e e m b e d d e d co n tro l syste m t h a t c a n n o t s h u t do w n a n d m u s t r u n reliably a c ro s s a n y tr a n s ie n t failu re in so m e alg o rith m . S h o u ld a th re a d e n c o u n te r a ra r e b o u n d a ry c o n d itio n b u g , a n d h a n g , th e a p p lic a tio n m u s t recover. In s u c h a s y ste m , all w a it o p e ra tio n s u s e tim e o u ts , b e c a u s e re a ltim e re s p o n s e is c ritica l. S h o u ld o n e th r e a d d e te c t th a t s o m e th in g h a s n ’t h a p p e n e d in a re a s o n ab le tim e, for e x am p le, a n a v ig a tio n a l th r e a d h a s n ’t rece iv ed s e n s o r in p u t, it will n o tify a n “e rro r m a n a g e r.” If th e e rro r m a n a g e r c a n n o t d e te rm in e w h y th e th r e a d m o n ito rin g th e s e n s o r h a s n ’t re s p o n d e d , it will try to re co v e r. It m a y a tte m p t to c a n c e l th e s e n s o r th r e a d to ac h ie v e a sa fe s h u td o w n , b u t if th e s e n s o r th r e a d fails to re s p o n d to th e c a n c e l in a r e a s o n a b le tim e, th e a p p lic a tio n m u s t c o n tin u e a n y w ay. T h e e rro r m a n a g e r w o u ld th e n a b o r t th e s e n s o r th re a d , a n a ly z e a n d c o rre c t a n y d a ta s t r u c t u r e s it m ig h t h a v e c o rru p te d , c re a te a n d a d v e rtis e n e w m u te x e s if n e c e s s a ry , a n d c re a te a n e w s e n s o r th re a d .

10.3 POSIX 1003.14 POSIX. 14 is a d iffe re n t s o r t of s ta n d a r d , a “POSIX S ta n d a r d p ro file.” U nlike P th r e a d s a n d POSIX. lj, POSIX. 14 d o e s n o t a d d a n y n e w c a p a b ilitie s to th e POSIX fam ily. In s te a d , it a tte m p ts to p ro v id e so m e o rd e r to th e m a z e of o p tio n s th a t fa c e s im p le m e n to rs a n d u s e r s of POSIX. T h e POSIX. 14 sp ecifies w h ic h POSIX o p tio n a l b e h a v io r s h o u ld b e c o n sid e re d “r e q u ir e d ” for m u ltip ro c e s s o r h a rd w a re s y ste m s . It a lso ra is e s so m e of th e m in im u m v a lu e s d efin e d for v a rio u s POSIX lim its. T h e POSIX. 14 w o rk in g g ro u p a lso

362

CH A P T E R 10

F u t u r e st a n d a r d i za t i o n

d ev ised re c o m m e n d a tio n s for a d d itio n a l POSIX in te rfa c e s b a s e d o n th e s u b s ta n tia l m u ltip ro c e s s in g a n d th r e a d in g e x p e rie n c e of th e m e m b e rs . M an y of th e in te rfa c e s d ev elo p ed b y POSIX. 14 h a v e b e e n in c lu d e d in th e POSIX. lj d ra ft s ta n d a r d . O n ce POSIX. 14 b e c o m e s a s ta n d a r d , in th e o ry , p r o d u c e r s of POSIX im p lem e n ta tio n s w ill b e a b le to c laim c o n fo rm a n c e to POSIX. 14. A n d th o s e w h o w ish to d evelop m u ltith r e a d e d a p p lic a tio n s m a y fin d it c o n v e n ie n t to lo o k fo r POSIX. 14 c o n fo rm a n c e r a th e r t h a n sim p ly P th r e a d s c o n fo rm a n c e . (It re m a in s to b e s e e n w h e th e r v e n d o rs o r u s e r s will a c tu a lly do th is , s in c e e x p e rie n c e w ith POSIX S ta n d a r d P rofiles is c u rre n tly slig h t.) T h e POSIX. 14 w o rk in g g ro u p a lso trie d to a d d r e s s im p o r ta n t is s u e s s u c h a s th e se : • • •

P ro v id in g a w ay for th r e a d e d co d e to d e te rm in e th e n u m b e r of activ e p ro c e s s o rs . P ro v id in g a w ay for th r e a d s to b e “b o u n d ” o n to p h y s ic a l p ro c e s s o rs . P rovid in g a “p ro c e s s o r m a n a g e m e n t” c o m m a n d to c o n tro l w h ic h p ro c e s s o rs a re u s e d b y th e sy ste m .

A lth o u g h th e s e c a p a b ilitie s a re u n iv e rs a lly a v a ila b le in all m u ltip ro c e s s o r sy ste m s of w h ic h th e w o rk in g g ro u p w a s a w a re , th e y w ere d ro p p e d fro m th e s ta n d a r d b e c a u s e of m a n y u n re s o lv e d is s u e s , in c lu d in g th e s e : •



W h a t good d o e s it do to k n o w h ow m a n y p ro c e s s o rs th e re a re , if y o u c a n n o t tell h o w m a n y y o u r co d e m a y u s e a t a n y tim e ? R em em ber, th e in fo rm a tio n c a n c h a n g e w h ile y o u a re a s k in g for it. W h a t is really n e e d e d is a fu n c tio n a s k in g th e q u e s tio n “W ould th e c u r r e n t p ro c e s s b e n e fit fro m c re a tio n of a n o th e r th r e a d ? ” We d o n ’t k n o w h o w to a n s w e r t h a t q u e s tio n , o r h o w to p ro v id e e n o u g h in fo rm a tio n o n all re a s o n a b le a r c h ite c tu r e s t h a t th e ap p lic a tio n c a n a n s w e r it. H ow c a n w e b in d a th r e a d to a p ro c e s s o r a c ro s s a w ide ra n g e of m u ltip ro c e s s o r a rc h ite c tu re ? O n a n o n u n ifo rm m e m o ry a c c e s s s y ste m , for ex am p le, r e p re s e n tin g th e p ro c e s s o rs a s a u n ifo rm a r r a y o f in te g e r id e n tifie rs w o u ld b e m isle a d in g a n d u s e le s s —b in d in g o n e th r e a d to p ro c e s s o r 0 a n d a n o th e r closely c o o p era tiv e th r e a d to p ro c e s s o r 1 m ig h t p u t th e m a c ro s s a rela tiv ely slow c o m m u n ic a tio n s p o rt r a th e r th a n o n tw o p ro c e s s o rs s h a rin g a b a n k of m em o ry .

E v e n tu a lly , so m e s ta n d a r d s o rg a n iz a tio n (p o ssib ly POSIX) w ill n e e d to a d d r e s s th e s e is s u e s a n d d evelop p o rta b le in te rfa c e s . T h e fo lk s w h o a tte m p t th is fe a t m a y fin d th a t th e y n e e d to lim it th e sco p e of th e s ta n d a r d to a field n a rro w e r th a n “s y s te m s o n w h ic h p eo p le m a y w ish to u s e th r e a d s .”

B ib lio g ra p h y

T h o m a s E. A n d e rso n , B ria n N. B e rs h a d , E d w a rd D. L azow ska, a n d H e n ry M. Levy, “S c h e d u le r A ctiv atio n s: Effective K ern el S u p p o rt for th e U ser-L evel M a n a g e m e n t of P a ra lle lis m ,” P ro ce e d in g s o f the T h irte e n th A C M S y m p o s iu m o n O p e ra tin g S y s te m s P rin cip le s , O c to b e r 1991.

[A n d e r so n , 1 9 9 1 ]

R e s e a rc h p a p e r d e s c rib in g th e a d d itio n o f a n efficien t “tw o -level s c h e d u le r ” m e c h a n is m fo r o p e ra tin g s y s te m s . T h is is w h e re all m o d e rn tw o -level s c h e d u le r s y s te m s s ta r te d —e v ery o n e’s re a d it, ev ery o n e re fe re n c e s it, a n d everyo n e ’s b e e n in s p ire d b y it. A n d re w D. B irrell, A n In tro d u ctio n to P ro g ra m m in g w ith T h re a d s , SRC R e s e a rc h R e p o rt 35, D ig ital S y s te m s R e s e a rc h C en ter, 130 L y tto n Ave., P alo Alto, CA 9 4 3 0 1 , J a n u a r y 19 89 . A vailable o n I n te r n e t fro m h t t p : / / w w w .r e s e a r c h .d ig ita l.c o m /S R C /p u b lic a tio n s /s r c - r r .h tm l

[B ir r e ll, 1 9 8 9 ]

A n in tro d u c tio n to th e c o n c e p ts of th r e a d e d p ro g ra m m in g . A lth o u g h sp ecifi‫־‬ cally o rie n te d to w a rd M o d u la-2 + a n d S R C ’s T a o s m u ltith r e a d e d o p e ra tin g sy ste m , m a n y e s s e n tia l c o n c e p ts re m a in e asily rec o g n iz a b le in P th re a d s . 1 9 9 3 ] J o s e p h B oykin , D av id K irsc h e n , A lan L a n g e rm a n , a n d S u s a n LoVerso, P ro g ra m m in g u n d e r M a ch , A ddison-W esley, R ead in g , MA, ISBN 0 -2 0 1 -5 2 7 3 9 -1 , 199 3.

[ B o y k in ,

H elen C u s te r, 4 8 1-X, 1993.

[C u ste r , 1 9 9 3 ]

In s id e W in d o w s N T,

M icrosoft P re s s, ISBN 1 -5 5 6 1 5 ‫־‬

1 9 9 6 1 D ig ital E q u ip m e n t C o rp o ra tio n , G u id e to D E C th re a d s , D igital E q u ip m e n t C o rp o ra tio n , p a r t n u m b e r AA-Q2DPC-TK, 1996.

[D ig it a l,

R eferen ce m a n u a l for D ig ital’s D E C th re a d s im p le m e n ta tio n of th e P th re a d s s ta n d a r d . A n a p p e n d ix (w hich w ill b e rem o v e d a fte r th e D ig ital UNIX 4 .0 a n d O penV M S 7 .0 v e rsio n s) p ro v id e s re fe re n c e in fo rm a tio n o n th e o b so le te c m a a n d D C E th r e a d s (POSIX 1 0 0 3 .4 a d ra ft 4) in te rfa c e s . E. W. D ijk stra , “S o lu tio n o f a P ro b lem in C o n c u rre n t P ro g ra m m in g C o n tro l,” C om m u n ica tio n s o f the A C M , Vol. 8 (9), S e p te m b e r 1965, pp. 5 6 9 -5 7 0 .

[ D ijk s tr a , 1 9 6 5 ]

[ D ijk s tr a ,

1968a]

E. W. D ijk stra , “C o o p e ra tin g S e q u e n tia l P ro c e s s e s ,” P ro g ra m e d ite d b y F. G e n u y s, A cad em ic P re ss, New York, 1968 , p p .

m in g L a n g u a g e s ,

4 3 -1 1 2 . E. W. D ijk stra , ‘T h e S tr u c tu r e o f th e T H E ’—M u ltip ro g ra m m in g S y s te m ,” C o m m u n ica tio n s o f the A C M , Vol. 11 (5), 19 68, p p . 3 4 1 -3 4 6 .

[ D ijk s tr a , 1 9 6 8 b ]

363

364

Bi bl i o g r a p h y

Bill O. G allm eister, P O S IX .4 : P ro g ra m m in g f o r O ’Reilly, S e b a s to p o l. CA, ISBN 1 -5 6 5 9 2 -0 7 4 -0 , 199 5.

[ G a llm e is t e r , 1 9 9 5 ]

the R e a l W o rld ,

POSIX 100 3. l b - 1 9 9 3 re a ltim e p ro g ra m m in g (b ased o n a n e a r-fin a l d ra ft of th e s ta n d a rd ). [H o a r e , 1 9 7 4 ]

c e p t,”

C.A.R. H o are, “M o n ito rs: A n O p e ra tin g S y s te m S tr u c tu r in g C onVol. 17 (10), 19 74, p p . 5 4 9 -5 5 7 .

C om m u n ica tio n s o f the A C M ,

[ I E E E , 1 9 9 6 ] 9 9 4 5 - 1 :1 9 9 6 ( IS O / IE C ) [IE E E / A N S I S td 1003.1 1 9 9 6 E d itio n ] I n f or-

m o tio n

T e ch n o lo g y — P o rta b le

O p e ra tin g

S y s te m

In te rfa ce

( P O S IX )— P a rt

S y s te m A p p lic a tio n : P ro g ra m In te rfa ce (A P I) [C L a n g u a g e ] (A N S I) ,

1:

IE E E S ta n -

d a r d s P re s s, ISBN 1 -5 5 9 3 7 -5 7 3 -6 , 1996 . T h e POSIX C L a n g u a g e in te rfa c e s , in c lu d in g re a ltim e a n d th r e a d s . M ich ael B. J o n e s , “B rin g in g th e C L ib ra rie s W ith U s in to a M ultiT h re a d e d F u tu r e ,” W in te r 1991 U s e n ix C o n fe re n ce P ro ce e d in g s , D allas, TX, J a n u a r y 199 1 , p p . 8 1 -9 1 .

[J o n e s, 1 9 9 1 ]

[K le im a n ,

1996]

S tev e K leim an , D ev an g S h a h , a n d B a rt S m a a ld e rs , P ro g ra m P re n tic e H all, E n glew ood Cliffs, N J, ISBN 0 -1 3 -1 7 2 3 8 9 -8 ,

m in g w ith Th re a d s ,

1996. T h is b o o k s h a r e s so m e c h a r a c te r is tic s w ith th e b o o k y o u a re h o ld in g . B o th , fo r ex am p le, involve a u t h o r s w h o w ere d ire c tly in vo lved in th e POSIX s ta n d a r d w o rk in g g ro u p , a n d w ere a lso p rin c ip a l a r c h ite c ts o f th e ir re sp e c tiv e c o m p a n ie s ’ th r e a d im p le m e n ta tio n s . D o u g Lea, C o n cu rre n t P ro g ra m m in g ing, MA, ISBN 0 -2 0 1 -6 9 5 8 1 -2 , 1997.

[L e a , 1 9 9 7 ]

in J a v a ™ ,

A ddison-W esley, R ead -

A d iffe re n t view o f th r e a d s , fro m th e p e rs p e c tiv e o f th e Ja v a ™ la n g u a g e , w h ic h p ro v id e s u n iq u e c o n s tr u c ts fo r th r e a d s y n c h ro n iz a tio n w ith in th e la n g u a g e . Bil Lew is a n d D a n ie l J . B erg, 0 -1 3 -4 4 3 6 9 8 -9 , 19 95 .

[ L e w is , 1 9 9 5 ]

T h re a d s P rim e r,

S u n S o ft P re s s, ISBN

A good in tro d u c tio n to th r e a d e d p ro g ra m m in g for th e novice. T h e firs t e d itio n p rim a rily d e a ls w ith S o la ris “UI th r e a d s ,” w ith so m e in fo rm a tio n o n POSIX th r e a d s . [L o c k h a r t, 1 9 9 4 ]

H aro ld W. L o c k h a rt, J r ., O S F D C E , G u id e to D e v e lo p in g D is trib ‫־‬ M cG raw -H ill, New York, ISBN 0 -0 7 -9 1 1 4 8 1 -4 , 199 4.

u te d A p p lica tio n s ,

A c h a p te r o n D C E th r e a d s d e s c rib e s h o w to u s e th r e a d s in b u ild in g D C E a p p lic a tio n s . P a u l F. M c J o n e s a n d G a rre t F. S w a rt, “Ev olving th e UNIX S yste m In te rfa c e to S u p p o r t M u ltith re a d e d P ro g ra m s ,” SR C R e s e a rc h R e p o rt 21, D ig ital S y s te m s R e s e a rc h C en ter, 130 L y tto n Ave., P alo Alto, CA 9 4 3 0 1 , S ep te m b e r 1989. A vailab le o n I n te r n e t fro m h ttp ://w w w .r e s e a r c h .d ig ita l.c o m / S R C /p u b lic a tio n s /s r c - r r .h tm l

[M c J o n e s, 1 9 8 9 ]

R e p o rt o n a d a p ta tio n of UNIX s y s te m for m u ltith re a d e d p ro g ra m m in g .

365

Bi bl i o g r a p h y

[S c h im m e l, 1 9 9 4 ] C u r t S c h im m e l, U N IX S y s te m s f o r M o d e rn son-W esley. R ead in g . MA, ISBN 0 -2 0 1 -6 3 3 3 8 -8 , 19 94 .

A rch ite ctu re s ,

A ddi-

S u b s ta n tia l d e ta il o n th e im p le m e n ta tio n of m u ltip ro c e s s o rs a n d s h a r e d m e m o ry s y ste m s . If S e c tio n 3 .4 in th e b o o k y o u ’re h o ld in g d o e s n ’t s a tis fy y o u r t h i r s t for k n o w le d g e, th is is w h e re y o u s h o u ld go.

T h re a d re s o u rce s o n th e In te rn e t

In th e m id s t o f th e w o rd h e w as tryin g to say, In th e m id s t o f his la u g h te r a n d g le e , H e h a d softly a n d s u d d e n ly v a n is h e d a w a y — For th e Snark was a B oojum , y o u see. THE END — L e w is C a r r o l T h e H u n t in g o f t h e S n a r k

T h is list p ro v id e s a few s ta r tin g p o in ts for in fo rm a tio n . O f c o u rs e , th e w eb c h a n g e s all th e tim e, so n o list c o m m itte d to p a p e r will ever b e co m p lete ly co rrect. T h a t’s life in th e in fo rm a tio n age.

N ew sgro ups c o m p .p r o g r a m m i n g .t h r e a d s

G e n e ra l, u n m o d e ra te d d is c u s s io n of a n y th in g re la te d to th r e a d s . T h is g ro u p is fre q u e n te d by a n u m b e r o f p e o p le h ig h ly k n o w le d g e a b le a b o u t th r e a d s in g e n e ra l, a n d a b o u t v a rio u s specific im p le m e n ta tio n s of P th re a d s . It’s a n ic e, frien d ly p la c e to a s k a b o u t p ro b le m s y o u ’re h a v in g , o r th in g s y o u w o u ld lik e to do. P lea se, d o n ’t a s k a b o u t s c re e n s a v e rs ! A nd , if y o u w a n t to a s k a b o u t a p ro b lem , a lw ay s re m e m b e r to te ll u s w h a t ty p e o f h a rd w a re a n d o p e ra tin g s y s te m y o u ’re u s in g a n d in c lu d e th e v e rsio n . comp.unix.osf.osfl

T h e p rim a ry d is c u s s io n g ro u p fo r th e D ig ital UNIX o p e ra tin g s y ste m . T h e re are , o f c o u rs e , h is to ric a l re a s o n s for th e n o n in tu itiv e n a m e . T h is is a re a s o n a b le p la c e to a s k q u e s tio n s a b o u t u s in g th r e a d s o n D ig ital UNIX. If th e q u e s tio n (or p ro b lem ) d o e s n ’t s e e m to b e sp ecific to D ig ital UNIX, comp.programming.threads m a y b e m o re a p p ro p ria te , b e c a u s e it p r e s e n ts y o u r q u e s tio n to a la rg e r a u d ie n c e of th r e a d e x p e rts, a n d m a k e s th e a n s w e r av a ila b le to a la rg e r a u d ie n c e of th r e a d u s e rs . c o m p .u n i x .s o l a r i s

T h e p rim a ry d is c u s s io n g ro u p for th e S o la ris o p e ra tin g sy ste m . T h is is a re a s o n a b le p la c e to a s k q u e s tio n s a b o u t u s in g th r e a d s o n S o la ris. If th e q u e s tio n (or p ro b lem ) d o e s n ’t s e e m to b e specific to S o la ris, comp.programming.threads m a y

367

368

T h r ea d r eso u r c es o n t h e I n t er n et

b e m o re a p p ro p ria te , b e c a u s e it p r e s e n ts y o u r q u e s tio n to a la rg e r a u d ie n c e of th r e a d e x p e rts, a n d m a k e s th e a n s w e r a v a ila b le to a la rg e r a u d ie n c e of th r e a d u se rs.

W e b sites h t t p : / / a l t a v i s t a . d i g i t a l . com / A lta v ista is a m u ltith r e a d e d w eb s e a r c h e n g in e d ev elo p ed b y D ig ital E q u ip m e n t C o rp o ra tio n . It is a lso a n e x ce lle n t s e a rc h e n g in e t h a t y o u c a n u s e to find o u t a b o u t n e a rly a n y th in g . A lw ays a good p la c e to s ta r t. h t t p : / / w w w .a w .c o m /c p /b u te n h o f / p o s ix . h tm l T h e A d d iso n -W esley w eb p a g e c o n ta in in g in fo rm a tio n a b o u t th is b o o k , in c lu d in g th e s o u rc e for all th e e x a m p le p ro g ra m s. h ttp ://w w w •b e s t• c o m /~ b o s /th re a d s -fa q / T h is p a g e is a lis t of fre q u e n tly a s k e d q u e s tio n s (FAQ) fro m th e comp, p ro g ra m ming .threads n e w sg ro u p . P le a se re a d th is b efo re y o u re a d comp.programming. threads, in o rd e r to av oid a s k in g a w id e ra n g e of q u e s tio n s t h a t h a v e b e e n a s k e d a m illio n tim e s before. T h e in fo rm a tio n in th is p ag e is a lso p o s te d to th e n e w sg ro u p a t r e g u la r in te rv a ls . h t t p : / / l i i n w w w . i r a • u k a • d e / b i b l i o g r a p h y / O s / t h r e a d s . h tm l A s e a rc h a b le b ib lio g ra p h y o f te rm s re la te d to th re a d in g , m a in ta in e d b y th e U n iv e rsity of O slo in N orw ay. h ttp ://w w w • d ig ita l.c o m / D igital E q u ip m e n t C o rp o ra tio n w eb site . T h is site in c lu d e s a lo t of in fo rm a tio n o n th e D ig ital UNIX a n d O penV M S o p e ra tin g s y s te m s , in c lu d in g in fo rm a tio n o n th r e a d s a n d m u ltip ro c e s s o r sy ste m s . h ttp ://w w w .s u n .c o m / S u n M ic ro sy ste m s, In c., w eb site . T h is site in c lu d e s , a s y o u m ig h t g u e s s , a lo t o f in fo rm a tio n o n th e S o la ris o p e ra tin g s y ste m . You c a n a lso fin d in fo rm a tio n a b o u t th e J a v a la n g u a g e , w h ic h p ro v id es a n in te re s tin g v a r ia n t o f th r e a d s u p p o r t b y m a k in g th r e a d s y n c h ro n iz a tio n a n ex p licit a ttr ib u te of a c la s s m e th o d . h t t p : / /www. s g i . c o m / S ilico n G ra p h ic s , Inc., w eb site. In fo rm a tio n o n SGI s y s te m s a n d th e IRIX o p e ra tin g s y ste m . h t t p : / /www • n e t c o m . c o m /-‫ ״‬b r o w n e l 1 / p t h r e a d s + + . h t m l In fo rm a tio n o n a n a tte m p t to "define a s ta n d a rd iz e d a p p r o a c h to th e u s e of th r e a d in g in th e C++ la n g u a g e .”

In d e x

m u tex a ttrib u te s, 135-136, 185 th re a d a ttrib u te s, 138-14 1, 174, 181, 231

A

A bort th re a d , 361 aio_read, 230 aio_write, 230 A llocation d o m a in , 181 -1 8 3 A m dahl’s Law, 2 1 -2 2 , 297 A NSIC a n d cancellation, 151 a n d deadlo ck s, 29 8 a n d d e s tru c to r fu n ctio n s, 168 an d fork h a n d le rs, 199 -2 0 0 a n d k ern el entities, 1 8 9 -1 9 0 library, ru n tim e, 28 4 a n d priority inversions, 300 proto type for P th read in terfaces, 3 1 0 -3 4 6 a n d seq u en ce races, 29 6 a n d signals, 21 7 a n d th read in g , 2 4 -2 5 void *, u se of, 311 S e e als o Stdio (function) Apple M acin tosh toolbox, 23 asctim e_r (function), 213, 3 3 9 -3 4 0 A ssem bly languag e a n d th rea d in g , 2 4 -2 5 A ssem bly line. S ee Pipeline program m in g m odel A sy n ch ro n o u s cancelability, 150-154, 249 co m m u n ic atio n betw een p ro cesses, 8 definition of, 2, 4 I/O o p eratio n s, 2 2 -2 3 program m ing, 8 -1 2 , 15-21 sigw ait, 2 2 7 -2 3 0 a n d UNIX, 9-11 See a ls o Memory, visibility A sync-signal safe fu n ctio n s, 198, 234 Atomicity, 61, 7 2 -7 3 , 93 A ttrib u te objects condition variable attrib u te s, 13 7-138 definition of, 1 3 4 -1 35 a n d d etachin g, 37, 43, 231

B

B ailing p ro g ram m ers b a rrie rs analogy, 242 can cellatio n analogy, 143 co ndition v aria b le analogy, 71 m u tex analogy, 4 7 -4 8 overview of, 3 -4 thread-specific d a ta analogy, 16 2-163 B arrie rs definition of, 241 m em ory, 9 2 -9 5 POSIX 1003. lj, 358 a n d sy n ch ro n izatio n , exten ded, 2 4 2 -2 5 3 Se e als o C ondition variables; M utexes B locking th re a d s, 42 B ro ad ca st an d condition variab les, 7 2-76, 8 0 -8 2 an d m em ory visibility, 89 an d w ork crew s, 109 C C la nguage. S ee ANSI C C ache lines, 3 0 4 -3 0 5 C ancellatio n asy n ch ro n o u s, 15 0-154, 249 clean u p h a n d le rs, 147, 154-161 deferred, 147 -150, 249 definition of, 1 4 2 -147 fail-safe in POSIX 1003. lj, 361 interfaces, 3 2 3 -3 2 5 po in ts, list of, 147 -1 4 8 p o in ts in XSH5, 3 5 5 -3 5 6 sta te , 143 -1 4 4 type, 1 4 3-144 C le an u p h a n d le rs, 147, 154-161 C lient serv er p rogram m in g model, 1 2 0-129

370

In d ex

clock_gettim e (function), 13 CLOCK_MONOTONIC (value), 360 Code. Se e Program s, exam ples of C om m unicatio n. S e e C ondition varia b le s C om puting overhead a n d th re a d s, 26 C o n cu rren cy ben efit of th read in g , 2 2 -2 4 control fu nctions, definition of, 7 -8 definition of, 4 -5 level in XSH5, 3 5 1 -3 5 3 a n d parallelism , 5 -6 serialization, av oidance of, 3 0 2 -3 0 3 a n d th re a d im plem entatio n, 190 S e e als o A sy n ch ro n o u s; T h rea d s C ondition variables a ttrib u te s, 1 3 7-138 an d blocked th re a d s, 42 a n d client-serv er p rogram m in g model, 121

b ro ad ca stin g , 8 1 -8 2 c reatin g a n d destroying, 7 4 -7 6 definition of, 8 in terfaces, 3 1 9 -3 2 2 a n d pipeline program m ing m odel, 101 a n d sem ap h o re s, 237 sh arin g , avoid an ce of, 30 0 signaling, 8 1 -8 2 a s a sy n ch ro n izatio n m ech an ism , 4, 8, 30, 7 0 -7 3 a n d th read -safety , 6 -7 w ait clock (POSIX 1003. lj), 3 5 9 -3 6 1 w aiting on, 77 -81 w aking w aiters, 8 1 -8 2 a n d w ork crew pro g ram m in g model, 107 S e e also B arriers; M utexes; Predicates; Sig nals C o n te n tio n sc o p e , 1 8 1 -183 C on text s tru c tu re , 6 -7 C ritical sectio n s, 46 ctim e_r (function), 213, 340 D

DCE th re a d s, 154, 290, 353 D eadlocks avoidance of, 2 6 -2 7 , 2 9 7 -2 9 9 a n d lock hie rarch y , 6 3 -6 9 a n d sig nals, 215

a n d th re a d -sa fe libraries, 2 8 4 -2 8 5 Se e a ls o Priority in versions D ebugging, th re a d s cach e lines, 3 0 4 -3 0 5 c o n c u rre n t serialization, avoidance of, 3 0 2 -3 0 3 co ndition variable sh arin g , avoidance of, 300 a n d co sts of th read in g , 13, 2 7 -2 8 deadlock s, avoidance of, 2 9 7 -2 9 9 in tro d u ctio n to, 13 m em ory co rru p te rs, avoidance of, 301 m u tex es, rig h t n u m b e r of, 3 0 3 -3 0 4 prio rity inversions, avo idan ce of, 2 9 9 -3 0 0 th re a d in ertia , avo idan ce of, 2 9 1 -2 9 3 th re a d race, avoidance of, 2 9 3 -2 9 7 tools for, 290, 302 Se e a ls o E rro rs D efault m u tex es, 3 4 9 -3 5 1 D eferred cancelability, 14 7-150, 249 D e stru c to r fu n ctio n s, 167-172 D etach creatin g a n d u sin g th re a d s, 3 7 -3 9 a n d m ultiple th re a d s, 17-19 term in atio n , 43 a n d th re a d a ttrib u te s, 138-141 D igital UNIX m u tex erro r detectio n a n d reporting, 311 th re a d debu gg ing library, 290 p ro g ram m in g exam ples, in tro d u ctio n to, 12-13 d etectin g m em ory co rru p te rs, 301 SIGEV-THREAD im plem entatio n, 231 D ijkstra, E dsgerW ., 47 D irectory search in g fu nction, 212

EAGAIN (error), 314, 318, 326, 344 , 353 EBUSY (error), 49, 58, 65, 3 1 8 -3 2 1 , 345 EDEADLK (error), 32, 3 1 8 -3 1 9 , 346 EINTR (error), 346 EINVAL (error), 3 1 2 -3 2 6 , 3 4 3 -3 4 6 , 3 5 1 -3 5 5 E n ca p su latio n , 24, 75 ENOMEM (error), 313, 317 -3 2 1 , 326, 336 ENOSPC (error), 345 ENOSYS (error), 3 1 2 -3 1 6 , 3 4 4 -3 4 6

371

In d ex

ENXIO (error), 35 5 EOVERFLOW (error), 355 EPERM (error), 318, 34 5 ERANGE (error), 210, 3 4 1 -3 4 2 err_ab ort, 3 3 -3 4 errn o , 3 1 -3 4 , 117, 228 errn o _ ab o rt, 3 3 -3 4 e rrn o .h (header file), 3 2 -3 3 E rro r detection a n d repo rting, 3 1 0 -3 1 1 E rro rch eck m utex es, 3 4 9 -3 5 1 E rro rs EAGAIN, 314, 318, 326, 344, 353 EBUSY, 49, 58, 65, 3 1 8 -3 2 1 , 34 5 EDEADLK, 32, 3 1 8 -3 1 9 , 346 EINTR, 346 EINVAL, 3 1 2 -3 2 6 , 3 4 3 -3 4 6 , 3 5 1 -3 5 5 ENOMEM, 313, 3 1 7 -3 2 1 , 326, 3 3 6 ENOSPC, 345 ENOSYS, 3 1 2 -3 1 6 , 3 4 4 -3 4 6 ENXIO, 355 EOVERFLOW, 355 EPERM, 318, 345 ERANGE, 210, 3 4 1 -3 4 2 ESPIPE, 355 ESRCH, 32, 314, 323, 343 ETIMEDOUT, 78, 80, 86, 322 e rro rs.h (h eader file), 13 ESPIPE (error), 355 ESRCH (error), 32, 314, 323, 343 ETIMEDOUT (error), 78, 80, 86, 322 Ev ents an d co n cu rren cy , 2 3 -2 4 a s a sy n ch ro n iz atio n m ech an ism , 8 Exec, 204 E xecution context a rc h ite c tu ra l overview, 30 definition of, 7 -8

G

G allm eister, Bill, 294 getc (function), 207 g e tc h a r (function), 207 g etch ar_ u n lo ck ed (function), 2 0 7 -2 0 9 , 3 38 getc_ unlock ed (function), 2 0 7 -2 0 8 , 337 getgrgid_r (function), 341 g etg rn am _ r (function), 341 getlogin_r (function), 210, 339 getpw nam _r (function), 342 getpw uid_r (function), 342 gm tim e_r (function), 340 G ro up a n d u s e r d a ta b a s e fu nctio n, 2 1 3 -2 1 4 H

H ard realtim e, 1 7 2 -173 I

in h e ritsc h e d (attribute), 138-141, 176 Initial (main) th re a d a n d creation, 4 0 -4 2 initialization, one tim e, 1 3 1-1 34 overview of, 3 6 -3 7 sig nal m a sk , 216 Initialization, 1 3 1 -1 3 4 In v aria n ts an d condition v ariables, 71, 75 definition of, 4 5 -4 6 an d m utexes, 6 1 -6 4 S e e als o P red icates I/O o p eratio n s an d blocked th re a d s, 42 a n d can cellatio n p o in ts, 1 4 8-149 c an d id a te for th re a d s, 29 a n d con cu rren cy , 2 2 -2 3 paralle l in XSH5, 3 5 4 -3 5 5

F

fgets (function), 14 flockfile (function), 121, 2 0 5 -2 0 7 ,

J

Jo in , 3 7 -3 9 , 139, 145

336-337

Fork in a sy n c h ro n o u s prog ram , 15, 19 definition of, 197 -1 9 8 h a n d lers, 199-203 , 336 ftiylockfile (function), 207, 337 funlockfile (function), 121, 2 0 5 -2 0 7 , 337

K

K ernel en tities a n d co n ten tio n scop e th re a d , 182 im p lem en tatio n of, 189 m an y to few (two level), 193-1 95 m an y to one (u ser level), 190-191

372

K ernel en tities (continue d ) one to one (kernel level), 1 9 1-1 93 settin g in XSH5, 3 5 1 -3 5 3 L Libraries for debugging, 290 im plem entatio n, 190 legacy, 2 8 5 -2 8 7 th rea d -sa fe , 2 8 3 -2 8 5 Light w eight p ro cesses, 1 lim its.h (file header), 308 10caltime_r (function), 340 LWP. S e e K ernel en tities M M ain (initial) th re a d a n d creation, 4 0 -4 2 initialization, one tim e, 1 3 1-134 overview of, 3 6 -3 7 sig nal m ask , 216 M any to few (two level) im plem entatio n, 193 -1 9 5 M any to one (u ser level) im plem entatio n, 190-191 M emory b arrie rs, 9 2 -9 5 co herence, 47, 92 conflict, 94 c o rru p te rs, avo idan ce of, 301 leaks, 198 ordering, 48, 90, 9 2 -9 3 sta c k g u ard size in XSH5, 3 5 3 -3 5 4 visibility, 26, 8 8 -9 5 , 294 M essage q u eu es, 30 M icrosoft W indows, 23 MIMD (m ultiple in stru c tio n , m ultip le data), 107 MPP (m assively parallel processor), 5 M ultiprocessors a n d allo catio n dom ain, 182 can d id a te for th re a d s, 29 a n d concurrency, 1, 4 -5 a n d deadlock, 65 definition of, 5 m em o ry arc h ite c tu re , 9 1 -9 5 a n d parallelism , 5 -6 , 2 0 -2 2 a n d th re a d im p lem en tatio n , 191 -1 9 3

In d ex

a n d th re a d in ertia, 2 9 1 -2 9 3 a n d th re a d race, 2 9 3 -2 9 7 M u ltith read ed pro g ram m in g m odel. S e e T h rea d s M utexes a n d atom icity, 61, 7 2 -7 3 a ttrib u te s, 1 3 5-136 a n d blocked th re a d s, 42, 51 a n d clien t-serv er pro g ram m in g model, 121

creatin g a n d destroying , 4 9 -5 1 a n d deadlock s, 2 6 -2 7 , 63, 6 6 -6 9 , 2 9 7 -2 9 9 definition of, 8, 4 7 -4 9 in terfaces, 3 1 6 -3 1 9 a n d in v a rian ts, 6 1 -6 4 lock ch aining, 70 lock h ierarch y , 6 3 -7 0 locking a n d unlocking, 5 2 -5 8 m ultiple, u se of, 6 3 -6 4 no n-blo cking locks, 58-61 n u m b e r of. 3 0 3 -3 0 4 a n d pipeline pro g ram m in g model, 1 0 0 -1 0 1

priority ceiling, 1 8 6-187, 300 priority in h e ritan c e, 186-188 , 300, 307 priority inversions, 2 6 -2 7 , 63, 184 -1 86, 2 9 9 -3 0 0 priority-aw are, 1 8 5-186 a n d sem ap h o re s, 236 sizing of, 6 2 -6 3 a s a sy n ch ro n izatio n m ech an ism , 8, 30 a n d th read -safety , 6 -7 , 62 typ es in XSH5, 3 4 9 -3 5 1 a n d w ork crew p rogram m in g m odel, 108 -1 1 0 Se e als o B arriers; C ondition variables; Memory, visibility; R e a d /w rite locks M utually exclusive. S e e M utexes N N etw ork serv ers a n d clients, 2 2 -2 3 N orm al m u tex es, 3 4 9 -3 5 1 NULL (value), 167

373

In d ex

O

O bject orien ted p ro gram m in g a n d th read in g , 25 O ne to one (kernel level) im plem entatio n, 1 9 1 -1 9 3 O paq ue, 31, 36, 163 O pen Softw are F o u n d a tio n ’s D istrib u ted C o m putin g E nviro nm ent, 154 P

P arad igm s, 25 Parallel decom position. S e e Work crew s Parallelism a n d a sy n c h ro n o u s pro gram m ing, 11- 12

ben efit of th read in g , 2 0 -2 5 can d id a te for th re a d s, 29 definition of, 5 -6 an d th read -safe ty , 6 -7 S e e als o C o n cu rren cy Perform an ce a s a benefit of th rea d in g , 2 0 -2 2 a s a co st of th read in g , 26 a n d m u tex es, 6 2 -6 3 problem s, avo idan ce of, 3 0 2 -3 0 5 Pipeline p ro g ram m in g m odel, 9 7 -1 0 5 Pipes, 30 Polym orphism , 24 POSIX a rc h ite c tu ra l overview, 30 co nform ance d o cu m en t, 307, 30 8 erro r checking, 3 1 -3 4 realtim e sch ed u lin g options, 173 signal m e ch an ism s, 4 0 -4 1 , 8 1 -8 2 ty pes a n d interfaces, 3 0 -31 POSIX 1003.1 (ISO/IEC 994 5-1:1 996), 2 9 -3 0 POSIX 1003.1-1990 , 31, 209 POSIX 1003. l b - 1993 (realtime) an d con dition v ariables, 3.94, 80 a n d sem ap h o res, 2 3 6 -2 3 7 , 345 a n d s ig n a ls , 2 3 0 - 2 3 2

th re a d co nce pts, 2 9 -3 0 void *, u se of, 311 POSIX 1 0 0 3 .1 c-1995 (threads) a n d cancellation, 154 can cellatio n, in terfaces, 3 2 3 -3 2 5 co ndition variables, interfaces, 3 1 9 -3 2 2

erro r detection a n d reporting , 3 1 0 -3 1 1 fork h a n d le rs, in terfaces, 33 6 in terfaces, overview, 3 0 9 -3 1 0 lim its, 3 0 8 -3 0 9 m u tex es, in terfaces, 3 1 6 -3 1 9 op tions, 3 0 7 -3 0 8 a n d realtim e sch ed u lin g , 173 realtim e scheduling, in terfaces, 3 2 6 -3 3 5 sem ap h o res, in terfaces, 3 4 5 -3 4 6 signals, in terfaces, 3 4 2 -3 4 5 stdio, in terfaces, 3 3 6 -3 3 8 th re a d concepts, 2 9 -3 0 th re a d s, in terfaces, 3 1 1 -3 1 6 th rea d -sa fe , interfaces, 3 3 8 -3 4 2 th read -sp ecific d a ta , in terfaces, 3 2 5 -3 2 6 void *, u s e of, 311 POSIX 1003. l i - 1995 (corrections to 1003. l b - 1993), 2 9 -3 0 POSIX 1003.1j (add itional realtim e extension) b arrie rs, 249, 3 5 6 -3 5 8 re a d /w rite locks, 358 spin lo cks, 359 th re a d ab o rt, 361 w ait clock, condition variable, 3 5 9 -3 6 1 POSIX 100 3.14 (m ultipro cessor profile), 30, 182, 3 6 1 -3 6 2 POSIX_PRIOJNHERIT, 186 POSIX_PRIO_NONE (value), 186 POSIX_PRIO_PROTECT, 186 _POSIX_REALTIME_SIGNALS (option), 228 _POSIX_SEMAPHORES (option), 235 _POSIX_THREAD_ATTR_STACKADDR (option), 139, 308, 348 _POSIX_THREAD_ATTR_STACKSIZE (option), 139, 308, 34 8 _POSIX_THREAD_PRIO_INHERIT (o p tio n ) , 1 8 5 - 1 8 6 , 3 0 8 , 3 4 9

_POSIX_THREAD_PRIO_PROTECT (option), 185-1 86, 308, 349 _POSIX_THREAD_PRIORITY_SCHEDULING (option), 173-176, 179, 308, 349 _POSIX_THREAD_PROCESS_SHARED (option), 136-1 37 , 308, 348

374

JPO SIX TH R EA D S (option), 308, 348 _POSIX_THREAD_SAFE_FUNCTIONS (option), 308, 34 9 _POSIX_TIMERS (option), 360 p read (function), 3 5 4 -3 5 5 P red icates definition of, 46 loose, 80 w akeup, 8 0 -8 1 w ak ing w aiters, 81 S e e als o C ondition v ariab les p rin tf (function), 15 prioceiling (attrib ute), 135 -1 3 8 Priority ceiling, 186-187, 300 Priority in h e ritan c e definition of, 186 m u tex es, 188 an d POSIX 1003.1c op tions, 307 priority inversion, av oidan ce of, 300 Priority in versions av oidan ce of, 2 9 9 -3 0 0 a s a co st of th read in g , 2 6 -2 7 m u tex es a n d priority scheduling, 63 a s a realtim e sch ed u lin g problem , 184 S e e als o D eadlocks P rocess co n ten tio n , 181 -1 8 5 P rocess exit, 204 P rocesses a sy n c h ro n o u s, 8 lig h tw eig h t, 1 th re a d s, co m pared to, 10, 20 varia b le w eight, 1 P rocessors a n d blocked th re a d s, 42 a n d th re a d im plem entatio n, 190 -1 9 5 S e e als o M ultiprocessors; U nip rocessors Program s, exam ples of b a rrie rs, 2 4 5 -2 4 8 , 2 5 0 -2 5 3 can cellatio n, 14 5-161 client server, 1 2 1 -1 29 condition variables, creatin g an d destroying, 7 4 -7 6 con dition varia bles, tim ed condition w ait, 8 3 -8 8 con dition varia bles, w aiting on, 7 8 -8 0 creatin g a n d u sin g th re a d s, 3 8 -3 9 erro rs, 3 2 -3 4 flockfile, 2 0 5 -2 0 7

In d ex

fork h a n d le rs. 2 0 1 -2 0 3 initialization, 1 3 3 -134 m ultiple p ro cesses ,1 5 - 1 6 m ultiple th re a d s, 17-19 m u tex a ttrib u te s object, 136 m u tex es, d eadlock avoidance, 6 6 -6 9 m u tex es, dynam ic, 5 0 -6 8 m u tex es, locking an d unlock ing, 5 2 -5 7 m u tex es, non-blo cking locks, 58-6 1 m u tex es, sta tic m utex , 50 pipeline, 9 9 -1 0 5 p u tc h a r, 2 0 8 -2 0 9 re a d /w rite locks, 2 5 5 -2 6 9 realtim e scheduling, 17 5-181 sam p le in form ation, 13 sem ap h o re, 2 3 8 -2 4 0 SIGEVTHREAD , 2 3 2 -2 3 4 sigw ait, 2 2 8 -2 3 0 s u sp e n d a n d resu m e, 2 1 8 -2 2 7 sy n c h ro n o u s prog ram m ing, 13-15, 27 th re a d a ttrib u te s, 140-141 th re a d in ertia, 292 thread-sp ecific , 164-165, 1 6 9-172 u s e r a n d te rm in a l identification, 211 w ork crew s, 108 -1 2 0 w ork q u eu e m anager, 2 7 1 -2 8 3 protocol (attribute), 135-1 38 , 186 p s h a re d (attribute), 1 3 5-138, 204 p th re a d _ a b o rt (function), 361 p th rea d _ atfo rk (function), 199, 336 p th rea d _ attr_ d estro y (function), 312 p th re a d _ a ttr_ g e td e ta c h sta te (function), 312 pth rea d _ attr_ g etg u ard size (function), 353 p th rea d _ attr_ g etin h e ritsch ed (function), 32 7 p th re a d _ a ttr_ g e tsc h e d p a ra m (function), 327 p th read _ attr_ g etsch ed p o licy (function), 3 2 7 -3 2 8 p th read _ attr_ g etsco p e (function), 328 p th re a d _ a ttr_ g e tsta c k a d d r (function), 3 1 2 -3 1 3 p th rea d _ attr_ g etstac k size (function), 135, 139, 313 p th rea d _ attr_ in it (function), 139, 313

In d ex

pthread__attr_setdeta chstate (function), 313 pthread__attr_setguardsize (function), 35 4 pthread__ attr_setinh eritsch ed (function), 176, 329 pthread__attr_setsch ed param (function), 175, 329 pthread__attr_setschedpolicy (function), 175, 3 2 9 -3 3 0 pthread__attr_setscope (function), 182, 330 pthread__attr_ setstackaddr (function), 314 pthread__attr_setstacksize (function), 135, 314 pthread__attr_t (datatype), 135, 139, 231 pthread__cancel (function) a sy n c h ro n o u s cancelability, 151 deferred cancelability, 148 definition of, 323 a n d pth read_k ill, 21 7 te rm in atio n , 43, 143 -1 4 5 PTHREAD_CANCEL_ASYNCHRONOUS (value), 152, 324 PTHREAD_CANCEL^DEFERRED (value), 145, 147, 3 2 4 PTHREAD_CANCEL_DISABLE (value), 145, 149, 324 PTHREAD_CANCELED (value), 43, 145 PTHREAD_CANCEL_ENABLE (value), 147, 32 4 pth read _ clean u p _ p o p (function), 43, 147, 155, 323 pthread__cleanup_push (function), 43, 147, 155, 323 pthread__condattr_destroy (function), 319 p th read _ co n d attr_ g etclo ck (function), 360 p th read _ co n d attr_ g etp sh ared (function), 320

pthread__condattr_init (function), 137, 320 pthread__condattr_setclock (function), 360 p th re a d _ c o n d a ttr_ se tp sh a re d (function), 137, 320

375

p th rea d _ co n d attr_ t (datatype), 135 p th rea d _ co n d _ b ro ad cast (function) ,8 1 , 256, 300, 321 p th read _ co n d _ d estro y (function), 76, 321 pth read _ co n d _ in it (function), 75, 137, 321 pthread _ co n d _ sig n al (function), 81, 300, 322 pth read _ co n d _ t (datatype), 74, 137 pth read_cond_tim edw ait (function), 78, 8 0 ,3 2 2 pthread_cond_w ait (function), 77, 85, 322 p th rea d _ create (function) a n d a ttrib u te s objects, 139 crea tin g a n d u sin g th re a d s, 3 6 -4 2 , 189 definition of, 314 execution co ntext, 30 a n d m em ory visibility, 89 a n d m ultiple th re a d s, 17 a n d th re a d identifier, 144-145, 266 PTHREAD_CREATE_DETACHED (value), 44, 125, 139, 231 , 3 1 2 -3 1 3 PTHREAD_CREATE_JOINABLE (value), 139, 231, 3 1 2 -3 1 3 PTHREAD JDESTRUCTORJTERATIONS (limit), 168, 309 p th re a d _ d e ta c h (function) cleanin g up, 158 creatin g a n d u sin g th re a d s, 37 definition of, 315 a n d m u ltip le th re a d s, 17 te rm in atio n , 4 3 -4 4 p th rea d _ eq u al (function), 36, 315 p th read _ ex it (function) a n d a ttrib u te s objects, 140 cleanin g up, 155 creatin g a n d u sin g th re a d s, 3 7 -3 8 definition of, 204, 315 a n d fork, 197 an d m em ory visibility, 89 a n d m ultiple th re a d s, 17 te rm in atio n , 30, 4 0 -4 4 , 53 PTHREAD_EXPLICIT_SCHED (value), 176, 3 2 7 -3 2 9 p th rea d _ g etco n c u rren cy (function), 35 2

376

p th re a d _ g e tsc h e d p a ra m (function), 331 pth read_ getspecific (function), 34, 164, 166, 325 p th re a d .h (h eader file), 13 PTHREADJNHERIT_SCHED (value), 176, 3 2 7 -3 2 9 p th re a d J o i n (function) a n d a ttrib u te s objects, 139 clean ing up, 158 creatin g an d u sin g th re a d s, 3 7 -3 8 definition of, 315 a n d erro r checking, 32 a n d m em ory visibility, 89 a n d pthread_ kill, 225 term in atio n , 4 3 -4 4 , 128, 145 pth read _ k ey _ create (function), 16 3-166, 3 2 5 -3 2 6 pth read_ key_ delete (function), 166, 326 PTHREAD_KEYS_MAX (limit), 166, 309 pthread_key_t (datatype), 1 6 3 -166 pthread_kill (function), 2 1 7 -2 2 7 , 343 p th rea d _ m u te x attr_ d e stro y (function), 316 p th read _ m u te x attr_ g etp rio ceilin g (function), 332 p th read _ m u te x attr_ g etp ro to co l (function), 3 3 2 -3 3 3 p th re a d _ m u te x a ttr_ g e tp sh a re d (function), 317 p th read _ m u tex attr_ g etty p e (function), 3 5 0 -3 5 1 p th re a d _ m u te x attr_ in it (function), 135, 3 17 p th read _ m u tex attr_ setp rio ceilin g (function), 333 p th rea d _ m u te x attr_ setp ro to co l (function), 186, 3 3 3 -3 3 4 p th re a d _ m u te x a ttr_ se tp sh a re d (function), 136, 317 p th rea d _ m u te x attr_ setty p e (function), 351 p th re a d _ m u te x a ttr_ t (datatype), 135 PTHREAD JVfUTEX_DEFAULT (value), 3 4 9 -3 5 1 p th rea d _ m u te x _ d estro y (function), 51, 318, 350

In d ex

PTHREAD JVIUTEX.ERRORCHECK (value), 349 p th read_ m utex_ getprioceiling (function), 331 p th read _ m u te x _ in it (function) a n d a ttrib u te s objects, 135 crea tin g a n d destro y in g m u tex es, 50-51 definition of, 3 1 8 in itializatio n of, 132, 186 sta n d a rd iz a tio n , fu tu re, 35 0 PTHREAD JVIUTEXJNITIALIZER (macro), 5 0 -5 2 , 7 4 -7 6 pth read_m ute x_lo ck (function) a sy n c h ro n o u s cancelability, 151 definition of, 318 lock h ie rarch y , 6 4 -6 5 locking a n d unlocking, 52, 58 a n d m em ory visibility, 90, 93 m u tex es, n u m b e r of, 3 0 3 -3 0 4 s ta n d ard izatio n , fu tu re, 35 0 XSHS m u tex types, 350 PTHREAD_MUTEX_NORMAL (value), 349 PTHREAD_MUTEX_RECURSIVE (value), 349 p thread_m utex_setp rioceiling (function), 332 p th read _ m u tex _ t (datatype), 49, 62, 136 p th read _ m u tex _ t 1y lo ck (function) creatin g a n d d estroying m utexes, 49 definition of, 31 9 a n d flockfile a n d funlockfile, 207 lock h ie rarch y , 6 4 -6 5 locking a n d unlocking, 52, 58 m u tex es, n u m b e r of, 3 0 3 -3 0 4 re a d /w rite locks, 25 7 sta n d a rd iz a tio n , fu tu re, 350 XSHS m u tex types, 350 p th read _ m u tex _ u n lo ck (function) crea tin g an d d estroying m utexes, 49 definition of, 319 a n d flockfile a n d funlockfile, 207 lock h ie rarch y , 6 4 -6 5 locking a n d unlocking, 52, 58 a n d m em ory visibility, 90

377

In d ex

m utexes, n u m b e r of, 3 0 3 -3 0 4 s ta n d ard izatio n , fu tu re, 350 XSHS m u tex types, 3 5 0 p th read _ o n ce (function) in itialization, co ndition v ariables, 75 initialization, m u tex es, 50 or sta tic ally initialized m utex, 132 in s u s p e n d /re s u m e , 2 2 0 -2 2 1 a n d th re a d races, 2 9 5 -2 9 6 th read -sp ecific d ata, 163 -1 6 4 PTHREAD_ONCE_INIT (macro), 132 p thread_once_t (datatype), 132 PTHREAD_PRIO_INHERIT (value), 186, 3 3 3 -3 3 4 PTHREAD_PRIO_NONE (value), 3 3 3 -3 3 4 PTHREAD_PRIO_PROTECT (value), 186, 3 3 3 -3 3 4 PTHREAD_PROCESS_PRIVATE (value), 136-137, 3 1 7 -3 2 0 PTHREAD_PROCESS_SHARED (value), 1 36-13 8, 204, 3 1 7 -3 2 0 PTHREAD_SCOPE_PROCESS (value), 182, 3 2 8 -3 3 0 PTHREAD_SCOPE_SYSTEM (value), 182, 3 2 8 -3 3 0 p th rea d _ se lf (function), 17, 3 6 -3 7 , 14 4-145, 316 p th re a d _ se tc a n c e lsta te (function), 147, 149, 151, 324 p th read _ setcan celty p e (function), 151, 3 24 p th rea d _ se tco n cu rren c y (function), 3 5 2 -3 5 3 p th re a d _ se tsc h e d p a ra m (function), 334 p th read _ setsp ecific (function), 166, 326 p th rea d _ sig m ask (function), 2 1 5 -2 1 6 , 343 pth read _ sp in _ lo ck (function), 359 PTHREAD_STACK_MIN (limit), 139, 309 p th re a d _ t (datatype) creatin g a n d u sin g th re a d s, 3 6 -3 7 , 189, 266 a n d pth read_k ill, 217 term in atio n , 43, 144 -1 4 5 th read -sp ecific d a ta , 1 6 1-162 p th rea d _ testc an cel (function), 144-14 5, 150, 158, 325 PTHREAD_THREAD_MAX (limit), 309

p u tc ( fu n ction ) , 207

p u tc h a r (function), 6, 207 p u tc h ar_ u n lo ck ed (function), 2 0 7 -2 0 9 , 338 p u tc _ u n lo ck ed (function), 2 0 7 -2 0 8 , 338 pw rite (function), 355 R

R aces avoidance of, 2 6 -2 7 a n d co ndition varia bles, 73 a n d m em ory visibility, 91 overview, 2 9 3 -2 9 5 seq u en ce race, 2 8 4 -2 8 5 , 2 9 5 -2 9 7 sy n ch ro n izatio n race, 2 9 4 -2 9 6 th re a d in ertia, 2 9 1 -2 9 3 raise (function), 217 R an dom n u m b e r g en eratio n fu nctio n, 213 ra n d _ r (function), 213, 341 read d ir_ r (function) definition of, 339 directory search in g , 212 reen tran cy , 7, 2 9 7 th re a d -sa fe fu nction, 210 a n d w ork crew s, 1 0 7 -1 0 9 R e a d /w rite locks, 242, 2 5 3 -2 6 9 , 3 5 8 R ea d /w rite ordering, 9 2 -9 5 Ready th re a d s, 3 9 -4 2 , 53 R ealtim e sch ed u lin g allocation dom ain, 1 8 1-183 a rc h ite c tu ra l overview, 30 c o n te n tio n sc o p e , 1 8 1-183 definition of, 7 -8 , 172 -1 7 3 h a rd realtim e, 1 7 2 -1 7 3 interfaces, 3 2 6 -3 3 5 m u te x e s , priority ceiling, 186-187, 30 0 m u tex es, priority in h eritan ce, 186-18 8, 300, 30 7 m u tex es, priority-aw are, 1 8 5-186 policies a n d priorities, 174-18 1 POSIX op tions, 173 a n d priority inversion, 2 9 9 -3 0 0 , 326 pro blem s w ith, 183 -1 8 5 soft realtim e, 1 7 2-1 73 a n d sy n ch ro n iz atio n , 295 R ecursive m u tex es, 3 4 9 -3 5 1

378

Recycling th re a d s, 4 3 -4 4 R een tran t, 6 -7 , 297 Se e a ls o R eaddir_r (function) R esum e. Se e P thread_kill (function) R u n n in g th re a d s, 42 S

Scaling, 2 0 -2 2 SC_GETGR_R_SIZE_MAX (value), 214 SC_GETPW_R_SIZE_MAX (value), 214 SCHED_BG_NP (value), 175 SCHED_FG_NP (value), 175 SCHED_FIFO (value) pro blem s w ith, 183 -1 8 5 a s a sch ed u lin g interface value, 3 2 8 -3 3 1 , 3 3 4 -3 3 5 sch ed u lin g policies a n d priorities, 174 -1 7 5 a n d th re a d race, 295 sched_get_priority_m ax (function), 174, 335 sched_get_priority_m in (function), 174, 335 SCHED_OTHER (value), 175, 3 2 8 -3 3 1 , 3 3 4 -3 3 5 sc h e d p a ra m (attrib ute), 138 -141, 175 sched po licy (attribute), 138-14 1, 175 SCHED_RR (value), 174, 185, 3 2 8 -3 3 1 , 3 3 4 -3 3 5 S ch ed u ler A ctivations model, 194 Sched uling. S e e R ealtim e sch ed u lin g sched_yield (function), 5 3 -5 4 , 65, 221, 316 Schim m el, C urt, 94 scope (attrib ute), 138-1 41, 182 _SC_THREAD_ATTR_STACKADDR (option), 308 _SC_THREAD_ATTR_STACKSIZE (option), 308 _SC_THREAD_DESTRUCTOR_ITERATIONS (limit), 309 _SC_THREAD_KEYS_MAX (limit), 309 _SC_THREAD_PRIOJNHERIT (option), 185, 308 _SC_THREAD_PRIO_PROTECT (option), 185-18 6, 308 _SC_THREAD_PRIORTTY_SCHEDULING (option), 308

In d ex

_SC_THREAD_PROCESS_SHARED (option), 308 _SC_THREADS (limit), 308 _SC_THREAD_SAFE_FUNCTIONS (option), 308 _SC_THREAD_STACK_MIN (limit), 309 _SC_THREAD_THREADS_MAX (limit), 309 S em ap h o res fu n ctio n s, definition of, 3 4 5 -3 4 6 a s a sy n ch ro n izatio n m ech an ism , 8, 30 sy n ch ro n izatio n w ith signal catch ing, 2 3 4 -2 4 0 sem _destroy (function), 237, 345 sem _getvalue (function), 23 7 sem _init (function). 237, 345 sem _post (function), 2 3 5 -2 3 7 , 346 sem _t (value), 237 s e m jx y w a it (function), 23 7, 346 sem _w ait (function), 2 3 6 -2 3 7 , 346 S eq u en ce races, 2 8 4 -2 8 5 , 2 9 5 -2 9 7 Serial program m ing, 25 Serial regions. Se e P redicates Serialization, 21 S h ared d ata, 3 sigactio n (function), 215 SIG_BLOCK (value), 343 SIGCONT (action), 217 sigevent, 311 sigev_notify_attributes, 231 sigev_notify_function, 231 SIGEVTHREAD (function), 40, 2 3 1 -2 3 4 sigev_value (function), 311 SIGFPE (function), 2 1 5 -2 1 6 SIGKILL (function), 2 1 6 -2 1 7 Signals actio n s, 2 1 5 -2 1 6 b ack g ro u n d , 2 1 4 -2 1 5 a n d condition variables, 7 2 -7 6 , 80 -8 1 h a n d lers, 9 1 -9 2 in terfaces, 3 4 2 -3 4 5 m a sk s, 21 6 a n d m em ory visibility, 89 pth read_k ill, 2 1 7 -2 2 7 ru n n in g a n d blocking th re a d s, 42 sem ap h o re s, 2 3 4 -2 4 0

379

In d ex

SIGEV THREAD, 2 3 1 -2 3 4 sigwait. 2 2 7 -2 3 0 S e e a ls o C ondition v aria b les SIGPIPE (action), 215 sig p ro cm ask (function), 21 6 sigqueu e (function), 230 SIGSEGV (action), 21 6 SIG_SETMASK (value). 343 SIGSTOP (action), 2 1 6 -2 1 7 sigtim edw ait (function), 228, 3 4 3 -3 4 4 SIGTRAP signal, 216. 290 SIGJJNBLOCK (value), 343 sigw ait (function) definition of, 2 2 7 -2 3 0 , 34 4 ru n n in g an d blocking, 42 a n d sem ap h o re s, 23 4 sigw aitinfo (function), 228, 234, 3 4 4 -3 4 5 SIMD (single in stru c tio n , m ultiple data), 106 sleep (function), 15 SMP. S e e M ultiprocessors Soft realtim e, 172 -173 Solaris 2.5 co n cu rren cy level, settin g of, 58, 119, 128. 145, 152, 266 th re a d debu gg ing library, 290 program m in g exam ples, in tro d u ctio n to, 12-13 realtim e scheduling, 176, 179 SIGEV‫ ״‬THREAD im plem entatio n, 231 Spinlock s. 359 S p u rio u s w akeups, 80-8 1 s ta c k a d d r (attribute), 138-141 stack size (attribute), 138-141 S ta rtu p th re a d s, 4 1 -4 2 std err, 33 s td in (function) in a sy n c h ro n o u s pro g ram exam ple, 14, 18 a n d client serv ers, 121 in pipeline program exam ple. 98, 105 a n d stdio, 2 0 5 -2 0 7 stdio (function) a n d co ncurrency, 23 a n d fork h a n d lers. 199 interfaces, 3 3 6 -3 3 8 a n d realtim e sched uling. 190 th read -safety . 6. 2 0 5 -2 0 7

s td o u t (function) a n d client servers. 121 in pipeline p rogram exam ple, 98 a n d stdio, 205 in su sp e n d pro g ram exam ple, 22 4 s tre rro r (function), 33 S trin g to k en function, 212 strto k _ r (function), 212, 339 s tru c t aiocb, 230 s tru c t d iren t, 109, 210 s tru c t sigevent, 230 S u sp en d . Se e Pthread _kill (function) S y n chronization a rc h ite c tu ra l overview, 30 a n d co m p u tin g overhead, 26 critical sections, 46 definition of, 7 -8 objects, 3 a n d p ro g ram m in g model, 2 4 -2 5 protocols, 26 races, 2 8 4 -2 8 5 an d re e n tra n t code, 6 -7 an d scheduling, 295 a n d sem ap h o re s, 2 3 4 -2 4 0 a n d seq u en ce race, 2 9 4 -2 9 7 a n d UNIX, 9-11 S e e als o B arriers; C ondition variables; In v aria n ts; Memory, visibility; M utexes; Parallelism ; R ead /w rite locks S y n ch ro n o u s I/O o p eratio n s, 2 2 -2 3 prog ram m ing, 13-15, 27 sy sco n f (function), 185, 214 , 3 0 7 -3 0 8 S ystem co n ten tio n , 1 8 1-185 T

T erm in atio n of th re a d s, 4 3 -4 4 th d _ c o n tin u e (interface), 217, 2 2 3 -2 2 4 th d _ su sp e n d (interface), 2 1 7 -2 2 1 , 22 4 T h rea d s ab o rt (POSIX 1 0 0 3 .1J), 361 a rc h ite c tu ra l overview, 30 a n d a sy n c h ro n o u s program m ing, 8-12

a ttrib u te s, 138-14 1 ben efits of, 10-11, 2 0 -2 5 blocking, 42

380

T h re a d s (continue d ) can d id a te s for, 2 8 -2 9 client serv er p rogram m in g model, 120 -1 2 9 co sts of, 2 5 -2 8 creatin g a n d usin g , 25 -4 1 definition of, 8 e rro r checking, 3 1 -3 4 identifier, 36 im p lem en tatio n of, 189 initial (main), 3 6 -4 2 , 119, 1 3 1-134 in terfaces, 3 1 1 -3 1 6 in tro d u ctio n to, 1-3 m a n y to few (two level), 1 9 3 -195 m a n y to one (user level), 190-191 one to one (kernel level), 191 -1 9 3 a s p a rt of a p ro cess, 10 pipeline pro g ram m in g m odel, 9 7 -1 0 5 p ro cesses, co m p ared to, 10, 20 p ro g ram m ers, co m p ared to, 3 p ro g ram m in g m odel, 2 4 -2 5 ready, 3 9 -4 2 , 53 recycling, 4 3 -4 4 ru n n in g , 42 s ta rtu p , 4 1 -4 2 s ta te s of, 3 9 -4 1 te rm in atio n , 4 3 -4 4 a n d trad itio n al program m ing, 4, 27 ty pes a n d in terfaces, 30 -3 1 w ork crew p rogram m in g model, 105 -1 2 0 S e e als o C oncurren cy; D ebugging, th re a d s T h read -safe definition of, 6 -7 in terfaces, 2 8 6 -2 8 7 , 3 3 8 -3 4 2 libraries, 2 8 3 -2 8 5 library, 3 0 3 -3 0 4 a n d m utexes, 62 a n d pro g ram m in g discipline, 2 6 -2 7 T h read -safe fu n ctio n s directory search in g , 212 group a n d u s e r d a ta b a se , 2 1 3 -2 1 4 ra n d o m n u m b e r g en eratio n , 213 strin g token, 212 tim e re p re se n ta tio n , 2 1 2 -2 1 3 u s e r a n d te rm in a l identification, 2 0 9 -2 1 1

In d ex

T hread-specific d a ta creatin g, 1 6 3 -1 6 6 d e s tru c to r fu n ctio n s, 167-172 in terfaces, 3 2 5 -3 2 6 overview, 161 -1 6 3 a n d te rm in atio n , 43 a n d th read -safe ty , 6 -7 u s e of, 1 6 6 -1 6 7 th r_ se tc o n c u rre n c y (function), 13, 58, 119, 128, 145, 152 Tim e re p re se n ta tio n fu nction, 2 1 2 -2 1 3 T im er signals, 23 tim er_create (function), 230 Tim eslice, 8, 42, 174 T ok en s, 3, 47 tty__namejr (function), 210 U

U nip rocessors a n d allocation dom ain, 182 a n d co n cu rren cy , 4 -5 a n d deadlock, 65 definition of, 5 an d th re a d in ertia , 2 9 1 -2 9 3 a n d th re a d race, 2 9 3 -2 9 7 u n is td .h (header file), 307 U niversity of W ashington, 194 UNIX a n d a sy n c h ro n o u s, 9 -1 1 , 22 a n d erro r checking, 3 1 -3 4 kernel, 154 p ro g ram m in g exam ples, in tro d u ctio n to, 12-13 U N IX S y s te m s fo r M o d e rn A rchite ctu re s , 94 UNIX98. S e e XSH5 U ser a n d te rm in al iden tification function, 2 1 0 -2 1 1

V ariable w eight pro cesses, 1 void * creatin g a n d u sin g th re a d s, 36 definition of, 311 th re a d s ta rtu p , 42 th re a d te rm in atio n , 43

381

Index

W w aitpid (function), 15, 19 WNOHANG (flag), 15 Word tearing, 95 Work crew s, 105-120, 2 7 0 -2 8 3 Work queue. S ee Work crew s X X W indows. 23 X /O p en . SH5 X / O pe n ( A E S pe cification, S y s te m Inte rfa ce s and H e ad e rs . Is s u e

XSH5

5. See

XSH5 can cellatio n po in ts, 148, 3 5 5 -3 5 6 co n cu rren c y level, 3 5 1 -3 5 3 m u tex erro r detection an d repo rting, 311 m u tex types, 3 4 9 -3 5 1 parallel I/O , 3 5 4 -3 5 5 POSIX op tions for, 3 4 8 -3 4 9 s ta c k g u ard size, 3 5 3 -3 5 4