From 21db8e7e45fcb16718ac95c4340c709a9e3d4118 Mon Sep 17 00:00:00 2001 From: Nico Arqueros <1622112+nicarq@users.noreply.github.com> Date: Sun, 22 Sep 2024 16:46:07 -0500 Subject: [PATCH 1/2] poc --- files/thinkos.pdf | Bin 0 -> 368105 bytes shinkai-libs/shinkai-ocr/src/lib.rs | 2 + shinkai-libs/shinkai-ocr/src/pdf_parser.rs | 651 +- shinkai-libs/shinkai-ocr/src/pdf_parser_v2.rs | 354 + shinkai-libs/shinkai-ocr/src/pdf_to_md.rs | 118 + .../shinkai-ocr/tests/pdf_parser_tests.rs | 63 +- .../shinkai-ocr/tests/pdf_parser_v2_tests.rs | 92 + shinkai-libs/shinkai-ocr/thinkos.md | 8668 +++++++++++++++++ 8 files changed, 9593 insertions(+), 355 deletions(-) create mode 100644 files/thinkos.pdf create mode 100644 shinkai-libs/shinkai-ocr/src/pdf_parser_v2.rs create mode 100644 shinkai-libs/shinkai-ocr/src/pdf_to_md.rs create mode 100644 shinkai-libs/shinkai-ocr/tests/pdf_parser_v2_tests.rs create mode 100644 shinkai-libs/shinkai-ocr/thinkos.md diff --git a/files/thinkos.pdf b/files/thinkos.pdf new file mode 100644 index 0000000000000000000000000000000000000000..666f29bee64d5e9399b970e7013a9929013bbc57 GIT binary patch literal 368105 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

Xo7bU{)gBNXR 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%0Aeh zJUG#cJW_2Lm%SAHJ{-PpJ-RWU(~=h1A9TzBrk=U46vd>N`Q%-}4Y*xuFO`)+%~oz% zq+{9GN=V-Xih4Z(Y`Zca*ddp(p2&wQyNrp$(5HnKk4+en#b~=&eJF<9ib$~)(+uC) z#6M*wel*3R%^z%htw1%Ng%|-|WPf1NEIQYgh9k^V38PFeyt&bA9476fJy^(`0qO?h zm*#_UQ|4z64O7Hrafz*pQfCiqP{rcQY7hNe<7V}HoL$?MY60mH*;w;S(H^ot`zx})frgh+V)6FS0 zc0;)=m6cX`)$j-#znIBj33#tD!qY$D*_KcOs}E;(NqTzDP(@R+LZiutjVfit{wN6f za6SClM8P7>#TydpkZ1j|;EloWRm)xT5JXJGtL$hSQP(zi5)nNz7Y1sp%j_xgj3(gZ z*B{PQ6X(We8Hs~QX~6Bv$9$!lMODDrlmjdVVo30mp8e)(c)m2DRCR!x+^=A&6C8+Yd}N&8o+?Mf(!4K(I{I>NAVp<$5no+J zZo>x~%bjoEx_@veqVn`vH|LCk)^Vbqs5Cy$O2rtJ)t?a-$l%GL3U3rsYj^5=wsJ#tM?!|qRG^2nA3 z<6v!rpNRw4m4U{Gr)A9s?ds3z(MeB`Vh;Z*!xUd_<8)*c*GLEtwViJieH?Gc7xAN( z^-Y4}?2dA)Vr`RV5!{sCr4g(yx#UJ&&qxS#;XQgNQRHNQb*AI`)Q376`<(H$|WmsN4aZhh@3|U zC>u>}LLWK2!$wn7VF-1zq&SI^C{m7aqag-aD9lR9;UXA@> z?G(JPNSH!rEFSkdJm1BYl*X^_172)r=NU}?9)!+Ua2xR}zq1)x^41l^+a5m!C65ej zt4LzPz?#v_#&4DNHGCRey_P0?^VOI)rDu%xwhSBDpU}R`eRh#}xSolx^Lpl41TwKZMnr-XI7-5Jq;Z~EDpEkumE>Wh_fzLtg1a(dZ#uy3a1B$FD< z;O|EAF;`F&G?ka1N0Ei6&$|mVQsY^kY1>(Ujmw5{611IxtARh@$=-QY`*ZFSbN&EO zJqHYXt-dho-YDV(sbe%7#Hko;cq_{7cWy$%rgZ3dSG5NJgy$YHK5nI>OGpuVkd{f+ zRvwYmUc(Ajq``F%X9U<;K?V{7f#%r%weC{bZKz1j-stJUg_tG(eRB@_L$zPD?A!!o z-ZPPJspYa7_b;(t3IQm%dviEv;?#9YUrk=LDg)=B8XmU_P@;miT1%~V=&*Gzf9}5Q z|EbFUU^{6+A)?lb2sQPBA>T^M5_4Dsq%C&hAyXxVz6jOXVodz5Q+Ib*vg3nK|EP)X zyYEiV&0F0&Ec1FWxLti5{y(`}T(zE-p2&qn9orgv@n$b!Aj4 z--s9E^TU7EB##T!YF7o<_=X#@ zGT_ZDNHF7Sk*<}Fxgo7eWnnZ6R;q8gP>f$U473hOCy6bhG(xfWaxgl114t=mRr1V> z;SEj|y51)_y}hG<;9LE#iLagkeCE(f=AJknq;MvP^ko|xwf+L-q}^hK2eq)dEvFe_ z;L94Hd*{28;1^Iyi!UH5V^}$bdbBk{EU7Y2JaXuqko+ywCf08)ZfEpk;tupXs63E(_v9X-mcCe?3>)?TWkbX}xZbXq`ohNyI9$;_>&+ey@rS z5=@6=fSNvWbc{+)j`KwZuWiy4>40@6jMaCnz23qrpo@d4na|HMBQt=JV(BKtNxdZ3 zB*Ra0>egrOXVgiZpc7BT%yiYj*+A_szfHwVI?rjJYfiVQcLX5>>E1p_EhQeHnhtqc zpu?y;m%<$2>zut3Yi>5Q!S&YMHZ2u^BjkfE@CUu&V}Z;gYiow)1Cp2pp5d+chLSE!g@vB)4^n%w$lr!;`3=O zIR|3FJBMP%iW;`iKxH+bZ3~rNNV0Buv67Hjq$(D`M^MPrms~tmZHuC&xVv$I9>Kki zfN_W`3Ro^N(zzMQ__pJpXto4s*FWXCq+II{BArC+L5OIE8!_&KTodoF6o@J{?%Z4u z%+~T7ZDgocm#1DHaH-l-^&4R?431V&`flNTunwCU3#M5R>jfosRLWaa6y!BDqVysm zUCx|y3uh@$cW;pj=-c$IyeD`4&G* zm$pWAbM}NT80}}t3E5NUVF=x{*K|I`hbOl>?DHgw1Nx^F;3}1qL6dHkWOB$$3alrq zSp%9C?vT~{6EsjK&_}e~K*CX}#to^?nN?^lGZ72&VN!g!4dljg%|yjAAECY;@J~V{ zBKF+~d>#!udcPUV{r90C#jw7cMoqeoW8 zoMPYIb2?4nUwoNJ4t9g$hd^jHjK$ca3p?Tt?h)|LH18H0sn8*njSz%NO@#XM5P9o! z0J|tvJhAK)V>#IvL76=*HIYU}O3|S&y;{vRo-dNs^HSJbdhST8a9)he7{R4yKOE^o zmgjETzo@(j4!IxR0_iImORShAdNu+Rp;iR>Xzfdco`^D+z`W1O!OI@TN&NribjqA&6IRe5dNJDLqzXPlRM2>Bhos_({7O<2ZJ5D4Qc^bXkU^< z`|)MqLnMsUX`8vQTevp&8~Up@%4S&>%4<^h)Mz}|uEsxI6U zA?9CQ{&D1F{YQr1(CT162SGQsUHhe9;rKS?B0s4|i=#WuiYIG3B4^K*+14T`@7BK2 zM?haf{eQcgy(LuHs8@KqQZKE~QqX<{DnI>msI?*nxT+>)S|D`o&@p_{N5}a zJOooWd0r>;d_uU%Fa@otyVdOI=PPLW{}N$>O6tqrMeU!TTu%;KcpUe2)d!k(#*jY^ z**IXkv)nAamZJ6EXl}Jq@E>z3_f*by>}Csdc`a9-s(KcnfO+$-@J8n-j{iv ze=yK?|IOQntI9#N<{jkR%PB$++vNCF_?O9}gG8mnvZ+Fn?QBc% zzZRc_AF4?ZP@4IBmiuWsebFvhGic1Exy6a%3RX%Wq9j#Lar=*)4h8QyK^jgcy`UqK z!$)6zvLf6@kna#_xqRWRye5{Aq_-4-s0PMYMK)Rf(?--kk}vQveAPsrGy1Sh;441# zv%abjxt+8CF2N+$6BOq4r7@?7$_Whb*N_1_?X?^aa{PjgQ+nAT@r}@$46kszpc?J& zki4cODUYN|v?UgpaOhoPl*smN6O;z z+R@G<2sU@6(v-!{Ft&u%Yv&N5Tp}kDTiqEPA^@$vSyUd7&(AN*5TjQbBmxBGmeuos zP^Sl8DJn>NR0x&Cw#)kIPK`dJ+u6HVB+CY3l{~x}>t<`wqj(Abnq9z6IpH-rkHUXqq=d75 z#rs9(2JdFa;0)5T(b%PL>05tG!OrT**HmWLOO=V5-(F#fij`L~P5|E90Lk`$w}R4w z_UaVt`m)rGHUEG`Z;+F_=9?#X`hI0!MY)ZSQ61gZZo5axrg3z$L>1F8fbT-c2VG*? z*P~N0eaFl@aoR06kdGCUv~sOJGw>6{c-^`%P>i)O_?b!wizi4=~x3)HfM>aoX7;`}dy? z^6pL;HnD@@p7g{lcU0dtt8jMMOJxy;ls%Qike#Odn0VVWyDwfm^*l`DD9lht1QwJ%`|_=*3cO`xEh#3e{m-t$P1QfIh%v-W%on<6{RTU zgZyww8e04CQ8V$W9?gU!%TYzz5NqJPQT-?#Z@`}h$M`LreH<}=0wK?O*X&X5yv#`0 zD+cSS7DEgi8Ez)z0D{T@x?R>|74I2}<{cZx2)@zPy9~>Qw zv*t<#nu=Ix3F937pgbWQ6(fKZ;w8g^sDnFfJ1Ek+6RcSpL4<`CK`~gENpQq0B+Vu& zE=n-FIsrT9zjd@4>fv zRT`<~Ze?N3XysLWmL}J>yMYN857lKVrCER9B)&`XmzBElK;nVi29&vTMB}+jK-wyTWZ*tcVRpnR;Ce%l~1EZ?9 zP*7e_#Lf8;a5S>YzGV6j1s=F)$nhRQ)rg2naYD?gJ|<&HvEl0Jf!!f4vwPNfV7yar z7BwmfpVO2Q(LpW!w@BeomAsB;+RoO|1Dj998j201ij>whmD`;y!P$v0bx|%bbA}3A zK$rU#mQ}j9os(U_!RFB>G2>nkye#EnQ*Y5?=p5<)ZJ_K&a;>&7jB`Jc&srDVif!0xOLdtU-@3M)RLJ2z&!jL+qdT;I&Z&7*FoxWWL4yD)cxs0@=2d_h#SFTeQ%tB12`t`#Y*JTkv zOF~6Kl1*|PcAVB`bXcI!r1e z$ZJ^ht`DmE<-boRG(Zg&A56AYS^L%pD<^K-SkL-Rk=*^qY4!7pPASKlwDeUK%wU*K zfjQhpOwY`!+;osbxpg9^6|}2n6cPYvWL<|YAvnne-j7Mb zt-$RqSDek+s|$5IpPfiN^EvF_3}ypan@I<0imLXgPP41)kYC;zNam-S)5mdJRsmZ& zy656kol%?YhewUe!~ahHQ9{(?gXI336+s+fXjGF09B+!X7RulEm^RWa@rd6|Nv-`9 z+^lZ+eMM-Itsfhoo(jIR!OLxE(e-WtZM6*vxlw|XSCV#P792vXtn-uiDreF)l|%h< zs%=zXMNgyFkR)T52KzhSa=p?^banDMV{k7k3+v`ss9Xg^S#&uEo)VgiQs51&N;$S5dr=)i-r>A$-zT}uLz zq(77J%?o_CC#yBS9ckHgm&yY#bm&=r{09> z=0H0tBau_GyF0k9~vnZnJkrd=ZQ0;t$`$`)U zMQ6@@M9mt9Ick@}DS34t#Mh1~t#@2lZV}-?MtW=0F|hvryJ2V^7Em>M>wk(kA;f2= z1(ud@ua4u~G|WN#(Us8*^ozB6m=vNc1r5Lq%7wq}0?NeF^EpjrsvaGO>`h=!2H1Zx zy+p><3`ok$$-6HR^Tr>#1jXYrO~*U4x|FJzVj9^z`I`W`O>8D|&}5c=5Q~K}crTB) zr5et*Y>nVIW+dD49EBqf2f;r$Gqxaj#^w|{tSb6q?(HPoiBM=+aZumc9BNPAh0(cw zgylI7O4z1Y=aV1j`C|cbcvD`EY!{&sLa#OVc4!jK;JRAK%nS)>l>m+CB{3{ptGK;w z7VEphiu5HC3vNbNC@iN?Si-Mxu<;b?C*bS;P}+%qnOOmZ9%)KA`pTT=yuDy_eFD1qDRLndeCB;#Ct7uux)l8at`Ow)M0#sVF5xOeRHMt zujk%ls}l8v=`)*3+=FmJge0tnr2p#FQ_-4tU-OoOkE)aBkFx1sq2Za@A0%JUZXdEKluSydC|?iLfJU(MTjQiX;ql z*S|Q5bcBQ1PV~Em-^OUzHn>bvNz699MD-UADN21e9DF4%~FWWq>jkMalo`&EG zsOuY^+4lDMVsWBEVweZFb}}Va0JX>RKtY?d*mn9to6$gSMNWoqw33$+)KCS?;N8|{ zha@Y^I5()4k|{;wk)On#MDG=Rvv8xp@py+->Ez*SWVfBWdleflCzKh4dP^<0PodZm z?H*2Mg2P;`#%AZV{nRV5WYC^Hde=Q=4T&cnsio1>epM(ze;(5iVtL^`FYI@O;mo1Y zZQR#SMfH}1^>Me^$Wl;E8J&u=ZqMana1i3PO@sCiew^6(`or{Y@S}rhzu^V7spR4| z%lgbnT@+(QGrra8SoWa_)t@HGU_Vxh2cGexvz0M*y6{r7gMG?yhTUxU?@CygS0`4= z)oDG?Mnvt*U7%xu$1R$_wI0v5vbo#{oXz%igWuqInhfTOWca^ZVBB#$$CJR$E&n*U z*z1fA^Ki`Lxjc_K-!WphLybar-VL{8513w`w~ySyLO#qWC`KM(yHi@-sA+|($JXy= zL@7foZ?0^&4DUyDs&jqR_f_CHCFGcg$b($_(4OWJAi|z6Nd#PSu(T8|%Au}-0Zs^b z#J-Qh8Ygu%J}ZQ3VjE0qui$){w`dVL938OwW}MpJ043NijTAN~PWj_feAg7r#4=`L zg8sqZ5;Y#()6R+Ma@2^uDAX;xV^ck^*3z7t>RQQ>b)nWk4r_PEkLJ4Aq0KO_0}06q z)Y+;&4R%Oaf_Km1NCih%XR6{Rmj$b;>-Zbmy4~pyW@6V+jO}aN{bP{9e~2v5@Tin-FYMO!DNwj1Q)|vpsjO$~ z$m%gT$2!fcg#b$4;d)DM3dS-ME@S6X6fUxvUrqS1eIqnTMlEPWPYqt42mPyw-$NBFr>mcU!%uN& zbVaIsUlROLDKVebYaSY%7BEw;O&jS$DaETFe^%YAm~jbKLqR- zo9~m`=mILM<)3nBM*-1zLP?l5g0V`92{%>GMXjB4#DTr_wc6aad*-q~^8e9Au&L-! zn}Hj)`a%z$slb5T{K}xD6+;B+VxHj>J#Nok-%l@qGlrggPP_sSGxv2Slp~T|EfoLA zc>4Z2IYhd4o`2#n9F8blIT2RlSR45Al5DQ%h?eC6?;I*&f1#=jA5S^`1E1n4qMI(S zhLkxv#IA@*zB( z5i^&kA>jnmWdzav{>7;az!c8n*?GWD&+R`} z__ap!lHL6F`^x8q@6-d1w>gxpvlw*?hzLB4a9t2bfY86Gva%2W0OIHb0I0qG?A#?^ z0(?y0md2Ae92yAf-%AA-*Z>6*+j%$X8{^KV!U0oobOG>h10>)hMCe68fY<{90{sOI z?t}m|>9bX!_NM|DfP@Pos6Q*&m&>J7z}7z6X8Y9wN~g&HBoGwzZP`5skQ5JxUP6Ka zE)PujC*$nIrR|3UuxTSj34Hnzha^MPCRvaSPg>mG&H=s(-}CQW3ukNu+$xaJ_D2H& zbZ`jL0Q7~0Q2^!^`jHt45QU%n8$$H+*1W$W;Z_d~Vt;DyuO(y<-U*|gjyeQt-^wYV ztq7Wb0}}8JSoH;15BS4{4G<3ebnED6`bz~8@+}9Ztu=s~)5joBF$HD->*5cvbgaS= zk0-$ffMNCw4dE)#cl*$9Yfuinb^v$R>BJx)r-Tg9gMC+bkB~~IKu!_}4CwO4N_1Ms zdC~Bb@wUrIN!bS8mz5I*-ZwK04dO3A zK;ZvtyZ<=Lgk^B1Zv*f zjobHwT?zkQq@@~;y0m=XTNEjAmxDxN$mV8k27Yf3;PLZT0Kr)fJ|qPk+0^tsn8EM6 zt*_4$p0B1qB&6G z3mF%c1`pus0O)13t^1ub41EW-O}PYhaG$jSAP0wmuhvML-8ow&<6>1t53&%isZ+9lm?Q&(-AY;?R!0&;Ivj<2UX5 zGsjMJGpX9qM;ZsKJOfV8zQ2H&|r0!VXT4+<0S z3936pXX~uIU+r~($%*Rk$%lYh- zo1g;MB2CHmJv&F3ADc-wc~Nrgz!q|d&ng+5G|Jt?wVPMQ0uphd88jO*+*0qpf&||) zli#U~!V@ECRPLtoPp>4wdFnFWHC7F7GZzT#^!_46Vc%S1OtJd|=~Y|$-TLG?y@?P^ z19S9ZqD+V((4*)MswJXBk8T{Toz`S)uWLpzPl?U&~Av!_lyLwD5}QU=!9Yoj0#j50%K|djj!hm z686pUOKI223Exbe(7f>_PbsIyBEgzdyWgX(R8vZlOAO0hz4u$9gv>(h9D)C@~k9D{t4R5f%A)aV8Ta7Ol@m#?+lUt zJ*fG0I9dB-R~~+9<*>MTV?o{BdfuuEkh1eN!!S;tR-a(2OI-D7<%78yStRJ&D!5)1 z;c8v(jMN0uJpZ6=41Otf{{!CMtYPDG>#=iqQbX0NdAP3x=c|sc;&svXx3m0qSTNVB zQP2jR_I=M{CMp84RXuPVArO3~3^-~#*HLT+*U5bwcf1_Vl~9Ab3_FCPZjqhRDE)e5 z7lq&^iW5aG5uMaQ6@Ak>rX-*9+`2`|pxn_Dn^n_W9jxNqe8;<(q?aW}5b1pqMd@YU zhYv;XI@-v%6OwYXCW&e3=vdCK2xL_haEHO~D%e+A0% zDeS&r0fj44CQ!6sd84_`{F&y>(S;n`lL_425p`)N+S}tMiX>k%<36 z*g3?A7PVQlY}>YN+qUg`<$7h?wr$(CZQC~bbvl32gHC#KlAE05euFzWId|>7MB%xx z@IF@C4^;m)3~#9Ch;y<(721_`S4VmSr)}k4e3ZF@Kk6DINGf&%7R;Rf6Afuqn2ZI( zm#IksnksH7N=Wgd=%vRmI7O_=`$jY!dC#3XlsUWm+DJI4oQkcn3#R$^y)nf=DnIA1 z26VG2zja53KooZ|#+BD>cMP+UgvCQY1i`c zR!tw=S)M-mSUs@0ZumEK!6lkh#rcJ#$t}vddI{YU4@fs@7SMj4Ri}s~gM_N2$j=9UQS@x( z`3cng@MIf27u4h)`I|h0bC6};dsy)%T*5>o2I^?#6;^6qoxO{O7qC46meVk0q}wgr zoB5xUu&qbdEC}*`+=I11=^_?W;doj25MFs_Bf7^ zEDG04EVV6iR422kcVohD3_3H)kB-4FTEbAn%k%K@Ol`!<2t>;Ix<>7%<68MDt~zpC z-sUsR%-W*8ySyAPc`6&sJoaf^BYq4Qy(7(=bcW(}fqjH9owskEE$x%T63GCf$60R5 zd(G27?rg4@uTD!W>q_SF6GBh!94YNyFM14!bPHE}r4>8oAFNkqCWU|;mHI5wK51?R z@?sfU5kR~1uLz?Qc}=6LP11%72m2)u>Rm;?xl>ialXgu6#P>5MeJTe*|ErNdKMO&= z^#C)B1$68-H@Z5Qa$)HXhQ9=TM)JT@lBq)x>D=6xL4y5f_?se6AQkOjRAt*ZhxJy> zt%TcZ0uHi&V74~K2E%7{v1`r;5EApr@}3I!$ZFq~sTSO3IzWI0@|bKU{)-9gx@$JV zYD-z@I#IEci-@7WEs!GvAH=L%XkzK8yv|QQFd_q~FSR+nUp|8soB@dx%VT^u1ug!> zEg|&M(BiD@u)N77clOVdxq<_eHjPjcKd+>I zD}6f;99Ib}w7YzmiwnGaJy%phq&0NNzsU$epRc5v6d7rH!-IYWN z`v<2y3@z?QGd#PowxG9W>4m+MzulQ3Ud8lLxv5yhiL2su4C1I&6#_V{rlq~IY!5h^ zXwdg#%3(#ariTX#5i=)wu@LP1!Dnd}f=B6EtJ@r?0LY9W!UH`z}dUrwO=L&a0NprIx|ll7YmWgagt`B@G09@ z-=RmHp(K`+5?tgL<4j1`0)TJFZbaU+sT^+We*(NcP?y!m*#2oeKrO<` za>U&UVg=16mwz8gjs3Qzd zBUwgKiDiEOb=C;;G8!jP6QrR9^B|LVu?Adq#)gl&*O^TX#eb$!2BDPqMV z+LqAoi*L4n^M&G9PoV%OYcu zd2^Eh>aMY5$c!Yl^`25A#N9nD0iUB~YEB^vnpA5GhX&eS%%5Mk1u7ZieNY`FM7VPA zy`RFihPYeSuB{1^u|NT+8rVFAYdwDE$NYZ9Y9>pN6J=e=@*y{k2ycBfST?#b`E0!W*Si2LoqL$12+tY!POY+FApNc1RWJ=J0c#Z#Z# z`tcT7qYvi0cap083VDCF8BJO2RFq_O+KM74@!h8&eN(F( zPmUN@COemlgq z;TFD*O^F6)1BFPMGdmk$A<>DBc-(7ZZD!OBkB3zqTg@1>`2Ha^N4!{p?b}Tu{grp1 za+Hgat|gz0is49Y3|t#w4m=6o!7s(b*R7BOQS{BSE7yy3Hj9^P6tilD@Zjhc6#>0B z+`c^KvVuC1#)CU(h(1rz7u|8;SoWxNq)xO&M(ZyJmcQ2=8ym&oXy%|D~qYX3S$5(xa#0vbp&oW`yo|r|C zrV0$lqEE@;A1qq2?g6^%Gdi#kxvV@is=ty5g{uBq7pd*?GK#@)le&2aj^#b>m`cit z%Ux#lQNk;(s5w#!juv$JC)m0|=2d0p!{o8Y%KFmreAYd~nr_wP<7tn&pG9{Y?g0e% z@!6Xr?w$yb)CX8XIk(B+ZOCnf@zW-2ap=k@b2Vy?;7;lR1T$mPAS`Z)m1*lX(Qs6a z>4b(@;2w1(`0*)U7CaMty5rpZ9^gjwl+yKg z+DoRDSyvU=&vp5EaI@{+2E&q$5eLqV_f)%nJsLR>&2CiMw%Afx;NtGXq5U$Qhz`qgvQ*Tf#wIo85tVH~ll zw(Rt(<{@4M@wlDImYJ+;K}LhQ9R1`dw3J$MgeI2DilZgEMa+mTe`4qqj==M@TlmK= z2_GpaHT*dWDnD;QW#&4pI_2`(I;eeLqv+%8etL~}7Tc6?l&peQwO}zzY<9c#XiE|OSoqUzis%*$a2%-7AN zYyi*K$=zx|B$Uz0cs`9>t9_>2t9v-aR->v!@1a>PQ!_gdG&=WGZzNo`!WW?Cb&?mS zXwD6J*oIUz&%eR0VnL9D%9kN^sa_V0-3h_fL!zyJbzq9_792ZSbsA}|X;MTxS5JY@ z3Y7828#Kj=9EUyrrg~i)?pA@v*GIz>ExOEKNwvEpc%t^N<)Qk{nQMzrH@rUr=d9Ee zKwQhgCr7m?0wqffGfWrhEoZ90Z0_AK6)cn&w3z@iWj`tWA-i#O8<(*FsiVJj0W;g& z9E2BnAEG~ngsH?3O>{c6shDYOc#)B7GMZd@5i=$ANH?KrrhkhDeQ~G7?)>{5at+dj zL@M@A!rD|c?UZSXa%P@{0+c5Y#kSrl8Ri5Hx>TmeB6hKmQX|o;e9s%M&BV0z^QB-z zUGS{Ml5tZq=vL}ky~Iu}?{CsHctUtg8Z9obt+&EViohTPn@+_ridJI`=HyQln3+)v`f} zKe)D$n(TC(W7o(-lHi3~zl&ya)qFqgLi=_Ax!uv4@kkZUbD|Q8u8cu%Y%#a>*quHX zAP{!q)X9aReVws!a#utBZ7l98Gyz*|@qU{6>*|m#_EZSiWH9u&-Ox)knXsFQy6~Tx zOT7x!`h7a@E%9%%EilleV(j+TE5BFL4r=b4V)FEvp|beF88V+6(b>2%2d;S4v6Y6l zX-ti7RJgWvm&z!TcK%$4YSJgJLhY{ouw`QvvU`@`i%Cig-=Ca-WC9L-KlX@0ULsYRj*4Tw2ciUisCD-c zM(bpisl%$)kW;P3mXJQhp;XC_Vu*pso>ZUFJdT)}9GxHZ{KTjae*BPorkp2a&$u6x z;qkg@|ICT=lDej;AB)?IpND(gjG>!AHQ1Qe379EhbPTS0_n+OCENKQb$NOGN5pyxn zcYMtqIT!QU4J^|19$yX;bxP;Xy;p*Q<#`$cg*xP5)larp4Xv{KNq0MlHx?O!iG*HU zQoRiRm&{TzZ~5}T>sV1i%&&aME83p4MELiki|6-utcQ#h-_Ti!x64fU zmd<))IymlJw$q0`ULLpS)@#7D$4y^=#upZq(sZS~Gfuu?6ssan)Hly(E~o8S{-2uc zp`3U-!-s}i-PcSRm+2pbVet+>nP^NlRanV(BI)?k9MS7IE4S?{c3zT(3#P8T7I%WwvFt{pPp|x`v_cTxUk08Ew$dBz9Y1W8qIW{}1zZO`9FajRUyTX=L@j9Z zaFLJqASd;K#7l&u8py@BOprXyb$t%ux&sL*9PI78A?fnirGvo~R)W5)UH5vuomoS( z+W7~vZ<4$?EbY?tzWjaS)*~&S1PRGcy#L~;s~uJwhWEUJ5v1RmQG$Xo=j1Uw1z4pl zE2F z-XPJ|PQ8%0&dQQ%Sg44}Fg}8Wc={QRACe#tnjASnJqL@WwyIl8mJI`}>>X?C?o_IT zhq6t~qV!sp-wK%_WuWX{mJq&BrwF$_DO#qPEf|t4hBdu#4bn!ChkD*y$2Wyw=)go# z7ON96mpWD^Zu;r<2=txhNVk}BoQY{~g(*>F)-6oe?5PRORy~<@`EPQN*-Elzu12#> zOvs1Cej)GR;p}!WE+)QnUrUR1M1B!BQX}MM5XP*L?0bJtExct}vU>Qu<}>IQtjfGN zMHhPBWSvy8uk`5=MGiPgxRm`IGSk57r!EWST6w3M|MM zO=K={C9^Uq5$@Ux+98P0;gyfgdxx`i=>RkpC6V%9-`}_HtgW|mS~Qc$FZJm!P509A zsk1^alX9Wkkf@osPxsAZMI(oFthk)2X>~xvm{dDdAk9!_v3hzaUSwKQr!DMC)jn$S zd*`rKw$DT(l(mme(A%yEvUhUt$G0jd1r%=6n&QzT6Y@!|{18Ud%g6szE=MBFuUCU0;&o>+x%Y;0_*<)Auus9vHS-~ z_*YrR$-v6~pU3}QS;oY`%>F+Z!v9YpM7;vr7g@K0!Hl+K$JokNh1+uDP7SrN)|0!M z9mp`%+iteldaZl*o@RT`{HlBFyQsc8(dxfyUHVi|N}#A>1j*V)`yaHh$-&S>P4NII za+;!<0WdRT6EibY064|`nyO*v5MzXvR%W*Q7q$k@iKl;g zfXZYo0BE+hbe?=WfrG03;Zn%N*Z??*$)WR}#l?_`sr@3V!%64HzkP%AP8#hU8x9SP z99>*YSsGkTnp_yr^YX#lw74_@lKf)?z|r$4_vi-z+=;FC_@^-TDF7KpROX-O!te2We&t;a}Ck1Xt9Qar!&li?G!@iRH)A^QcUr>93| z!U8mb18mFCr2RnEUi<<7(jI?EeGBw&EzPdR?YjyDncG}|dAkQbJ-0Xl0^#7~0Pg1f zt$y2uhzSNYu(CV=VF1g}-st-d{~-j+_zvXHxHUKjn=|}L<3$5_)X)9pJNJ%CEw7GF z{=|Rm{hTBrr=lXJk$r_f{JjtnvDpU5fw`Ij08@iA1DMno9(lgs`|cg2z|#CFjq-h$ zT2EUCYWppJIZXR0HA?-30eJRJ2?V?AH6Gvek)cHp_%Lh*wG;mFg+}_@((s`z``!BUD{gCIYkB;G9~hhO;`*Thz_}UATKC>tg4O4nq6TMS zb#C+R+pHufh95~_WBliN*SN_UrPUcYgG!4lUE_4a8auC`y6{+k70PeF zko8ymwO)%%pT7ofG&cTA8}w@}>o;3zYGi2TsTS4vcn<`FlLMoD(3|BQ*a3h?lh1V? zLwK&HTVjvQd|ls^o+ zkK{#vXc)*K;q4z2Ba`5ZfbA!F0dEA(Ao(kZzi#@I7whHdJ15Tf&VNRnJK#G{ZU&He zfd3RP{|^5#R{8+$eWd&y$oE$MZ}&UPzuhoezoJ|CT!s8+g=mNTXM+nzy-cYmb}#gAsS6LiafkF4msfZ6x3OU- zzXAB5nqQQ+hhel^*ED>8?)lO1nI?Vv;cN7NLHWnDzM*~UzSYa|)u9)Ag}zlQuX9cC zTkvZ;e9QSGnm-GF?wUW{w%0TOr?Y+}G=GS{Pb=PP-wM@T@zH~>d*u?212=lZ8olo9 zznmEG$8r5vQpj4=T7GNph-Y%k@I8l)j;ucEpTXTv|Gn{n?%yzsy1&ce@OJ;yGqDrf z|2=`nSNSh-0{Gm1uF9{qxoj3L-x}Aqccl-_)9+sIZoEJq_8iC`hnbZi_A_Z0g~>sB zLofA^ZN?wV2;FEDEU;P8P_FktY#A8Yr566ZikPv?ZGNqw{_IXNVPNbqiGPojdVPORacK!u;?x($N= zjmq!~s)XB|8Ck=IW9g3N%Q1I9((BUg-#(avl;L`P;nGv5=PBQ&mk>PepSpj|@gEU|tr7C$8niYIA0$y_~x=zw<~U^>y9JB=2o zwDe|vLD#?-ge-?6H(fE$)K$H)R@ioRw8WacS|{25vF z%deD9G~wbQZP==8NE*YAHHuNAFP$qn8tmTTdi!;Gy)in{`EG7~MvNNly`STF?%aEs zZk=k*6k`2wlT(ra!>7CzUjY(^w$RU+CxgqHCKVC<$2qm{`+_Z2850H%-Jp^6}TkhR#)>-9ex#tq7O_u9*_qLZj1tYpv0TNoj9tTC8)C3hjspXsJop<2jCg+UIwa4vO;Rzz)v%8U^nu*6a^e9IX zyHS0=v8x{T=qmYfAT+j}J20Xpx9I+wgD+`$ zS*>;M7t|5%x2`!drg005$C1b`YPppE6XA75(-^e+C3gs)Kp;I9)|FKr4Z8!!G(!_= zGizy8KoFN=sll2ccf6dqxbydhL&V9Bk4yxm{UtDy?4e} zy~p6?I$dOsu@*T+Z(Ndp!ql2EHF~Jc&9UZ?WagaD8MqIp;Tn8VV%`4zwjY^UwY13u zL*2wa2F#M{yq+|~geQ7Hq*;`tL2Ew@Vmq}we!#R$s6!Jqt#r9p-Cl|^AyJzbpD&q} zfyBV>%y|!I7C;=F81LiWz}{5sgi@1o3OSmZSLn7_++O)S+t&MNLc`OZXC>=U*-6Np z!*Vgh(wE@Hl`uuF$Eh_IwHo^6Xp+PzeQpmXcGvDgFU_1gSs4n=PCWK?i)T}y9Ivy5 z?5a8LG;QKCf~^QWik5O~IvN_)s;&bO->ZQTg$a!05(`31k_FNBK1)~c}N)v{d8~-RmBR5>w@Nubu zpr3{$a{vXt&1nbRnWh>LVi++pz~01`L#0NCG7>YU)K}F^(v1hj0e}AvUSarFA-1bU zqFZB(e|gINh9VCzPD!KBR9D8Vnvsy!+SgeDE^ZkspZngNj~VwD|Rv;&90h<6Ij6Gn&t1@_j>cAiF?r=1+}( z$B!7oYQ$L&@!z|dbM*}6;$08Bqa;xn;-WsstjQ!uA|J^tjnNZ1k(3VG02*?3e!}_6 z?~V%KKe{hFM~rxsH_)JwW~vVwQX8bS3V=Zx3h3eU2!wY#>ZReq8j6@2Eknh#ys!G7 z?ln;%%YLeB8#H*!@OldsY2$8lRM3p)r!N5az@q}@GRnL#sGYwbVw9ywimLbDE2Ipk zh;SSt_;#-?LFi|D*70{saeGlNnAj+m66VL@;7;%=9l4RL2uy<~CWDDO>MV}wPkpM` z!z^#fyb<%Ix)VYo+6{~N!D^Vq;;VKxr|1Kh?OIGgm-;nBAuf3}Go5jpOjvBuL1Ak7 zePwaYhLXDv=gQ|eihGiOCFc5X#?15~JP%t!nO_q;xVne49|4lifwlPZI7` z+?S{%2L;D%9^Kq>(%QlW^Uqewh5& zb*5Ozq%|goDa|zwX}ahX+vLA_@dgrt8`o{}>~Esfxj6qsYgfwA49pyprbD<697b_n zy;DI~jnsrYlL3?-1Tec3;KhLUpT=LPzUeKfAQ9zeE9r63ac={uv+J-_(?W85tHRYs z%qIte$gl+11SXG|gl~LKM+);>5gCG1dOVFYqYWm@&qS@xIGb-q7Rj#yb)i4?;03ZK zqS&`gCtq^@*#n-Ui~%fj0&cUwqB;0;XwD42y9#(>x8k7K{O97PwOP6>F}=vc1doqn z*LR~`$A!oYDP*X4hxQ4Lkt@vJmw2?vat?_W-PHZUfr=58sFVH!gy~+D&zVf<1l?kW z#m;ARUM3*9_YIj9-HOx*L39`}g z0s)HH7QIC<72kGWba-Gz_;I#Quc)5PB#7%2k@P=-)xYDu6*Xiup)~Cu4#lI}E^>3{ zGn9GzXN8vTBaNta6C#y;JS)X%8f=&4a#wvNORl$>s#2zPj5QK}>B$qL{y_zD=zi7P zQyBT8{^ZpOWRHok)f#&JGhbPDy~_s9hkh>Br0S{FKutC(g-KA`t7k7rVW)MjR9$_` zjY(tqHbY6mSJA(9Xg>T-G6QE9ojncndf=t9wkPyG_>NuOb+V%jXb(|Nxq+dCh^VA7 zcSCIchD&$LHQb!!8^$9o{<{n<&}@HIWEe@!)0Vm`aWW-Kla3p$Lj|k_T7<;!tezxm z-<|J8BsED9S5n-m==M6L0z4<9l7y0sv)hChy0@Hn#uYoS%Xy$#~YUvC^foVv$#?;V+w-h%>S_e6J+;8u%CmV@hCvP5u)O|hP?ykJ8T znxOOB9?Nq;qN=b1bji&y*;XcMPuXM;sCf|=Wn}MU)OfH98n{++*Kkcj13yj>X_1I? zuZyr?04u#q;I@uK+_ORsT}dCpJ`s1eI%F9iC2_U^N?uo5;}qP+R0AkSaNk#`}|gb(aJ2GaHpPZ%9PZz z?(E=asJ22S8eNm3OVg|V<&6!Rd*(+@t)YMhGJ_W&MzQPG{>9;u_eDAQCx9Cf8IPub z${82rJ%VPNPoz(f0d+;utwrhFq`f#lkA(VS@?6UiqkwELZ-FkcIh!XG2EA;Anqe!l z#M9kynnH)E-AlOBp(A0NQ);@iyVbn+vjhT47?wejDXS{k*%9PHf(e)kl)123n4BWX~q3 ziKE|r+t%h*t1KC_UCZ;))8Rh;_hu2&@Oatrr;3?lOyV5#PzIJ&?GF9l=4V(f-e$#* zJ0Ipp6n(KzNs`SOVib~HLoo5ea9F%cA~$%U%F!CH!A2K# z5n7OMPNnw%6?;9%O!-h>7dQBC+cw(|q6{2!{bp-SMhmY$@=w$s~R${E>vI*DK)022n>Q{6loEnfS9+2uy z&iUQr?v>Ey50_-585}UA^EvqDNE-f}`0O+y^SxcR0#?ux8axbb2&}C$HHxc0+iieM`HYyLkWYw?bC{OEK>%*b#Wt3u7r zbdQ%>+vh!2**yH|LW_<9oFrdfo}peJblcDwj#w{V1_*0Xr}$FO^!;TDd<+5EVuN+y)WRwIgf*XyFI##(9q|X|PGUd-z*t96bigD&&ZupI<4S{M z>V#x|KDp@k%#Rq)bW_3FqK#u`f-cgwHdTX~t|ttL(f+6e+TN#ivGFtEvu=dPxYQud zrpp{(imiG%>f2IKW&(H?*aBiR^m>}3FPSV~Mwrqk$Y4)P=k`i1-e%RMf^Mjp7nNn} zeG+V;kBrLOLuSoAq3V=MZ48nj`^^6v`&Vg#S^}`lqX-D~chdEs(+p03Lg!p9~91 zQjQz|Ux08f_B6bXo@TI+w)kote`xPK%A#AQa;wlP+Z{`Bpfc(0ZH)cq*+iEC$1LsO zZol<;LLFsOO^wSgEZrP+9HL2dqh6acx1wmNJrBX?0&Whw5~cI>S|X!*g!s_8A_?kq zg%^>Qp5=?vMnHNK8Z0$5Y$IMpBD>?uWq-SAgxum#{iWf(eC{rnL|*rNC@m9y18~i~ z@Vn~+?82O(){ye?Dkxy5H{m#Uj-1+NS=Y$2lH*Ny`%b*!+qvxikpbc$#N*(xqp}HI zjc3|x{38!gQ1l3M+NpGVDFUThg0$(!Sc|PG%)+?IT0a3HKaOs^v}hUuMt;s=LFS*Y z6a3l;BLx1;`b($7-mM?4Knuj8eY&3A?BS!99=nIrVoSmG*^YeBMe+2IB&u?jGQ8iR z`XH69q@KWB$c{XO8&JVhDg=FSy7u{SdpAdwkzF~Z>Sf9@jfRcor0`RHWfpz#&zWYF zf{E@^88ClVDImv$0J_=c(Yr7hYB|XsW+)dHu%ogwXx%SPDGX%I+hKM?x29F%ynlg~ zCAYiN#Ks9@TsQ0uv#`xo2-Lsa&_z_na%lZ297qxrw|t_&QM~68t{nKHegmTC2DS{F z(+>t}=4-zw#pr1)yLyq}L1!?K)mTpJ{-g`XbsJ`$<{wLg2C_?4gAO|%HXPzD1m~tm zJ>}+DT;9eY4v#<5l)Jyq@GYdarqLdNX$EM!3$LFxe_#1!byLiO z2-Twg&;&i#^I-o31$Q@d8=qaRCBYS@d)-UM9Wk<4@@I^ zg|*6zy?c`9=Cw7Lwxm?&;ykSEWLCarIaxfQFu!6`LF5kZh-j)c<@Xa*L{zw&xX`|t z-8@B7&7y55Ud-NUcoleUwZBi%k*pquc`4uQg`xrd{0-U_gq182U;(CM3CTsT=;@_qi_NVHsP^zw| z#A4Jz(j;X-o^>8-Id#7BGSOk#jdU^+RE{o2>PXpE*A_5LDv|I7;p4;8m&LGQUYiqS z;=uErCdGToR$H47>%gsZyCfTYIGpdtnY;2WOShIEgEKBnVF*JH;}2nLXd#<~hAPvG zBgSi)%A&U!`tt^#D3ib1)l_++lFM@C3VNES=5O5rw*8eMK<1Ezmb+%0ISAuFU$4N1 z-d#{v-k5I@sPi6rP^HQ7?R#cqW4x#xV9|0S*q#~(uKQwN|EhcAXq@XrC=m@WJsJgR z8oPIPYWzc4W4>^Z+zNP2W4fZ9OX`AX@_}2m+~c$?x@7oE2uLBH%w;aXt7wtF`@d%0 zm-}?%J|LP%C)l-}UPdQSxZv=6)4R%iIsM83U{pCQ`yb^A%av(g>!J|0&$uCGd34F; zs3f>h?s&q<{rIR3=*ift3V0F!Uv@-#m6rc#)q@yCJ8wJBl; z&dLk~&z*J5Ge*P2+o39jT(JTd{bS5zEtG&R0e7xNnBKQm5ql==JFeqGk-49vl5r?8UayCjKOx9 zw?1)Cfr|B)iwQ<`mchWbsc`F=QkPBqRl=A#EM(fP8&!|K1%SjFW^%Nnme3Q*=&why zX)LmKM0bsar@62ZP>%+)Q-m%}Kn4Ss_-v3RrELdQD1kC@+TiTeyd-p!Y+TIA0Tuok zzyYAeak2+sxgKrP6}G-jhL1zCJSrZ_xV}?nF;2Dnqlq0UtB>$667SxHAA6Lkp<#Qg zNyPh4Q(Fm%pG9OUIPy*uYy^|X7X&WIj7cp>QEufL1Amgd*2_RdQ&%EL+-VKe6 zFnkb?;CJNej|CPeyWLJ9!>eVp(m*PZPaXJ;Dvb)Xi+5eMt^6xXG+5kF&|A{l;VybM z8q#@6I=ucBezYGc(CpT;suvh>-cW8!vD7=fb!*S!#COp*mk$xW;`-t02x|>Q?-yy@ z=7VM+s){X!zW8DY-xoW^Jo+lksP5^|+-!f>p%oIpaJ*ME61zqFdwjdk-@-A&-H!pzb})!KrjMFQ6p>JO6f{2Cr$N2kuvBt9242=0)y*AO*S7;8uWZa0h-H6 zyAl&v?426?U;aWO;cXA=)FpL&JMG-qKef2`5BtRm_!k1>2$aH@n;Q{!F^*atHiDcLX|>xr%z(uA9c3vecSIB1#u z+f?2-DqiIgV~7FakZ>jN#D5g3nq8nAoNEWyN_EK7%XZY9+~t}ujM8XmG5 zHu#1(>Uw7Mw1*DA;`kviyeySEX(E{)(zMp9?M5dRQ4sfquJJd7R30a0dq($hnM9p| zm+PH&JE7qzs14a(Y2j8*`C(il9kJndLwd^96S}`{0&0j+MP%}-yLSbz7=g_F87FMi zmzFM6@?{!A#lCIN0MwtFEZ6P8c%t3yKrGC^QARL14^Y}4+%;e$ogppkZE5^wmBo%7 znABA0tm+i^yw{$tR-mh#HW@mU>lg#lh&5?QN82lSIPGxkt#y3pHp^y`5*Fj$!YpR) zb~tVr3*Sphm+U3p3?&Xcfn4y9b$DT{Y2ImoA}J+@$52_>%sShnH^Mbw+o3j2ky(YZ z(;%_r@Z-Eun(qn{xKt5*{iN}wd{Ipv0Wpkp?ZT17Mjvry8Y_R&Y1frN%=jkE-hLtTV#QLS%%?RS)E6^^a!5u^$-TX-I5@ix ztfd^czYzyaM;QHiSys0%?4G4CppShyPN;NGS&2?TsHf=_%YXupTO*!eC=!5L17V6X zM!b6Dl-grn4#&y8dYL?mCt+AGb}RzvFu;+;NI%~Q zm-9nr*-|x#3raC^JG{4^@2pg;?KsRZ30kBOk9>X`nD~4lf}8mrc|*ly>Jc659IA{R z*RA%#C)Gl+3!_*wjFiAWZ6<7})6;VzT^w^LGvtog3sMm5uykklvxl&q0@LFIZ}t$7 z@tIH!Ebz_~6TZle+T!J3YZgypR#CqW)S+qm-lI+$MGjI<2}`G5;4Pe~A-8X&_1L0w zE2%jE?e8-+y-e)jk6JpLfxAOLw-5=pM7)~+$iB{gn{gewpzjs7YQDat4K0qXqJJ}Gp8#{u?1ELuWY#epv~?tS@-B|d8-!}LW|tZrmB?5KN+RKp|V ztjo-UQ@LGJ;azRw(ezgqI*jAwYW58q*E9ry5NBfq#xOB?XpREHn!UtTqI&z(vsV*Rn2tBU)vNnmPQj+;?a>1XP zi6O5YswaQR{=V%+5k!dts$sV@Qgr$0%h_mY9)A1#Q+R95WjpV2?CRx$I@l4*6-UCOYp!{%y< zQl;jQbf-g-HJY5D8qyna76|T!cD}}Hzc5#|^oslU-^^^;dfO+=fs}E=GTP;gOW6nS z({Bhxe1u0To|DY!d*aftJdW`;QAH%lj4caF6%ioMC)rNOwsU9(C<7Y{IZ{m=5ZL$Q zgi3&LP&|mr^>ni2IG?tki7!KUs)@}Qt0#(myP!RnT^h&ydcgsP%kPo`!f}Cg-8Lz%oVx`#OY=#%~ev#A*7dF{;#xdr> zI^n0X2btN$lMHWfTpvAoq7{82a5lqkScaumKglC>0{WwtK0BWN$$)^YnYGva!PPc8 zYb@^eWbvWfG?S|Z)Md?Cw6O{WoOM`@MCs00=Oj1&Nkiyme5oxyKtgRRj6m_p=`~wga%qgCWh07eJL)} zd}en~PmW+ihN4r`g!WoMBeJXYqHo#7Z&iDU3dCZI1qdS-V~Um<27>l9gz=GPRsDPDgFsTJ(=h%kZ$qkKc07EvPj{kH@V-r$IT2OZe?-8c+|8NtN#*<3Z ztKc~SW@m<`%)1{=y^CP3r!{4A&aC|PzCP1+e9RBH)Uyp&%t@Pc#J^bviWT8~ zF;@H&uKIg?ZH&R}t)2bcG^W969TRu8&MS_IvV>OakJ(|CR!+X-N9@B4odhhl({Ez)FPNRNDWGEFXBkbR!Vo5O4U83z^F1*ClA)*nu-E;~L-K}7$ zt&>}&@W!lm#n5Tf=|=CYuSzz_VR7srMTma2pQiTOk-&+~kEd$l)68GbM>R_VSpQM0ij01W<_A z<(|8TYve!N-oT3+cPJ%v58eAnH@z_237=b?xw34_u&khbF5%@?8{}lq%^lpid59=# z200oeKNr_-W(c0JpL7Iwj_`2K22u;T&hk23YVPf7wWX;S-yjjjI~>9i_FS_O18N(i zafUd(_PlWtUOz19j%!x(WHkY)?(Xy(X2YjO>^0D_aU)%CJkk`zgSlS|pZ>q0JmOdgCesj^q~uZg;pSa>d^DT++eoHy&XzG;$d;Rj ziT}meI|K=%1nahK+qP}nwr$(C-Tk+1+qP}nw)ysXcX9`3aHknrv#O|wFEZEK9L_lP z#Gr)QP66nyE3R;y2MuQf-;1KA)yzk1Fc8V zjFKkKNkm<=)HSD~T+y#7$Gf{sx9*j^p~tHD@{LVj8GMzxTHek2a1UXosCf;-6-5DhUpN&l4!aOlpWhd~b!5{o*ZJ+OMF6K&N(5DDum1sK_Do9>9y@#y}*^%3Z2 z#L4I%a8YewoO)?f5l@{7KLy1>-A3#;>sWxggT#Bvj27jpxZRWPgKRi@`&VJ)l(4<1 z+}(>`>A`kF*&qNR7@fJ>%zVmhWs+0cKt@RFPHBDQJ=euq~Ibw?7jo)Tcs}UkehqCOxek zZT)Y$T_i5YsabtbzaZpc1hA@5*a%<*2sv2=6n=?35ab)Vfe?%VTFv0>?#+ErK|%G0 zFpIjHqpMS|%;lLO522)GwISDgr?u`DQSDZ_Tqtf2`rpB}X^~q6J(eD86==9Us%;ph zMLaI|*D=x{sksSMqj1)sIkp%ynkH~ZH$Y+oZ1`M+UT@iz2Vl6;ocv*v&%%#DUc+kUujt>iRWcLJzqh5#e_24^w) z$Rl5d135C`{BRU>$o(O*2?5Ak5-{8hqm7|9j*VficD(sGc%XKu%AZj^4AeRIHhc5> zjA9%*R})&DD9vmGzwLvv16w0`?EJ?mBuUvW3hu2m7-Gbbxcd;e=q^Q=y4|zXYKl(h z&MvP=;Ua?zsSD~c?*+6Oy`$G-_(zhQ9H*f%zS?*eud>vZk@c>-Fj`x5$pIj|?ql*$ zqT8PM@y?_&BPHh8<;V+w-HUQwc4GU3edj0gIvq&AvIRLZ8TKuqEv8f4%QX+qR=<_R z$f}y}qMfcBLhNXq=YE;NpA5(<$BOs%VGV11)Ws!fl6bl5HD```tljfzwn-s@Oxp>X3ayh-Za&t)L5^@F zw(T)#y?kR5X7~XTb6vh;n+|NwMFZ9B`vUoSLp4FW@EFD=7eGhPFrcZt2kd6%a;2s=;j!%CA5#;T=fqI^$*P%c$C$E+XG})OgMQg zR&A03+yl75@Sv^idgvH9d!0uodzCBa_2wR%d*fcXQ4k_cbPgCuU5hZskEp?6bcMip zz}fn1nOqo)XpNvH&q^Mq(L@fhzK}>am-`8JCX>(d-KIeBWiZvSli448{^C^a=j?NN zEDS9(l5Qj1(8&QrEHa2_6>z3*;?obVVJ@3a+A>R(&E5yzrb6O5YWA;m`&K!RqEEbe zux+6&TdoGgTrG(Ws!sUN?$IaMGHUqv-!#hlP1GI>f^|e?;|nvS^yxiNj6Dd^j2sI- zbuod;XIp~97kA&T(JRF@cIjS-Ym0j{4OZE`1`y(U{lAcKGn@>~i9y^$D__*mv#ANjsx2nnEF+6 zjFr_VAXplL$&a%L7Dox2xgP$CRj00Tr)Q!n2~}_MlUz!o0MH2yE%JsH^F+kTSNY!r zoPB<>vK(fM8P8D_KvPXm=uyrF9J_Yfu5tjVA|>iIOz&7jjFGIp%sJ&dw_PPt13=uK z_034j|2e%!# z)1#-;&xfz1IC-154pEc?HyAf=@O8)q4qfhht8Mu&T}=wCTLfn3k_Tjy0dE_wb{UJ6 z(rs7H8l{^IPV6Td$tBOspux`;gvy`~`tAADDR9oey+}94=?<(!MTG^qkZPjDV^f`h z#-e%mm`|@YV0CyN9)DD5mAn!~?^vTJ7tY95Vj}P9yimDL_UZI*F!p!@wexq_m*drv zRXq@*6Sojk750OBvj$GpxBGSG8U=O9Z;2&6s{}ZSRfS?p&YoHZZzuoh>?oqic~DFU z$?vN`?(!rt9lH+Te~5}07ezCMW_0+`E}9alAf`&$AD8_0eswi;FgyRZoR<($GCgeD zR)tC@Q!Zgy+>aED+*4Rj{U5mA4YlXfol`BSe`$}k3QM|Y4wd;FK653UX0q{MEo6k; z9>Qp%%T62au*6grb&hK=wMJ79a*IGZ6gQ7nVXULav0HC+()>33O8{}@4SC`pZ+BCt3O)eW)!J-cN!mmE~I^QSyYT@mJy?iBT}JS-eHw z0WH@)dq+ctnslTP`S7_I0Ml{hBmg-}lKPvg*w)t?Z$%Tjq@ zr~^FXs7&IckRj{eKIzZk$NhSlCENi9lut&e8!pbW2 z*dZ3?yS`VtCuIy2nZn~ggnu(RGo9lRA6V&MKxQW2U1(@YD;$2*e0EJOktkkOSgbD| z#2&I?jD!g((%@!HN+s;g9h;2yTD&8%MU;8o@CmCg3n{P@T!+RjvxQDqYj#VlER(J2 z?0Ui|^s@0U>IorRfz~^thT|}{sGc5ea}M#K0n8tc%I)03%R=PTpFfvsxXvwR7urox9hr* z59>-C7M{Ni0deIrt~OA$Xf>I!AI6s4*^ucg4p<^$2pL}{9IwUG+!G!tRSFjd;B_}` zM}R?Sx2gI#XpCTJK-TL(`a}w&o$gvkn`a!})jt+iX|-x*=U}b=!J065Wc-(8t`2*L z3`yTCej>>a1S#`U2vw|Bq2wILDLxS!)}ifM$W0->a~(u~%!_{6ReY;hQG%BAdgwx@ z`!kd?0i>wmd+r7Dr5{k|=1lx#Af!q&H5D^!XnyB#$wj($ z4ir=IuV`SOjg)~6e3H&bCpNQ_%tO##j@9?$j{pQfyWFuX4We)@Mh(zn>kVQ5=-LV& z3_qY~S^Gt*I+aG2gMClsMRb*~y)E|29;&=+BgpE8F&`)CA}oV!KB6(C)DH*v+&r{F zal~pZN`EgqE(J$yRJyITOL66m()Roct@;U$zT;w?w98|KEMB5v=;Sg&L?8$+r|;_i ztjPnSmcqHv=cQTbqR)kRb<44k(ZSRAA4fa`0q}c|vz;a>M%|%=p98KF!fC zfJZ4Ayg4g38#s@+8ODg{OwKL+3XWZ^q8sJd(FHx6%il213d?vV)Rx-r!ymYZnZn^c z#~tYt7;hF$BNi9}jjAd2gg1F`wT%}8)Li?Hwo69gJr452GzqMfR?|}NJ!sEezH?m= zTP3ah4EZv&cI+Wc=Ius(It$FKMBuC6j2YF-36wB6tp&N&Wq0!8604Bn6%FtkvtAkb-S@gZdrG*Sc>3rEo2hO9<8V zN%7WHL;|7Oy5qtOvB*12U#v<(4c}tSI481`pu>@qoy_UU=|HypsNlM=Z7}R*mc4&M zjEX|dBVt&!lzuLZM=7W)VvT1w&wNg0HP!d${R@kr`3-?38brGg>r^FhKaGSByE3RY zU6W29H?_JcAnPyzlKY2Le79H=i6?cH{e+9r`k25I|4%AB&CXB^cP-(FIx5qFE7*X; zQ-)Oz9&7NDQGWZ$px0(2_+5ZCwdP&K(fsC!d{-F3J`UG#^>$cXV?4(iUI+v0+r&^c z*d3)z5%-zS4z9Nj-i7VxMwngU?L$RO=m3?$Nx80dv-)d0v!X&J+RE{+>^6=Gyc zhrYna(0sJydxCfVG$QUaMFED#WM{(FvdNrbOW5+NDIi2{%+%`+DP(*a@e^~CF9ljT z8Qg>AvSQPWUb10_Qg`lz40kn2B=lZ3zuoH(NkJP~WdG-KCZ@Ylh~%ohWO}p~jGR2g z-^ZM3ZO5@a$ZH3UxfnFYqwBbm!(NpnT!3%T7u~;9^CHJ}T06ta0+B3gUHaz+8n@pgUvq6+YZoMcK>v37$aumr{hhE__X z#TlZ^=1f!IM*2PBk}E5s;~D?cQ|^lXf*6TOL~vt(aOo?~Yi)6iYn;{5y`E@uv=v4o zpMDi&nH6qQjKzxr<(Qh0jIzS-`=_u_8O4xuOEOS+k|OV(Bx&0Yznri5*fa*~U;e%F z%oV!NF{J!{%Xtm&yxD!)W7?fMV~4rlQ*Bibl3Ol8g~48zynyBO1NO*dUJH?|zwOq? zdb9?!{+3PSe+b49?K3l7#e=$yUe-(a7Ci)QpOw2YGtoohYc7%mi;|*z5M`INmRAy&b>BK;Ho+Ikjlprc4#<7O2YOm>t4z zK<%#`ouD(+1$nGB*ShE;cPVoQJIu3RrB@DPnKVe9^fIX({;S$h*15}L58C3PBdN`7H@4Yy=pqZb7}_@Afytz)p#SdUo^3Ct-z}FdFDRLE^mbI<_>HN| zmHX3|M3;O*>lM4F-db@8aQ7sD#;KooGTSXW{kT4RnC8Jf*5b!$dyeg4pN^Dhe-deb z!NJfT%Ehd=1I`xPmKkZ`dyBsldv}@SMI(=JrU9>&F?#R?68Btg`UwH)S{S80#i!3p zgZ(ZnnC*I`n)%*Ha~ZAAmzbh}1G8x%AqePT?+#7&cvXcW&gD{%HeU0p;LwI6}X z(REyh6H28 z=fNWnJMxHm&qAFPo?hb(dK{=VHyI4n3*%fG?VO`*emAKV-;g~8LNRS9dGS6nAIy(9 zxtNIxJoSul#47=z@hZRQk4w;l>g`9*=A{sZ>GUd7{CouMJD602+n19b31zLHNf$REdxDu;zZa>^)BnYbsn(niyIh;7}gImmwq3 ztnT?Oe4Tn}11Ezo45@JXv}uZ@$7+HwIb&}YLuWF_*b!(4AePoK<*JeT7`*yyv_rn~ ztzXBqgKu);DrTxE;e-%>%>{`EsHaG5v9BwvUVU3jjbTl;2PG3m-d1Qb-;`jVUNP%b zboy7{6+OVozC`{tkc8YK zC1CI&oK2>^nx=Ikd>Gmx%=DkTHuuL+Tt-scarILENE6|16&jY)98z|h+C&t@5o%79 zD7Qd2e)cfoETr)GAKinvo=r?Bk$tnG%c>|fmiHKDN!59H#^rNRToz>Qh+l*da=`$b zw0^*$iC^Hm-KSahKfbSIX?2x;EIhHVI#RwcS1<=B7wUZIan`eE>L7}-dvaf~T|nSL z?K;XRg7LpHW6O&#;6>R}Qn6YIE7D?z7{glAxf1Xf4=fesMJNW*%%^aDJirdi(l~C( zZWf;GUqdg2ATJ<(WkD5<+;DF@<_BRZnqZ;+pGc5y)h-Z2tOx;VI(2RN3=(cV18n$q zWDKyqI#RP|GIdLM0|TTQJCW|2oz>Hx=%EI%kfO$6`pG_XciTOIMo!y|guMJL?xd-l z^;|UOR{9-EuTu-1&9vB*QQfjf(1p`C@bf?=K@O=#xn!n0DT#j9x{&h+m2=OW_L)c} zui5(oF^DinBBb4Jbs3%jaUPW03+0wV$y(NIaSe8hZS`Qz?qGInOngP7{1Oph=cLR{&sZv@FH=UmL!@yLw4@beR%HfCsiB^Zir0KT= zCneYcT3yv?uOea6WBjYm5TW0!R67Cla@L&2j?(^*_}+#~l=25YD5Xx6Rzynw{p#km z=_M{)o4QOK@*ng~?ziVMI01l&-uQ~R)~GOM=clkU<)EDGygKif-%W!e&NgFGun7MN zK&XY5I{_JL@IkX=yL5iTqOJCP%y8Su%63DX4p!XXleg(lg0#+dEEd~5F!PYCOgq!IIj()5)w znKf5AY=ytp4mAiUUXX9Yxf#PmP>I#l4rtUBvu{s;?pCzTIC6VUw17eQaP96kE&>7& zh(?%;6hG98B~4uflo6&IY;B!Yuzcnll+h4RKte-+BvyzFi;v5mo;a||(D6b0p$zv> z(K%irA3-UQFsku-?{QQb4;`9)S&oN_stb-?88_ZZQAJt#Z z+8AOw_4h|wRn4O#dzl4K3=m_q{2q5Ugx(_7PFEaN3?%Vdl&Gk#1oliX8vdmb#&^IR zF8v)iN@P}uDaOB`Xw>OxloP}hw=!7!1ns5Ijd6bs)AL>; zKeZbI`G-5?liH9O1UY4pIM@1LOv<>t}d2KF^Q2bA}61NZMe? zzVi9A{-=!uCYyTJ@~#ot*^;r8wxQ79v(Be|M|Zy+vjGTSO@z4byGU+UvY6gK$zZet z;7PIRWq%bC`ZZCykk=1Lgw$FgjTzag2ospk#B6GH?FR9M?B`dkzK5Ru2X6w|G}WLY z8E9NLGjSoDJ@?cM$BtS`HYL_hRbDr0<`}qxT-z;tI zQ%FzAMe;x-_uPOpxPjDrn{A!)APx1zR=x6Eycxe)ksORLGcQDs0%exUdAgd^1dsFs za_NXdLBrm%W1nFxzwC)5UA-GdsG7}lwSb^%Tw*>aX;?F92*{vn0jT}o$AgkmcTfQv z`uw62Nz-V)WPpoT#- zy%mtLJQ~CqoiqreS2z1%GIlgry{GJM^+gLtW1WR5I&TEN5FndmY0a%GBF$8Im_No? zFX=)!IQ*#C(LyOD@?j>J`Z5&V(%PRU)Y(b=or0E`w+ENZa|c5?QkC2YEWdmX{9A_e zvC^`|WAhgUwDg(Ymx9bVW}0)ng(L|yEy^x-VLcXj`mgOxp9Ji|l!#%T%<0DhkwgcR z8OesT%X(ZRdZ{p@PzS5BWKE<`>KJgb9Yi}^NUo7qJl!bt5{sr%Y%}K!k@~du&ET|A zLP_yOM(;73)9bXdi%Eyf4ruS^-nJig=AirV3l({O^I7aWG98czmYfe3VB89+7L}k0 zcT*FkF1Rd1>J;;W|HA(vc;W$Kx^|vAlZFWK4s0*`@zP9Lj))8S7=}6FdMMP6V+a|Sp zT!3Au!O)m=G;H$E&FQfspB`UH(VXbd!m>`3=?(s09L1T1yke8CxxZ0qaQ>?aG=?MA zHjucyq%HuP(xn2Ggd_#x^&q-40g0la=>PJuBR173N+iFhK;}3+4 zWB@*A+M*SYuH6X7V>EDRCkF4%vzw35BCP5Cjia6hjLgB@;$W!N%WdChK_gHAHN$mP zFO_Z?jmmj1T)t|Bm!=I$uy4^*C{Z@PE058@Gc#D3LOS$&wN2XcF2fMe-Z+FLUhMwg zl?nLn2&|Sg1j&~FIJ-MCo7q1mN~VB(j^4QrIinybc%Yw4m{S|$tIC7ur=OwkmQ+Wb zAVi9FS;m!4Vc%Ey{*Y{E7s}CE81ef3RI8f&$_GFQNlzF6NYIb`Xe9WT)97xsSmqo*5zB-Rdxyh*ckL7infe7WV4s*QOK z8LSc}rrk^sgeMQAY4IViM!mP3B2Rno)(08@e`C!eNaxw3X@H+gz)XIT(hmkXYZj;? zN9*TrtrfIsKL+QK9KaFs)cMN<_$*~q5>|O}alUu&s*>>cSjD^GC|P#lf>!Q$xfr~_ zyu|;e-tGh9xV4VN=D3m)#OE;aOV(NeXj4RDU9)Z=+|SHr`Nzgm`g2WAK}N(L<3R}} zby(Z}TNpSL@iZ0@)RjF3$aQB8z0{LswDP$I3|)adrD1}9y+njH)|JW};lSZJeB3mNuYFI^GG__9Shm$=zG6;nI$ zM9V79Yl3kLCM;ccAV50Mtog@YLP^XSt^EwlWMXBRXho7!Dt;;Ri(3b?X>%h$K4CDp z)M~q4#9g3l=Si6@sFp38fHmgZTAQbd~thx$R^v&L!Pk~F~T*>ABZ&EPz6-~5~6-e z4hYoh-$pAU0Lcg*H%0xkY**5cXW?S=>@mYG6AB*m9 zUVh!B93dA|Xj+S@YDUPTdx(?2CiF=O6U8c%&iyX3KbWodE|H6bM_hD>0Y7=I2fkHx z=v&r6(RV=%YUL5Uy-iQ#_{(^AzA<3dzOfKM_u?YZ%Ze$II z*dW4+)eH(W*Oyk<^X{NQEgq#cq0j4okp+hdG3S_v1;rQ;Ak_OUlHAi{tYclkQ3EMhb&Qc6PD(Q=W5r-ek=BG%qnkCEgl;qf!G$I13w2A(F;+pv zZMk*)up$M!T;2<`Y+2VDjC>slL^ATGwlKQdI0VlBMz04$$0y|M-H!o9G%5Onz*yEH zI(MNf9#QoJqhPSj5a>3E51W9P48{Xx$>{?0@A$+7gM_av2jHWKzJ;j8zd6kPIr-F| zO;H}RN8txhV$II+r*HX>*m9bB1D|N=ATGF4_LQWa-C;}?v8GLrBn*2}96zpYHx79q z*R=$LXjL=pc-9)Wc%y46TAP>C>=z>*!x`we!ldd()DM2%d0EI799H~wVt4LS&TtAY z!w~^mN+BQ=nEl?BZF}qfHy$AS|HcDkXZpXSgiMT#?EkBkkco+%f%*T@N*L1ys-Oee zOdHkJ6-L(H)zyW(UEt^rZ#O{NE}XD`i?kgK26=mn1ysk(?4H!|r{1HkB3M^ry~PO& zTG5CV9FY+WsjxV(n-UnBn1N1Enm;)RWngAzY+`06nxC)G=F|fEODvW@55U!>!MXnQ zYe;Yk!{P=yF&wKa=mrJ%3ZTiZ{eNhHX`#_+|Az+n#2*GX+YR7o>`u)b07NXXI)HZ` zBtUq&e|}(hB^m zi%ARwDzLLSd1Bv@8Qf77-oT6ifV8fa0d%7)fM@q=CSVRg!6_gshL?W~(fqfi@oNw4 z)z9Da|HA;WZ}IQ+1FNt9oY>e{UF)4$THhKQ+W^wFH-G@8k{)Afb8DXgjJ=!m!$w=_ z;0XMU-HoZWjgb=u^rvG1lZdDQj1>a^lFy7TZBEWF2hWX6zp6w^^$i7dQ|sB0o$H%` zH@i9sz7NUmPGDF-TXv!^?j|Z3M9T=FIogeCf1LOem%PL5h>h3S~;`;lNY5Ioqp}u`^aB%=n^N9ld)J_HF@j>v> zjok_QS2keJ&z{N-`yc}UBLSM3UP3VdYH4f`f5*Wg0nhx6<{xltdjh#+2zHGD8T`IH z-I4pwdu4F0Z+ZQ&{aN?Q+%*>;Cy$)}*1qfKl$QsS_lF0@;`aAX4gl>RoPs$xG5~-7 zVvBC9U*e-p_vxBm&)@>^`2PcSz3_+V`eXLL^tTHJyWi7@g3B)f1uFNyYsX^-Z=yU$ zpZa?${X2R5YuoQD{N8i>_D4=~X=?eAmiva8MiQFj2)4gC3I zTLJm?ZGsYDre^Q@t4VQW1=|UX=n1{)vu$=tY<>jEq}1-n)cWnA@t@lJ;bPLJ_Ren% zj$WxNg9-=?&G_)Y5J)q%0`_uh4`6$wM@4Yq_>-kHw7)cXy&BZuwYLGz-DG9Qwu+BOEk3XhI zmKN65FJkQSzSBO!@v(3C@n2}IpG2?_e_^;*{rMku%~buMy$=q*4DNQ$zeHFQg9mVs zkw4jVTowUodU5IeAAB@|4g8M`!JYbF;Gj|CCvXtgtyg#mtP%W_#(>RlZYJ>Y6+D+Z z|8v0>?r$<+C%5-_ER~oedsd2c;&WOXduWzFUM#m%|Ki!d3=C`vbPH<%`z?MM&c7s0 z&hK0v?sCq!Ry#WXV-U$~Klo>KC*aQSm-7$zJq>?IT%ABOvev%?ATQ7Fs&{=CkKcuF z_320JP5hlP)EQXus>QTm9FR;f43A+mCw88 zd~}$9RVB>#@hRXht1CkX@ZbtCZTtil)3^Qt2+Z;PYADAyAK)ONZ=b+Hn#oRYWH@UQ9R`Ab|@!6)8O%blyjefk0}rJ zp}HwOR&t!fXOEa+>Fx_&fuznTA7mR(9`=Shm=OmSjC4GTXLfgHj80{Gk|xOK2;Xu> z>ruWgY#PS+XFclF%bL1g_Y)7U_Ys8ljH6|gz9R5^lZSp!l(c&8c=9=87uoC0(q;|3 z`LDaGD!vYU-Awt#>4znwW5z+lNgoJ3yJR^Q>Oz?iL%F^Wx^6qlr%_ca!=ZYV3zw=B zsa3hcsEOunZ&u*G2LpdVy44{!atom#v+;1m%*=q z@FC$5fkn2}kM1XRL@Ozt+nVR1_lxz84e>Jw2U*B=97_7^o+E1vgY2fnM*8JLP_?Yo zeLC_kx_MXVObk!VsoLd{g+!E_WX6}r6eCl4bEjiY2w3+l&xSqsspBmRLSMO(L?EHv zpUN?>mlvu+sUNVzBM{+X#1Mxh+md*34#8zxI50drw;f(@kF4ac6!$ zP(yGn`xwvRFrOSgaAEftG9u%|s3w>QH~g+%yy8Q1rEIa`I997am_n`aHh}8CvB)>! zTXs-`^R|BQRH-~^{no&uj&Fmd=QzzYVimt&tY2{QIZsW6A~<&&)A%tPR`^LMb`lnY zYVYEiMRVK!RC8Kj2@g%<36z+(oz-Y9Z}8H)+U+aPwt0u?HX3#F9fKjf-DISv`riVx zEy}+#N0KkixZ)F&7skgHy#|q3k>30-F<{unpf5{@Ng4-F$$DKxHY2Q)Cs|sAu`!F7 zI{(2YX!kQH3yN0C6gi7`U6zMbYVY(zR2C^5nKlSNT|dt(l=P#{A^zhYepWDea&3O2@GRoWX4G6pw-qLP=^S#vBl6Uo=G_pt=>-)SaxGK2mBDb+$bn>lq zFfYItYCa{og71BJa$i~oMPgU#3Eml;zmYh9Wy|>81@B)vDGwAX;U4I1vE9f%_e#{s z%${hTJLvqmXShMtz#P6K`U3G2^3ECCcicAOCev>&KkedJiW5^!Ol)7))#h`xd2m!ial}(SvReVQ<`HINl zN-Pgn1o(zw5Hw0=HkLfmU~G~-%Q)mKI6+qTL?wF-pQ%}!@$9nYt%W%Orb&rNMi z`B`*a@SI{k_5246@j*sE+mFP$B=)W}43cFA<>|T0N#D?N|1><)a=uS>l%^(dFAbL?bnu^-s(OS4$Zu7e67 zJERE%_x4Eqr&y1rGo~z7Ybyj>Snk@oGX8x`f1?+BW4@A@RZ%_V;_SJ=$*G)<>HJkm z`oD~MJgKqcUI^Gy6e_M4J&suLsyi88x}AkWPJD|s-H*1<#6-svMFi>(iP1ZSw0sd) zZbRzbalFau&7*r|ix0Mhn`m0Bx_NY4@}D8)i8(`=axpNCZ6-19QBG(}ja=>%wzT?S zyCfl--m1}B$rLHQl+c8W68tYWd6IMTQl^`vSg0lnes`m6FASpD7x}+oD#ABE8QT#_ zu8rk^8>?wRxk;YKf7AF6-w}Ek;wEwBZ_2C*uOI{LtE@4X+>{XpZ3iCU$$1My9qwmN zJ=WljB{)PLUZZEbSo>;xVC99VhF)P`mkC%f`EH&P82-$4Ih@#*t&QF@QHJK^CQKDd zKD-4)5`DqR+8=|hTakXAt{T|yniEb^Y9P+p25)e4dU&;3D*^48r87qO zf`yQtGyg_U6f`;luf*N>rQr+)Gn4dpmnJa9Jo8;2cR=Ir4DJ%S1-rDX4_b{@6Ch-~)Ipl~3 zN-++ThEK3LU~rGXUSYRITiE0g%%gQ%qAy82%~OlKi~SbFg! zux+xX=-*e{wo2g&O=UgpBN&^ZC@K&X-WS^-A>oc1=qDriY1}}il*_Mb;BZ=43vx0+ z)5z9{@V;9N8isMoR*?YCA;#-`$?ZHs`me0^WR>O2CxCrB!ue-!E7C9<-=|~5+GTf& z5~BI_8f$)pkA{noj(sl>sw*=VwSIKdo=&g-b_P({#X;F3UIJDQ4MU)9z=&Xx1X)cV zYX&NM6GD!yuge;fKL=6tT#gY_WikrCk{;6WbKZPgb&55C3IZ>&#=>U@V@xA)1=l_g z@i#C$SW;Er5(M4>N|C&zGEAg^lbB9WLk@^WlQ1?N#o&ZiX znAoYy!DwBldBq^MOo2AwKSJA#vsLnhc;SArVe646efrsTvY8zr)IBF)H3D#%ea&QF z`9$T-Bp|h2{4)!wd;ZU3hs0GhtftVTZGW@in-7T zqc-Zl_o3BKM6dPa2^B2kRtDGoPXK*6)EuhD}Kj#MA^4uiDc;<;EyNlHTC7z~Ovqwt`BhR1*~vZffW z#MyC$5d)SsQCL--s=aOq4-x<1eKlOE^I2S;NY&9Q@l`uvBTF{)ip(?rE(By#IXs^#6ZxK{?Tnmugc&%sRXe*hj*EeP$8~eT`~qxT(Q_jIRJbuNO)gmso&Ws z8*7ufzTnT5Q~dBJD|6RW-A;#ve`GrgG(+QIA>nwqdHi+`bA)84IPk%P7{PiT(EjD8 zKZ~TH6Wj|am1LPwGyF!S=KX-**U^l5)DVvgkHFWsH-*CmU&%;yMV=7NJD68hn>t=~N!$7sob0HaPQAmCm4h&^nO|dTgD6DQwEiT?udn~i zQ4WTaETSQZUxeA|>Wr-Bh=9DDJ(SAV=Z)@1(=vH(&%Oku1@vb?hJnN?9l#F7^!tdI zDNVeku;PF5x$g~ z3g}40<|-=8ckc7h^s(rURyprt7&ryslTu@I`I)n>72|ZT2DnjfFx<|FTGRrd(_qw~ z<-(YT<=g4X4|i4kK(#fisD3qC_ESe`!4O3R6a#NjDfxPI2Vb^RJZoMU$Z{Awy2JYW z+*7ZMS+qAt@6WWkuO>0jiwY#aWpQccS}|;>(iF#0L3`kray8q4*&6gy(_dy5%LXAU z`(!eaI&VL&YmOw?8*Cxyo*+_F5NF_=(ILDfo6&o5x&bS^rMEc$gVw3?df5?n-4?F# zQ{jHVA`K!NVPuzvm};|*BFeq%`A)xz#ZrZPuatU;OU+%x1a@{AXzC#GQ5D3^kw4qD zGe&F~%A&mu(~K?#$CD!j;(ZLAUOrT%38mk^#fBi*T8+Lrsd@=mXOw%$ELIU*IrH3q zxd_F0)(%V8*|e{(Gb;G@>#GTh>$PlUy7Vvy-$Ah4cAfeyHvM^-C6kN?v-^soT~z^{ z80ZfkKZ&FgMf=D}s_pY~f(g~-o)&n1uZ#_sn@m)5XSA_=HIn@NS-Lnsa|7iwx-3APinf2Um&x(0p+Ym+D8iQ?sw4|Cgf977RJ3R zE@=~2rR;BG?em#h+fekMTN~+JX;F@Kad3uVA%w(F<=mGLW0?8i@$f>aA;+4IoNWGP zwo;HviGMnCs_MtU=?gGM1INX^k(avz`1uK3t&%1Lc1J*>`N6B6z@!_P8&Hp;g$4n_{ z3-M2PVY!^{z})*rP0JOaHmHT_Ak?p=&}ibx5}bO*x?=-g>p<)P+J81Xu>*kbEpX!-g`Jl!UJxuu3|b4=xnKk?Iq7);1~nuu zw%0AW6>DO-{BE9-Y!Lz;+vsC|oFXo@+{FZ4Dl-QwvK)x9Dq-TEKsBSA4dl)NVJ0Hsg9^hMV{K#qu*F$?jo$`O zhYw8yip>-wl4qC9-Jp7JDkH@bwSWA|o z=sLF1r3}%7lm2;0cFa#vMlCVE$Z_IYq4ML<7jScw0;KpJTX_VIvJCN z;ZA{~@O)dPvrUp4FoafPigw@xOM6lABC>7jJ(iJ1X{zIGF;`K0vm7`4(iNFGPrP6E z5c3mfrO=S?Eox=$g!6$2MDX$614!2JS=HRPd&G)xXe*>Ud2<;J|u#$Raen;%jf@N>>S!d0kSO`+qP}n zwr$(CZQHi(Z@~h?X{2$OO;{Rxc$11;m9T+=^e8xyk{b^ z_&KYKD=Y6x&`G#GHbyH|T0C||H# z+^*E;-3YE&QivYLZ%`?77mcWcAK!QEjUUue41093qh&ru7kUc>-0zl*owR*G6kM+GmL*BE|?< zIfn2eI3M*^bdZa0XL2hF1R+sw0!VQTY-7!>*^q<|96oy_8<4%**QQr%4nBlBa%;6w zOPlrL0_}J+=J%>$D~IHmddNrPYk_mLc>cJqt@|RuyLRgBf#oOte5LdPu~s<{=X%X~ zCAQCkxn01<`me| zP*~7%F6dx?1SMo8YyB*i61SXFYfPc~s2niZtTu~%fya?V%-|b~e*3h%Ad?-bTdCfZ zr_CC}0B-3a8{fBL%hH?MgV5FJsCgAh=2SLkCd>v_7;LFvA=b)sB|c2+Y@I)>jSDX! zPV7TT+fR8XD+O;H)v}UdcU_Y&_z$mI3#@jyk@8M*;J+)oSE7}=NhRB{vpX7mI?dIe z7Qa))ybnU)STOeG5{`V(9KRuL2*DfDypGt(;0is&C`hSyTgH^q4K^Ke=r{7fsjV0W z>aD(}t*Ng$yeSTtm~V$}76`3#3e)yI;6fEHXiB6Dh-GIcTljyYVgR#&v(9q%(Aol& zc44A*Oq`o7jzBJPjk#mO=f8tW{ALZou<3(y3YzQO`XLSFKd#J4fpHjZ8YF?&QJDcD z`&eRAr6xAed#o~UNC#OX`yDIyHCp)@j6940H=r>7RVYkLRY9{k3L0v^?CBUEBduVPkrRyB z2g(!BGuufPWs8@aYtHbM7X&_~CR>Emd1SO!WIl7A%!_TLyf+ zhpWVkO5GdIFsLNN@w0g<>3fh6V&nZxqt+bVUXuM%*6N^4;`UCMpB6dy;hKU)CEv+b z^H)Bma)dVFs^%1$){VFNQq01u8*P1=6K03L{@7t{1KK_(#2g9X9B=@=P3H&+8)3u( zwfJX8yNh0*&{K^IqQXPfkALlMeXz4(?#MSHjFRFR*VCKwF}dyZy0$y)y0B2BMR~!G zX~BC7*^`X)rioUBqdj%!$EbhI&dkE&@$z-s)>K*dCYl_~bzgMk*B))+M63GoI2WDj z7YTlN{~P~zPp*VizYct?$~0!ECf?qyG8omeFsBby0=xdX(V!B14w zJgb$I`^f4F60%=Z-$n4{_7KyJepXtAl#=!nLBsg5+B+*Dld+^RET1iDf5RIS^oG4l zi2r(OLv?ASt(p9h$cd(4y=0^1bOdMa^o^?4vX4w$jsk>ht*~Kf7){DZJg*jR4VgL5 zOn@J2_Uy8$x0l16`1PnYwA4K%{e4nBh6`QgP1dAJpdWFvYG38>Z(<6CxQbGaElrRfHW1JW+VQ@o(v2r*@5V$1Cwg( z$K|F<9NQsh7b%K#osapiT}Mu5;q~?MO%jrik46`=&(&x!fM`U|Ga!s1SX(Mr>D0se z2$FV|R}}rGj7{Va{{x?E(NKjc3AsPg;37gYRU*y+{bK?14(-PW0Ue&#uo!bq4Ky>^ z`s!_je9cvS8x$w3vRtVZBai2nAdg8V#~5D|N?MStY%_6T;C`G^*jo0+Z5UvHG4)P` zKw>kxFddvcU%yTXa+n{}wr^gED>r_Des#3^M`be|NOyK<*;@aa-E>9e;-HPw0!?cs z(uB;h)4cjMXXQAZL;R2>toI!D$BKHR*XhM4gyT9xJ(vR0rz5bpq9$v-5^k5KmHSwwI2t~V6itC=y+qB2LO10b}`QORUH zu2bh#q-ZXE5uT4D`&kF=ny}^DPIBh_+o@)QP2ipI4jT0CP9!GGjeH`a{0T;hsAi#9 zrR8Xo@0;hZ!MXoJAZ!LAo3;0&`$%7Zv0^F~i~v7-_wj!N3fzo`i5UMU$Ht$At)#QJSTwCz*y5kHC!zaqRU3FD|ww9`^;zd@6Aw z=Y}ltP^toFy5BdXC`R^qT)&5WXwp z(DIfe2H1zgQ5u_#GbFoBltIdKv0(%DGa7@Q@gEEHSV%7)<*gyd8|ce+-CP|WgQGHX z#nF(gR-pD5$QQDM=>%rJ(FkF%-K)CH$^*Cl<7AYOULHObAw^MtSAzvoSH>8nwCCnf zlb4V``DB=?>NWV-th>ZW^~v}9@QVg(MJU}`>cHZwq91?@!^zTKY&>OeyRgK~Zc<)g zfsmhlLJo6uEw(`1?7SH{-n=u2+`1_PSzL-yaj~e-uf)3vsa?t}w$hG4IxtWLPzo4` zqGCE(dN7!YRA7{h$RII$x^t;v+Y(WAAs~x&>S9#*Z=bBSql6(FvwD`<-;xTxjGd-w zwZa0k@4F5{Ag5*?G^5Q!1h>!Z-k=?`%_;L_RiixUgM7{dg{6-GQ}Dz}vuFc+w1s6=opbl!QBwCZy{YZ8<+>jud&juig@#0n@65+IZ%TFZ?fWCi8%>#3@ z6VpsHHjf(vS=MxKWLK{?n3-u%5RUo{P^F$!Y+q2*q7;~B$<=b^7KDa}5QSqSqua-< zs{6P`OT^|9{V2h59&s(722WjG>6ciTC1S}tuG;g`F8=)mC=nVvZq{*RCF5}T*_Q6% zfjF+x%I7X-VBjX$G@#F2I!y^)4cHmiwtgK0o&urgZIBLCg0bB6fEF6Z;^V3fz9^cM zX6$pTPBM{=>_QcSGDB~CS+t*=YHK={H{5R{x|PU4&e$6xR(|;~^_-#k&hz2s&m)VNo7&TZkQBQ2uM`y^GpU2=)T(_ z`cjB>H4&Lo*xdvDPCbE1`(kwZXAUHnSM-j6LL$X`j1c`p@GxhhOoMgpN!&8Irv@*W zT!E`q5X;1?lgc}AfLF8U$)6yt%V|^HOC3mT_4|yx<~pQaSATJ)XQPcSAFBq2<}~-< z+h_J?dDcXMB2z9aE&79>?xPU6u#nOgX8ZlAi-)fjU-`grU)M>X`f$sDyhW6+uAOk1 zWZJd2W37cL+I2Q19Ts`Ict+KMDxrlKjqtenv9QRL7ySn&u>Vp0=N>iANMhNdg0@PS z>mit-#*e{`C4*!P@LpS)r7!g-E~z`tr2)A;K+uD{mfE=IHSTFyv}4B7jHr+II}w%4 z{LMU>AAKQ@6z}Y9G-t9<6AP|EO}`I0CL^wLiGVN0Mv73@TL4>9?Iv__eBk7$PN&;y zli9a86vIRn$FDyo?DkeVNjt<>eIjj|Yv7l6Oba^ALzi-eX&3JBzFdp9(_jA1S>-4j zzVj(fqGYPtk3;^ens4_NFjumYh2p6c$a(ljto#fHMkqAJtmjP*n4ezL)L#B7q})Vw zB&T3ZIA;Y@3&oJh? zq_gaV7a{7gmwI2FN%7VYvq8yR1?nOML`tds{jyi1Zr*9cc8QtF^seM=1ct$)!w&Kv z$gDVt15;39&2$x64s*lJXB2Z%d87toJ6?y}fpp{Q!H9zE4FdB+mcuR)OX=DfSz!R? zZ7>D9*+=BdXLS?$Ge-?0e~vQ^8Muy=;l0zttr-N7dT(47MG$KJf?il8uNZPxM}~h6 z7kqKi*^)oEC5S{0KE*z^q&zSn+S1K|6~%UPN>jqsTGeYF%8==bh*2wf$mC|u@dN(s zgqB(gC=WPHiB(sBy!>{r1121MV8!}De#Vwt0D43N0at~l?4fB8_(wP zQf3T+q*}>q2a^2TMn^w_EpiJHqMO{7Ja0fasgD4c*uJ~xVTbaVA&zu#>Ks5OPs5Tz z@r9K*#`gK&YV$*V9;T-_k%+c&z#ZFgZT1J+kc@rm+osR2IKQAmZ{eWc#T(2^u(Du+ z&cNm5XX6v;Ld!(#?06-ajY5QAC;Ad67>Hyv;(vK)i*Jg`HCTC^J^mGH&Xz?rz1YwK zf3Ikqhws5AM^Dm{cgO%I2`OKVgfyHV$#w~BPtweO z>fD>u5ZYJ|Jiy;{*_VM>0nL4aXMR>07ywNV+C8RXisn!lRe~^&S-@=Jdw`;-5{)aw zT=Ja>ePdimRNcs7(dPJ71LR|Tc3W10op_3TdRy9ulEZ5*mVO}1h)AvEUd+C>d_`5a zJLBY&fMgeC{SOImL+=v_#@lhDb3h-JQvwqtF69k@CR~uEwLa^?NVFt(;k_dPohgVY|&d9m#>rjjq3W-0O2~^ zL^&ABwK%j7{7prZ6?*o$Y$p~`n7G#e&1i-3O)9$l+pPKzm>N2<)oOQG<6FQK<#5Am zW$5}Z0ZaFZqCuUADe)ZgEBfTxYJdZgxrw3aTN3w1seAF^s8``ep$@JmZo{}Sq_m;{ zP0o6BW4m6h>^ocN!ejw&fh~{iBR}Bt1sAI+Jk0LlN|(aE4B1kC0GkE-fX7r6lVRA- zzM5qA#DS#>*}f(ld#5p#7)$!(Y*WDo(s|3W@@x zBXuyRJLxY+6E@Am+Jka@*-w}i%Shhgwpt9af`EFXv&G?zq1ovvxXZ}vN}@=2m8Q!> z7sg6|+M;;Hh~@5VRCej57(xV}HR0TY#@TizOe&2Pg`n!mw)j5EedN+I&U|j%%?(_~ z*68F<4OMMcqrEZ9J*jT*5PXAI34p^63k3@8>cra`%o`hQg`Fhil$ddka@_b(q_MRt zv|}(i4dYJwm~KOi8V8HZ{g~IJ806y@7A&@n2^ZNpwN6zVXi=GW<<@^3?qPZdJmkG& zulveiTpN1a&DL;z=D-ilhI)OHf}Vo89X>dnJ}u%}0fE?kQygq-6#CR1zTNDUkqU}{ zui?obGdn&7jQ*mAcAzeDO9^pTsF=5^w$f-Bc*gs=~Qs0rK zvE4z%y1w0-$BfS3h-Mzi=6TXEOG`_3C^IL*0cU9l&?i3APY@lJ-EekT-~Nb zyX}F-k~OU2l)-7&yqB5;F~Y8ttuCsYLmK$3&WdPm@5>~%T(r(GP9EunY|`qc^0hzX zSPyc zjs`EVsbx}$=4ETZR!C&eS@ns%_8RP+mldAmQ_Y%h^@*dVn{?Gwb7@7QJ2 z*xEe1=ujGWphXrePbR{99E+G)hCo4^X`U_)uY?SV`7g+f2Y5OhB~-g~bB<^CenB-a zdfC_%;$g1Fbvyq4X^_Rwnx%Vn5#fP0VkjDnkG=1pyg;Dl;-@*vAJ;DifkhdD@g$1) zW8?FqB;RuER%OzlGAWRPFYx(XhoOzk7sYd6WKK@#p~f^n+L{^pSE!Y7eAt*h zuP(ud zkPsgG?O{bqu`y|fSnE_%D}{yLUwI0-Umf$V*t^Eq_xLHbB245w5=QH@mZLGGzF~qgYbyQH7b!orDs`@vHRuV(j zB2T96h7|Hb+q@AfZ&z}CNQr%w%#?edj zMdC0lv!*>Y3|$|a;xbfdSw-V=*8nNHan1RPtO5sl7qV5)zdm+jV|50?40SFy-BE#| zg0be0r%KJ5A!kvCAjWj6=}Z7q#PM*%KUiKdv|YpY=Qg6JWa~tmOoCAQIMb9m0qq3V zB*9lJk8t|@0+CRob@V3j`;547UvV10uc#bhln^^N`&q)bUZe{2eThw)2XUaiZJ}z^ zhHkG0yd#_^Jx2B@o$gD%=sncm6S8 z`amW7kylg64NO|!Dh^a8tXe$zZpe8@FWYYmjbcMkr#GQNOv2RgC>5ZpiJpJ_FvTN5 zfrznXd_;*4`OseJ=Z&H2KzNC*yHjewHSepfghZweA<22+xSWNQ+NqJxd8a#~xGeD_ zVfc{vHdwM}m79xY5P8y0J0ofsTHMt+{z_&$4;}$79|=Qm#WGinO$kEY*UQ#dG01Ws zSdxpjR-FsLl)IWX!M*%Oznc!eK`F}#2x`g&wV4V*|7q{6qWjMwLsP96gAW|l#<13X z;}$e_H{`ZYwsPOSk2f|{X3@fV?De+nmSQZTa6k(#l zU01#|Qpgc)1u_xV#6M7j|BB5M^&%Xu@5ow;@Kz%lfB4NjTV5gFS0W)aJzni`ZK1JNIWLoiv&Z2r zSu-}t*pMK z?{RqQKfFj%K9lAYg_vd-xncO5SljJdv9kgC7-d{fjUxWDTA1CkOdE}Ch+Elx%j zJ7bNt4Z>Kaqx>=UrMeeHqy9mV!oE#Ru_-~F%9?TEKHt}#^oVoBhurXa$ZB1T*n4j6 zXynkAZMde*c=ZYK3HfZp<@%rr)i6T&`70If%7`r!K3G{n<=L^;(N!)V!$@%j4Fo-u zD)EYv{Elyyl)f^p$-7#oaBHhSdQ?iT9<5mQ)JDALAN7Y1)<((*;jYemSN}ga$lrPv zr}GEqs__w@-#CNYfqP6;aIIYTkvpr(xk;0R*Kyc#bb`n0$wQhX9b6R+@bR~iVXvRo zGX&~l_9LE*m<22LpxL>RB9D4uO=}}kLvYR7o%pdw+>gySE3k+%2U7VP5TSb45F0AA zcZli+>oBEW20|dVMtw=!(j~3b^F4!UrZ4aEN_80JkL=vqfdHQ5t_N43tE;@Y>ltRj%%vw);8sW z-P58tFg@YwM-JGnXJOTw=D>24*JM~zLfnFt!^QNX%1V!O9E9aD`!B#UHO_G2B|}c< zfEQ#SaSs^KFkD}RupZ>vJ9h%4%GgRb_$HOiaN$FIi5nZlKxg%c$7{3??`ADzf9yoR zmC~5;kWDebB^kn7AL_Ypb?y=6Eqi-ff2C5Zy-9!h`^JoB*YUgQ6N@D#?d~ioR-FP@3{xMkN~MLT zh1LIM5^XO;j9@wNaivj*MyjS3v$A%q)`>>$^I9t0dBDQZ&0nMu%43wZP@|np;+Qr* ztVOIRxD)_N^g_g2xC{ni_cUKPEWHUk4uj8DLCRnjco|R&9)og|M&%*(EupENX+CuI z$1tNQS7;#T``bQL-J7e}|F$@ygf!C;Fl0*{4q;A=*!$GnQ4-TUMIyH;cX$fH!oGtO zd(!+Ci!AD(Gx<;|Axu!KreXrg`D2qzfJQ6s1WhJVe7MMpO)S^Z3ns{R#Y53ac#cix zN~;(e`s@S^A~6P~6JaDpe$w&++KNGx4w0^S-yvzmH&`eh&cZg)avbM#ja@1m0W~_t zAI&P^1%vSLhS<`%b|ehfxwlH~O1voHkFUP-SLBr%B`{DRo+=G2#$DXm<*30xQmbL~ z?7b%+ z(p$Dmnxg{|-e5S}z?lf&cXt-&JBvk+@+Vxp86EpWPgN;vfNE1l(LZ1R@Qe05`R8CC zS|4kDu{UzA3tD0PzNF!mscjSlG=<vA;d18wDmLOzYw?-XrtxiIQ|e6Dv;T^6)&Y7;p~db{_ls~R|dd<{QA zw*?pg=`x9XA(Z%H_mbm%=cud1qaO}Z^qpOHaLgt0}j#KM!?N{ygVfK)k_nleO%&l6JZ%ry~EyxYI zQ$hWU0$Y5(laGiCzX4X~zy`~#F!BSv6dN&yCIQiu+>ee)Q;Qa%Vu3MAUtELS?$%x| z*ZSP&bdvt+oW0*=y$R{7OHnf?6QaHTlh59#mt^q5A-2fh=ZqNd2=g*Y#lju-s)~ys zd4>C;$m2hE7DLX(ItjrJ7=dGO?2&^y3BDX^p9VlrGl#gy$^)ut z4|w(wnf64?WxdBXUB!0nZoXUS18rYp=w_XRbO2nmi%ZS)5dT9M98S%~=Jmnm)fhBm zw{mwJB@0#=&A9pOv)un=wiYmmI+z{tr?L+Eadb#Mc+jwHl(~ih1mmWY)(wx7R8A@? zOmC=|zez!HgqRwC^%V(%Es|8Q>Cl*(lI6NBEPvN`;jw_bDVANd4m>P z!QTi$aFU?O18XgotOhzPddMXY@dHyL{K6Y?fU$W&0n;M=*YTbaxFPe_=226gVwyojzQSk#Sh-C+aGj zs;l)YiWEC+$x5N5d=u?otWR*)Uijdu+1((NeiO&IrX^7vzEiX;1R6)cKbi{mC>{1K z2~s@~hsOMCuh-h-$z#EsZxXdZoZW^73&!r#@N=U!(!f<6yB63&OZMd+*B7*zA?f%Q z{nBr0=vjD|DJzP@yWMr%g8VKV?tfm-r(CE&U5zs;$iWuC>Nt&xiiX70*r09_V$yys|#MFH;Ca^&4j(-vfxS9#I8v4p0QZ;F-`*1+CWP6PrwuW1$ z3d7aIKF@;In4{TLcOk+=w&|d0GgW#VO*mBGXm420;qn)D`kt3xUFg4v3@J#6j@d9( z&xYIs2e-tpbFNkA5#nz0Gw8sGJoosvbUn^r_hoKa2Wx>vt7?#1+>Xp6ni_`P%sz49 z-d-!A4=wS|nP_A;njM*+PgH$MD3xa54=(#mioGJ@kzQ^2XZ(yyIm_Za2pqZU+ynjs zGSs!aqT4p}H5^+s_%e!$6L-yzZ8V2*4U6|{!voUSWF`{}XL+qHCe(phqdt}J)I%xJ zos$RC6>FK&(ZvTt*L7_*2Hy?V!>`Ab{pi?hbx~aSn<1j$o~rEAR0$ZlI`tLY<1QCc z`ao27w*kWA7H1-T@O53cO0Bij?m>IBqhj$`@@S3+^e10O0|M2xg!%rZ% zmK=&?Pr-X2GUd-{edzZ$9U4rv2@N*+xYNW(Qb+9c<;o0gtg39li+xYtT0IyGsO2Tq z3F@;{P0zJP0fn&#?*9xJ!v(!tvP^#kHM!9}3?^IoU|7q_aq>-{QbSU&0aeBgzA)pV ziaBg*q8@3@sW!$lrtxX!&+wV!4!j~`kQ2)dRNe&7bk)+D?BJLgCiyEv?9+}v91;dD>KmeZW5%= z)&GXkWd!F$y~@15cRd6arF^G;0jvu%;T>9J+`n8*e|PVBL&z5=ieIu#=>=z}a05a3 zlC83q+>y%o)BrVGK4G8{X2-gvXe0MypCA#C{?S#p8cz--YHSqh8TA7M{UG-agit#_HK`u2?-3r zwr)0B zM^^tEzkyCHV-KgW^su7pyRSwM;U(1oG09O6^Y8(-GYHv&NT#LAXUU;_AfZh-$GpG9 zCN6)Y3B#y#XxrFhYGjz43RH7EA73kG*alOt?84(fqqsF+=VGD@i00F)sXNhwr7*;F z&Hte_6%i??%s_Q@1W?Zx<~k+G+{St2yoo6f_FQ*a?Q>rUwqI+-leVOOCp8)1n5B$b zmXv)?L&#od2cJ&6+u!|xS;I2prDz|Ke zVfp=#$RWR@Ovx@&U{|&VkfYoZ@<4=bOHS>RKhPQ)`T5_gX2GPm6q&m`YV?z!F>Ky$ z>H3k;)p9Nqtqe^_64|ugdgw(H&voH_k1%V&&n{UDaR@Np+3o*S+?q{L$S?OXo6{I zX-J`1?`5(BwK<&CE$t*&a;=b+i;B6AO|=_YHS;F{X@m;m2ag1fB*zYTeOn!<$=U^a z*#5q2mjK{v5Yw$1#|~16sP;;c%oqSOICO>n?LbHsDvc%o2IZZgOZrH)vP3iIl_8IO z#t;?Rn8L!ao#okY?t5=`sKi$>{xnN5DX|12yscJyxm=}JbWHFGAr;RKVr%3PAc2TB z6b!vFF7ivkNb5R-E7jwM2sZTGb4P6r$tcq4#mjuJ$|eSi$Vs$x+*_VF;9Z8Ibb2tgyBGN83^%n@T%j6_1= zmx|QQ{g=6=q2u=t(uZwSY{&&4JIr%rTDg#_VnOllprk~1JUWPqwpqV9amya^0-qa# zbhITP{FkpT*~PF1c;k@zT}1vtd-}qv^m5=M-0Y`aPSiK55WkZWj=CW+`=j$m!#gU*GF6z@?8z1op)T8`nSg-YTn&!t*pDMGxfK406 zieW4YX1&xK`mQ&#U;!e!&=f1gw<}s|?ip=%Tfm-mHhQODe#AdljVK=-etI4?LAEfw zu8=(Em!Tol4I3K)-At<{&oc@%I?xzS zec>C0wAK7w6m@HO>F?Gb4I+8fDhV;n(_hP{FG}xpXTw{ z^~rbWr4@wKebXk-;6|OoGBI?7ndYQ%g>5YdxO8TwV#z~hMb`ElpTwy_8ewh z{f+Csq4i9w13Q|_(PS&59ISezqlvY=(qB)68QYa>l_RaUOZ6$r=QDvoimOCC6}DDN z;0RT#PT^#xetYMKwqPsd$hM3W7+D+@yWIF3s!!}{L->$vVgbnF-5VCwvgv$yF+3S% zH%yxSVOH-VSjbX|+lb=)seibmWd9H}B++RKGJa1s0?e5fXaD%gOBJ;+q)*P#_bJF} z^~W;NCm#}s7d%&(}P2Z~F1~TJo zR|I|}s<)Z^i5NE`k3g=((_WrXs?zL@&6VAkc zWUsD(SX?a&mIT!i?3s)-?=?S7aFjdi@U?9LG~PO@11LN|zI|lY=|Z^*a~}52N=0_I z&w^8}JF*J0VffV3XzJ3)=IboTHHR(4WYqwhGHNQ^)6v1`BmUOvaN%&-BU^6{8;3vQTY9IF6_o%lRy@Wr=$|dmf zxFG3(bam5Mjd96mY<{=*8Gfr({jl>-iI}jbuB}iCk(X(u5&H0?VfxNY%@}JG%Om-Q zAk*di&kWKP)YI!Gj>;rFLJ5q@IaPt}({;2p6t8#TDnj}5dS{>tYR@uXpu?W4xAiyL z;Xtgo=9JA7+yr8w1o&icy6a=MKaUqhp%n`g3Iz8f8b<2EC|wH*%;1SQ- zHTx+j^W>IMpmIQ93D&gOvV#+(a&iN<>FBMZ5+~yK^Tu=fpj#5oQj~D_#;FqD_59ip z&_}!zFnSpMJw#$k8-5Fz%UKf7=RMv)X)o%Rlpse*@V>WT3=My@y$JO^^X}YgdR|+K z=sHpZ+B6P$8L=AX48QPHgUBtIOmLQ-)+iDYkL-XovyB40< zIA`>mmF&{_G^FyX*6rGFTD$5Od4eg7A#~+qnrGC{*o$_={_$Cp|8?W%7P2b?HfpD? zH%%ICEKtwgClwU4u;-s-jtuaaz0yI%KqTV=K4rtK7k!{LmaW;Q!Ty|p-qO(2cq zAV7-I$oz8+=fuIidWBadE$f%y%$!vtUP&Ae%#Y zr}84k?=a@Is0$^&uK;vcRGHstianRz65;7$}^oi$EI%K$`0ua9%HO4Vq89MGIn`-{AGcy*iC`Y#$( zDTqV`hL%T>{aY99fCaCpG`Jx`4;$;ll4?lfE3qwX>l}J1q!3|ru@X1x)r@@lP9eVw zhN>hNvO{zA&W7Ww4VQYe3Y#^$i|22-XQuDG*?u6hUMWt^J-DUIoWmtvck0`AVfdbC zfRrn&#s7uqy*BQ&vysrAkC;)wZb(|^vQu-JHU4$JIiuF6u?uBD^sDwYJ#1HRrc+2Y zV2-Hm6l*thbhFA;!5dUPVuy3wRxcS$`apP=Ji5%DF3@@@79s}%kE^NX17&N>4KDGd zcJ>&_fbO=?5Km-vgYMpwR#jgucfyJEF^`ID8P{1^;9AxFjhc+bIv*RFu0y0&J7hNj zA_vure?*_Rj{GJS=^MK>3Nag2C``vVO_XJWL{7y**{|*2($q$uS9lKB@GIggC*sGA z6q&`*8U@dUmP!NA80KsNN>K_%a>%^GYI-`GT>cL{H02~b9GmOXn+M{RrNTJF5u?Z! zUI2Km(ANuGzaRG(kI9lK`TqV`X~5 z3f2P|oDNL5N=RPUD0%YHK4Tkg(vpCnCVX5=E1nPt)@o{8&%XCNVaY2hqd<@I7R^?;WfPC5V~xLWbhw&g0EH-%YZJ_mEiZ7&QI$Cg z>bxK{-ZnNep>LVY??&la+8u)c?Plsou{%nKqu(lb*8gWV6^BL`|CJ2$3NDZtFeCKi zifREC&v>4K93ikRZi~qhcB(_&pYvI zyz9fr0G&P?P6H%UFOFU^)y7}9=Z$0ttY;Y5YG6gEH#vVsjcq>m-Ppd9?Z=nB&R`ON zTl2m8IFWn}kh@D~j%-?fH z3l;}~Vom$-#cBQb%5&j#+0-)4$r8jqk@(;b66j`rQ`d|1LM;7fl|Tb!L*h^CZC^-sR{s}YkF;=(W9`+|9= ze!&Yr`57g$zTF5+`h6Z%&UJd*lJYI33pz9&1v=T+=CJl{8gq)wiN~pVeKaFES9J3> z?&X0V?_CsVsUjk^jT+tLu1>*(Yc!!&1L>=3EoK$r+3gQ>ncb=5*mXm3+ppOmy=PgR zjTfYb4Tqg2qrZ)qKDXog8t)tLlXjFh?+V?iBGfCu%Uj>|=}Uiu-FbXzvILB6i*qP^ z>U#k;{10EBRQ?q+a^yF-*`B3%5K4lVM@nd6Oe?fsQt}w7^Mi0r%mQAZ2|nL_N>5xg zuC0MWQhF%xWFBKd6cLTgsf-N0bvBlPR#7b4c~Sb*z~|*}??c4HbiLh*nJ0HmPWT!i z>}#Ngq7_{Zfyh)Ay}g6%snsQZ4!mHFc0e$C{N$0`W4Tr29~KEWd*ulT9|-A}27KhK zkrrJy%-~Rs`lDQo(wBd1EMV7Fp7;grcz`Xx^VyPmhP^PcASvo;` z>lv)seD$7^0uwk}lNr2Svy+88HFxWnIElNpx<|e)Zm1;SAD5s*Q1fA!0ZsQnZ5A!N z8o^SIM>*P9rT^S)IYALm%No+M!$)BPu3*+S$>jxP<*x#AJ=WPXkdO^2m0nU?-WvFo123rGe5MIW+5k^17g_ewi4(?wF>tBPCOzLJznyjL;|8 zVuLZkLluCmkAy9Td7(bch&erl&Skp3B{w@gw17c!e}eJ24BDzds+_GlNfy}Ew`!CJ z3~*>}8Dwo+M`~R{w_p|HwZ6l+i)SOq^^?C1(}@&Mm2k5TUG6JXi(JnL=)D}Bag8%o zqME%t8{bO06!*1lN;V&G%6&;cw-B-O39{*~tnIKGVVeIVl}f0)Q=!NW6gDXn^*B0lzm<%-9wVjj{v&i& z&OfvAVm#d%TpA@t0A-id$RNDRY;RNq0~`4vMHY4MBfJqA@`*D{`z?a_g(VNc+S74t(=R!0bQM9J;QV|?n*pL&7B zCH{j%H~^_X0PJh9K|odpGW79uuJ=|D?4r1JhsY|@7m;^Lx?|CEWMSRovkk>$qk40hkdF zn;w50Q=WU^P(~_I?Bl|E>_|s6C$B`$&xDmsB9&(HYJIFXHQCEgIzH96lh68jKg5T2 zW;IzbLkwZDO0HDz7hMpQ=V19@okjz`i5UcKE%E{ea*_$7)EKLuC~`wpIjhiYW!Ly^ zszVy~k#+%-B>8=4^O|Y%GUSq@aWyK_H}=Go$#I~rY8>PtQ{x-iAac^THbaK1w%|si z{7FGh$-Ti+x+z9!a@!M@(wEO5xY9Te1U5ZrF3OZ6cb8%(8x_XABrj@Ye_wPJEvTCW zb1sR?RD)L`QWyBs1(gX|Jzi8|a70O9b?B`vmXbL-u%PsHvsgNgF>OOK$zU)NoNbxApnA*va1;C zn>arSv;EqN661+sE~fSZyfF(mR$yp%mp_`F$*`Spr`y+|i#)OJ_O_O6-Ze<@QZ?~% zfO3nR|Gv~TUK4F0{c)_l+;E&ElcCpMpr5{j$RIb>D3N?p=_}3wu1ahHs1k}1Fj@cV z?tD+xOUv+YC--lX49&E7n(T%#72CNW?nmH`ymQNs@N|-r@xh~u5_i;c%wv(n^giO4 z=-~{wIVH8`tZ_zS z(8WRuFa2L%4`rGg+DNz8(9_#0inBq%%e`I|=XBY1^2CbOGQHSjHC<5(a_j9brzOvG zt!ECyEW$UcUY;iK@@td#o=*QiG2+mUh|mF|Bv&pU^0vQfm5pF;A7&a)ltMM_2Qg?} z+QiH3bf(Qmz>-bLb)kQ%f#q9nc0S})YdQ=FuT;aUW?n{QCq+E~KZ^ZW5#^w#X`u&v4sCA*6?MxtRYwxS=xcF!Vr6+MO;xDzk)w__ z$KiAI8ATQb{;tw*^3(@N2&2rvG~Q=NWb>W zoEPVm5T_4)*#`$>SPmtYN;#IfWTLMm4+nZ+yA)I{4CiJNe3BE%gUQ7HL;t~bp1$TN ziLgCz?_9(dxaV-}v@dh6i-+k85;ndIkE$GEF}E8zjWscl5Ek3E0b8>)1psaNxeOH& zh}c}){V}QRWAI5^DETw>9Qr_-QmVHJ3;`iie6-$$LTBx9R%jrt{wjnWW!)7)Rv8Y0o}6vBjwHg2Pnfs$gBIW~lUxFO62*hil5&XO>f3x#DVFDy5P zFk$)?>zn68=iyMvX8GSZ$(;X%lg!A@$p}R+V`^vaV!=ef$jHRT{{Kg2g8vYd2^g7} zIT`;)PI7D;r~s>S&aQF5b;f1`4!5P%e(0RTFDK(u~_v_M8O^1$B- z$|wFX1$D!Km{Rg_u!2cAg&?5-y9$>D1#^7$gxuaw>8#&(NP`wLAO}cD$cCSDxC9rV zuAmxPLI721ckhBlX)$YQ1_5jpW*4BJWlU}=T!AsXqnC6YY^%!~({m`09*6+~Yl7kHkw3sj zz%HOYB;Xd*RRBx5feHOFsy|EypkKah0CaA3zagKSpYZ|&D1^7!qM4T-x<*7 z*EDu7mY$}R8nPxXl%3@d@5Z*ocaa3x4pgldyB&5|o9PnF-;Lkn7eoVYX!I$D#ELtE z-2opT1tza>VwZ%5aKXpOmB-~Dmz1Q$9}WlL3<%I&ea-O$UVC^5{iQVi9QIcH$4}3! zjH&OX7$T2v4E60H3m*76_l(Xk?^^H6 z@x2D$&Y$6Q^2z~_{rBzbH0^xSeVv~`Ki6;Sw@VL}g+mC#1thhX^CwPL67mA(&g5_( zu+HJp0Vvr09RR3H5a9PWw!i@5qZ4w*PaB1xMc#i-Z@4FG;TQSp{q>varyEP!|2MW6 z)CWTo-~T=rgKhulu*vs*@cEbf+^^&77v>F5;m3~Yrxz;m5g_PSndzte_qU8Dn_oY- z7e?1~W$@eNMM7Mrp#}PoDa`m z=mBnCZwPKL{v!++5S#Ir0FV|S?2B*c&z}5OSTF$g#V>(?EI`-@-;-haH{3lCyYr8b zAP@lTq~94y*2TrrJt()S1*)7uz@vXOkr%sLOuBZryo5 zF{>SVdoz7HwQB~iS45Wy2r1*yKyVENj^e3krMejZ;5td56LV*O{oAj-EeZSerDoI0<=RWW z!2)}pZ+loT1K5AcP+%t|O+mGnYSxbiLHfsBE|-twZDb5?2YPtRAj0!UAL%oeAUN*x z8i9?!0D@u#lWW>}Njbte#r)03E1MjW&hlnG5bex4M-Z^^j50fuznW{|L2_l}g_x0* zbT@|FO4Squ1I{aJdUcdqq7j78VKD+aigD~Rh`Ypk53|Gm(-yS?FTy@;ec_U-z4atg zw_OOTMc^Nl#!4UnCC=GS@!+}gXhVhwxpI{5Q{wi`fz)VptE+4T2_@WqIU__ltfWkD z`N%_Ze^^K5r8bIT9hF2#`rC%|u&@}_N`k+4lYoOe!pR*HmN3HM2G=;z(qQAKwsqi- z)I-D+q=A-$4~P==`N-sSO69cQoj9QuA@W$b@n74&-Iq~>$WBv!wOW^Co*L<3EOEar zSNAX15GV_RTns0oE%vhdUSnhXU{H*X*f(^9m~o6T+!$tvzBiEj;KWMCNH-;KvD+Pp z>+3)*+%u#VjH6@ehYiUiv#|u~#VppMMzUZFklKhvju(dJ=4hPIB`h(cN?GHBQBlu= znojO#SSOF$^$?8@iPx*6>FN+5xxKBVC|)S%SQk%K(80E#IGsw_pVQIna1Hnjjk3Hn z;073LpLZ!BnvZinBlU88ggOZJ`YNwEvDRIhlFRqumYP@cH_J=X4`yxj@=M>)NVnMh z>d^>K4z%T+M;7`OARC_7UCgo-9e7t6ZvYfJnCU!AanVf{P6TB_`k4__dc<3O4|fos zsS3F4Ul!!yDTLfL>h*uW+A73m6o9`)qq6L574p4Thi(TEkbhv$O>;Y5wdPoze)!9L zNlPEg{wyhx)f}x8zy%V!AGrySsk& zOR10=6IEHUCb>O_wtf$ryd(!V%ZWNSQVf5eJ*)QE!}{Z4@2vt{tLZ6V;k=z|wf@}f zWdeK?bgyCZOO>t1bVHl}cGYwurAw3(DOz`F^(_l9bW)VB<$qzwC0$m10Q!;)RjAxT z+PZ@lHTx>^-ErmVyBkB%%ARF}1|ZKDmDLktIU!7YSod-ZM8wrrVb0&sWc7vVb9sbB zmN{6A?7i}p;Gtd)tgk;H?^GcW#UUDrK($PeSAWqrXqLew=iZYlm)h}!LP7lQ*s<49 zbc8b9vD3B3?FTIhgMO8pk)Ado(`edbi(+{D`9-0tCEu_Q`1(B5(L9DEG^U$ps15Kl znw^@aC*;y0(;@5+i}O0i6W1pz{!-SI@xYgl$m~ zh4R3?x&75*|Ncanoe-{Q&R{K5C9=5Q7G$ZD!Obn$c812gMuA!ZqR1MMu}SsXQ7(8q zI6P31)=tqK9*z8=HSd{uF=s_bS`O5mQb#8E)*P=`>dYj0w-$&RC3tD+m)sM3K?)kA z6EPHCG1r`9bxwOVaBM6M@^SDC?u?fZ>@DyYkZHAM%91rEKQX*FVuva%qgJ9|N)nxb zJN%dWY>)Gp^};wcyvtB(9zFKQVL6$U zA2XpG0}MPzGq+)HX}5|6m2Y{fj!TB%_MQ5JY9=k!SzzVG+{ep8Q$Ls|DE!}E@7dfmvwlVh2$ZAIwG7W;`a zEP!&~r`uITo*~Xt{*4+*PcYUr#r%?Sqxy|4m-)9r9OPvMlwoJUskLIVukL8%H!Wa6YaY<~q3|1xB?$6DrU7k4f831@dxnCL&sv&hR((i(_ z5?nqbs1IBt&3oZ0@S^7%ITP}n|?VRnT= zYZ-_bu+j7#MHkLBn#brco)7!ypS`gMEceppR!n1SZxVn;0vAaIf#Swiw}Ja%{IA7- z<7gd^O0hWT0fZxJ)!MXX1q&BRhJhN?S*1f!If@&3*YPP+PhCQ(n$oY zH4iBTL!e;Ce+61)6AE+putP2<&!a7wq^J^Pzjf2w^>}iewA8=`18?>kE-oi7nG#0iE~-6@XFzp#v8 z&x5hRv|SuDE1=1BeN@o8qUbJfkFD(i|H{DxOa+@MN8zK`SgG~UyeeP4T#67;;UQ4U zqT>zQeMqTm%G}n0n!eQ;*$Gb9nw@g8wj~XT<_OB6IlNmnGPcx2>g~V92HS_~HJfHE ztRj+;U4(!n$H};0Y)~UqQV_F(=DQmfc}6nCs+}Dy9`85AlepTwqQAPqLXAv#>u-jh zIgYa(mE~psW80^W(eRW<-1>da=+nsB!mjFbUq(2XT^AEEeykWQ;a30}k5bF=dtiTb zIG`bJ2BL#lT5!p@RLxZ<(OW{71pkIYNeVap7xc;@6|=Fyig z{My4EIGbNlV2k|p#=&|1oDOa**n5Q^l;J91a+j2E2{zlQ%d$;VP9Vezq_EB>nGdO5udStq+_0CtiM8@h(2+2&# zB0N_>RU9PaexYJ0%bFf;?5yU22~<}Q{exW~K-Hd{+uQw)$PzXxDb8!{S#p`?Nt$V}u$Ov^gBKcT(iT<v;OFYqxxr7N4p*9GSaGB-S_5vh%`n7PMzZ%FL@ByeT4uUBvbEYWN^JbA_C4ro&%#x9?~deNT@< zSWfJfyCm?&IHPRz^x$N!kRC0nm{>YM`pfs~Y7E$t^NeCRLnSL-@|LK9UkCXtIS+yh z!63_vy#2NkymJ@H8N92HJcc3Nlg}%%3s`cWZGCIMQ;qbaRx0^KUUV#=d-gd=)p1St z_E`C7Nc0DPa9plx*6-85Q7N(`J4!ymj16gonl6`e<3Bjv8>$9a;261tVRVtIg;o9n zb@;>l?fy|eQUkjv6(ayqBvtI1Y*cX=0qO;gQs?A zp#y3%4_5LI$k3QkB}`q4Q4=0<&;#kpADaE|>7j+0(aU#hbF-MoSq-nGO|wphug+8A z!fAx3Qe*JP^FD#f6jxorRt1CeIyVX2A|)zZ&Dm=Mf$M?17O=0PZ(Sht`INZ`B6XQt ztr4>ShPO^}K-jYG9x-+gS$sYZBDTSA$zx{#L@NDN=HK|R`M5g5@5R)+r{i9AyM1eJ z%es+Q3C?a1>psu@VEfoNq`nVaFlWZX1j9-D+lX~Po56FG=d0F1z3x|64pNpqq zrVpS=f{q(1VRxXmv~Q0Mi~F{M{S*$lHD~8KXVGQ!l3CX(_G5omm=j|n$@rFhdu;)L zvpo5J1MOQKJ`vo*)yGfoI&ESSskofNyF>C!eorMsx0-N+l~y%u#Z^>7y+TGzJDRMO zC>{|Bn(W1vnqHLgg5^L<;U#}!JWa=9bC_5|KHw{&xx5O^eTy&&+})uG1c-)R+R=F@ zjVQ4>V|c}3YKaKK7409~wKoIFH)cEv?qGa6@b=my2Z=3qes5)(KC0|_ZsmpnT&Y^- z#qsnSv0Ilqo?L($^aWj%W+r=_$~gdOg9j|8zKFzPz4e;XLb1lil2G4-F!xg)cuME^ zIzr_q_+fe!R{EP$bgK(6DpWT~&Si%sOmJ)gpvHX2^k86*eG&D zNGW#nJDJVs6lN*l!ZDUvt$gvv7`~`2HgBwEhg87YOhfvqzrYoiny=Mpb zzQ3;QCugejH#~T@yNdiMsf*lqn|zJ+TtDV z=o*^@5GaIB^QGPA`>mEP2&^TogWRbHG(^EHoap#TYy|V&xvr#D%iB#$(g+vOl4>ba zDBSWli1SOmk@RVHwm}XcOf@cvc5GiM&92T0{RD*wSMG5~(tI!xvdQTZYnGGdQ(YWK z>Z~@`{LLX{Cf37c{2Rb^m3QpSC}b-4>m#Nz18hnx;S^f0hecKR0vsy~ecg1a)v!74 zB%K6cOuFqE&$Ceub@MW1@S&zHEwx%P%lmQ?WX;9Yp9EB{4cWu7+e||0Rh^L`7&m(R z_bHZBw4$)Yn|X&tU2)f8vue8_XF=sXR^6WMbM|)TNzrxTLVg!HNnzzQ zV0s*Gg=swUi=;|TACj+{IKuB;@TL@S9R#98^cnjs*J_8`(;%J{Qsz2ujU5xQ#@eCg zU3)`JtNfFT$}~nN#6~AvT2@!lgvk>kc})#fI6N=_*a_8VTF6B1MAcREBx}E+Wy>%1E&Nz>4ntY~IavY3P-E*mTA!@6TayqP&}lBk}&xN&X)?}-Asv_zpZCCd;7d~>1q z17caXI7X({ItFO~8ZS8vhQ*b0rv|prqqU+CGSRyQm%RTk0G{jPFcRvWa{%41joV3( z=o-Gyx@Xo)rXFE$Q?>MIDq3JQVr=(W(>RCpmoPId+N^=rB&5?FZioK5BEt<<25BR6 zI+)xtCVgsyO%B{#TtaZ#8{j&Xk@o7-x98qB%b5ZGsoQBVWn>qCKG5(&SVd)R>zD;u zU1rlASHpBKHCwv9fqR-S))Geh8G66=f=K$0DY}@H>bMx8KJ+L4F}h@#OkE=Zxb7!M zmI;D{FRG7q4&l4enNDMxR>-bBDi=cyW$#ctJ%)+o1G;3uX$h6yvh5=B>a4Tk>P@0& zXX&KAUP(2t-_f)x_1}aA47A|ql&D$ghfMQGZ>)&k-}9h>)89NG8+H|*lFNSNHySt5 z+5>Ud5Au&?2ho73x4cv%qth!Y#Vr`UOZDF8HHR-#<`yw%UltZz(fdAR)gUUZ0z(mo z$E2+w8uQlHUHrnj_8?h1(AVf`bRKIh9Lq}PJZaMfU^W%ZBKf8cL8RVYbpSl+5J`NUJ15mzA3) zC&@l;Z{5OZf6za7R*6%plZxK0+RDZDvOX7Lf9UxoqH8Uei{q3p^z9(sohMc?<%-}$ zbOU`hd=IB?q+bDTUQsG`0Tkut<`PgPK!ORGeSCO>_-uL%?Nl&bw+oryc@JaKT@-S8 zGInPtHutI8Lzd=>k+}#yq>eRFJ0me^dB*L)6_ZeXivy>Lks49Z6OR=y+Rsb6GzvOM z$rl!`AIGOfC7UqT&v-hJTfFZnDZ81hfNUBJR|SX#0FaHjbMA|7)y$-7y#8wQ4Z=Wh zrgQR=b9v`9yiuH@n_+?Yt4~=Yvh4W^wArAl{2MxW&CJ~=8%d7m!Pc#bvGRGNI+ls{ zi1Jx%44Q=priv-9$OvB)=%^sZwU@#wefROp9l}2rzO;_RiBuM%} zbh{0zXiZ3`i!w^{LpNRU{#g$?J^o7&N>tf~uLnz|5!yHPM8jihLz)h)5!44NC&k`m zRDK+qY$cG`Pt-$HApMoHrcgp)=&oQvC_$=QTVfMBt48t(&~zrf7N3Z_LIV(kl;w!b zu~-7RYCE`<=6m<~qikgkZYma-&#<#I>gu0=y`HRpsIU{iAU#de)vK~#02VZE?zD>t z;pn~WVVFlc`M3x$&K!}v)C68C7x?tL(_yI1)c;-lvwsj*mrkj^eMHGA%1`hu6yy&r zV75QeJWKmR7Sk)XOrBn>4SFhGrHS$_pGW~|Z#olW5j>J%%?;t~wBXo30%GUk_jOfD z>@lI)Qr(@)Qlyu4mEN=nIlNBqN`^yaRv^$|fcm(i4Tc#~_~_Hz`79}1vLZ)Nim2ea zos&`tIBohi-7`-EZk>E@Pw#7Y$8~wR#)bWLJYWRLfl=tSHpyDlb*!{u=T4Tcz&~(F z$y6s20TE^c_w=$^@Iyrn?VxIDzbH7b)BHUPqJ7aLI`998TsD+o1(IA*BO$kX^#431K7xX%~SE!$pB1x4J30R6l2>M%VFg@!r-Fz zI&zbw30M7{w+XBa1`4c=%3TMGmGuX#|tIF#N)7C;u+PBiG zy(2_#kRpyC;?vS4@cO9TH}fb<_(yxH?^}pD#Y*n&rSa7{bt|8Q=?k|_IZwmqG^!(; zc?J-|8;q$&&9nrFjjJN<(l6 zJ-pg;jV^9)IA`fBDXue8QTMgaFBBy=9|f})rBaUnSbG|h>B%qb1VTk^$tY)RrH^M$ z)E6sR@U@Lj$++itEfoJDT6L3|S@f~&MauVss{ka(VF%vrdxLGsPO1=+dI>_0a*vLw znvpWh=;>a@q|MMl@L-}Dd%go`eHz9AR={gh-Ff-b_wGI=?fA-LC93L&CNz;9@xek? z4Sen|@TtDkD+(bwS|Vuc&}@V5!mOH;0!IC{$$ThUsS8J@}KJ1udVTI zWP-c;gr^6M~Cfhm>{5v|gSf%)o7w_hhq_}ObFkUhO?Nn+f zS}XPbx1KHA-$Nhmp*&|ZRBk6vUyZL;R^Ju4HKn0e+bT4ytU=VzLE(vm2GUg)thQ8Q z!kECpM*3!tH>wk93OEK)AJs9lGChUVSt03NAds^s;@;Sh;u>bpBUD2b+2P!+OQgpY znX7F-O4;C)AgWr}JmWPhAu{ILs5L4`iEX6Lb!uH_>2MRq&|&(bt^@4*>POgiT=^3G zwNq;dI7E9xD&vJEU&)~B9hWFkJr9r=lc2pf_41>_XH0fc@!rFNKpz)ceIBv7^Lugi zZPukUeZA(O!?6bB=zEuv?r4#qUm6iBQTRkoQ1L=xZ6%n0jb8+3np^6Ck0S~!43%+I zC06xKSYlp*%=z(%tza)~i2oX#@RR<&P{p*^?fxHW=q+=I>t}xrghMk+Y8lp^`DwYf zjn^&|Wf)%ATl_(R@U210KyL=&f86^_4)>DR_`Z^QHcIOI4BQS0nIY=ee2uE>6VcwZ zec4Rtm#M9@>MTD zu3FS6@zUCXaj(F_KMp5gY+OgDadFi%%i(Aq1AN4Q`Q#~+T4{s*0qTi3S-tx5y2zbY2h zj~>~QRM@mT7^RH})u;D+q$mDgFBmG=}Oh6;+o_LSqIlvI{1qmoen zfyf3wZ)Tm>punP5!XOHDbU0Tg6N5Ey9U)E(*@aY*_$2T5@ezVYSkdGXuZT8ePRb6i zL)!quHaVV7#>UvK7^G!Z^+l`{>pD_%AHt1S%aB6-7=ITmfrb!UtBScwo7k{AK0FsC zQOE4UFgG8#lbu~(9t)dRK|#8eM;tPBIr(rlc0EkLS@}Nr^+jczQL&RX_4IQ0El0hUD_TfnF8 zz!g-3#K~a`-NqrS#zP0my zL(dm#GD+yooW`4_GVe(GB`Z1xAyq2=jTvcwTy{uH$1l;9p{65eAeWmG^ga)?D3f`f z(+;&GEuF5f9F8(WwR3Y`_gW2@wX4AoM=sRh#5ODLA^9P7C4)y;Y#eTv%UH`{=)&z( zl*_RU8hKOc7j$@N1!zL$KlWIs-L#Tpeo}N6MNq}Ha^jpBpt}|U=`hM*jW6F zU7e?%r&&gO#-S-w*YSIEZ$;+4Pkh*J>%)hNdB^2>vnf_(al8J494yM1{y6NakmW|C z7^YoN?l-(m&rcdOkOiXeJ*RI+mi0>EZOqHz4i_^J2j#^qkK`o+`=mX4u=+Gyi9{<` zXRnq0P~zowCmMm(EuVtuYsw`(=8{8CH>YQ3CXHOTEy_@`RK#FjC^r+q!N6lyKVYR2 zmFt@Fzfbd7wEyxczhwxJX$J8i31^_;F2k|tSzSux;kz$3OAZccO~qiO+B+9ifM@d9 zuu{Y0IsmaoGLKI1p`M?t`^=$c;z#QEr@~Hop01W^Y3pBRp<5P3&27%4)Z}?(2j7Bt ztIQxoJNuCpm!!kqP31JXRC&bW2Wtd5UUa44SgxW} zTe6|hy~`fr&bAa2N>c1$NiO9L93i*(C-dBEQg5}V+@PJ$LDU4{)FcskW&Nh$+G6uP z4}$<0YFmZyrrTqS)5HT#TI=*AS7`a{^J6&P1`;R{vQt9Dq)TL^szwyc8OwAA5hCuW zXZVSU=h>R(HeDCO8;-)x#m{IuuWuZZV{qZGG(e7x%mehd^+>9KVN^{Y7pp7lIW#?V z2lWM6j}iXt@`Z%#q#f6Lqmv;p^47k7CyHr+&O4miz~d2q8)4Fk_01Ajx?m?TGz=qH z6!Kpm^rcm|sSB`WK`WgRyp@Nx=bJEJE`OBv$Z2GY)BcZsxpAI_WsErpWOwaK#U`V3 z9^w@fcLZpKZH<>ny<48k4WWk=MN zp-2q$GxbI#9B$YucqJ#e-8VDBa8sM@-a&QR<`ImW&# z+Ps$&u2M^=;ccrA?8xU78W=RFJ)cgx?#iWZmuIqEOklTLx!sPEm^BDls*iSBJFQr& z%f+V~U>Cm@o>GgpP;Tf0%gHP{mB5t)t*#JZa|;DtL20-MUkA=gJJ_VledpjVHoelP zc40I7lMaDQ&haPJClyaP_O|LqlBK_wc^nnH?TEL(d)lrw`YmqvQP#WmaLVTw=(hbv zaPO#jnC#n8aUB$AdLdz$bQhie{rsJDp;BOsiM1&#F4D=?ovm$F66W3mTZlDK0AaIA zKLzyto0i*RnZ8bFxIZ&sM5?X!Q=p+IeZK?wI%hzUe4UAP4W@e~V>@MeXUdN60wMLi zpPjPi`MDaJ3ZGBe{z2g+$GC6|*JN=7Z>tJiheT=yApA2CjUUnNmVt2Hj{|p`@IAKZ zBZyd@fCo^75gb?7fyQVpOAiap78TnQ5N)$gNTAB$=(|;BK?cS%JuTh=(X2UUL z15WDKuFE`ziXE$Fc@r{B*PgNloeSY%g(J2zIHr(JK4tr!Ub*kSQl$Oax~cT@CpcFg zXc(5JmX-3v$xFRyvILWehQKSwGo^b}k(llnSF62GqrI1g-_Tb?r#I9z{?e*sPTRD2 z_=iGbUg94tUSw`jSz%1BA|7+Zntc4E8I~4?jT?*bXUd``j>|ShfzPbKs&*4N4l?sq z|41`34-^4F(E4doYZo6oyUSJD9pR3jbw(jd2uQ~VkDswnrM(Z)4}AIxx@07$FBpMD zF@6~~Hw^EGA2B!1R&up8fh4|DJXh9r2eSz5jX_U^5RQwKXQK~Zo@6aXicPLu@t-0T zGkAkk$?oWhV_6qV!}M7#^od^3p<8|aeGw`#T?nFyQMhfxuRI#8-Grj3qZvr1OQ9KM zP>U$Zxcu5P6)aBRBRU3M9?TwE$D85mgo}|wmD2wy`w@O`Y4q6f(JC~TZL{|R8HUY= zwf$VhC!1KOmhhU)W3VA`-*As$?YpHMv~WW1%G1?BjLWp4`HK26{rS3@ZoCSskva#r z2wa+8I1iQaVHt@lMwx&4n&(vxAtEfiD1gbpFNoXVfc;K^6NI9atw3ER?!AWYLkKZX z(>Fhci^a6+YkpMm(pebSS+P}1HT%@cDtXZ_J+IgA&Zhx=?>D&NS-h0m{UJ%EBF5q* z-x21#7&}^k9#Nh95L+>d;}oJT-Re}hXKO+~%(~>-iKCzFng3Ky2L`=WVYJb(&eEAC zmo}TV4e>JeU}vhYz7cXqn4!{q%v7t9*S`CPLqO;{zn*_r^(NemAR5E~wy=II+*~O6 z7cjkF?dEq=A+oLe$UFCUNC#=X$B{&6#u17K1zpzrD1ch^co1$Ll`ESqT{V0|0#|)( zig8oJx2}DnI1k|NY?01VzP%s|7A^u-Yz;B|RZ^RDdOSd<>zSVm3SAQcTQbg2(7RwV z(a9FMp?@4O{#Ih9TZ?{cLPN`-2qdT_sPYbp~;bT`Q{-3c=N%| zLDtCgkk~lIE-~nW&J;jjJ#hNynK~8EXutT8b;MBtZY5_PcZj}07ep~ZVA|?0_3)0yXUJv=PqByi zfN%TWs%=oC{361jgS~FpFI<1W4p(Ze2^1!qKFni+He11}1~t$O#wG&tSD>3F^70h8 zF|k(t(8L;5Xvg%q1h9jRyfJF}?C4p(<1U@&(YG+wh8e;cJT{IR(!Jl~I@C?@{;fL= zDw=QKCtsNXX~h5VH!v~$FMk6Q%l{i181Y#+m|6dqy@8dTjpM)W27E|5Q44El6GwbH zQELNd6JZl0J7W__US3EiXGaqQ8%Xz!7*#Okq|JsB35afSF<%NvIYE@&ED6eQA{_+I^yk9ZGPGJwLMzj^(U#{i(L1y+#{ z|2*L7)2OAdZ6C-$9hjflooFAt36G%e#%Xs8ho%75Pw89<)m ztatGn<(mot@tX@BG|Whzm)@Bk@fx;`pc|o21&4@28(tR3KVQd>W1#Dse#l)N0Qwxp ziGcHq78~@eEEAC4(9h516l|2x$KF@bSNv8FC(y5$K(~Q)Lj@^FkYJ9TZ?5*EDPA2o z%l)!{Z`bHq&(3WeyGb3~0UP+Y3F!)6=xhHQfb9?}yn#3y@I6@YYY+%N0QL$VLg?>pADnw z?QYo^-J4$?J@NwA8(r3znjdz;=LmWM(A@92Wy~9qno%&-0^W0O8858pl0WCh_UCR| z_|u{QD1o+20(;viUd30v);D508)6Lo@Ed_254k@vGSE9*bQxtE+Wq_;(ZfAkFn;7o zu9#)vKKiQOMPh0an7%qSHM%f1g991ZUcN9!2VtP^KMa*rJ_EZUIKMR=wEdvIK<^1f zCAfdY>;fIp8D7Nxk2xa0v@oy-pyw6aCPY-53GUFU@b&$TojT9b(D66t%~edTj)nIV?q6egTdTvp&a?nA6ffsgThxP8v#p@J-+WEL@AGy0?|{NdQl4ZYM%A4RV~13S6( zb*wbOj;-p)&5!w5X=&<$Z?(3dwriI65f}AsDD57L>H-Wq@17K7DU|5dchrFiZ%ZQk zS!mq!BDpq%D5;)j{)UXN@3_y+sV0<-4xOeTTa6*(_xM7+@Oum-9%Fm)G0~W;>?=$O z%on;IhSaoFKx!cwW*KPWFRMt?n%L_N1ms_p}C==7Z3 zXx*^>Hx>4Nm}t&XqSUZ1nnW6VT#b#?KaA1wMk@J4$k_93CF1DpscO3i`vvi9nD*h0 zQ(z&~PWJY_Xovalx-___#|oU%Cmt;J#pi{$m>AQks~{1{BxK9sVYjlL2YaW$igOj6 zBHx884ip9J6z7Gl?;2X|pYLN)<~QyxMRX)Z9JRakUaFZJfIB^A{ep6tv@4~5Rb@Q> z;7UGoxXl0Ei?xv55$DA{_SL#yD2DME|Fhq^s%daGbp|YVRg7iRJGzhbFqX7K$ z%jnl;w8v%9wFfY-xa90a22R_#Qw%(J0M~Aeu!m{w2+H5P=cJp$s5jWNFjbaS-|9Pk zENiE~s>3RsMTpn9s>h+^1xl@KvtTDM zT)qi7D~a;et(mUOZds{MC@GaeC^L^4*mx$5D4SQg&v(-lbV- z9g>W6t-+k)UOs=|H{Rd&V7(N3(xFeDwTFYqHxV4bb+?2s_S!fD^BCdL+!Q$28d{`w z_u^as9G%?Jsw(x(g5juSP~m_S_fKMzTj9xgs#YbA-$buvbfthMaPKleqd`Sm%kvOy zoBB005TyT5vV{uPM}I!Bo}q+%V9bk^^g}m6IvC*LR4V*%b7E;6>MVdkc$CXg1q~=X zTqmp5aA0~SJ-&u%ccOhY9z^)N?vse>lyrBI44lqv%$UZo&yt27uR`FU!eu30;b64O z;o(H0aT-JQgR`Q^u<$66xs)#<9N>#+5zwX$HvEPA4zhq_#XxuBt$MhiY4@||GQ5IU zqcwuv;f@)idFh#S6i;|}6#Sf{w1#&|FHIGHJmd_zAq&e3wB;C1i?bYv=N+!IsTkbq zwhw5f=_9VB3J6^vC-4GK2%T+}c8bh&ygWU2z1WqcP3)bsBpUCI&u6+qE4$D_>E7`Ut36h}r_(;dqAsy_?}Wp@=Og6QE+$)<9uqyb3IVDS1`Rw4o4 z$(;mut|9W1|HfWUHbdW08`)3@DtbCNlp`Fi%4!KA-o`Z_OLr-KpWun&P(k!d_4(I! zbr>}?LvsQ7naF5v@fb6HEDxM%9Y>UOjBnL|6;x8ZS@xbzP?3L@jg>W_`kC5^>A)q~ z{y0cB4=!sU>_ijuec(rq{CRJrKt;<=#;{r-_?|LDLY)E1{GX&1#^^FI+#c?S>@DtCa-pq0W&k{3Byf1{>Z}>1jdBQtkyCV*rvqPNQ8k0`r(_y{)hE9F8;4sY5UpkFTWiu7;UgE7mo}qxr1Mo4~=yaH&>Un*f zjBHaC3NQ=I_&9~(CJ-jWXtjG$CDYlFcoZ@cE@snxw!g0}^Ds)4*$=dSzw{441~S}v z(%Es17rU?Yp=bwON|RR10nN&wyG?bF1Gyx+^_t(~`gTZ)36IU!;oA;qj@h1T98by|#*Yb27EpNAqGtYRWl?JreM^`zVHik3v<+=ylWsh>W4g zi6ZOGdU5W-Y0%kvT*VTIGoC(xSgj%&S}ask@=mLOjJA7M9Zf5KgfIqbo2~!sHQ>ej z0EJTdMx!88dy6ce6QI0Nk#fc6oHmA&TtmNn@SJ%Qn^a!c1I62j{fx*|_I|Ob$=ut~ z^{9Or$=!u4-n(Q7H>e|hf!{swD%y(`myMWenUps z`5c^;WNrM=v|3CVV=Dby;SJ0CG`rNf}(|KiDcH9ETxiq714Q+(`O@a3r&a*LIT>K0p3zIaY* z3!k+5I!I4IGfuuw*hOtnni^+p_V~w^XPEMp?~hE(>cxVX;zOd zERjz3WLMT{2UMl9+`#f<-V3)&tF~Aae07BPJp2`OqRw|>{Egbuc948bO|2=nR{ac( z@N=3}cds~alG_Ns9f2217O@b?;2}ELcqZw?@Fa6cyD>PySo@pywugBZY*NDcEp*A# zgW0~ZIE{>^X)3}#)+Ne`wESksivK8Mh5|BJw~aW}XUIy5u#pb`SQha|WJJ*D>-@bZ z`qsyHF->Ah17L)*D6eV zg(BLof=a6{IksqSy@=!nz)(>ZWq9eVsQt}Z@NlBbvHi1RUj>x>4PeFD_uKnQJTkmd z;If=uGZW~=&i)PbQjgoa zYsm;-cFBqT&tIyMhMjV4E%Fj}P;^6vhDGfd=l2Qv$t6F!2&E?VxnE#~x(AC?OOY!{ zUZluG_z@uwPg?4qmlQ15TFZQBxz^VOY-CGD)H$lw*u_*$^yG}ALpQbk{ZruVTm}8; z?8_%JzTMSj>AgTC)92gt)~Ggyq@IEx#)_Fz9|eTc29~0O`6i=I67AHBQPPV?-@Q}k zxs{vp9TixbM>t%z7})UxB%{*wQz9ux`0a3#OGc+Mo#i#I4+le89lB1(T0+OJTVbz|vN%dQM zsn>F!R{&ny+&&5#z-)@TE`9x;@^im{6Z9$>Pq~(ZX#T+qP}n*s*Op*|BZg zwry+2w)4lfjdwb?>NalUwO9YERW-*P6ER=XGt=cpiW+uB?(|^&d5Wl&#%4yLSFrb> z)b80lQ#sisR2`mz$Ni5oOPzW(R+PlzW7MVWcR~?5$5%(5|Hq(LQlinrR7)!WyNk`A zs~%hBXTRcIudS%WY>IOJ>Vk5BGF9$M`suIvhnL8KS?-{7m&wR30|DnFbuU>8Mn|5W zNqZ!|Q20gvj^i0EHPiz*qq9h*Nj%P1f;fc;gTOiRt*>>xX6KaPzkrnj2vC2EF_Tn@aXCxr2XiRN^Y{p}940SQ zs_}vp-$zgaW+C1r&o!ru1vj}lgQUwBUNfQ&yzNuZw-@bifds47x0^v2cv|e&k`^34 zd~81;#gSD!;6$eU3$?)v&OAYHQ5(Ylk}fP?SQ~=6 zyuVZTA}tNB;+6Kld^W&hnP?_gVq=@DuW$8+CkPuYE6#jZx(7E-e&6U2Hp86*I`@M! zh(Pb=Smo)l!0X;t3QLE(d^Evf5G8Wg-YM0Ii@Sd*jL(+IMb`sP75i5R1Je}szk9x|P?CpYyL*rF#nwQ$Fz9EBMULL0Hux#rm|fs9`COXQ zTP1iabb)~qMB1TF-l$eCXiaLLDy|IcFTanor7x+u0r2?+Zt9bvNP$lBP4|vYAJyHX zEce@{el=*kv9x(&Xo@H6@%M#?Ny(De{`t^&#@IVUefPcfPUE=a<#0)l+faunji|Z7 zmbpdOa-r@C3wKU6_LX+ss<}n54c!ouoryWjKX9~J*z~8l_hFeATs8pLh+>#20bcu8 z*7wr0CGT{fqNutt7BIicOH@>9Ov@g>!fio=N{N^+=9k3ZFjGRgpoicjYv7tPh|M|Q z6pPmrb@lwuyB(kpGpkIu@gwx~^zUP)O~OH9)W%1?13JdYUq^XS2!eRoKvz?h|7x_x zDVN9j#`-CI$8UYVrYVI%b9Nk|)PMO(CE{RpPr)EixBkW}M~7T{ zOMIQ>_`t)iQE|D!1yN2F+#is?K{9{}E)wCB$I}=xzdmUd=JQ8mTy11(j`Lqw)r9d` z!8}WP^UBF1-l4d~0%lf30{?R(O` zEs5#4UF;WTOBSjwPXQ~BL99>ax7k?iv`fv;IzrF;GFW-}Ekc$Y;{SRQh*Qu3=r|=A zD@g4ERd1$o7rX@KS*q7gVM7U^SEDgFMMo(C+baA{Do@nHdeTWLh(=8pw>=q{-OJBV1n&kgAZCpT3NIz!TaPpLnbxyi@leXt1EeCv2~*wyxMPq$z*ievV};c zeAgiOa;z<&lkZfEEF&pkZ;0&#>GL{`Rje-2R_sJN0<6-ltClR`)43YDWs3x%dx)#m zN<|#IAZ6Ohw!-`pN4u26Iw}ms@Xh9EmoX$;ny9qH>yx>-WVb@+B*O*??Y?v4+ebBb zWN>}ii=RJ3I2QSD&WAI5?f~^*OHTW`){zsn=kQ%X8$i|2Njpncr1atWapy*AX3UD+ zxG8&&k9ifc2UcXXneSMfvcgk?xT-1zg&0GU1l-taS_c^7(?bxB035W@gXeVul7l^b{>L^FNlfypm1iEWMBK$N^_s`s>cJ(^o6W zF+;oCaBRxi%J7*K=9=6g|1?;)@svT6hxzL~XzJRVcN4uG&3_oW?YyMewp==WNK~%H zC(lgtL3?rw+MgG1xj2v&AK4+#Y**COsfprx4#c=pR?Scn)V{EYd-r*o^PL61cu(sM zb0e~`>Dd%z=)CwePL0#@)Kr%vl)YmmWHLt2W;KK%vgV_7o5R-zp0SA^pqwO+%hGuV zNY5;~ExroQB`f4poM7JysCwb_Vo!O-!w^DCXGl}meb)D^^qI3r^%VSC4c&}VX7|cQ zGVhuTX9O37Y&<)Uw1K9CSP#`P=q>h&)ea*P{VP)KY{SJO z9yO)uJ0DF*$eqZ1aH`(XewFv!QB8CBT*V#QoVj0$`Ss$hgPUxH{1+)ccN>)IfD_Nv}$WSLjsG6+XbbQjRlPcHUPwQ{58u<3nhYdwbTC=ShE z^wwu5?Pu9JX;Q}ZFR;sT66$xe>A&QSPz};>cDi~%`QAKjZqqT6{WCLEGtkUakJvjK zuEWG|%G3G|PuTJ2g72hNc?Cu@Q!~5uJdT$FSB27b4 zwc(LN)Mv;WSCx;v_`+eCBWYwlf)l;8>PzJ6p?(p##$Ul1m|^&$D&i#iv#H3CjMhr~ zN2$`@unS24uy3)y0Lz^M*q#%b>bDQbYH{PWk(S}SrY^-LAsT`VWW&P#%dh7$T3CWD z{aG;{jT3=IBPHsN{`v;UUq616e4Njt!jP9l(m zhv43vn}#9}-VU>?Ac7N+qBat*pH~k}8c(~NJ$O<-lS9rG3dxu+si*MZ7SFFE(J+&9 z&nc+h6JXAA0`MsXpGk%)j^?>~&fRLL7~+&O=#@R%H4B6u=qhmbJpp`eh9KP5JMqlO zy$R-!-8+Sm2?2_sHQR2UGv6u-gFU*MU~G$~-ozxUVtcXg;pKX5jjyB)a&rsH;Flb| z$retQOv0UT2U!zEZa?+5aey_dOZdmOBd*G>s&YexIkTv2*e-Qn`{`?GIecIH?Xg9% zgAjk4ac3EY&(vjf_CIg`+Zx8j&h`HvtF?furr2O|z>xr`sX?Ws5ONm*)Qju`15BVp z^Yn{)i<0G%Q7-Q8(lAg^5lKme7oKyTbDzI9zPnkid7ZDVhdYkf*@5z+*?NmG=D;VH5a>UQy=-`%0Hlp8^DeQ0#Y$m=|HrNYzyREvBD_o9Km|Ev%9^52glsr!TFZk z!7U`OjB4m-uxqfwt@Cd%4$1<-g6T*jG^hXHHm4SbH95Sq1CTKCtY-g1GVqXa+N<8{ z-WR{RH`O%!#q+5xe3-V@FU{cONTLcRjGGfM_2ieCBcjoF@J0X0(o-h#DHu%xu^KO*CjHVFL z0E}%UkY<4GfMSh*(e4n@rQpN&(Y~R30P!0CeE?9ML4Uu(=<9YA_xDwcXu>+=Q{%}hwsB`sMavxkRLMd z-O^vOtBsvzjQ*VJE z^}w6-lUVBj0jLM??b2jd*1 zA$+jOcNXP;o-maM%qN{L#KHISfqrBHpmO%NyhVS|?N^{_@E=4XpuLct(+|!8TCly4 z@AT<0*gcm%i-%nnq=CqW(BPk`pi2VB;BQo6q=9qjpkLr0wYpMRJiq>{{&SDr=-=^v z0}P~beACEQCfH^)Pdkn8uJf48ks>VQ z&dmy>TSYO<_|a_7Cn>8Hz58&X;850VFTOW{gK5U5+~vx|tNct| z9fO--BBy#Y8x0pVnA3B=$dpz=P4k!+&`as7r9gWtd^?)+blFgNE-^7+6_1P!e)(V( zlRcVydGgc?iCxK*mr#=A<`Eb*m7Sb=0~YkG_CL5$CMcO%r94*OpH35rMN3OGmD0UC zb9zs7JZ+AlCKQVyZ#RfL39L50FOtSK?&d~nnz2alR{_iKSBY=wr!d&`PsBrT)=F|D zL9!TQ(O3_b!%7f(QrFNJzUnp|6no$0$IlY6l#Pbc&LHzzMb0l{H>uA;+!zrJbBEn9 zd2+rrT&lV_YHP45#t@#Z#jBlp61K^q^f`UzheoGQ=bu#46=01Q+k8RMjfQMOWZjKL zU$j#*7&d`3R=@xD3Add|Qyil`1$cmZwitUm$n{XhGGcB@$kdu*p| z-YYcJzCO*jGkgf6Dmim15_C3oEp1h=J4d0_Cg4lG^^;hTdT4ryeBdAYpw$#ka+`fGy%fQeNo~?L`oLR(ii_O|2B}L=wFI}o|7%1xIUAF z(5HYdQ)a8H0wlqFJx<9olYhcrz;l+@eiJqnG2i)Ug|(jWxFf?}U?w%%u&RC!oN-zN zEb$fSqq=}zyzfXlwQ+)zJWxQEJC9B}Wh7O%)DY9?7}XY_QgOlrohc!lBRSt9HMUn6e1G9Z7>yah2;NL*ujzsBpb-1KW@}E_ z71uDg<7876FTA$Txb)jdPwFm;hx)ShDIFg%{FzVlT^QmJ-$nj}bJXS`c(B0bMf-Fq zo3v1PUP1ZeT#lw|+J*=oK|#+T_(Fqs9r0>o6CmIVUGXZO6KQ{D*9m@+dXUNif+Mor zWeEjK#g}hP>vSE#Ih}ZCtm6Kw6LGQC$|n!85B?QHp4t+N+9H<9n!Q3y zLumUeWn`GI^Rcd8{M_S7s*8F&NF^Y0U|LbH(?TqUqwg)(=XRFa-kV9pik$LK)(7ID zavhaoECF8>CH)!En!lBJ2$_`cMsvHck?XJs5vSf|QAvVBU6}R3euN|uPrg6HBb;NS zmM6)f3MUs0jJDYKvTku52btsilI3olt6{>$*!UinfhBUDYfPweczJBhN)_2Rrvdh8 zhi;@?HLNpVzljUvClOP3Estm@g`Vgx&R% znWOJ0$m{lR@0tv_1bnu6Lgh8XgF?%JZ?ka6AWcAVU)8GHlL<|#{y}7{L9kwUub2St8VZ0ZX|81 zaYzm5d&htC+)l0y$$0>pX2oj?l(q?N!Lu_M?xCwym0xKP0>DpFgJ#rk$5-TQNca#p z?=2MX*8D4+?Ilqs>nmouhZ4ORJz)`E?&b4&(Od4iiGK9~D?ZBZ(bF(p-6H6x*G3#} zE&x)1%KDUCQ1*7VgJ`k4n3KB!b^Tx>0pDdsR7TFs@4r!JrwX6ZJR3%Wci%moO;x_J zu8363sp&4#u#{_3IQ1QOUS@`_jP<#yDK~-|SOXq1w1|jBCa(UfB9k$ibu6T11wtcN z(}|8!qwj#p4?o zXB9|W1whu1g5^9x$@*2wp&lR}YwDdbw+_jVf1Xr=OJFs^1Qt+kT@9U7-U?qhvUqmy zJI8xiJ55o3d!jr|Ae~6M*M)C8_~=DODs9av{6ZEUoN0`NRaQr`278^uHv$Pjv9(~b zH$ZNl79;i=GCZKzj*(VrLje*FAM@FSy*kL|<9izO#*(#5qfAwGAcPVx>Ce5iDXP zB7G)^~Qcw^v$GK7YF&9|w`kjcL|u@sEf7>XpG z=`?$J0Ef;mdjsZa-KTPnNOqq~jAkE5(p>aM_XJU-yO&<~Tfwakgm`4Z$xxu-D_px} zw7Fr)=yCI7QAz)^+GE`>MpVdot`sdi?BE~i3Lf$Lwr|uaFEkSUDIXgP1Z16qN~r7i z7ZKAsc(qpMMm@wxT`JST&KY#L0uhJXUZ57#jmi5-?)M8hBvW8gzW9=6{W;1U+$yVB zqs8CY2YYCcoaauneaeB$K3eh}Sa+O!n(GDq`dn~%RUc4^+hS0sY}3x z{gj-TFdRJ*Qdb9^-K1P!)!%Y}AR(_72*-=3vmZOr!?B(2As5}^6sIyvOXPVjbt|CF zH9aQV?0%B*R24L$ucZT~xvI|aZ^crLgdqDHT3Y6d$OpI>@iP+Ev6?Qz7U#0CfESO) zc4~nqS{F$vkBY$=@r&X^McXlXgsH8==oVJ`mkxi#;d8HFwjfg`v8RF>t2l;@o}Bb6 zz54#Px`Mhlfi=&dVaw%!w~)1 zjB?9`aI#jM?)mCC)t{-6!3}0Ie%37iBcttNvCx)v_0h_yXAOT~qgiGD>4@Oqo=F2K zce%dgf6LRUM?Y~CwsPFft(>H*%#T$MBnQs>Ta`7ITM=7U=2}=d0B26)u&>lb` zKiMk~-#-_JvX+gbJZ0j%%(Wz?85q+y($+SCqSRxjbuEc9SE`_wl$Dj6bdOa(sAUYb<$cQ|)h30*r9tK*MAB)YxmuXKP-`A~N!^GRK6L zwcDiS+vkY|O!Kh*jv*dYcZ>;)Q#9>*O)%A`{L-G(pVwpW5CI95>1`iXayeb8JKN0m zz3h$_P?KwKmC}Jo3LO~g=O^8}gr~_7bczhq=$$h(V>vxX3;L5OvVj`7jdM<~Zgkvn z-rEpT^_)M|=cJCfVk;ep^-vtU1!qBZFG=bQJQ7Lxl0K@=;hhE&NPx>8uiiF4DJc>T zx~*M8TmiXNdRx^LmK)%NpS8L%5N^XShb$%XM{4(lj3;}ke_lXy+xP~$w2n1Wwm7ZS zlS|)uNYP*<#-#QLo8xQah}q4HUPW1seKfc@zC$}e`zA5N@NsR%)Hkp*oH6pwJQ)7M zS^h6v1!y^iZBR`YlWS-hm!S7)j_i4C>sba$B0a0J0K1&O1O^#|Z0`dZL27=of&1;& z;Jy#i9|JuNO=5RH7*YBLbkGNt zV~pm-N#gWb%jFShAed9Fu&L7QPC62rYV12Ok<;793$8Xe?{A7~VD1N=@xKCOT%;*A z5$D*FQ*P1tf>DQ!^iqwIDfC(Y1t#u4xn|;UKkHiYpX999$Q`+S+wk3aPvx5qy;FY{ z`EE8$a)(r6G#ibN{`jE==vzdn1u{&`{ zRU*7CV%+=tS;v|-li?X*FS|X{AO>)HbL@ZjmG84z$z`r)EXC^T!IP!lB&*oR;Al}>@#bLJIHN4Ba(Zdf&RPfim0pxLnvh?tyTnadCj->42Mt`c5 z#v~avd!&qJKMWFS3R#|rc^a)1swFI*zlTl3iAmK8JPyD-s*0Fqh zg2S36?ITuY0Xog*tCB=od3iH5E#x(fXhK}Iyk@st+k1`qsmSH8ydyV+#B1D4nsYt) z+2K_`t;sgNn6Ug+J_t z#ad>*hff{KbEIc^rrs{zSLEdne*eZY)x$qNnpFnJWD3AkjKgd}=5&hNY-pB@PHeUwV&G>H*A za10c^g2G#w$%aE{c}UR}f*jt&eKjO?)w{5wK#69yhFBQNZF3sRdPu`(?mNx?6AZ34 z_&u)N>Aq}Kz1;))w0o3yR8M7*QoTJPki6+iRrqrhmfLMR!J%k1^`ib1>6*+tM1Ogx zhAyykMHXKT;Gidqsi0h#7~7nEUJ$N1Jfn0gg`@BNzHHWT=GAj3uWgr3%>=ep(YO*vR}eRSQ)i=;>Jo-kva_q^?h<@$sQITMf;#pw_;n)pLk%&kdNhqn}32L zJplr10MSVRjfe162ay;5^Cz}Ng=n$~KNoz7CI&>1+ZoJ)}1};;$?v zeBSooJFWs)^nDWACe}l$!tachu`iX1kEPL8bP7Esl5|PgXG%WBgPQ5W%$AaicudOl)+Zbgd zr}x@E+$-$e-8*~gL6t8Ft$;z&Psj8~jLv$c%i#lw=d zI3i?BET1nTaAqwipH$}eXfLhB*W@;pPPfWlLb4sY8i*w0&DoE|ZFG|9 zND7oD^legX^4L<#xnpXaCf~fIH8}~|8moL7-~0!o^$d&K=~Pj-&G#=0KD&8}n_y+5 zywQ5|th|4%{#%7MTe7igyT!2L1qKX-!EW?jfz(2Zz#kj5;&ihv#*ra^Z1l@n9VPcN znE&g1iAi&o?2~0@K;->6Dp)#Zf0^V!KU=dyB1r$Y{n-(8Hp&iKxFi3r$u;K3_n%%f zcMb86<8qmiXEpb|Vu~bed|9)=M+J(HGTBr=Ii+fSSQIm!`d{S-YNu(wEt<8$@U{zn~qX&rDgz0v|J2GTc7dOY&ZH zmF7t8Tj><0zJU&~Gw*vh3g^)V=is}jCu?OYCq~fY4oJ72AFp@Wu#^~JJW23Fz=2mV zohx8&OM+D(^siien4<6$=H_&rB*|!2ZHn1)O>mPHEywp;r`NYJ!^1@4&3ade{*janyVpd z#E#_$30zT4tNv_~CNRpOad74=#_f#PM-eow8V#8SbUZthdb0U2$YqH0R2=sw%P zts~aO?L<6;O4m>c+9;UiD7sAGr2YOPd*g`(9l6oHxu?JI6hp#bcGPji>axJDP~icm z`O@QGVTo$zOBvf^3s1l;x!WHCLL1$eASyQ35jGZK)_r(O4kEs}?md3V_D>jWX+5V} zhj;!vTp3l;l1cKaM^Ee zK~Pakuz+%~>QjT?4F8q7yMzeIgh+9T9p~rG|C#}6Q+0G`zAgQ4J}x9z2xLL)<~^IE zgF1Ca=vC+EC>ul5P^He1pVWtr2N)&~4RTToq96QY!&f~sr1ZiW)HxG=8_x)@mbrf4 zr50KQ=bEJ4ubj^KDRvCgirdoBg)B#z7hpXxUQKBjIA1H{jXf;0s+|`mLe;jQMHxTkAV|hD=!@_-W8IR{aH9(xvIOC9f4WPh|s8MUa#UerR+)cTw*G}HOK&BnZew z`A9elCxZd!HW>9n3I=!NnKnZbl6X{_{(c`M!XmWkP*2_Tr|#`hM^+f-mWHqKFh~j*w%rn}Vp662k4M*}rS&Hg{*m6Car>t0co)%R=r(AZ zKf7mc&WP%#L2je;I6{9atMj{+aniRk+*Pru;Q|@~4Cp#0vE9wX$u4CAflj_X4aNcr zGU};hOl()MDM}DFXr2t`AxN*J%}?_iaxsGc+=}F_-LEDJHBva1S<{BU`+8o@HV1Fj@>(BXy_JwGF4Klsp_!0nrIEzHxYOyTIBUkSR9{IEY zZ-iA8yc9M%X~nYsAS5CtPWQ?ECCnVDVi6(eT2m4?l z;$Y_ZKfBeO%q;)^5QsaZs*24LgJfcvYAQ{kI}}l`KW! z0S5@eyn{Og6bvYsI63$TS)fn=5)#!tCsJSv7*!yjpD4;`!unploD%mJrJUC$xrfN{Ql~$mxI;1xP!`gnJo&dpYP^2TwFNIFQjeeNH zz5ZljH#aCu4Ww;ch;~RJqgkYYx+o06P1qS&puxfZ03r)CkYvOMpursBHmrf$Rbe1> zPhTJ?*8Tiq6gcR{p{wrpf&3xY zAX2{lK7SoWEIhbxc8GO=+5i@UvvYU_?f0OeuGsI}6|rRi6cQ8~qyUi6HV_gcFJzzr zES6`th#w@le7Lq>}TF^VmgLohx5fIxV{=w~MKj?2;1QQBi;D79XSNXvXz#B=k zaz)mqLU~q0IPx?mmOLM75f2z^*(8QDUBjXaHp-iQ@mv0uRmS~yYXYV!Ka-!$qlW&J zf1P!_&W88U>97U~kXM=&Hm2}upd-9FdG!;vZ;IXoBe%Q^8BZWrAAK@DVN2T4InZ;V z5Xk8XpxdDCRJhrGG=2N)V(Y=~DyO6~Ym|U@~N25n9E-8FiFr2)Kzb)&0BoQq} z2py>-a;nnA!_;Dp6ve7`gFaC5nX|JYL zZUvv27Jm?U5GjkINSOiN814qsJ1l6UuZr<1qa2aLR8BHkr+ef(q!8+AUa@d}| zZtSO%Q}lf?ranJxuX)08YWCS57{cB0lt8`&Gtw;kt9+zwWtO{$BwcWG#|B7vPYDgKOpr zq!&=7Am27DwJe#+vM)GGvN8B@oRJ{+VEJ%CQ#X2<%>0oS^vum1;&SLm8%yFlt=b+0 zm7)T|A!oL~XZeu}xbZxI_<%Z%!h9;rm~xB2zTF`nPO>`2oJ+intz$-W#`nQ_HcAG)f*;163%ND5W5IvZejlo0 z^fZaHSxN^&vw~J*?zaj?Wn-l-E+Z&8;3K(;VqY)Zo07IvTO6?r{+wWsB#^l$WuOeb zO8A8Vy?RuQa@1kbgrt(d#j>%T*XH#<%3^PioGmuuFOyy%>y9BdjkGw>`!FIF**6AE2AoqZ&Bhnx^0t z?HOpGjE zTA&J%7+-ZieSWa1_mo9r`ldf|Q9^edL*gOtQ(uMWM?zKv0f;5u)4+c~3*5i{xh0a# zo|vypX7dfkVCc>kJ zeLk~vTneeC395J5J!)KL*kxrZjgMW}9Fp)V(8CCjsY*S3S!>CyN)^1$Q@e>#r^>?h zp2=vt-}?Y<M^pZGSB38^Ex~X5Ek%D(Gt{J>Fr}yr~vqlf_2O89beG0y$%aL$5nPD`D>MAMINg zbf0bgt8QuYLp=;T0~RI+s`er4S2QTd=w;6tV_{%|45|i|z-#OCZwIH=Ow<3uUev`H z9rU(M?*iFrWOw0`u`sSaj8DUVhE2qm33tGF2$I@Zu=72dMYkBgTK(S}jpFWJ=0b=i zl14RG%Vs%U=rNi`RqP|r-A4}j8q}@?C44jfsn5E7u(d?WO+^n7dItVC4yQ`MGf7-s zS~R)&m}I)pzlXvokUTra>7!4eyPDa~_5&ULE|4qVXkq38mh!OB+7EQ7*!g%&JBB@) zZra|*0s~&195~QwMWVPsgsO>R$;}m6Sasm z2ze=5y1Hzxb*eKuWK&)i?)}9AxD4xk^afVwNW+ybtM7B{ZRZvRFurJ`Bd-=+VG=3N zf4(egR5EVqo2Y;pU5tB)pNA#WrH-!4W2^y+0o(*s<=h@$sPnF6-t0@m4V695RhN`T zAf#z;!MOxMvszo(!?V)6jRu0a>tnG;>??+TRi`DjsJZ|V&unbPt;eub$;+X6fRj=@ zj#Mwt<=)`k!m9+_0A5@-3{ey(olO2T;qVg!T#bK&S2>l{&g4sE&}EmY=O3orXj<@} zl@d*wQ{$hhUK5buo={89K9wf`946Gi?`Ggu#6WNfuIldqH?^3}JQHb5y;GAn@YuKb zwdFv*o4Jct<4V4E0lFN9N4~aSYHr>`N-@DLNfs*Y-G%>b$ySSdm!GNnoy1ZnhaCJ~ z=OHoe;eI+d^TD>MxF((39-_gN@7Sp-|9r~oXvbQ}SB;E-{}Ls=C$Ou2V>!OmMl@Je zowmC>{;NsK7-EC3(pRE$*Js#C*w3OXW&A`o@RoAL?lPl41iHJ-{~OB@OWsTJWoYa-*5qRN+ew@4?}0>ZVOzPMP$6dTgBnxH=4N^QZF4fp1=E{ zWmAg3tn9c+b1Y#!@0BBZ(##3SR6EN1yBF$xHGY;9jOs+}j=YJ?IG%J^7MD$Z#zo%n z1d;8qZbep;7W_S;@H{@qmg(|V=8?wMTcPfF@_nmeb+L95q`%5aboc4va9C}xdGi#k zM@9svLB~&}%Ezs?5}P+m9PLt;aN{1m%9YK0^6&dJYm@CDHXk08jur9<-4IYEkIf{e zt)C04*uwgb!>-cbMh4VVRnwshA0bvO@M46m&yYW~6l zE5WWA)lzKPO^@7O1@vCKm{0ZcQRxK@v7O}1NjVv@qC75^u{8l<(0Rl&Q@q_q@JPS?L`g{Uu!i+=O0`tbeHGYwrDqF5Q*^fh_d_=q+Yn-NA8lUaVxEeWGP ztEp_xGy97=zU6c=0%I?d4!!b7QCPQLa}+$L`L|go)!VjD3N=x#66pQ()eC{Et!;a) z$%Mi3ALn?BK+6k$w$Jl2ts|)og*%^Z0D84oO{9>by-1=sw{DMHojY1}+--oR{b8?9 z@Kly)EYGP9UI_D#i>;2zv z>Vc_8RQ?ZP_>l$dEIM6Do}IR>B~7j*R+?iyO1*aX%-tuW9NyB$jdH`?;`&3LUZeXb zpU9{!jF@9RVb=Q3n(?y|p-*b|(XKFmeW5~cc*HjvMkJ#%8W2xpU_vcld%B1W`du7} zo^cqQNYgzPygB1yp^zu}-62cWx{pq|*w|UIS1UxbI}q7Ah+?JLl86vazk$lx1iyB! zwJ0X1t_kQfMQ$L3Tz!8Wjl3Rj#N<4(iuQoWnn+gEHwH;-Cp`?rrlToW1MWyqAplgcPOuFJtfEFR`_>?!8i5??8mPUFwTm{Sum)OX9l`kQ zt`c^-wc;a!7)a2?4+Jmh1i>o+S_#>|^@Onq1RsPv*JxF@V5nLn(HLrg9|7wQ4EObis`OO1Wn;U#|TU8ySWx7f_NfJPg#qTGp zXs3?5Dw_-^xe~}9-;;vx#wpWTZ59(dNY0Nz<7mfUn8A%zUXhfghxy2VW(2j?d&`dq zC|M+T?lgX6u(*{ztBFm$a^T50AVbZ{uv|A+?-A9}`@=WJ-%(-r2gN;w!PfO>rk~Yl z-()^ist51%LT@vU3HEuRYAHOPv#?p<@9P7y$bU7N^r_3Onj9T+k`t>$TRlLQwe^B( zz85+F-jUB40dl+^@};+UNcQ1wH=V0#<;#kTnr!+`C#Cz z(SJj{@WfK-@wsI>X((Dg2$4w&nx1;Hp-v4~^GC;Pow*=>N|~4}nd$8oq%+vTW+x%f zFI)&L6{}sHMS}Y4#=h2I$y`r&o$9N-e*;EYJgT|Z55lXX5DupE{IKQw7MeC`*uVOh7|2!aH7d$cAr4L_5BA*aUFM6nM_1xMGG*2>Gf$u0&Dy#=$_!U`>?rhnm znEEk~jVoOkos1tG^(C!%dhBya@RBY{DDpdmlp(EuVnIH!V8F14@12Ft^CJllwW;)Z8> zeJ&Yr<*Zn83$iS_QMFhs_hw<^@hAa>v*h8S>YJq<6rzoDHn)qfQ$Z@L?w+7LheKj$ zlGO${XOs?#O&xHK#*bmSlZvV=%K})$aen!ek1-=ulfkWsjX|fy&Inn^tPA9 z(%anPmk~47H+`q0oAlggoky(@>Kg^$zxRFag0&H<+6BlN6tQN zy!*1U`um~$w{GZ$R5(qsa}>}+a;RH4A`P1AYV^le8$`xBzZPsZ)tilD`nxv83>AxA zKBYIfga8sa%UUr7qG@u?E>pj@C+0++MsQ6+!c=~&B>Ps`=awa_1-z)N*AoY2ePwT&1U0(7eO++yDCdi0! z$5m=Y_)sW*ORO)dNMGJONwxRT1+nRJ&>axUHiX$m#BuhZ0NY(>p5n_y$s4<5P#DLr zaRj3O5^~)35R6*Amuo~uzOcCWsQdI3xfJofb-9&$SHI1h83VDZk^DG z;X`8In@jBaNYM{8oIIdeIS~yo48W9uo9A!cw04=3G%5MwD)O=vfEO^#8nBdC#&iS1 zWZE5fUpZ+i)t-7O{SXvtl#Nq+zFzds0W<#I6-S(V^gStGN6cRD32lf|WkM%+Cs{P1 z6qMD9D_wN7ai0xiuLU>n*kd6ZYZ@b1Dw&aije zONl2wgTQ}S{(A}4G#(&~J^K)Srn5(~<>^7-UPSnb&$VdTm!>w_WrbO-C2`-9Qv_{oWQm zu#K+~XSLEz;E7_!8D9HPgD@nrSo|24+6e-4ZR$1F!hn}un3|Qh#+p(gY7kDWL4ab&S834q zq{gV3w_jE@RowxfU>Qlv{_9?b{L^zss)u`qTHd94TrhxeM};>fJD06C9zDAgP4yvg|(0Jkn4cOT&+^-88_Re`xBcz)yJDDGN=Lvgd^y zVCQq5IW9??gIwK)mpwy+`-Jl>pT+1=++Npnk?kM-Ead~CD#Zry8*p#%=0g4`toUW$ zEI3Kj%UDkJbj5jWCPrR%;VVSQCv17jbjRB12dNyFOcE=7ZLIIup?XwY#(>h`H$UuL zwzYNf2wy;aZDNzyz*VVKm!VGUfin^PG4}QE7n#zCwd?S%^d53!YJJx)+reS7s|{T} zOUgP3EG}-N|L9YCr|seBN~#Igq4=5$!M*0LcvgX=ixA9CrxJ~2W&B=f4F|-AYIBf~ru6p(DGAHNyR8MmC zgsc-AI1C$W`Q9SuK+gnx@SDqC5jaCg#rW5{veSNIuEe> zltNWE{Z$o*l=LN=`5k$t#5XE4pE|SLmW$^E)-bxE5B>GHo*KV=?WlE@4M))-N|Cz0>>s3jTol)bjZkN& zhlTjSz%|AhS_8M%f3$^_sjq%o^(v(|rve@+*gpU8??_p{@fDpWQv|da7*)n>^4^O& z5;UaFc#OM3ay&Q{JAZ?>5Ps?MNpJ7l;S$2E%q|;XoVggQ%#vv136|qjlOS=S9DBER z{av>&BA|ERc32V>7c|>WHmq9!0UsZkW%{v+4>!93WgIT^f{sA%RNCoDiC1*0oh_^b z)p;A{CoGeFJ?gKarKJGIHJjKQxe_aRFaChFiamUMh#-#gBhmCwYr_MHh?~;2>B8Cf zNj{!nM-TOwf%%J% zQc6rjoRRU|!AzoP{KqQoOpEq7K)@0m^4bW8(}sABt#syVrM-LqAjvQzWYKTO+T+;* z(#P9c8+lyH-)X35&XmQhMl2mWhdhpw9kc&twi*k`K-mPM1b;bo(`D4Lo@cv>$jO~H zoj}s;Dc+mXx?;O)C#IFcY!+T$?)a%eGr zwV2cNX1-~7=MM9#eM7SOZEgQ2K#}7=0*Y+^OI7}hm4)kn;Kl!~D(7HjVfsItHG4v` zZEh_Ch_qdW7UAYEh$6OqZbTE9Lye{)uyaq@y&Z_jyus#uD7|5cL#QGdf`}sT@`F|gZX!cUl4n1L6&*rCST%C!ApOwm zAiza}1&cePDcNj-=!d}JK#w6n>r`ZDa)XsY&QI>aJe@PyTA`1q9r9{;Qrm9 zDY^yrj!aO{bD&0eg$%3s14Ll`VBldQ%-cUu1Ed!b10B+^us+`2Fu!%@gsC_nz4Ul^C|Kn4Q}K!7A7A-k`44Cn~}5BkTq5AHWiiKc}*gO}h2GIRt( zGc2g14Y?bH0uq!QVML|Xe0z>!%bXkbtNH*SAY%;C5YG7mgv$d-a zWJ9FxPXe@CztWdy+W-?>kN|ZPun^F$sX3`R)GrwPqcHvhlA5Zd4`d*uL>*X=0)|9H zLPGM-x)}}f^@lZ%80woc{^xc{cu*0jvhVLm-og&G&*wbQY(DTF_$O-`KTNeQRp7~v zZ~zb*WKg36$&W?nkNewC<)=o=WM?eq>38jr}&rUpE;xR5`5c0~sm(BUz} zJ;lH?PB#kVYm{L*3dqwty?I~*63RaxaG(bEcThtrjwFLvbYN+qkSihkzM4MxA`&2@ za03tQMfmqI{Ef6eU?Ra)@HkhApUFV-F5{1gAj6wL1KTl&L&CM+TU(nAyAIe!DnCA7 zANqm9y#<%^c?;@Ccm~gsd9eGc9l8it(?7I#M|7q8RBrID?A(LXU-72f`K|LDmCN*I*-ic!YMhs&BO5IiYmY#~M- zfA&Ju$1Of^p~LLQ?onEMa^h%qtb=xV7b$`w-oJ;6GlSuVM68I4m#drNEac#)p}@j>Wp?y@I<3p^?EhRpQ-uDN8mSFH1PpjoG&H;gfM#8@d1cr$8qA4q*(Hzyjr{%FM&DW4; zZ3G-Boo?~{=ka~XQJVP^n|g@Oty?tEX$?J!uQMt6m6iY*#gTjg{e-ZAczk{5 zvR&UP)TOk-4ck4@c0mGnsdoH{BdOP1a=GfmP>cC^kRTdUov{TH3x(a{6)l`1Xuwv5 z60rSLkK3NvzQXxY2?1fvaG*}|>l^&l|9WJR&60lWHqm~&ub9gcJW$E`s}`5JzTDtv zv*T$xUD%HY;=W=l@_v`(s%J~>H+o}-6~ z5ox_oU3dFCu=mr)&l=;ak$9aGj;|aOyTv26F^$dfML1}MvNS!G!?*>1{vM>=L{8GVS*6KqOZA#^ zN8RS)hNR004qTcuq3<|-`vFC;tG+U!#F|%O0jbSrK|1z{N0n(lO&89<`Hc!Hl9KU2 zj+V4baz*F&2Q*4AET;;HvuHx8Km4;+adCz^0A$oQ)vCDY(WVPcp6&_zn>)euITb-o6W4B8ff^tvXH{2uT_( zQ7B&~(Mmq8qMyr{k6+30x=E+Vc~3sSg0>b2;Z0n!7Z4Tc2ik5paXO6o@$uIcw?s<* z)N>SMcL}QB3QbiJ) zOH)lM(W7}1VY0}rM9{DtRFCSc4N)k_SlNa^i-UuH`jJw8K%zgCExhJ4SqzNV>!kz< znbeI9gto4q#j^s;Oy5ffI1TW)=65FB5S)QI1H7%i{rzl-NY;p;u033fNdg+=`{ z*q4xBil^gkTDiYyka_+YNpy_gbrwp!S6$KH80zG#=XOpDL%mGqDd5Wn$vu@gh&qL2 zz60eL9DI@<^JEwwW1LCpg$>c%9@{p<%8n#s|{Gz$5XZW7D*5u57vRdd*vO)<4%?|kTURV#>id=G1 z1a(UvqV>|}Fmf`Oqv%8OWuUCzr|r-5Ac_^HThI&NwiT>ClMZ%#Hp{*Te>nHV2y7gp zwDCEwuP(fL$a=qXJqFP!>0Eg-I+=Q0*R7J z0VsaL7P2sXJL2fG-pOxMD@T^GN$F7IhWJ>?BXarV?Y!N5o%uMIfK4-x@FDsqATeJ2 zc5mhCp+2TpD8}W**$>&X=S{>Xn<(YpKkES+3Hu)~igvTD{8@K^@%TTarN2`n(nS;5 z9n`UoaZ;C6vbxrpBA(Bgr=xvs@D_*|A2alUWipJ=46azITG#+k>Wgs)XP^B07#Epk zQ1xU=QoK2Q?nNguOppm?*DMunJ)^q7+d^{qM=mW+^?kGT#fk*ZM~8M<=(vk27S}Ad zTz;W@N_P>#6G$TaO8e=ZGsiVH%KR%j{F&labl^}g#snOc&t@S8jN*;ASEVu|kKM7e zmVDz9TxwZYXE}48Tt^(R$goH;d3PJps?&gP>Gk5&SjD9;V^=~2y3>|zMWje>dp_HP zwA==39g0Ah>nN!F#L+`3h>_dM$Q`M0QD48`Q8Ev$O4P|G9m6V=&rXKf5r;l;)_*bq z*Jxkria!=}+m?Hl;ODpczWH(Gi9_L$O7ZbKy1DtC z30tCpf5vP%9j;*-G5KUIsat)_7J)1f40S!Oc+a9u@JYx-Dfgm$V70=A5118V0sCL? znVtP?0f^` z@;w^T&Zm`s_cjok7SI0ZG1Z?uXZ8iK6%F6#rDJslu=p37|7l?lt)gT#67sOk)b%-; z+)Jya={X$iIu*pB|8Q+oYRSI3m?m$IAoO43wDN!gL}!Oz_ft$4wG(1PyyfR9yp8LP zm>LDlx<=!^Vm~9<7B!auFq;3o)dxr)lN#-LII6**RiKV8Ul zJxc7akut~|zSF*NJGQWAjH*QyaP{K-lw8-=_+m}_?jY^IPz^qyiKlLH^wAv?=(D=~ zBPlHc{k8Ae{cdRv(^17u%dB~=E`}Ks`@L=l*lS}U2HAsG2->DP@R{a~dU#N1@*V4s zwTt3=*VSe?>m)*tX6l|C5KBTIx^ESmXbEX9nvHFKq zhs^$pGb2j;z^jQ6Y4pCxsWzHZaQCXY5qr1dxga~xM}Jy+_Qei>$>EzjLt30C*Vei+QNlRwe*KLf=Ap{x zxAVJ&(aQQ|qA6V?ApZ2K*7I=f}|U}CbB7`b}52g0&6T( z|Jj;5%#JGkp)beD=U&Y2Et=i@zBl+cf=kW3OB^9y{gFM3Kb(JhaRa;(8t8-adPFL7 zS)#)%)9kL}{n?uh%L|jaJ^JxPg9)=Ux2Zf)M4)qA3zriX|^eP&4=Mard8AEbug(Ol)kJtebW zj`!BbDUO1Qh{uj7x2w&A=TfH8HLCwWIeO`vxx(M-rM}Eu?56h9n9%Tt^mcizRuOV5 zw7?_YN=i{jC{&d+``Vab)9{dt zl5YEY5!ddEuFJ{YN_?3Nfnk5eL<{suPwDMm$j;!9dJ+=&islg5BefUV4O*qMp4 zbM=gb<4XP$dTAb^o{yt1cRI&d4Q@y`YLY|76nW%;;%;7t&Fk1H=cZo(8}=m4!tTr@ zK#lalWS)$@cB9ztb@wxS;s7TU;VJ=RkIc;-nzfLo;1dG)n)#SS=JYS*^(gw?CGZsZM*SoRX>WMH}T=(+WKO1O}Mu?9fc|jIlB_{=UOE8p1dp2w@ ztT#>PqTHgp>Cbk6Q--aA0;QO7X1`33j6I0l2AAiHS3b7CcR!l9=2vri?7Wm*QJX&z zw6{esc`0)vwoa2_e8u4`83KZ}!3Muw6?>?XV2Ryq*G#Dde!Fr~EGzFMsGt5RnIcEZ z$iR;I{V|>^s-{~5E0BgOIRVL~^XbSyM`bsJ-&S*o;MF^;ESfGNv_Ws9{`sE!J;Wii>PnuF2dlUzi9LC4?K)J6-4aG42TF~fxL(P%`z%SLpLJ+9e_ciU% z9YW&de#kIDh+3O;Z+lR|n|-cdH?*_v_rO(URhLaoN_X6a=dXFOXGr{EOda}-BlnG> zreup^tFO=3ly0o!>n56uyPR`Lh^x;@WzZ4K9Pdc&0T~_BjG`_s#Gr)ROvo6y!DpLf zzHsm3^A-`oyJ}{Ci&}*u4CVU?r$t_2o^wv=6^x)ey8i3_>Z1Sx2)(Fn%C8I zAuO$X4{tur^NsG~%Ds?N*oW?QK+(x@XF+Limd823b-4vS}{~y-=D6B1n-E7Rd(v3cBf8JnIL^~xf5Y#?moB9usSKl~iJv+L!EFUQShuiiMi z;0EoEky7;uJIQ$wSIFoLsukTU&Kq!$SX{;Wo4oMQ`0NbDjx&e0mN$UoJ&Z*c`y3kA zm8l~CJxK^O*~gwUs!Z!Jdyj>r_a6?Dtq%Ui8|{9EXFq$$H`Qxde0auFPCM?3i0LzM z&PJ4r#H6|t-am#?zf+9qy|g9Va7O5+|0HU5?$y3_-c*g-9zo9E^r3mPnL+detRS2I z(MOX?p?)#cza9r)M3o{t^p&7M3*X;iu5Yfi6Yjdk@B5q2LUA6s?-1S>nD$ zJ2$WGq!Kq>AvAa^jHv7^mcEv_uwC$tMAuHtQSZYtim6i`%u)XBP`GwCDOK9NrxHGlm6LUFIY}_p9SN7X{A?}GyxvTX?2#AfM%RDs= z7oRs8{EgfIk=9hSO7R^W< zcVo~w%Jw5}fF4c`4tdnRZu)josa#_>+UDoO%jto(z$8v*NgFLbZZ%GcJzp|zm(VGQ z5R9rNOn_>p)d2bE9HYKvm{kO5?`I+1v$E(J1)T1Vi$01SIIuuxYXIE}gZUDiY!88J zOtryXfylr!!;Ak+nctb=LXWIyPH|<~4X}Geg=F_rO#QD8Q ziF7)Em7nX)7b825?zM>`H6dzR8+rJ|Mmp+4j58$8`pMPaeKgk#ygphpKWwag7@NqV z1$Vz83c~Y!46Z*UTU^b$IDzQIW(;E9{!+~LAztFCegJ)&R^_xz1=^+HPu5P$2UAsz zOW!M8IlC{_GJL0OV_A2$ZNgex!`IfxW5g<50Enub@w#P1B!byX z92{1FZd$~~-TWhZ2@&7fyP|8e8);r#0cyvwnwQuIXApE={iA)VCUU^Xl4wdI=3RTi z*Sm{yk?!=He3Vyt%R;gUWNyoy-g?D2M;2<#r(Yp>(CuG+Bs$oPP4eV$YVYYFfh{$7 z%QwxwMSwOT%0T8x?!Yx}yUSIuYPeRs9i>ZhqQ_nZD?y%2Y3ClF4lXvt-m2`@v#^|9 zGia6iv^E5~uFsamV3SutPXopXWd%)ei<&$mg{hr>NsMt-xUeVcPJC2tNl1y#Z7;vp z^l#j^-C&q_>+H?iM79kpQ!0Z6_c8c5#a#SIJ%&5aBVg-=XU20gTf{EWv-RE9mh1aSs>_?i^n#I`(tr$}aU^J7(Y1p+J@(Fdlcr)Tdecm!7P&0(9`!$44Fb!mfM?XYD1%aL5fpAr((sQ-Z$A~n1^KOY;N zy4>3vFtxrJJlwS<7o7yU1?toWT?}LpwD2eZ-;GZLmM(kl@6$06E&;RD4A%WtuHez^ z^3LD}1$F@8N#H`dyg%NDXanK~-EIP1G(!iPh!eau_yZGw%>?w#j|W7HdJ!=6b@e4d zg!HOlq2l5K=_8@ifC*&_-T<}+3_PI>BU_hO2M46mFhUqs=FWiN@LhIYM#Q7i%n>Xg z!vQWCSp_1y!~NMUfazk9P+Se03_ErmPmuWo_2530WC-g7>ElDRx&(d~|4t@2Blytn z@?!k`;cPd6Kwy~vlRyq-YxE|8i(wx(m1UTajH{@=?~u)byf45)TRh(*Ts&4Kfv|PQ*qnY4!JK>pmdW*cc%Xh)~>}0f-crk~T0kH59*pdK~2TV~3Nbtf240@NHBB z!}bhl_p5rd-Q`_j{5oJ3XnF@$81{8XQyRe`85V5rll2sWE{E>e!J+0SfAmWs{U<=> zTO#FWMd+swU8-|!?W?lEV52-_ChUcc)Eoe$NiG|7S%N_jTo*283SF z{`p6P_QLwT4Zg^*x;@g|^vKY7?^OoDIT6GQgkDv!?sz#sZrZ?kTHtva0Suywvm@}^ zbFjy&vEh?&Ya=Oh1HdPyyDk2pfPQNi{>@QOwz@g6A8%%Ia0rsY&6Dj-+|(n7hD%A= zAO2)VOCOjQfWR7<34OWyehlJyF^_0?wj1+0I^ygEoH6o^^d+_lWPbO9!T}qobxvpu z$~5^Y;@}VSLr&lh)ch_m3~adk%6JDDVfzaA1e!AcL1GMC`|Nv^_?g1^5mpCcy)}4M z4?OC-r7vIl*Hu3CC7|}hy<-BNvy#DuasPDEGZZu#|NB`u% zyYzs)4d%{o*qsT-57eI%lc-3D4o$ z^N0j7KB%^MRG=$L?NIC8Nw3$CRYLn9efF!cMd_m5C(p$JcE))PseoS_=etd-ICigP zVh?)^9Bo6|SyxQ2@o>lOGiu`yVkR3d6O^- z-qrmK%=~~Awp=Gd;MkFI;eYbN!|}0cN<`S2i?wUyUES+c(gu&TP50>{CC^Vaw122@ zPoDeZogpOW)YrogOwc6WHl|Dp8N+*Z!R{$k0<|W#^v7S~^DTqyH$*_JrgZ--f&(fm zM_8%J{8}t|o^N+jzt9e;hGs+vT@t)gUkeC(jA;OTi5pTnLua0}{oD_*$?LS0{uBlZ ziI1-oL+2<(!v2NJI1Kd7Z>AeZ5yT0F5%R~Q?MUQx_c3t^KIWxqZhIqc-G!Z=fIQlH zjrP`P^AFN2k4m1zQC>ZR#_0#A0O_1cmwDlk6-gnzJJ&OdP@vBHTE#ANX+ZL^ObH~O zX!*rMY5$DJpSphQRp!I%!pISBbZNV5aidj#TIGD?w(otAWc9@RH;vuGr{Q_T zZ;!WF92WfYiCb+vrE31>XOfZ;8F1%9w9z6UP8N1zD(LSo{IM?)OSzE!vy%7>gYn%l zCYv|OV8Xp=feLjR6z;ouFq#=E#<^b~%Ku6kYN{7X!XLOO=k5Wozi@48eRKQ2)Kur_mUsh^D-hs>Uj%Mbj-Xs zP2+M93!^kB>sZwJN=dKq}{z7pM zVqX@vg&Dh!HA;iRN!+wvb6S#ll4*XiUagKTG4bVY;znvI-f17jkoa_Nq)?gQ4234x z9wDCRum3RHkQ8R9_Qw2^-D`VSc*)y6;Ihz&7NCi#RY!l;tV>H!!g6e4#BRHAs*n|o z3MMD^j{xHpDK=V$Qlp9PDP-V0dE~cfAF4_@J}Vg0O?rFT)~A2McKDsm|B z-isaiyyu$98QahjvJ;X>-nXoIAQl(bMCTOAR^cKU%}$zx_YZ%Ua~mK_DI3Rw{*5?_ zOa|o_cm^d^is;`%~F#V3@w%wYgO zHGL=cr%%vY-W|*A?#(JNRlPSPB9MhN2h0Evaeg(q;86{0#jjfpp^~oSa)b;bO88oc zhah0sN{`4VIx`xT4V5{5zR9}ll*`RB8h!VRuSxglDxLjR*yy6s zyT9igBA=|M_X{^(VffPxys+M*SG32DV%wC2TRyukaFptNe!41Dlu{=oRADB`B#BP% zCyS6brsH=gqMC4CyNrTl%7LE4UuYQg`!v5aG3AqAHpn+|lHEV7Na~JQqA$CeO=t`; zXip#?HuDvv9g}y{h*7^Yp#Tho)TzJEz2Pgg)x7)^G%lRfSeZ89mTYsmiuj6CWC?7& zn=@E>pX(2irfX6S|M*qEJjyGF5I?{_QtEi5qb8*?zJxxVz+?p}*OUWux1D?q1dBJ( z3{JPre^{u7@&JA^H{2?C9^-)FWq!#87Wv(pljwELyOjFW2E!lTYvp`@Wq2O8^zVky z05pLw?M9l7Td_!QWPuZG%%=COdqyx&2xl+uzRaVEX-OV0F<7IPd4rmFu`D(?Z7Uia zd1auFMBo=yipW<1bzk8!B=64UW=_fjo(r_l9%Q8?y>~x3ximttRyW zWj0vKXM0eA@clq?LK|3`c0t499;Rt-mBKfwH?iFNDVY1P!7SM3N2OY%1F$G4JmUkwagGn|0>cH#`XH48tnrn`_@AZ4NCIlVFxHJUc zJ0X-Es$^DnC14*G`!a z!_eUZ9w!dspP1@qa3LnQUQ5fP0{64Md?0EbIA=P$l|3f$PipT$u@Aof4hCQsL}$5} z34p%LL!G~vVjUSiPgMKJ#xi;)4}|$021pFfc#Y^ym`JY~#-(f_^DOYF-cSomxEYcT z{UnJ6eT#f{9S*NXb-tmbIwap?M9(8M`VnM~aik{`@%W+q&q;9VUBh8_7_9O1f`mj; zd1QA#v}*frr4sdxYp;A~tXod);X)L)R`j~oR@j1Jg-9auvw`!-Yw+rURz8dQf)K9F zW6;q?6BRNy5Bh6PofEwoR0L?3#Jt(d&nm=nJEg0cDeak?Y{ev&(TSD#o1wgwCN-+W z(2?>#{`A8Sb{*PV`Eq)62Z!NAs=(NZrrS6fdwk#9Y? zk1DxlIH4>~K%975f?RMYINy|a`D;0T8RUrJRUgN3^Butev)1sGju~oJ851McJ(#U@ z+X?=JYmZ<|z(Cd*Q8gO6Ibwa%Tosl`eV;_m-(3c;D(h(}cYct_FzxtUfegKUt8PFy z(0Mtuz^^H#Xl7*i6nxyr11jA)Dt)ZT{l#S;xw@I(A_HfMaMHDS`h2m^C?J=&kil@x93zj&K}SrEx^j3fD*NLGW$d zZRunsRrGk~yH|1p7~kDCN?{JQX_s*?c}&xt9ts4L_GLQo+&J6kh#XlyI`G5F6|f84 z3)T1i=g6xZEN&d|_80NH2QPAS`Z2!0zrb*S%DMHoG{V(QD2E=ZFgT1+n8JX-yMsd% z1#&rD5rBdKS%(h~Po<&sNSTgLc#Ux1jTD^t4-fmEo@zj_J}r`46BL8vg@7dPQ4K~n z_r>Tbf5aFbVNC*SZrMog*}5lXN3{aJb)<6HaeAx6D-s1zY0Fk(^aZ{EI%l7xjQ^kg zMPBbU4C?6_3_ejiR0ycXqNew|P2e6K&9g6PYMh5|h!`8~6iP7Cj|}Sq2)%E&5+aj? z6OAc)2J2;UH5BbI9q%y;$ku;3FdjsP<#~h9qG|7zZXA?a(+Wg9tz63~A}WvT$(`(q zp%bWQr{Q=?0$hJr=7elSk9~EyU4GsBtgCHd$wccBEN8v2Y8_LHIjL?_E|^+>)FdI4 z!S?Mb>hJIHbh(8}&{8KWej8v387uS^C*7Q$D$sGagMhf*E((i7n<+ga)dd?%i?5cJ zNT(ne;DL@3MGRx*0dt`+67$gScg;OC zC(>tnz@PnsHrrKNp}H&THig$VikVH9#k3wryc7xp49PYzUq^0WH)xR1o-+2) z*u~1YQOV+fkc;dLv(MHFDmk1Y`HpeZmKDOC2hLnc%4O#VJ-~TrYW|#_a?Zop5aPE$n}%YL1nV zhH>6gBKx3`U53ZKr4spn59?927x&U&h+oS44!WyRKL2tuY8sfw!A$jMeo?HcPK7s= z@5!9M=|=hqg;{S&!Q?rt=)wWEDET~l*To*E z<*f^VRPs=5NY?b%r4XGmRx>d|1db&mG(uW(5IrhO>^>P^2=ObEpwA^kHhTy~Pu~1g zt_lG*VeX&-St-A?Jo2P%#dHKYNYyHuWTprGYM3o7`-&GlXWTV*S|5vd&xYHvso2(_ z5j`>`wjvo5JTmASC>tTBvV2yYTyyHY*J{UcZp4v4>7Wlzqa9M$a99#Q3&bJ(@@$I$&(0%LnnfZ9dJ zTImtu@qhHHAfG8f_O!3hj?2Uts4aoV51TCwq@Z^nz$QtLFB>$2|LNO^AedSqr47A|$B5GTf_pBS<}+6N z(~%D--4mddS-qV+#J2B3HkzBKrXGZA+1#95{-#<}puef8g%5kQGhqHc^S+d56~Dso z#tlJ~t2{n(RLC=K;P4)VDJUP3+=w%n;Fh#7BI0Ay%hU@YJ==-VDi7JKWrWAVH6wgk zv*dvx)ROC|?%SC|KY8dMPx+5$3i#cw%#5qINh zqq@Zj$%e;aTmw&(Ta#V)OkpKmHs^09M1J)ZaIy!}$E#sGoW?Vl-nhPv_;k&1dmKwR zU5U1pvY>J~MdTT!NnZ*I{8)X8(NJuUxW_poe(`+&=364_Foxo zi}yeHlYzI4u&n$_)g!eZ#=VFf2aE>*6DgKifjaUnGu}MB-&87o!rIjv`#6|2rR0SN z7AdabS_|K+j&bDgl;%la>7ZWvtizy!cP%qz#@x0fB(`0ZMR(FqX}_@C8%7)BN$ey3 z=&xOkuo^~gTzRnmW0t4d*`^&}roeEYuFm=)K4mgEok9ZR*su^tDPs92y}%;j1UrW2 z&Hu~)UF?hO7iOWd(^!bMQn}YDl15~)dsRRFuhXL|jx-z_aiPpMVv*0s53)lEXwG#K z{d~mFrVQsGqQ1`VPHy&a*~*=1B}UC9UeB87?>=vorSxQnO0qYv@<{2^_CG60STG%j zb&DT3zN-cG`bDO5m;si>-t80I)`TpbP9_5(@?7_AO_l!gI<)oSvWja1H3~+wAybsX z!B!k7xtw>71cZ!=6Wy};-5*5QtUUxb>@N*1o<}k*y?xGhM~|Iz`Z_Kx6(i)S2y02v zQbGjRpee*KJ}rtBMZw2gG&M4$5HNsE1df+}nR@KS^(`_8k$Jg$emJs`ug#k!mwLs^ zP`MvcS+aMXl!k%^h@cYBFyV{wl(-oM`R#|%x^yfi6zKewQbjvPT?196dMT%{f1y~z zmvffu5}ZlTA< zHuK`YR^q|7(7d!=8EqyZs*9X1Qj2`hm0Ai~(Ou5n-B9Fs#WTQmRL{Z)@(Rfej)7VB z+w8?i-l{Y=2(*AyopFTPS;wdh*GI!dg$-kOm@68oTV_8-#9cFZ2bxRLeqQI=&rxDG z$(r)JX6!g^O$gBh8s`Njq$q@d6=*NamrPo*0Z%^#){BUTQB&!k@qls zsK%Qpo}=6YkuErz@mB4bR|UR@gVSkhW3m)d)Yt&dVJiATtVZKIx@7FhMMM>FUPS@7Hmab85Lc5y<|TDU9tcBf{PpMLC2JC)0KFnq~n zS09$?OC;n6qzBKWaUz{x@}ZFhRaLkWj~;W1K5HJlGw`0iry8hRbiMCkgXx@Y%xmy$ ziG#2={z?zP#t?1P>XtBhh1Jx=n4q#y9>a03s|v_eDRO1T5p`Sn;wDnz5`|!w2f?xZ z5k??yh#RrX5B$BwSMiL-9gBb}WGJGuYW&e0@7p!)6K5y6tK-xeF}O-~VpLPYSnoL} z&0~)>q=04rTx{E1rGpPJM@h-+pd~TsVB{NS7M(Z+Je^|OK?qoty(gIBpC4bjSHf(% zTvF>D&f80B#rd+)6}Y?W=4t{gUk~`L+`H~1{O^xQi7gs8@~|Ef|LEH*;6`j5BUO;+ zThIR_s=bjKn@mai&q-+i>@#dZCC?bwK#LKD7}w5gUMJ3M-__Ats4j18C>jPGr%q^? zxG(O?z>8%{X%SJgU2PT7phR2f;zZx0WuVxw|E3A#BB=6Q>?n!6UW?Ev&XtH2X$wpv z8RMq-MrzmdxJ~`pW{i^3){xv|<)tOn$1|ode<-ZVKYEUgOf9L6gh-=55|ZWf;nOoV zKQtHf4Z@2ntQoLnePNUFHEFC|6js=9@hy=fFfub%hD^;(e@X9WW|gIh2ek_F8j3i- zk{^Y~L}>7lsbmJvR`OQ5@Bi-Z?TTAXntZjuU3$jRrnwi{uYm_EUrESEZqdW;HFx6? zttWnwBl|uHPay7@1(PV3JNsx|iW*oBq2R4`)~+3P^8mvwd`s#!88tTd0yKJ>n9*m& zMwYQ2`~f6j^93HE5&*RY1uV%nr>+jJ`lRUr!#n_N^4T1isS>T?#KhHITYXoUc zu^4JUzB1PpGG2C_)v{0Der5`pl&~~_9`JhYXq*-iJa)b0kc#iZK6)jBHQ5T4jhqyf zTz0QtpS;4aVGozU5eDfK+9&gNnD3hB4KBA_@GFEhQM^AjOAskhwdG zJ3|u@M{C8w!z*ySa=)9RZwdSvN@n)&@B~+72EHLEaI=(ambwJQEPQMX!|0*_W){Z~ zke{FP|K-wluNIe&^g?Ej%x*1s6V;^k!!b1Kcq`m~oRswD1Bg^ATw#hy2cQ&6Wdk^LLsE@;lgx7)yi5WFC8Y zg2n(?8jQ~1nTx_ZBp&bM(1rn^I@QO_HRZm%O1gP7)ntL%6Yq+5UJyn&d z?PfD*% z;?pkQwo6eMDny}DwXC=PJ3ivt!zmdCd@3N_AWo)0nKH0lqoSgD^}hsbjvqx|b=eyk zgb~gb+==E(r~RO?>yg#+oZ4r(DA|DT|BJD6Y7Q+}&}eMiwr$(ClM~yvZ96%!ZQHhO z+nH1IGBZ{8VgA8>>aObjt+h^_702&EJW(lNELF!H8eTTea<{(SI8-yIEUJ1PkhhwS z!`BvzS*T{$pm4UTx1+U^)~e_~?0fHV@wv@-%g&S(HuKc#L{)1lo9s%Lhn z@czuCj5R%OtC&JTW!-TXx0hm5jDcl}+e0pU(Ct8-v{ zt5C-(6PEH;?@UB28>KQ^<4TXO)2agtmG8*7mk+sH_l${R6HX?gB<8BVLW6$oq9oiE zt8=IK`ELzbhqUJEJgeUo#;glS05nCG1cGvT>T8iTu8Nx$X|-=2kDBjm_jdG&*(#v8 zCeWc;ogvH4XI8F3&^O(c9g+GyD8~?tW8&_gVicEJWl+3SPWf`>L2mhW2d>b+DO{m| z#06wa7^^s~EFJR1$IjO{N`}H|pF=xiG*XkdA|@Ma>TH+<0Te^s*o!x;V z!rx>mZ6wg(E4aOjQs|kF2+^*$gmXIAGMRbfp}cuIIAp-Mz(p!UNBJf*DA8~gIGcro zDA5QyMG{_=_}c0?sqeUyQ89DE<<^ps?ucn#CvQba*;Lfwh?_ymY+`(J+l*UbBDEEi zxp{Ag+*+_WdFBm-V?&02e7MUCyx(|Y1N!cB%QGvO;O4ALW5p#wU|1j*nB33BX@UxQi4@jMC{ntv+&b2vfVTIF{$AN{*o3YQ6xH12C< znmuQv-T2se!|xz&uw`kc5W>E9P~F~rF{;_92tg#84p=g^SfPQ)?M_qR&vsNvDKf1G#P$cypTPQE7=xLQ;Dkm4P= zL{l3J_OlXMXe?e9${&|GUAd>5-PD{;KV|?-Fe=BPw$ZR)r)ktDP9Vvycft)#2l2QQ_PuIvlS4xtmJn_?FC{dcf=2_GL3rx6DY=SSb! zhE6;c91QE*k{}e3h7bLTzsGw!|CdtA_n8jT>?}bS4EaYQSd9eRic_p`}e^pk*5%R0ly&Ux- zC^z=lg?pvsl5z|D?3#rR3xDSX2$~WE*fME~z`@xmDbpOiXWz2$imWuso$It4R?W^s z+r8gEy{s0M4J#Gi#Qt{TA^)FX!zW^3Yz~?wJ$&~wg$y1A-{cl@N2Qo#DgidglMuh> z!qvbCd4Sn&gd!{TS%ijYpwwKSps`rph!10d3KN|q;?nYsjG1SH76$g%n@_L1rGPywnM2;V_oHyUc zbG%4m(TNpyms1+;+zn&EnU!Hl6T~h~AS@SbTw$GqQ|t*nBjY+wwX%2wczuE{Hg1DA zCfIya9w6O8#w0U2s%D^`f)3 zIp%;RhoCB3z1y$Qz9lUF8qvT>Y||t4rLHcgM*IhOhre<@n76832&KXX7KB4^rsG^~ z6|ed>(_~}PhSSvfKKtuKYB@xSOHS>+Yxbjl8?TUgoskU)@v49*zYHgunT&ocl*-%= zz<4>-5xjrL>(MbZ%aRz{VftNy)uhFIS^LroP~IZE1GM){Y}D&YgYC%EQAsRh@amoF zlXa=G&A|QASnI(1a$%4Jn)3L3w@q296mpwo1iL3iH&+VFz*Kh?yfsS&-g!7H>5kFk zm7&a9^!_06tW%DHdQW{ha!YRpxWzz-*QfT9yqCLgyDx)tb?9;^HG_+yteWhg7y{s_jR287{aOs<{v>R^vR!9&y-Rb$AdyZKh2;qygx*pGa)DT&?G+HPRGRIBgkKnmZpTXKm@SM&){ zK0r}mEay5gWE1qmK1-wWg?0%k zI0TqTG4JEii|70FqyyQl`1c#&!uUHzdQ?gZwJxc}4bTXoCyLy4Zr>yB@1z6Z&X&ya z6@(GprmDcrlSh+yx7*rk0#WvIUTY6((W$hBNgFp@ZQz&L3-_^TgW-!N4QUOqXaKf(LnE~@e1Ilr0Dw?}dRIDB6-Kn!pJYMJXow$( zyE-V_WWa)1EU!IgYq9iP7nzva@bnwar`v={Hp6Rkh{f3#tkTX}jd>Us zA&@5*=C<;&c!yX;#Xer+5`K9$yWaXyOORpwh&nCsf&<|?YG-`lyz6ea1OjUK&+maPbfPq^t%Ut+w`x!?wzq|&v zSZu{D%Z|!PEeUVr;B2XrPzgCXht*Nml6@eF0qgp=^u8#g>S7yChGDMAA&;wAKr!WO zJ#!$8KGxkxw_y%cOtLyrtu{6i3tL5aU<}RN`$S`Z62FfRc9!XwQErpMI~0wM)HK;1 zi4m)Ul_~k-rhW7B47fZ%$xD7uh#e5{vHdc)GElmiS1&(11M!)6?;+9)vc2u68a*GP zfT|WnDqLoSkfffpxLwrNSnzvC+|RZ_`n;2DAhfb^Uu0tG*{Jm3EF1b^8?0`fPKm^M zAqU1aR60s=n6hz3h4zqoY3T9jwGA!bq_+P}&)MSA6WEcbpx;9|DZg^Xk8rE2y;lZf zb2%Yx4ssR?Y3iMeeo3(naXzeDQb~Q(H@psO99*Lw8*|;vh4*(~hm9VCuwfpTIe`G`FEQ5H-oxEji1krt-FL9|1MddkLTt_? zUh}b&;9BXah}n3;p*>`adooqPMWecJ$Zl2`N4L}l0TxP$HY}eInw_jpFFa|ML!muu z&T|erwk;Npg~>tK@|pyI{Ir!gCSBJcmsczS*<$tikuA#tj;NXWm0_XFI6jW$z+JU8 zRU}r{-brW9scvQNa0-QdSPJwCod$rG-wEy zTFkI~oe_48vK%KNu~NdFL&FjAJ=)X2TAhyFj;462aW$n&(9b1!;_@E%=91RA2o$&Q zX=Yl)-|1cO-FD=fEyEOpEph@@H>DahUcGm&2CN+9)U?JlEk6l;2R}SihZ0>d=tV=C zEj=MvgpiYYkf{uGTp_6C$?vIIjXlFz8D{Fcg-TT?%sd6f=6N==2N9J^6`D?@^}}6K z3QMZjjMv{>$LG7{`o!KimnF%MkhdE*N-YxT{73fHTCLuXU6dRCJI_%ri z;%e^lmwJvK7=v8i)&xNO8*3aW!TgRbLazz@De2f6ySMehh>v?wjR|m}j|1-46+7~` z`DV|9lLWG|N==QwPCHVca(d#^3^dEAw+2y1?LRQo3Gl|ejw!4z=iNt3?(8UAZ(C7i z=LlPcPKJE8sEzw02RIBx`2@k&3AhmEcIvo0c{?OOQJJQsb!20Aj|UA8?DKVbpBcPZ zt@?^{pa<&-QXJrL63jP~dLz!DYE6$Z%+XGf4&m0#x6FbN$ywH}AyfLODR7sH1WP`g z0ms{ON0y}gaP*yscv9T!3+v&M1hPF(t3tsB^;!q6U^qWarv@olJ$J2>g+WJJR&a9L zKRO$1uhi8RthQ%9j``V9$%ocj=JTk(e?4J)q)JN+4wWa6PbpOxeYC;<-fl=7^8Q;A z9O_z;>GQ2r_5~eo&1w;;aOWkB9B3-KK%~wkf`cY}7;Cb5{liz!Q?UfJaKs4i=SaY8QGEYnTmHk54?T60aGc}Cz#@#DSmBEWE{h6 zooIbC+z^fj^V#5hlyuyqc5l|)>~_UrK1-IRy;dm+pv3HeXz4oo5`|ssgH;hI2V(|5 zPm;bLAU|z~<-ZKYX^UPw;@cu>vK|MLam~>{iP-#Nn5tDO)~OYMflm`uR_S`%-d z3Fx^~qMx&KU-cbcFL6Lg3BhNsNB+BBY)%4~O($W7Gt>wtc2ee?RVa6uiRFMG&h&jO ziQYdGS&B7X(Y9}p5b}mHX)@#Vl>c>vR|(l@USGZ*A>MWdE}qVJio+-Ay{OJeJT-@N z3m}Kh&rPq&Tl?!vEKBWZ&*s&?_>JnISN;PJ!NT~TcnCIjhX2JwFfjj5f9n765R5Dg zjQ?$j`+x8dEuacI+Gupqps)G;SZ;2udssSwEOP>XU}HML+*Sz)+dx_o2-<}0-NFDM z(Vh~vxS8Efek*q>m6uPwCs#LiHekQj%hXAqc7qi-*Sn_xAQo z5BK(jii?+lI@bbzNX3hn0R?mV5x@)lG$e!t1=7sct@0-u3!sJo^Uwa-r;fnvA0Qnb zpdIW1+Bi5seoY_(paAuNxBJilP}%&6h5(PErKn*Yo`M6bt8{Z8zb=vc3}ztqP*9G{ z-Vfp8o4^J8PXxgIq2`9MjDNG|am>Nzg42Tp>2iNj0|kdRhKCiybGEm)b70MHr@#WV zA{ZM0w)*K-0AS;pAuhlg0KRN7^P!r+zqhflsb~czv97+-gpiHS58#3W0cL@?>o~{y z-`9ti`+-0}dCb7gsVIP#a0KD}FsXk{`hecNH~{3>X8giFH$UA7>IU)6^4mFwb`a0@ zAYJQ#Gy<;$09Z9m*wEq8(E#T94_XQ5W-uSF;GKa3ul-GD!ThAafs9Fa0sLoif41`) zIZ>|84yI0ET0XalKW`ak|D-z9#fPqK2I1&rEBdXzV!?oB@Xu~1ecui?yZE&eE&cndM_c>;buezI*;E-|s@CBq19Bvbh1K2UPXJ zmHkHi(12@1oPgaqJ_5giyaV+7;)>!z{B%b8xl?gy2mu88p?>ld`=MUFumfZK z=)sHi`Hd=t@I0b{7`(wx?>gQ&rt|;W|L`Y$$4&m?kNSzf_bz<-Q75`IH-7##d;3R1 z`~}|#y5{+9aX+c9oP31)hupLG@B7KR2>Q|1K#c)iS^oBFfuip{(n)Y>tbcpO8<=U< zfsYB{UK!bbhhh6gH2d9V;I07{!8w5a_GkiBW#i!d{`JzMbJ{%J9DL76^i#<{-G0A~ zW`a9Gh}xAN8J+|O5GoLmSBW(vbGUy1>f+36od-I)4;un-WdjeNY=qux=hpWp1&RFl zlmKl5yvpnq^@}Iq_s4y+8=?j$BE?;l-wR zQ%+_Pm2kQ$<1v{wGdzvOG9gv{BGElb|b%O_i7b$2TnJnMFebw zgns>lSeXS6>FZJ|q#2Ji6w%s@}mbvf@XAl{+J31#PP|H}+pD}LXf(vxQgfnPWwhrP|c)Q)$(GcjK z_LpqxKYHjMwd@7&!sqw%@rJgz*= zTV7Kpz1@aIM5$!P`v!b9)7Qu3xzp`69}`b$rJ4=0FkvP(>BI&F4@5PuN!dytx5aal zz7T_)0gJim-P{(yTf5MIk^F?@(zr|}svESoUg zavm`%;Ob(lE#j9+ziu!XUI36q!L=Hex`?Gq#W!8&bllSK(nDI|ZYT9kYGSh`h1I8b z4I6qyhN6aTV;l}<@x8Y7Q>K(qlEHtTU%U=>`W{+bW#ipq~C=)<@kI@U}57W0-IhK~hVvdvHbRyx?@(;nlEmwNbUukE# zKjPV~mZaCu9NyelGC%j}^O)6y zj$+(=TyK|W+`2io@nLt!cw^&8>3$*T=F!^vBp|L^r*_|uH3@);Bl}yDQmBUoG3(h|90l%k!;W$W#wCGzm)c+)y5=XRR+q4w2dBbUt^}+#58&EA~8|n2XRXh#=N_FQ8-w`Pc&hsY0Mc+r)WGlWm>h;-ZR1 znBsFQA#2M?2P*^F)7pM{P-VtE0^-T|1StKP_R|1jEw^&MO<(gY>FBq$4hlFawIzyL3ZwkqfxJUwt{|}*u`q_e zm3F(6YW&fpuMz2wBHR18?7Y2!aZlZms+KL(9^?%&X4_d0Q0l{SFMj3XmP>gvv3#Xw z;Mupl1?Arpyv67Zn;<|B;Wa`p)mMco={NkE8TNL*@0cF z*8tYV{|?746kCC_clAT44k+0m7E?*Sn^a$xqtZGdBNEttZkHYA6Y0izys`^u19Gx`(FNRFd-Vd|$T3B5$1^JR}2bUD? zQ8Q_jLL-)w0Tp&vd3cf7y5`T>a@y|hw_s?D;$Dz(OBAKk2F8*7J_BZZ1rjmA8uYAl z+QR94FVdI_t7Uy@3|gH3(AY_#faP^E!z+f|%n)GS=@V~$Gg-ctHN6OGuReBhT4$UQ zfo%?cCAomYbn$%rCizJ;`UK!_<8Zy*&%Lc4fCa56d(P5%v!mVTsmARw@}gE(5g_!d zF;ZST0u1LcIsHq?m5;{zj@Nw_7Fx znjDH?{NiLAn-r|B1Q6PU>Z%(}gKIeNiF3Xr5O3lE6-)popY)RUNP5VFh-9gV0XqYQvdh7>Cg_Tht4>*VKL@RGRJ!nqu^_>Mo+jXx>^w2m7ND z56Oc@>0cjhEuo4?;rGqVi4_Z0=E%r}FUutBr2|`g2}{xy_Usyk;{*bUM#q!2E|7cR z@!}V75gG1ZxfshBzED?-1c|<oE--S3-dg%7hX(I0QA~h(aIxZerwVxu~ zg=sjB5dzHkWFqEl6lZO!^j6jhl&oTWm1X?^lV)QT!_EW38Mw^ns-v^X|1HV=D!Plr&cMKh{Cs!SP8sRMvwcZImZ=_cUl=*cA>WVp8cqaN&mlSa) z+b6C911a_9}rr!yI^U!EDcx?nG_xsT#=|1=};wMx^k z4!A=$8YGwLq11_Yd+bJ1Izy(xZM2I=29(=-hlgW}1 z=be0VD~}A+rlckDiZ}_;6G8U4742aZY@6?4$&OK}Sgdzi7g6ONubBstN8m~JAEtYFI+>>U=ii0q_Z|gOU!IW{}BsVkmHbF zW9*|DiUE(vd;zS3SbLdSM%2C%w>d%bZttxTfb<j-9?hpu1r}?0v~=e9`e>9F8w1G_T+-=ruR6jf&^?8~b~? ziCHGBP*y=CI=KI5=`AigjAvbHGg7Om1D(I8Y~8u2xwk?~d&{Iod;zpOGsB)vHDg{f z%7~^@QvQ3rIaZ~_y{6WQFPl`sZ)<%0+235Sx@=04;76(0SKy0O)h<=@ek_YlW?_+@ zHuXdnS-E}g5p_+c+UCzV{JUb~ZoSXB$CVOUq8o{?s#|&)WmWSXvRO={*C;lzyGMhT zfOrHC1C8XvrZ|PI!#nCKnc1wJ&`Akb?Io*|RO^|OeuBFPaw|>-t9Le2t17$j%O!Mh zhWPPV?fZt0GRuW%LotJ@Bxc~hY#C0mq8Rh=Ljq6PQ97@kK2*t_J9E4o8Lnb}CEed& zJ3Mf1MqSyNojoB)L`X1THujXnQ zTeg_pVI`a569IaEes_KaHBC{;Hz`xDWWDsOdt7or0&8j(ud%$`H}biBc!O4PEhbfm z;om4KzbP7l%PbM9W$Z*_w^7C{ny(^EE8dw)F2j$>#0d1~5m7k}qC=Qc{%^ZZ_hYVk zApxK@vim;9KP*U4$S6@Prk#$oRCbOGyX461Ww9Gbf`SxG)?K7V7kah|87_C3s9vGs z+CSvW<4HY~Hgxy+Y74vfJ0Pitirj@C7t{olm|))*ux9T}F0>iG6$N}k0Y$dZXzeS@ zf!mT)(W4stOt5a4%FyyEx06lS5uFPUrk;}pA#74|+yu>SNu`-#delFG#GKO!Z|6sf z?^S%7wLM^e9G+J%jq|AvVlfyH&_6QF=q$tn-_nND8k%a3cv~&?y13c~SFH6Ad}pns zVNb}M6kQm$lAPWX^#TFb|C~Gpcl)RaoFvxCm^42a#woUR$rqb0tje<*$^u+W2EY}? z9yDedHhdi9bj#=1_-L58dZni|lk_sR006I&@(Z!NGeG)^-sA>A^}4wzI1YjlNS|A2 z8kQ0h&=IY?A($N!iX&uto@xT*E)HPc~5Nn zPBKQG3!H9I;^TUcFt+H|^g4siv-LHny^(L%ZxS-(M=6MlA*zHqR&yND_qw?Js^DFM zM~DGVW>YVXfb3j(wtL>~#*-`Tu#hY1M{cz~AeYyk(s>-VkX*vv3B3xtb=Wmqv}3aB z27bTO|2X#Cf|&4?{6{@X0Tu1F7sh6nkO#HKR~ssTs_NQ@k0b3uf;G1XPP^rZx1s`X zDNe(BV|Cu?%}Kyx$R!35p9+}uo9~v@7~WW}_C7)O9=s&T+$C<$owhHCX0DQ?;7h4* zQTY1xoxKK&XX#p-t_A!h+ws|gZMCaTZ+AjvEGd>J+oua~!lV;k+kHe~!}RD3`Kg9=7Q+ej@F7HPYown zf8a^wI1^Nu)S8lC4;3QjENhl6NC{e9a+YDyir)sE{~hWLg%ZQ2&CZRLCw2GC7?yOX z$$fzhpZ@RQlm2;;b=M8eT7B13v%ABj@ZQfRpJ^)c15vSb&Do*Ss}a_Rec~7-7yq4T zVwCb<$b;WJK`(9~ru9)oP)zY2zmI{+lsw30EuqwHh9>`b&N@Z-$k~6|ZmNeMwL&DH zCf7SYQbonV0adFP56mzQxn;;UL|a;KiwxX7XF@sH+f`fz81bq$TE&{q*eJ3$$dIPG zPcw1Br4dr~9%X&fWu98v&kCg4W_q0(maS5;_JAeejYsXWSxDUK*t1LZD7fh5EG!-U5VZy6$`gzhTbweFO$H)U=6GcXCFoUC?WMKi6m26zC2nP zUX(iprw5&*{I|06jebpXW_Wg{sMJw^%DXYia3Mi2r$8(P?4Bl&(uC@SOWGieH${5I zq;A09iqK_d}>f?maP4q1fu#jaGt2Z;( z5gRX!+E!oXbYakr3MykW*#R9?)3Km}j19s;T6z?^(h$B~G2#swW=S#$Jpu#H~Tv8 zf+?@7_GO0-9dX=|yGPGfj~L@Vvl{}rT@*WnQyw?{tqzEo14vYd)Dog-f(_cyVhTg5 z^qwc3B5Qh;6Aa_L1j#4on~nCx&?E}@hj*r!Kg6>@#VCmmIV0f7KwqtB<5PIL4c?YI^LqmG-Vt(i@Q z5}cvK)+Lwfk7=r{CT&Qs#JPs4&~ZYAP*6QNHvc3hm}U?6d4H)imFn%2c}=NuAL+!D zI~P?na1@gPZ0Yf}7bGa=2N075oZYY~B3aDE<15P5Rt3*8J=zUzVJXb`evpp6RyWyp zYY2I@;S@hqi5mV{ffW?aq30=y!OYQ_I>p1<0e5Tm{GvccqYe}Pfa^P^FvjZDd111P z_>RmUYsyD*Mzs}9T~HR#(3x);3|aFcBk0?&FJnlE(bREIgAI}450Nq^XH=3Qc`YA{ z#|b`aT)gh+hJYT30^qpLVc^;@ks$=Aw;tWtJ6@u=w=qKBVUEFe7X^w{4%y*OZ3VLO zR!F-<6k8DkM^Vd3QDeolk21Mc56BSi`B!S!y_&rFwu+;{B5)JLj|h_o% zojmGV6+s5%#CKgvtAAerD<5rq@P&Ug6TKSM=I2P%5JWkO^!f`zn{aCdH$|qnI$(o{ zj#)YbiNjUzFY*B+N@i7C`LwmVk0FMC$^^%9 z&Yd`s^R)qaicG%GrO<1sqbF|(?Ea(~;BDf~?trWn273#=y9K6CxCG+1Sp(5VU}|6EvU_=c5Y?fab7u>uQQvdz;VFN))jVH;td#iPJbEqDOcD~@MK z&Dt7ZBpUG%CHq}=P?6(TOsU;L8mjSEG^>eQez)Nypl!=`((sTxs`gq->H{AV-zO~Zy|5c;N|D{ehN?= zX(di$LT5xn{^9ud@9amgKF~S!(wAL&rz4t6%8K1AK@$<3g306*31~EqfUT=Tkmt<( zI19*cL3+aTd+nqWdH80LB0X6UTdED?k<|-)jNaGE?+w`X%b@6gbu^7ZBlQ>t$Ervf-43(!@u!YW0-3ky*!x824R=5$$v0mMAy$PT9FO3@dr zPaqR+{nCA@dZ)LWVJ)d~+HfSVwck6@MpYzd*F=BWJ(0Ax{$@c7*d{G>PzgpFkL>`f zDn@+R&&d(a_8W6RAct3ABif?j%xv}_eFa^R&pA0i4EUpeHPF7C zJb@VgtxhbF4fkUaA4hZ+1i(%tIOdYH8UPtxV+ku%Z{3&sfZ`vlF^s$25ojk^28;+A=-KjB-209Y_5bDJ%P(a528 z&%-h1rg<-KS|}-CyYvMGAb9x@#Gm_7cU1Z)!Amq8vKQ2F2dmmPYoC51gkk5C5V^zO z@y()SU3i*42&DO1!sCn+b!v$S&Pl_3g9QRy^=}T{ZLGwHP7$78O8eFlVBGvhf8wfMH!Q%h3QzNm*{vWl3STZTs&fN@ zMIJ?MYjJv`#r1gPTY;M44d?YNh+1(o{0F7>+a*U%E9D(n7Ynfnvec!Z7+5QxR`9fCG&PC zXAB093))845a%!yE+Tdv6++`^{ypZ)WRwzN4WZ_oXrPrQ*3V-zxiA}OT;wpNzRAvt zrQe57Nmo&xOm8jTxuI$<(~p#r6MBq1>hO1-8uAmqD!v)D zaKm;Qlf}L;@_^EoWEp{)lp#hXg{_e}3p>|Jx@vATTi2WUCibT=q^P?LL#BUMx)DD` zM4|irkx>MGpUaB<4t%pv7i;rR4$d!4d{^n_xNO$S;{A0tPowWdW*l2m5o#}$(Q66g z-lrQiMcz{?<>$BUTQ%>s*AyY4%NuwEvlKZuSPhWeOd!(6-{`Yo zt#5moaTka{JBI7={^bge6h#A$1ZkHOITR8+?k|O922RI24xl%(cU^L5O`vZ!E0u?; z_2KV9GFqP{rbo;!gl1K2`(l*&bqR{bV6JZ0e}K$+MZ_D*VK><&#d#ebw{0jMuYr<)Fg@${0*uaAjk?ygI6 z*~)@MGLU+?MdlHv*|ao{2%V?8f19f=qapoJTJug`QChgF37U(?uQ#8}6P!Xm8uHRp z|L%C~W*V0b+P55JA0NP@`HC=LC9RK9o_)OUa{AS;6u|Af7i`!Up|J%vEoUF2OshNU zp>3y{EKRq#4{lhq1?FYwDx@h|ebK2?`)?8I)e*VUZQkO7r)#avYEE{4o3SC@TgH00 zY5Nk6Lo;6yd5AFL2c1-P8$2CmqWa2b63ye3w?Ow$Sc`2kM=|37zh4JNYWAN)@EN|M z#t&?##%8gg8J5XGdDF!}`R#L9NmHs--MGblvpKG|+0?3`AEjK@$f?q9Q)wLSX97hS z@3u~5T>q<}3rg0Vy zIq_AeR#8Y7=D;lp%1kbsTUz*QJLiBsRcOtd)E~c3+e0Q(uMBg8 zn~0#G%qYXCIcK|keF3Qq8(#*VeYQ_`lkZBb@r)sk#~Lr@ysKis0$F zr7>q>yN{N!1!QNWsf{AW*}GC(Wlgq1OCoWehh{`G}%0}A=|%%)eW;q zKurgqg5KEpkVPw=5S8tb#?`&Llot$x9x2uK#vCL0lK~nDKBEpSOr0X?;2fF zafg#Eu*f=s6mGnyyAADLXAo;}l(#-g&#)RJWo8{0qN$-WBp2SkOksBT#i4MBJ_qj0ys-$ME#nO~m=fb3%iZbG&dy+FS$8|cs_DHq zF+1n-$6%S}&r5mfegi_0hVu0#=?5`vkHn z#w$zWuPbK9E+-{C6W~KKB`~S_-mdnl6q+ge*e^9dAHta-bSW4$&LhyvxGBlJl zmcUm!V%p<}Tmf&OIA-3laHRG=?p$U05L|@c^*3=UqMte7VcAEN<}wkIqO;gb*^ZQ9 zl)8^fOA$VsW80ZW3HX2=Z0il5JZ9ODh;r>`n0MAGObB1F$@Bu25^3TfU2w(*{RTY~ zjfrL6g;YLx+}$Nq4r!!-GTO%!ar11b-6iKoHHjT^+_dz8koJ__j-jV{-M(U2Gz1>Z z1Afd-JclLbZ$f@iH9<8*cIb<Syd6p&7m&`t$F(lq%QywkPkt%DRE7eOnDb|vD}ZP0XS2JO5SZkadgPAI_-GdGe3 ztEB+gGwXf+*FxKNZCgnb;%H}Ca1kFLHpWV;NKth;)kBKnZfLoD^F-%T5X?T>POO(n zUWRrQ72d}6kyan`ji+iT2Oxx$4K;VnW_%tS=%j5LeC*waUW&GO@V#tZHF@F8+~yN6 z#`s1fRV+V0-K(!(1VgA#s(dPF>TH1-#*FHli(XUpNZK_~LV!}<4aE3}$t8>fkPPcb zb^%y@;jo(^1RYVHn|;flVYG`YF1ir9?R)OQ(F#V6@0pKd7f zHr#a=rXk5;T;fA=qS&Rld`WO`a|*sb*2cLo$&FvoAERu+p8NCW%Gl2&6|qMXa-kVh zc_K1T0U98e>2R3KNr=A@p-8kO^1{(V-doD^6QGMjWYI+O$<#9NgA`>D0X9!MH7H6q zsi*KDiB718=qGU*9MDE zw&r+$F#MW?J3xr_OSvSY(NCo=@FTpag}x%{@K1K~N?YYRA=k}IFQqm6ZmoZh?i*K# zO5duAMl&HWP_z~&o>z)q8hE36b-Acab4#nY?jn)A$2B94x~|6sx?p+zyo$QGvjn_n z@~I$UEA`G@2j0)!z6R--ibfke^mpm%tA{EVj-)Yt%gj>bPDHvuKGpwWc83P<%@oZL zRFZ|rjp``x6Fny(Jz*X5*t!(D+)h`f<{w3zFyiYO7HKFmf`s*bt?yQiFxDiKTOdze z1MU<)&!F+(a*90H=pz|Afx+D?)BH7#sRrl6FMm>)P*8Z0)?$??qI{=(o0bx70>2%- zETM>yaudXy6Yd{=%Ni>P*Q}<>{)@45iV-DXw`|+CZJVcU+qP}nw(UM`+qP}n<~^C@ zpUh+?x%aX1)nh$WcJ^LN8l#?o*Y1aZPd@qkiNnQSHCPJ>@l}3!-^4zDdw@L}({Rf9 zUb+i)*s3iMoo7Y@CJt8C|2+L8!ZWk6 z{cmCR|J8tIWnyRhpEjUdL6uWB(b%Nj+`_FpIzi9lZG{07)|?y9|DoYiZ*G#4;VjM* zlW*+2X4=7TzkeBf>^Q(4rgEKloT|~Om`GK~5QVIK@{5~M!y{rco?-c=b!B2=aQh}E z`llu)VueLYOraV8e#ByhO8}c1*_&HDAHzb@apmDbQX?({`a&O8Q~@x-p#iYL{bN31 zv1hSWRROrEsdxQgs;_qdhMsX`U;!Vd05Gkn^Lda`(wk$Vaw_T}A+k^TdV$Pg&j75w zz5hh}wF3*&1h|%hd8z_<@WeyTA!X0=&jRIJ+UP@pw125VXaXW5jGe$jMVE(WzHP*F)eO_{2WN4n92f_YO>A(|E7Q)N{ zyS>Tzy@0uvvJrThdMQQi@-%$G0pm3Wrxc_&mypgu8OJ?!@;WGS=L5Rm(9!(j)U>BG zC#7uq#V1sx6wKeU!Qfh}FI7w1;QB8d{I2Lz%o&0%#=-V|eD3!4p8I2(n%kJ{KN$Y3A~uR!NREqF zFn%pQ^hzoySef}_BV+qVigU$w=gw;-F@rOxJ&+0 zuHEB<&HXguIs5;{mgvKt&?4}E3Od=S(y0R9!MFUHHT)hw{Epu5D*V*4{O(4Q{A+&y zEG+)m-2Kj9YGi7*eHj6sR0BhF0Y9wl$<%%5Exz{kqO0MVn_uX^_i9?iv-8i+$j*XBpiYsv($V>2W4mL+2F&;+VDt@Go4^8f0`zTr z07O?^$NS<_vZMQp9JQX=4Z-Ro`Uw01K&wX|g4Rd$6YvH=i||8)r}h_l0Id&be+yg# zq`B2a0QVR901arI>>;psZAS;0q5BQ&TSwJJ;OIQ)4M)$`IsbR0?)`U6`FE`O2;=~y zv80F4j{1NGGV}ZQ?mO>S)LS1{w;v*S8xxNd_MPlk&)QEj;OI&tI|C~#Lo>5|-IvUG`X<9}1`y_)Oc95=jKjO0&r z9KKd=zZ;%A5I@J!yCFofD}tz3qa$`?g)pU6b-E&*kjfV z4L$NcKweEjbI5QWYmgla+Mbkr9q3(eqT}z%CYOJ0h+mQaCGg_9;Os*j#U3PPw=kd< zMh4dp;!Eqs#{O)RKJp@7UJ?aMCG9XH(9BIMTIPN4g z=^>va5Fabe3cW~>k>>CIFqkiyy0z}o9uC{yE#Ti@LlE*!zJ=ctVDL5&hV%a0AN*zDcty90Nb z(BdO-@8EL-M!_8$eg*+?2KP+@`Z#|-+8WsFT0R@S84z)P{r3WMe$@5s=@LIQ(x-vI{xc#ieUjrrZ_?V9lCGtU877|d+=@9tKO^j?=r z2Cqd}ctz(RH~*@gfew7qLJE%RnCLMEY&yku)p;b;WaQLsvR36?iOj~FWV%cXK={JJJQy+F-dCY)!$SxA2B4H$_zkR*P#QtFAV zwX=PoOJNYotSW`W!^zti(=Wh-B)xjJMHutR0hCs>c#=Te6j}JtZ+!WfKVSD!ilEyg zVOD%werfFGi{IQDtvV|=KHGLRMf*5Oo(akv$B*Xis8gF}VfrY@q7)RG490c?5^6@Y z$m{_p3Eu^ml{*ZdsRSSlgL~~;Td+^hFlVkBIqfc!o1b(1S@W)IpNdm9g%uC_Cz_k3 zi*@>|A2hh?w>{mtd%Ol=HYUEzW(`-A7sRLHtMgNMhNU~(qgRsSxZ}V48$V^~EQnR& zk(1S#J@}B&b8#1Cn)C8x;}2k3&Kz*G_E*SqFgTi1Ps@SZ@xxf8taZNws33)k!`f%; zRyN0TMHo3Tg)(bK?d-OCwoIW!vQDT&kvW^gD0Rk^N0R^!66a@0a&<$_TF8RVP>gs!&fJ4nC#SZ>^dXze|>14p7Ng@cJBfJy$q1W{S zpB{?!iY~1c7vUuQsNt>28|P2>q&Z>*@ikWWaiKTe1SNZQCk*eZZ0{xI1Oi9$ zxN~);v>hIKzqIls5^t!DG?t~&8AItAoysG(mTS3=uB7onWqu$6&J6sP5oQJnn*?@< zJ=HBRYO?yRmrd{Ov6p!=+%>fK%srPxVHEC#gn3Kh@52}zHQ(peoFdnG<8jgYouFKt zN)lABY_Z*%)Yd2V(DO|iY8vXZ9w1|u9L#T0@<(nlpk*ZD6c0AuU6qD|5^fxyqL&R3 zsL5|jb5VMo(B09=_|>&qRk}-71XD<-*DCq7C_D0e;FIy0a@B<)B)^O?T@omlFoDS4 zl*jcDIP|?}+<}0vc;sLL<>{mJ7Ow=hGQ->pk85XV4+Wo(V{kR>?j?3HUP8)R*}!K~ z6Z|hn0FYR{Kw(yIlv}q_?~D3$ZM&RmNZ_LI!zw z`b8UB(KCYNmBu27jS;HzvW42FiSx+FGSXeYAl#&a(h4lUEYz0P?`wU=i3!E>#M&BC z?*s6V8Qsw00TCNB>n@OEp&$mA)3S0W9+mkn_jlHs1GT8k zv=-ze^^r>=ya}aCz?~&f+JdrjKaw zsPktEnuN`=`CP9OzdEISuFkV{%$eM*PhSF4L{g54N*eVA@Ri&&|96WiFQS)FwZe2o zZa6K@G8WdD{nNq&XANaqD|yz32#Vo@Feofu+r89T9s{NLtR({^(AU5uSRvvq1HA2UX4as&ngzZYV3HyvX#f| zACzJ8o{P~82&kFVQs^k}p~b)(8NhyI>0%$?h;OQu()!@c#H^=I-$WQ^?$T(ks;j)S z>Vt-($u!~lZ;u#sMBqBT9dAO&7-3bkDLJv;XyIq1vqLSTzYFNK&_s*tvzSAVRS(1% zB#rT+JE)xQn%Y^CYYW0Ja9jP@dOJVLA9$q$hD>jWnkK3E)nv)Ws6KRM{MVLl#mVW) zA}pY!Lan6zD9#DlDJUu~f-ad5c{3_x^BTpq*}H0&6{UBjWrBZ;eeTy@2nJXB8o@5NkHV@;Yz`v{Xe4C34WBMKq zcV0{zUlqHy#)Q#!Rhuc{Ag-;&8XHqNaNh4R@&rCYy!V0JSQiVvL1C|3&By8lYz8`-6V-2Agw z>}7T(R#s2nXNLT?%O7&Kki+;AdfvIk%C&}PL8et~W1xi_x@q8EEf7r(>5&|si->UA zt{O>RKH_w2nfQUF_Ynzf)%IDa{zkgplc*v2iXLyHz3+LiK$tB2X120 z%@^e9|M`Tbna-nCH;{uQsED$+a%r%V&DkcDaOv}*bMRzZ2B9OqBC7X-e|+-F%d{Rs z`BXaUemDU(ZE>Q4$LEa2eb--d%p|X!Z8HyeNas?djAm7&gPHR7ig@Ik`>ssHrJM3a zt6XYF?N{n>{JOYhf2!Kzm)Y%W6_;4W#xS1D*)^#%k+z4+6{@5`9n`OWv>_v;;io2v zU6WfYm9?UbC$W-bOr9B8G#@{oEiL(Whd<4tg<)2~D%`uj{!FRLv(FomrdKsQSF}I* z=7>Z!q6V={Hz_$yR?zuOO9a8s)F zMdQ$;!`7k+KS0*sVKaKom;B=-;c3LIVI*P@3(w5Ko)YYoX;DNe3&Eo_K^M**|8F-A zD~7})hDT zFt8YX${s-IU|6c=M70)G-kewYd}d_DUoQ^3$YHU-$IV!A&GFHQC4jkk6eg(}4cf>K zwiV*CBdY=q4B))v&*jIy+e?F!ajg*ooe$a+IQK6uw0=*XjB4;j-s9c$>IXLSyVVBq0W zt2E|dHX=^#6TLn0S(i_)3w?c(C8%^0M{f=LJUr+p4j`ttEhQ|KJRj<0+L7t{0*g!A zyK|v9p-+jqHjeTIZACt%>OMEtpKSWdMI9}Y0rY)p5^)s1=yov-h%d=b3H(sg`~By2 z5;tirlPmH2w8Str@7Evvo}>{pY^7*kuav%XjFxp*NwyQvvcx|oSNoY*4`L4|D1G?DxaNLN$vL(f}2SORjCgYmjjdh}4KSU8=BXQVMf$b=0-$Gwyd4aCGKVRvi$o6 zDF?~0i37YcFo#`-Wv($&B{4~sACs4+K@|8}JpaL1s8X4BlC3skhC3rn=T@`e)- z66+y=@8bJ{rgd(=vgtOyU@UPxS=oHv8)94)a;f`t35w<2e8tk@6=L&Il08@F#4I)@ zjMt{dzPvrR12_g>*=zoyL>oH4gH6BPU@PfIMm)Gn`V*jz?1YAmzENcjJ`Vw`d4YlSX2?;_IVZlBSgG2u=0!PsO|}yFTBo!gbJSQn#X{%V`u&L|R5Ou@0k` z0q}{ydSl^ty6Z+KY{vuRGwU-@BVgljCn<>cJ~8a0)$I~+w<@v>672ipEtsRRWk8p+ z_$cs{x2_!^H;!M0vFzZafXS7;f?9{op7NnK(m!viVhb ziiA2;%}TsoF@6V?C3gv9{m|&E1Q10+m*2EJuPx={L7FD>o+e?9O$qJN7W0Z7SjjLm zhc=HoA`8W!8qI#IwKcUZHK59lnDziN)kXNY>x$@>h&uUAB~9=#RHJMPk`uF0_2@8!MkO zGc~D)4ta{DJgpdH+c+HcUZBN9p(PpuJFvgj5H=bj8zY%W#ga#wJ>&ezkY7I%s)$6q z(uD=22(OHNj7fkmV{xi7&tYo&@Pa}peE=vK3mnj@{Fi^!qJr&XEWpjHpht;QF2}Qm zOpCdQobzO4(G_ajNyRsx#4H&3_EOnn`MFtA+eawaNniD`<5(#d2T6yyBFltvqi2Cp zS7FU!QUPHh*oTL?Gvu!wMlmu8I0_Mu&kilKYJJ6gvX%3h?e&OQtf)**-)c3G00KNO z?^D#-q2ma|Yl%5N&JdxnPwT^g18!JsQQi_M828i!OqfT+Es3IZ@<-d#rJOyji^6-Z z<9?R!Y<_8{O8Di(=;3xVu3C3rlYO#Wde`X~`2HM4_9`flb zz0xVe4s_HeRC&S5nz$26dsiuf!;Jpr`>gbeI0W9{Gwn=3@Y1Y z+LV~k>7)YP?H=N%f;=1(g^h}Swl~%oM9BOVzQy*JB!6z@Q%f-*ad5N$*<>c(Y|lFL zcaih&x7g+@d=yxmD`RTk$D)45i!Ywwei1(3>m6{1$Q))^nG03)FpD;iM)O{eOAiEAoVEXsDov6^h-_i36!9hw?fVR zQaEu0IodV?K3Ga9kUZhb0!O~K`}Co(LE3w>1* zV)heN8$D!U4r06WoXwf{uf4Dk&MG9b5*vLs`wX#-k3u!^h(^o02BDgk)`{*ixfd5k zGcTdng01GU4eqcm@w<0)k_s~G$sAJcrjtIYcHz^fjG^nh%vj}Y!X(p~7e2A(_QX^m z$Z$rhSm-n42#0N}>5lL4;asX)J zIg0{OkbIDBc&jdRI_Tv7fy68AwyD3kLj(Enhqt)hhmF^YnFw(b=NjZEYXbqN)|Qf2 z5AcxssU8^K;!jD)M8E%@1_s-@Z1-~im7SBZY1(WK;bm5uLP1Z9!n=iKk7=bYu0;o- zfG;tPz;pCyAtqBV#a7n45HZNu8SXQ)0LsyO)8 zMry278z+kl>2DXyl{t3QehEcMOrutPqg_*FRFh7MwlxXdbVV*HAkVzI&FORapUds- zXgxYtD!jJo%UUEi?{E^tlZsa7q2U5doiq`I2Xd!hf*q6?jWPc+wIc6<>6e7;=9zSE zwm1TtdScQO-r)^k+4wqt3uuYqtBX`5@}*>>JE7*RDF?KbszswAr}PT4r!R`?!j3+2 z@b7RMQ%TDeA~5QD!FI8uSr(qd%(as=)mO)CIEoO82rkB=MqT#^!!nWchqBtCsVwI7 z_yFESremzdb9PBtwYR!A=x5qm{ezm3Jmcl}lq7g;L>Y{ADfuO{<@K2|q~2QIcRY@S=}eZ+aL713py{yaS_ z@+XL4_LZuQzRd)i7~shd+NAk=y|{fN)*>7Hawtv6nLtJ(eW*C#`XJK8#A_QHb zmre1j&x2o`j|<@_Vrze6tdZIt>ZnN1Wl}Ziv^Fx}WEl_f4p6Nnd1 z6LXeuSksr&L-RX;D5zr`bX0fKb7_dDbbu%;P(EKxk=zK#GuQy)o~E~&daipXVGcTM z`s{vVU_%Y6Y8G5N9PNXQgZSmE5ZZ0-2scmj0hcXh$bN9nN-Eb3kNkm!b>9J}UO9yL zOTOR!^VObg6a5WM15_v^o~%Js6Lo&WQinSA_Oj7vx0OYw(g=@ zKO&ANT|9dLm$kHuJy%&aS4RI_5TT_gEFzr>J6Mj2g?2or#BrOq+bY2Q=UIax|J1## z8?GAZBweZ%2dDGS9|B{4G(Pfgx~hG5L`)FpCu$Eh5MhY{fiAA@`u;37Z=k+mI?6@m zOfq$)Am;w}RG0gqnAT(j_1^h)H?YfB_-FhTb@hrI#5-^cVm$g&(v?!{T#VLNkSZ6n zO?=la1QO?ID}&>H(kI|m`XBqshov~+$i(ZuZfS__QIiW9-6Ula{DCzzoMYXRclX?N{a69$g znj7^JEope+H#3F!I!qAN$j>ax);MzE{SC5rP*A>de-@6IE=5qI38s%YptBUZpUq1q z@N?2)unJcMiiX?Ym~3@-cm6b|Tyn$Q_yyp@ipob$B-^Nwn%h5sSjmr}z*-2);?e-r zU7FzeG|pylqVd-|Bs`k>xi5xm=d2;^7-n-~+uO0LZQId?toGQ%T^m#vUJeSceV$Ix%TyGMJi6W1rB)h&IXJ$b4erR_pTbgSSE6J zj_XgZDJ29qF>3AV-X228SOS`S8d({LNuq{6c(gY*ZWs!6wLcX~dETE<+w);-@dmzh zpl}zpY)u)}5e32Vgg9a_5cbhx@Qw~l`wkMVErD-XXa^R?p)kmHH1R^Gk2&O^onv!P>kogOPRvc#KRYruOx)t|5Gw~@ zZ1U>EWx3<kL z>u7Tf>$Y!|xsn*}n;@bf4!Uhz>!jkFNq_@ke~8WTKJ8xFSf}1Ram;hlan(>vdvz%< zBG@uc#UA}hQFBculX7wW)9zOPYFv8$aXyEKbyPxIuayrH7yJjZ`I5fzc|`a?32y1r zE=D?IyA&x}%b68*=MIF&OdN{>&z;0m)z%NYR>QT6l9K@HRz=MUf00}yCh?XyP!VRh zJOCE_Eis8QDOua*j@C;o#Qll>8spETCRDpP0qU^h&6=$^^Fxv5akmvGvkDj!&7Otn zcoXs4=q@ioby05+iDD~|fXQX9gm^s~d`W1rhgEA*i{m^Hu1AL#QcAZFD<%{T?vk7ZtvN@Ym~8Ipgu?lA>V^-wkU37!L*T00{9t^!EIp9EU=?1zW7@sKndF?~F3(`tSP-cqn{ zj)*Drs0e=^iA%U>Z0#R8ZA9`t<_Wh@DPa%{Mn3 zXr`6f=J&(*I-ZHXZgW9doi~5xK=A?^_)qZIdZV|#9y&YKEXd->~*Zh3z zeZy0kox0PZ z8($RW#K@L&k>^`{U3Ik)dc$!ApVzDOHj?w87=4)N%4Bodia;K~xlW^2w98r)7Li8w z^D>i)XD1j4Ke08JWCyGr4uxzG-c)Q;$wxjd&+VYh#X~Gi-M05uBPPfSmko4NvlLpAK(sbcNjw6i`b$}wiaH~SnCR8_;P1bIxFXHH zl~(1vFS+YsXf)OC1di7Xx6WmQ8rhp#+0+S&gAK`;v0;v$MA-OSe zbEzI{DGSgpVd}d0o7m$uD=vDBLP7=vOO(>_zAObr1(W|lH!0=rPq3E2@+g}M^QpI> ztC>6ZYe``(rw@wh?^0(buhGxB*IR9)%#}~>!n3rgug8c(DJ`PyF(R!75)>C%_8LH9 zVt4ZYdJ=*eF4VH{j}GBfq`ZXaI?XNp1^3ku-^Vm8X2&rW7eBB6v~ES6+zvlo+`SPu zs~_>8DAkLp78)xDJiT?eq-eyN+SrDXKmDt_OSUr%EU2uEiF6D1M?y_4bE=R zNm7d`wSEBh1#ZG`=k})ajl}YZpmsQz^KdcGt&I#FQ_7Hq`{sxotVEFSN|F*xeNy`! zgN3c#i{>QC-`Dk?uVhQDjJb6poTX*v8$8B6 zr(Fjz=SaV55{-NQP6<`fpa=hmC#>^1(YFXb_h|G2aU*}PWIlBYe?T||Af9XZ-STcm zmCbGy??C!e#&HOtkphbtF)A!tP|ukr;khBbKe`J-^}a`6!7LCYdRqx$B8P5N7W*Bl zNXI&SjC-8wx6pC;>fSBUKHNmXUXVJy!!0jxo7d(?kwD>LyU<7?yqPo`(HvI2h7RHC zigUaZ81Xgqn;EK(+dvWmqZ8$Xa1H}k1W~rr)X|6~<>(H^Rue6340@}@19+OPAD7t{ z4*z1EJ!D9LwAZ}n?nvi)_sUzC`-Bs@_eK)cu_8c&BnYyVyGlJlVn`iBI%pYpP)*X_ zKf03(y_;hV8T~L+brUMGN0j!sVl?y%e@>eJhq@05ZtYV;}G5D$FPB@Z5Za()wOX zMc(OE${XvH;wx6o4sfU#rYgY;!q?YlXxiwsf6uMkS2O)Q4e&Hf{GJxN$pIr5po3+R zNEo79Kg(>lX6?+yH#d|b?Xg-ETLtsy%&~siV=Glh#Cz-Gi;wfhFQl~ z_JN&PPPb*kD7GKMpn2zXuTImN!_97ex2vSgDios#g_2~m`Zr>}>bL#2;(Qs|>;kd) zK1o{VL(4Z3o`r)mX+y-U%9eOW?2dLw@HMX|*w;9UB5So$0B5-Hrd%;#=4~AkuyrzQ z%G8~CZPsDxoY5IS+}KSen9HE$k|zcwqy+ve{Wn&cbM#L3K8Q0kn+%2)$YGv!LYMZV z>%R8m>(JO&T^hn7p^@@$EwlFD7xq}8W!Wo?gtov4*aJPaZFCMPTHV(1eBh{fK6ovY zqygfCzoJy(T?^cw+797l{L092+W_84(SLZJ>B1-YHHcCFT2q3nu>Zq&5moFdER(wZ zzDyKZl1EU_n8nH;j3dc6fqkz%Ly0_0OVFV3u?Bj+i8oKZz&zUW^(3ECbd%K?5g-vE{`#xkPD1{`TsV~8_l`F4^hMLwfE7&+2tExBdy zj_nQ3!M@~}i20%D{5JV6+@OW{-D;neI35#S=7)Kc21n&l?A!nlvk52R-?-{w0@_l|>KhYmjOF%Y>RteBZ(Qc^8FvZiP3_z%+vf8BgoQo~1LwpZH z9wsIwj+oOx2 zqmK^x5CvqV+{?cN*yib`Ke~7xx6vt6{AokyO7OH0WKT^w296VJe@eV6lR?E6!gLMv z=d5MlOqa{>mR0~J%iDyyt~c~V0#E<}LO4YzY>JsG>D-UrjAyW%WG67cts!|^JbNZ# z6AU}WsJ4GV`5WlgaqYk&Ygv>M>PYOK!@8S*#ix?4-Yq8Oe~0#cChT&~!jtwz^>w66 z;EU)rtoj16V`&GziaNM2rO3IDyHhKIqZc1>9d{#fKqS|u2^>8d>C1aspqklCKikGq z?JNL$G$O5R($?ByuOb9SrL4|8eNwN97-K4DgBRN5BiRm z%sXJWGw^OCEKCtCW50;0y=6JShoI16nZR6bzix_n$<`nXaw>n9ss*9B;-PN*#40X6 z{6x&l`Cvg9vH(ro+n~9L9sO4}>~8*ey<^_c{9LNV`3A+7-)ul=tO4W=+n(auZAksq zcnQ>p(TBZEXnkVE#1SiOK+9t;!zh=Rb-PO5-(g;F&Utz91f{D{U!>#52fsEdV2WX) z25U33_Kh;qhS=H^05>5pqadwI^$QiLa|BWu^cqo0VsPU*LV^nzwj9Gy%TUCRc@S&h zM5*K?R8>tOq+a`TBY*4Agktu!$}laMK$25k0~3kBc%uH})D`v0+)H6GN-4K1mq~e` z07+7rD;MDc>cDc@Ju=cuHqBA&NQ+{*!-pLfoxJH7EYCREK?}yVwCvuV$7Sh7<+jg( ze(ng(cJPCfJE&1C4KWFY?7%c@;;NkWQ}}hg*@(LHMJ`!d6y2G%*a}&v7QZG=Ehknb zT&vMgPhF7vtw>T#Xr7@?>G?9S-cpCwGnZ8dS(X+e66_P|68wX!_^|X~L0(Uf$}#JXr~~vJbgLHu5~9PS(Yb7 z5^eocvPyTt@BOQf*rlt}Z{j%px#s4Z4aA}8Z{Y<%gFt#4U)^C}1RpM%n(beYPJau^ zGiaUG*Ra)?&xJ=`5S<&Snh|yPGw^Q&y-Ha^^mCkUNncO(7I0c~^yR1%|B*<%@0(j^ zaM%g{!V_2~m-&^@44?KOx(SM@mRmHZ8N!Q`7o&S%4_CzkrD(LiDkzC0 zohhcb2L&UvP+8K7re5rKRu6~V!pW<3b!kA`WXnG>x)*uMVe>)0^4Lk{+B>xm+Yheu zGmL*e%LV!*J51)Jrf!W~8a~F&4vNf4z2wpi<2dPCCN+XpD)|rY5x38_l=ScrG7`rX zKr^S8hOu$1)k0Jo4_4g!RHJ_i;W>(pbo!%3dLR$r05sFr{i<|N%M-+3zZtieCMk8p zaw(T4kDiqs3r2xX%U9&oC6!>U`c)_i++D9^UhDIl00!JA<9<6*{;>03-2SmZu# zPK0Qht7Lf4*eJE~7Q6FskzKWrd_v@<-#sP$KE3R64vh2g9v~DxK0fP(v7K}>?c9*) zIVXKy1B0^pd7TEiAz1knD200#MCUq?) ztd7kcCl>yuw{FW-kE@0yJndexhFlyp!=-DwtwhdBsaj1Vi&7AeAdk|a3r4SP4Nz9} z`;8*iaK>QS{;eFr*@o21(o@Sg0&;551I;#v;(1dXid#ts%gNlABkze>`Nxbm6ZmH_ zqw_|xMEh|}c7<^e;P`Z|z7gDHZx9#2(>U-MD5`IZIQ?!{xu#fm)OAb)2Sqn3;Tsy7 zy7U)!cYAQM7zHo z8I0J_*^PZ;;x=E%t(x~9~7kkbXkeg`t+i4kJ@${>Z}sb zzNK1iIjSX+qILhR9I60DnX*O^R0F=S6(wIqLI{DV>GX+ys)ML(KCK!moIYI(dgYZh z@d-?8BhGgrN`75cIY48aAkA0m)47D08t!8TA!)(q7GrJA-$S|D)pBzm_Hh7T!q*-n zy5-oYo%|$ljKG2TI6c9KjBvS~yI^X+8$D;fK2NvJCM-Lh;1O-3m~yPgs#;*Lh0a{C zNmHWG^@g`w$6DD$EvJ?=NT?rJVpq$e@6Fqq1V-!V(pWMmw0HV$5$@-d4|*ziKI|dsm3x16^#G+~h^>w<=QyoDOQ z)fHs4kbv!DX^jynLla}sln(Uc;r@QWd%l#ymyW@Z>L8c8sVvabS9-pA<)Q7~dCNBq z@!HEn1BDB==%a!hc$sH%igQ}0E2>jsLc%R88U{s2w6BeSW%IP=t61=x>lP!$2`+(S znF2nh=Tr3amKv(=woql9hw0$1 zpky!25+W^UsrHSDYO{BS25|VdI8RJ?1Z@>3fBpJPrqNa>vbEsqv6dvaNp3;GTj>HZ z5D7NlW7Ir;r$t>YI{gPC_1*J`W_<7Vp{>B7m%(*G8eELuC0zD)#Gvq)L}gM14IQ@> z2^t>j$9sbF8%;6Y^je*|?9kISvuZzst~5$t+LWPI(n!Ywo#|x1JrsixL8c|hObSNN z9&+5vf4`5a<1<}uHR;L-T%(X7%_k&C&F_#tn+_q;N-zUGt0|{m3#CvhOHEOb$~W8s z(Jo$tEQR6?)?gAbll$3@Dt)1L40Bw_aCEh`GoJ+G$$;5KSx%Bs`=`gYXvnje#Ixjy0CS z2+z0Ed5>qU;fZ>3M$HDqGtjtO9d7h%enz(LCZ@wwm+Sb90N#;uCOk2c-PR>uVYpM7{)xm5!Z@Bg>6-FJcj%RkR=)?sK@$aqsNzw^pn#}VYiJtAH z)^C|TF)6!^;@786+(GCTWDd{28Jcmv*X^#G@jzU?&ZHmylQ;i5LR6-H*+S4S$6tvtC)S zAO&WKvBel}sKAqgNa_Xs&x-_wrA(z4OU$VI_ZlG=@2*{vnzd(agH z^$Y!evyDf1N|WhoEP;rmwQgfJjUAZAWu_1#IR4?-QBQK|F=L#_@o1`1kgser|ER_( zl#90unwQiW_~T3Gi|A0u;Vf@*bJj3nfJ=D9s=z)v%Lm6J9vDe>%B!8%Bw&vl`o*&E zjR+*!<;VhXQ{|2sM*YAv1)nG{SPJq!WUJT0p3HB)=GAFNk;j-1U~)B`{ghA0n+r%LprHWlyRrqJQ<+;jDcJ@OA?S1;KJ3!*nJ5ho z75`oNM5Mb@@1LM}2e&T(c-i$en3FNL^d*2vnlxcANbFjAi$)TJ|%@5!*gE?8|} z$1Ptrn?yr8a+uMt0~G8>=(m3{vAN7uMCr}7YYmmO*LLsSz~wj%E_Tw@sa*xsDvSjj z3~m>%Aq1>NQQfYrFsS#jO1mO4ykOmV;z6drs8jx?Y!$92+v;B|`L$j*i6CbTU+|qb zT#|K^sM?!v2r@7ahgD)s95^m*V|2knGF_hJrlaSoEP^mNHo_=pV(O34)7+fq0966a z3g;EFy@;8v6;Wg-7V#fy+2Khcy<5jayfKft=*d`RHAMGSP-KJ^T|`2q7? zv)Gi~%Cl1IHY+i>xcL}AFC;wL9z}aO2<{X-eLwvmj^$qOi>Tn;l}JY*EDBp%1pt8- zjp*kD>Zkp%hl+WfSu`;mt;D{~Xrh1Cu5V-lrm9M}x+dM9uyfa62?dI%af6_f0Cllu z-lY*au5ocmgBWlfNlN!d*-5%CZamnS-d#>T6`c93FB5ORU%Ni($v`*bRKOD_GEKc& zP+bH?_PnK z&VQP%PUs)RZ=PY!vri0 zoUH$A8%*%u>yfUtw49K~6MbK6&qg!W@-KZi31ow9>H-1+nqh&%?5!a>ZLI1^<4EAA z-k(2BR9lr3Y2vMC9oY$oMk}4l+Yz)w6Sqx-CR9PphnCrQyTDY@Uo<%dk-zXup z%Y+0*qeK~EL%!CeIHbQ|Y?gZ^pHz^5NY>&Bo+VS~RZ>*UJH?93{kpZ<3Fw9>!VF4il9vCgF6^CyZLB2d1 zZZmO_k95oTmGq+UNrj<>>=%?ZIeA#^_Z6h@8X6?={Pr)ajy_p-U%~1yNT&r%`55bUb27kfid|cnhxF7=T7TkI6a1GHNX7gI+M!4V<4%NR9j6P z6nM=Uu%!WJD*;wF);Xd7FR(27=MzA-!r1qL0fb-gy&+9#qDinfix_gLI`|b|U7>L> zUDn|g(pFbneJn4&#J9L-qmk<0)`0rK`|vq)KS@2z&|%KyY#hr-dWBs6o6L4vkRDV_ ze|uUpL(h19m6PFm33kspg^xS*-EgpN8i~Fc)Q?ci>xe4hrJ4n)`ZDu;X;!eaccNVd@X{vXe!$mvQjBqjuSKQqFnxka9mN!p8?oUwrA7m4@X_k z_vat%=SI$G>IxpbxoUZqBuVf}w+7ecL_tk7XHy}@krfq~PdICmay_e4v#Ir06p(7n zWadEUdMPZdNeM^r0^m~^S8LIMv~8onxrK7+B}=r@xH_$hrP{8`{wA(nr7cPGqIgaY}>YNCr@nK_T-6eOpJ-m ziETTX*iLTV`<-*wS?ip2&$qU^Ygc3U{-b|gRbAx~w7cL5jb3zFZb6k0(%r{EK$;(V z@WN85U zjwxKGjcMo7^as0-uq@7ng{`ep92SFh`0iY*rnR}9>y){9{|>|$+byVz9Z7Q)91`Nj zDEslMs`TipBIk6MTV&0u6?*@568fR2jey_y-5|RJlq2OP0dMJ)0w!?e-XCTL?k~gp z)Vno`Js(~+tQSi75=Y_3mD$^tfmd#3=4tL_hnAa=)RO-1uuxoVYndfh&qx1fyOF** z1Jxz#dAD-h@5u}0nJCZFlmgQeCd}3zgAyBuh;>W3cno~p^}o9Xwq6C5i9&F2w%PmT zN69R*G1RF&N6qFI2}dW+J2$)WjSrSsBgR@Rw;iF&a#js+ z%w$SaD-zoHJxG3QMKqXU=g&6+EI<@jldFNpQV}aiq^$~GP9q_`V!@B^S2{2Oi<|uh zCODfYNvd#0x+boD=ORyFOrS!7 zcuj~kI105XBq=ITzM3#5BCDEJ>ZO?-BDe5z`*JFycxJc7~5xNVN6n50jC=yW{-(Gox7e)FVqkFX1a( zHnXi7L!{GM1`TnGXJ{(eFd9zZZ!7AGkR1<_TRL* zEq#C1oHPA9@nmK{nU1q$h38f7E%9k`-0UBO#SbH zNgZyeKR;j1&Ea80SJx$IiM=dJsB#I8`R0>Qq!78?(TsdZ^{kpGPnVm60QP%GR;}TV zPI*NQBFBb65{SlKE{DTolao-5UHcbK2xY(a<>z6zzr0ho;=fHbcXI?gdZ+i2l6d$+Rqa9>(#`Lrgu`wd8_x_y2rl zk$0%iR#4pjieyomimgw5ZpYGC}Fr2KK#B|~cSlgO8Jwr!o!MUZ!JC=x0XyA)aK_~QEW;h1m6*>XU99GI_%wy z?Ej-Q*H4bRzr%&i1h()^u``}lvKj}jm`_QjXZy#-*Rj@Qy+ln-w?v&-5vW_$cxBvqBe^#an2&U!TR*Nr z%RfPl0l=Wa0Hji59GIcQ&bE#5eE5G}8hI#{r6{4)C=Dthn;(ZO7ZAWvlul?ZEV$l* z=V+BG9N$^0pD9(9u0Arg-l+WYzPZ~Y<*NWEIS9LPh?#>tV70ql2pXZ7+a2KVq{^c< z@k*hMpSg>a0vKW@VYqnP@#oruqTBkb`h6 z(rsOcxb!9_*8Qva*0K6?&AhsG)Y)YpH#q6;&WF!Gv2?*~8m^FcE2Y$#U@vOd$PT=1 z1I-;Y2c~oVkYIO~f~ATo_bc&@!)3Z_~C|93neCWoF zC2MUK>4`arK8`MWbEdz_4TQ`>SVcTymJpbDWKzV8+XZEeu_Sc-)o`@V*vU#Z&4 ziR#Yo@;q}3;nU=CVbZ&p$zg@(helJSHvw00-!PRI&w#m;7abdaKBgHzsB^RXd*w;4 zf$T9kxM$OdNjw@nf9@UqE5%yy?N~`7cwRQ(G^sXXaWb7R)G!gKPkL=8qC)AlWH@^PvQ8-R|L&YUzq%EuP*6h z@t@ONmd}^pHhg4`fi+ZsOa z=veUVk2Ka&42t)`uW@&!{R9HXXlkLm4qKTs9qz5%A5+gUxBm)`thLtH&lSi%?pXch z=C9hfJmh+EN^^=XY5cTyM4Pq$1?R&o~XO)xHOBgeu!_|!3SQV6X%9jd{Tog z+JDpfF(5$nwuvsvb^$N1!`ANfEuAaVVo?TrGtFyq&yi_pZXn{;ZAIa4j5M#e9Il$0 z3ou;m2Po9m9AfG2+}-TE8@b6(oO|a#5w5ec>GuUsw`uksN%Y<{vyd`00|f6ALyo_Kw-zk#}=w;mUW^PMm>|j;Jz~o(!jAT=4P?z>VPdB|-bmWRde8 zyF2wTmfd{0iTo--154zf;13Ve`mzsun4DpfLr^+yUB$r=j6ikagh3p}Erbs^HoCY8;wnXv{xJYv1Cnye$+#ZQfpDRL01*joklo#=PIU~g_O4qX} zw7RQFFsqG|SlkbzomnH_NvvlD-Dm2yr@#>UE%pR5IsYHX>;`_7`nvj43=E}X zb3fqhJKp+;oE%--TfCwU{*Izo3{PknaGudsU!;oGs7LBQ|C4>9ttRMhXroilrT*{- zopexu`tR}vE>^aGPu{@E&ieo44b04pT>q}Tp;$}F9*+aTZ_6Nm7%MzSERvWk?^^v&Z(uWGBr6NCz|Ct}zS((NEZcD+sKn6M z?$_F(V2+#_LpX9x#!V=ZI62u(2SF_fa&gAE!O2yNjs~cnA$YJTiq>E(_$OXufdJ<3 zi@4uBh3nI9NJnu}z6&uT-9iB5Mp2uF08=qwKt2|pz4{}I1EmK%GU8Oe;ce&Tx`8A< ziX>CY0$Edd862ryN2WyC!~urD(yTJEcE=>s#C>*1sqA{hkrhuScv|3_Bq6VvDbu4Q z3he0a_F#qRvDD2ZRE}~S{T$}{(Dxet#3#pk&XHti!vVR3EKPDQ{T&=3hb%c_h(9=< zF`Fjjg5-T{e*{E{KoVK780`ehfRrKHQYcb4C?BE>$gr9i5-7xjAVADW%7$Dn@+7Gs z+3xRzfkK3+x@LTwsJun+-;@$lDuuLSu<-$o-?S98WKpm@v}B)uj!_5ErYH)V<_>ZY zIl~EtRqn%YiyFe>rX@`VYK5{ z$}tyGLdX~=Wnq$F1K%iQY$ikC%!vS_>B=LK*_0$yb*Zo;5lq%Jr$I<0&khldKV8!5 zG3w(EgcFVA(}nt#q?MI-NFSZiqv%F^P<#_4ixU9E`DO=+NiqX}GHbdw@eDpLi1Fe6 zzJ5+_ZizczfsK2H$$Y}?EaM4K1qj~n_9xu!H(_56PL*yvY7WaPT6Ifb_fM{`rsTUl zKi?m*zm&hcZTE@c^QQhFZzG5l_VV$FZ_7q+^RM&;D@;gY2 zQ88mc%44eckwM|YGl%SH)9BRI_$h;g^BVxctjLaq)x{8tjqspQl0x&6g&8loH*9$|t})#+_re9!j%Jlcvs04nPO!RN~;}M^G7=6X%H3omO|rutL4&PUI0dT2 z)b}8jP*W%m(a}vu@XHZxnJP(*b~yWnG6$@IW~4;--wF~xEKK!XU+voi9&88F;2P#9 z#)slX#`@|vFHKY>g-#Zcbt&%f^7~63seY9Ds9lVLaYD%1*jZOKs3VOk9_)2VC=EbB z;~^|Jc9^43GHBng8hJDh6v$tcASMQbI3A{Y&%Zl}sYGpj>D*56%zn-nt4Z0S54IsV zAr`2aLWAn0RS^xMTTdejz%L`1g1j^5`0V^*SbDA}G3a`!x9&2w@#)>YZG4Kdyrh|3 zPStMz=~}jEC#M{vr(T}y^26+>>WR0Ya)cV1egtzcnj}H-m>SfO+NnBJ1POM_Xph?j zrYketUI8`u%s(9?h!j>sbE@dFIgQ@^qXFQltj90A4FxyIclx2;iirQny34P6(GR|k zdCF*vOS2|v4LE(J?y0spVl1uCmNBJYYYC|=*cMLu@|!zKsaMJT)M9r2ALHhM_kVvv z7s};1j%yPT)I?$f&n(~W8u&zuOf#D^}=z`HrkxK_1Hm$~k9Bu2+39JDc6-nE9hh9yY|*&evV!+~=LG$Mjs*H|5ss zCC;1NbZ{EDwc;|Y&#R&rSI6RQA?j3eSEpW=qZRlxZM&j3qt7Fm;7}^7+-59!#;Q-_ zGVIPnp{QB4Pqa9<#;D3k{z4Nv)xuK*7#4Mzb|&R*;Hf$a1YA* z7opmZYqD{dX8EE@*e3u}XX}mY-W)H*1%3oDY{S{itz=eR^-pO<_ubrsuh;lF7YvsZIO3h_><{5Ds|OH;r0R9k5pk zT)Y1U_87BY3aWI?1+~d4whsV;gmFX1AWm|j@8dM<9`{;ymGsyK@BP8$`;PtxM8w7Z zUl5UytBZxb6D1Xcs-=q!;OnX4YHS5CarsJ#I01}YzTU|isRA?!-7Q@#2ra(!HBL?d zGeQR=6Kf-L02PCxlf9{{3BZZc!PM-FjgE<)m64u_or*yQ;OTDfWa>;w1@o_(EbZ+? zja&ePl%m|sjLeLTtjwHD>|g#I8R-~VDHs_kzWC(qP5(C*RVO0{2Y@LdgSe56GXRD` zQB_QnUfk8j#@NWt4&X#cscK>AO!#&Ft3R}a>HsI_ucirE=$TlV*tnS4+31+*+5fYj zU;JO+CTr;iAY^7_Vq*{m7+V_IQ4v}@7`a$D1B?jW{-ZcMJu^KM6%0TBKLh%Yk6SLb z{~xeq{Zd~2OOM6E{-x5A1=yK?4IdLb7stPgD?>HM?C>~{IxaP?u&^Ui?CU{=1d$Aa zINgwVDEh;HcQ|6y(h4zf`sdOkn6K|U?Drc({boBe{%ON5)k{-FDGCVMGgp>}_A@&G zcTk?WVX;bf+AS>?sEA?8G00+O7x%j!^$_8S3e1$=cE}tF0w#?_>cnbk*$R;Z)QNC2)OL;4YQx3?^x8+@6CKK^}I=;p(#nX2MZ8R>oNRu$t-Ap8kJ zDoqOZg&_s&MVXPnZj74!UEBEiSd}mr!#55N1hKA<^rNAkaqWv?O4Ct_+{^xM-ko=E=>;$Jhc7G#zTV$ULlCQ2bVmBVEGbm9bjnfrl^$Xgz)3TOg7|X<7FuE0f+nla+iE&@e6F?Pt`o-&P`}oz-EN`*A1lovThEal1S^b z)(1Oliq|II7VR#^ymdURnwR%C)FmDvuTxY;#Q?GcA`KVKXpm*s)*JgDytK7iMfEgs z`_QEF#0RnL~jfZ7tnEn z*hFDv84oL16pG-y^(XQi1<5jPOt8o(E?9ym$0(w$cBqfBB0FZAZ53$d(L}**8P+UV zw)JTfZ%Du^P;C+r&!bKq1M%yB_IO%eQVxj)igVC7~BISyWdE z;+%+vT&sg)Dc@sfS;Pg}4rq7-`x`v8ulN_7XFjwH)>;HB>igC=5vHBYoWe8<3{yd0 zq+$*DWsU0E&~s|Mruo?o*^9d$REl`3 z12=x0|8z+&(X?PyC|>;#ofO{ z`2G=WFeY>C6w(F689c`tEv$S{mTFQ2(JAvb?it^Oa>ct`S-gJ(W!&Ej&SlFhV3#0< zQ|^v%ihC)V#<$_t34?L0Uf;efr?K(QcB74R`<)unwl{I(X6}x~KP!P`Y{2!(Bfr<7>wc&{C#5F-)xksnl1fJ-S@YL9fwE8mWvGBsr$VV?_aIBn7wliP_a{6%2fzE zzn?R19UXc3Di*n&sTQw(`Z*+|Ku4{*{Zc;l89u+ctNbX!@y>Xj%KDzOD5sHLK3a+S zO*IvEVHWvuDsymxF?aFdbSKP8dKhqjSIKUxkdblY$7yMW9!Ya?qLsWvg1X=;WtyAG zIyK3_l%9RCGZ{L8XKQyE|e!ysj63h*G*VI<_@;?#p-P_gs^{F8)X&>+-d zB4io3`RHY8`upklsF$%6asH}r7 zPN;^i*v4i{K~0B_UPd(?;XrlOqt@foZNPtdf0^!lc=leSWxd9A^nuBV$?058`o8xT z*mF=xTY&v-8lgasbR4wx!G9pM&Ki+v_GhZBR+6rkS7)rj23J{{K-;Fjg^V>#XpnNDOGbhZkf z+0$b9TYC>^qfcXD$VMJ?6_RaQE#_UmrC!*#SD}cKEgne^Bs}4@Fm^!?EIgsLP`408 z)L@JD8J9?Y7pyACbEJHNV=Qfs41RrqL(Ys23=}IO@fn1|lbOZ{ikZ0ldt@u{p&4e2 z7p>Kf?~SMyd?Bk(a~9eHbdjR-WF$*u{$2$%)2`8#@FgnNrQi`Wp-b_VhGfUrxxkqem_ z)5VQ10!4G5F00cJ@T?203ZyD0!Spe6T6+2q$5$CTi)4%6Uo2ZuP2jP*_oVIS=lxcV zIA7H|OMSUt%kd6;|Mt6<=i5E#%hyue&bjq-`c+k-IM!*MNCz#?QVM7M0P}>qDlElA z;g{ae#c_O@m_~`SU&9z(gXy*8;H=YqC9d4FGS7@G;JY|ffUeu_BaZM zo||$xKDQkcyjq8zpPo)*w?lWPNk{mnBP3HgD?q-S#}*26UVA?UC=aXn;l~`(>*4VQ z-MLhtM2_?>l}QfkmG%H&^KrhdG7w}R1ig_rkGTn|%%cjDTI)0bMh#iflNyv-8X#C) zhGzriwA<0z_IjU;en>EGQB<$;osxaUHUI@!1%{Sl!JAnq*@U3TUEdA@NwNk) ziMm2A==g^nTv|8Iax4eTM1-5Fn_SP7+m!?3$`lFSnS?3bU*56R9Mo~lTF zq#&bdd%Id$ROntK2MD+TA;tj-Z1ovilI^nA8T}16IMbf5h`k)GVyF~7mW+0GC8DcT z4p6e`?aLH$HOS}VaGch5Ct7k@;Fvv?tp_#Inc%5CL9Ovybmzni3Wa3Oxps3FD>hsB z;@_Jj$Ja40l_LyLI)3h_d!Kn){)$*8HtJ0Tb5`i6{GJ6gOfb!EwceXuY(Toh-66A^ z8=k8mEk4W{T_VGx>LnZzcb-C%DRh;ZPc1_(XMJ3cA$O1uQcI+EW_VN0*fbM6)Nid; zJQt2_{qdof-v%cO+|Gw^Ci|=Scl_Okv5LXO*9>c;W*aM0%k#IQe#7NQlx{B&?1y)8Wx$3+Vs!0+2R;x?DKM3H@!!Zn}Hrm zWAt{cR4=#=>3(NO+E3Iv4Pmvi4a3QBH1jnm=qph$`)n(j!AUS#{0tCIu0s(&6%1Sv zEQXyP^{k+J+8M=*P(v$<#?m@jYUY!r4jLy*S;a>5Le-O`w08F6)-z)ydbKkq@g z(+wBEby_E)cW<_kMPs_SY#c`|HEpY#f-Y z2Z`C##?KORhxM~zF_?v=*!0e%iYv7E{Lo^du`FnynZQfDnK`JQ_933)CkN#GeKu&h zuYRr!-IX{)OZx7_REcDcq~k4cdjZWpTl)Hzhidag>N*-)xdXTO37`@6c%g7zq3pmn zSTok^uhOxVzPo5m#jh!Kof)qD)&${`u-m^N*9u|*%~Eb+UvtsLEgq{p{Bb}On?n2a z((o5z;V>Pt)nBe_{%jo{g)zzxH2NV?y%4vsNmCN{WBpzGKiL1xp2 zLPz!VLj{hoJ*C(Buzka9fhKzhwNpVmkHs^JRmVi_LZy%Pu<=|i~Ls6q9MeqHI9oElD8C5M0 z;jFR8UqPEL4;_)qBK#hM^wA>d7VxK+Y8^I%*5g%4t_;*3nhv9*Swfp;s^Id#fY9h~ zmQIbea24l-%AY#weMX#F(QrKspB67EhR0c!5Wc)0S5wIeDpr5$Soh1&5j3yDIb5Le zRXO3}z~sw`hG!EB)g^^sRl47peC;9p?G&z+s_go?h$w0t@UEm`pQofaEqe_F@@3?8 zdJ9y9_yPcF7brq^!BA6*{N1d*q6?QunBW9^GWw#M0MizqYnzWMT^9F#iY6C9P`! literal 0 HcmV?d00001 diff --git a/shinkai-libs/shinkai-ocr/src/lib.rs b/shinkai-libs/shinkai-ocr/src/lib.rs index 65a95da7a..3984e26de 100644 --- a/shinkai-libs/shinkai-ocr/src/lib.rs +++ b/shinkai-libs/shinkai-ocr/src/lib.rs @@ -1,2 +1,4 @@ pub mod image_parser; pub mod pdf_parser; +pub mod pdf_parser_v2; +pub mod pdf_to_md; diff --git a/shinkai-libs/shinkai-ocr/src/pdf_parser.rs b/shinkai-libs/shinkai-ocr/src/pdf_parser.rs index ac97a6e84..72e025ef4 100644 --- a/shinkai-libs/shinkai-ocr/src/pdf_parser.rs +++ b/shinkai-libs/shinkai-ocr/src/pdf_parser.rs @@ -1,324 +1,327 @@ -use pdfium_render::prelude::*; -use regex::Regex; -use std::time::Instant; - -use crate::image_parser::ImageParser; - -pub struct PDFParser { - image_parser: ImageParser, - pdfium: Pdfium, -} - -pub struct PDFPage { - pub page_number: usize, - pub content: Vec, -} - -pub struct PDFText { - pub text: String, - pub likely_heading: bool, -} - -impl PDFParser { - pub fn new() -> anyhow::Result { - let image_parser = ImageParser::new()?; - - #[cfg(not(feature = "static"))] - let pdfium = { - let lib_path = match std::env::var("PDFIUM_DYNAMIC_LIB_PATH").ok() { - Some(lib_path) => lib_path, - None => { - #[cfg(target_os = "linux")] - let os = "linux"; - - #[cfg(target_os = "macos")] - let os = "mac"; - - #[cfg(target_os = "windows")] - let os = "win"; - - #[cfg(target_arch = "aarch64")] - let arch = "arm64"; - - #[cfg(target_arch = "x86_64")] - let arch = "x64"; - - format!("pdfium/{}-{}", os, arch) - } - }; - - // Look for the dynamic library in the specified path or fall back to the current directory. - let bindings = match Pdfium::bind_to_library(Pdfium::pdfium_platform_library_name_at_path(&lib_path)) { - Ok(bindings) => bindings, - Err(_) => Pdfium::bind_to_library(Pdfium::pdfium_platform_library_name_at_path("./"))?, - }; - - Pdfium::new(bindings) - }; - - #[cfg(feature = "static")] - let pdfium = Pdfium::new(Pdfium::bind_to_statically_linked_library().unwrap()); - - Ok(PDFParser { image_parser, pdfium }) - } - - pub fn process_pdf_file(&self, file_buffer: Vec) -> anyhow::Result> { - let start_time = Instant::now(); - let document = self.pdfium.load_pdf_from_byte_vec(file_buffer, None)?; - - struct TextPosition { - #[allow(dead_code)] - x: f32, - y: f32, - } - - struct TextFont { - font_size: f32, - font_weight: PdfFontWeight, - } - - let mut pdf_pages = Vec::new(); - let mut page_text = "".to_owned(); - let mut previous_text_font: Option = None; - - // Process metadata - let mut metadata_text = "".to_owned(); - for tag in document.metadata().iter() { - match tag.tag_type() { - PdfDocumentMetadataTagType::Title => { - let title = tag.value(); - if !title.is_empty() { - metadata_text.push_str(&format!("Title: {}\n", title)); - } - } - PdfDocumentMetadataTagType::Author => { - let author = tag.value(); - if !author.is_empty() { - metadata_text.push_str(&format!("Author: {}\n", author)); - } - } - PdfDocumentMetadataTagType::Subject => { - let subject = tag.value(); - if !subject.is_empty() { - metadata_text.push_str(&format!("Subject: {}\n", subject)); - } - } - PdfDocumentMetadataTagType::Keywords => { - let keywords = tag.value(); - if !keywords.is_empty() { - metadata_text.push_str(&format!("Keywords: {}\n", keywords)); - } - } - _ => {} - } - } - - if !metadata_text.is_empty() { - let pdf_text = PDFText { - text: metadata_text.trim().to_string(), - likely_heading: true, - }; - pdf_pages.push(PDFPage { - page_number: 0, - content: vec![pdf_text], - }); - } - - // Process pages - for (page_index, page) in document.pages().iter().enumerate() { - let page_start_time = Instant::now(); - let mut pdf_texts = Vec::new(); - let mut previous_text_position: Option = None; - - for object in page.objects().iter() { - match object.object_type() { - PdfPageObjectType::Text => { - let text_object = object.as_text_object().unwrap(); - let text = text_object.text(); - - if text.is_empty() { - continue; - } - - let current_text_position = TextPosition { - x: text_object.get_translation().0.value, - y: text_object.get_translation().1.value, - }; - - let current_text_font = TextFont { - font_size: text_object.unscaled_font_size().value, - font_weight: text_object.font().weight().unwrap_or(PdfFontWeight::Weight100), - }; - - let is_bold = match current_text_font.font_weight { - PdfFontWeight::Weight500 - | PdfFontWeight::Weight600 - | PdfFontWeight::Weight700Bold - | PdfFontWeight::Weight800 - | PdfFontWeight::Weight900 => true, - PdfFontWeight::Custom(weight) => weight >= 500, - _ => false, - }; - - let likely_paragraph = if let (Some(previous_text_position), Some(previous_text_font)) = - (previous_text_position.as_ref(), previous_text_font.as_ref()) - { - (current_text_position.y < previous_text_position.y - && (previous_text_position.y - current_text_position.y) - > previous_text_font.font_size * 1.5) - || (previous_text_position.y < current_text_position.y - && (current_text_position.y - previous_text_position.y) - > previous_text_font.font_size * 1.5) - } else { - false - }; - - let likely_heading = previous_text_font - .is_some_and(|f| f.font_size < current_text_font.font_size) - && current_text_font.font_size > 12.0 - && is_bold - && text.len() > 1; - - // Same line, append text - if previous_text_position.is_some() - && current_text_position.y == previous_text_position.as_ref().unwrap().y - { - page_text.push_str(&text); - } else if likely_heading { - // Save text from previous text objects. - if !page_text.is_empty() { - let pdf_text = PDFText { - text: Self::normalize_parsed_text(&page_text), - likely_heading: false, - }; - pdf_texts.push(pdf_text); - - page_text.clear(); - } - - // Add heading to the top level - let pdf_text = PDFText { - text: Self::normalize_parsed_text(&text), - likely_heading: true, - }; - pdf_texts.push(pdf_text); - } - // likely heading or new paragraph - else if likely_paragraph { - // Save text from previous text objects. - if !page_text.is_empty() { - let pdf_text = PDFText { - text: Self::normalize_parsed_text(&page_text), - likely_heading: false, - }; - pdf_texts.push(pdf_text); - - page_text.clear(); - } - - page_text.push_str(&text); - } - // add new line - else if page_text.is_empty() { - page_text.push_str(&text); - } else { - page_text.push_str(&format!("\n{}", &text)); - } - - previous_text_position = Some(current_text_position); - previous_text_font = Some(current_text_font); - } - PdfPageObjectType::Image => { - // Save text from previous text objects. - if !page_text.is_empty() { - let pdf_text = PDFText { - text: Self::normalize_parsed_text(&page_text), - likely_heading: false, - }; - pdf_texts.push(pdf_text); - - page_text.clear(); - } - - let image_object = object.as_image_object().unwrap(); - - // Unwrap the width and height results - let (width, height) = ( - image_object.width().unwrap().value, - image_object.height().unwrap().value, - ); - - if width > 50.0 && height > 50.0 { - if let Ok(image) = image_object.get_raw_image() { - if let Ok(text) = self.image_parser.process_image(image) { - if !text.is_empty() { - let pdf_text = PDFText { - text: Self::normalize_parsed_text(&text), - likely_heading: false, - }; - pdf_texts.push(pdf_text); - } - } - } - } - } - _ => {} - } - } - - // Drop parsed page numbers as text - if !page_text.is_empty() && page_text != format!("{}", page_index + 1) { - let pdf_text = PDFText { - text: Self::normalize_parsed_text(&page_text), - likely_heading: false, - }; - pdf_texts.push(pdf_text); - } - - page_text.clear(); - - pdf_pages.push(PDFPage { - page_number: page_index + 1, - content: pdf_texts, - }); - - if std::env::var("DEBUG_VRKAI").is_ok() { - let page_duration = page_start_time.elapsed(); - println!("Page {} parsed in {:?}", page_index + 1, page_duration); - } - } - - if !page_text.is_empty() { - let pdf_text = PDFText { - text: Self::normalize_parsed_text(&page_text), - likely_heading: false, - }; - pdf_pages - .last_mut() - .unwrap_or(&mut PDFPage { - page_number: 1, - content: Vec::new(), - }) - .content - .push(pdf_text); - } - - if std::env::var("DEBUG_VRKAI").is_ok() { - let total_duration = start_time.elapsed(); - println!("Total PDF parsed in {:?}", total_duration); - } - - Ok(pdf_pages) - } - - fn normalize_parsed_text(parsed_text: &str) -> String { - let re_whitespaces = Regex::new(r"\s{2,}|\n").unwrap(); - let re_word_breaks = Regex::new(r"\s*").unwrap(); - - let normalized_text = re_whitespaces.replace_all(parsed_text, " "); - let normalized_text = re_word_breaks.replace_all(&normalized_text, ""); - let normalized_text = normalized_text.trim().to_string(); - - normalized_text - } -} +// use pdfium_render::prelude::*; +// use regex::Regex; +// use std::time::Instant; + +// use crate::image_parser::ImageParser; + + +// pub struct PDFParser { +// image_parser: ImageParser, +// pdfium: Pdfium, +// } + +// #[derive(Debug)] +// pub struct PDFPage { +// pub page_number: usize, +// pub content: Vec, +// } + +// #[derive(Debug)] +// pub struct PDFText { +// pub text: String, +// pub likely_heading: bool, +// } + +// impl PDFParser { +// pub fn new() -> anyhow::Result { +// let image_parser = ImageParser::new()?; + +// #[cfg(not(feature = "static"))] +// let pdfium = { +// let lib_path = match std::env::var("PDFIUM_DYNAMIC_LIB_PATH").ok() { +// Some(lib_path) => lib_path, +// None => { +// #[cfg(target_os = "linux")] +// let os = "linux"; + +// #[cfg(target_os = "macos")] +// let os = "mac"; + +// #[cfg(target_os = "windows")] +// let os = "win"; + +// #[cfg(target_arch = "aarch64")] +// let arch = "arm64"; + +// #[cfg(target_arch = "x86_64")] +// let arch = "x64"; + +// format!("pdfium/{}-{}", os, arch) +// } +// }; + +// // Look for the dynamic library in the specified path or fall back to the current directory. +// let bindings = match Pdfium::bind_to_library(Pdfium::pdfium_platform_library_name_at_path(&lib_path)) { +// Ok(bindings) => bindings, +// Err(_) => Pdfium::bind_to_library(Pdfium::pdfium_platform_library_name_at_path("./"))?, +// }; + +// Pdfium::new(bindings) +// }; + +// #[cfg(feature = "static")] +// let pdfium = Pdfium::new(Pdfium::bind_to_statically_linked_library().unwrap()); + +// Ok(PDFParser { image_parser, pdfium }) +// } + +// pub fn process_pdf_file(&self, file_buffer: Vec) -> anyhow::Result> { +// let start_time = Instant::now(); +// let document = self.pdfium.load_pdf_from_byte_vec(file_buffer, None)?; + +// struct TextPosition { +// #[allow(dead_code)] +// x: f32, +// y: f32, +// } + +// struct TextFont { +// font_size: f32, +// font_weight: PdfFontWeight, +// } + +// let mut pdf_pages = Vec::new(); +// let mut page_text = "".to_owned(); +// let mut previous_text_font: Option = None; + +// // Process metadata +// let mut metadata_text = "".to_owned(); +// for tag in document.metadata().iter() { +// match tag.tag_type() { +// PdfDocumentMetadataTagType::Title => { +// let title = tag.value(); +// if !title.is_empty() { +// metadata_text.push_str(&format!("Title: {}\n", title)); +// } +// } +// PdfDocumentMetadataTagType::Author => { +// let author = tag.value(); +// if !author.is_empty() { +// metadata_text.push_str(&format!("Author: {}\n", author)); +// } +// } +// PdfDocumentMetadataTagType::Subject => { +// let subject = tag.value(); +// if !subject.is_empty() { +// metadata_text.push_str(&format!("Subject: {}\n", subject)); +// } +// } +// PdfDocumentMetadataTagType::Keywords => { +// let keywords = tag.value(); +// if !keywords.is_empty() { +// metadata_text.push_str(&format!("Keywords: {}\n", keywords)); +// } +// } +// _ => {} +// } +// } + +// if !metadata_text.is_empty() { +// let pdf_text = PDFText { +// text: metadata_text.trim().to_string(), +// likely_heading: true, +// }; +// pdf_pages.push(PDFPage { +// page_number: 0, +// content: vec![pdf_text], +// }); +// } + +// // Process pages +// for (page_index, page) in document.pages().iter().enumerate() { +// let page_start_time = Instant::now(); +// let mut pdf_texts = Vec::new(); +// let mut previous_text_position: Option = None; + +// for object in page.objects().iter() { +// match object.object_type() { +// PdfPageObjectType::Text => { +// let text_object = object.as_text_object().unwrap(); +// let text = text_object.text(); + +// if text.is_empty() { +// continue; +// } + +// let current_text_position = TextPosition { +// x: text_object.get_translation().0.value, +// y: text_object.get_translation().1.value, +// }; + +// let current_text_font = TextFont { +// font_size: text_object.unscaled_font_size().value, +// font_weight: text_object.font().weight().unwrap_or(PdfFontWeight::Weight100), +// }; + +// let is_bold = match current_text_font.font_weight { +// PdfFontWeight::Weight500 +// | PdfFontWeight::Weight600 +// | PdfFontWeight::Weight700Bold +// | PdfFontWeight::Weight800 +// | PdfFontWeight::Weight900 => true, +// PdfFontWeight::Custom(weight) => weight >= 500, +// _ => false, +// }; + +// let likely_paragraph = if let (Some(previous_text_position), Some(previous_text_font)) = +// (previous_text_position.as_ref(), previous_text_font.as_ref()) +// { +// (current_text_position.y < previous_text_position.y +// && (previous_text_position.y - current_text_position.y) +// > previous_text_font.font_size * 1.5) +// || (previous_text_position.y < current_text_position.y +// && (current_text_position.y - previous_text_position.y) +// > previous_text_font.font_size * 1.5) +// } else { +// false +// }; + +// let likely_heading = previous_text_font +// .is_some_and(|f| f.font_size < current_text_font.font_size) +// && current_text_font.font_size > 12.0 +// && is_bold +// && text.len() > 1; + +// // Same line, append text +// if previous_text_position.is_some() +// && current_text_position.y == previous_text_position.as_ref().unwrap().y +// { +// page_text.push_str(&text); +// } else if likely_heading { +// // Save text from previous text objects. +// if !page_text.is_empty() { +// let pdf_text = PDFText { +// text: Self::normalize_parsed_text(&page_text), +// likely_heading: false, +// }; +// pdf_texts.push(pdf_text); + +// page_text.clear(); +// } + +// // Add heading to the top level +// let pdf_text = PDFText { +// text: Self::normalize_parsed_text(&text), +// likely_heading: true, +// }; +// pdf_texts.push(pdf_text); +// } +// // likely heading or new paragraph +// else if likely_paragraph { +// // Save text from previous text objects. +// if !page_text.is_empty() { +// let pdf_text = PDFText { +// text: Self::normalize_parsed_text(&page_text), +// likely_heading: false, +// }; +// pdf_texts.push(pdf_text); + +// page_text.clear(); +// } + +// page_text.push_str(&text); +// } +// // add new line +// else if page_text.is_empty() { +// page_text.push_str(&text); +// } else { +// page_text.push_str(&format!("\n{}", &text)); +// } + +// previous_text_position = Some(current_text_position); +// previous_text_font = Some(current_text_font); +// } +// PdfPageObjectType::Image => { +// // Save text from previous text objects. +// if !page_text.is_empty() { +// let pdf_text = PDFText { +// text: Self::normalize_parsed_text(&page_text), +// likely_heading: false, +// }; +// pdf_texts.push(pdf_text); + +// page_text.clear(); +// } + +// let image_object = object.as_image_object().unwrap(); + +// // Unwrap the width and height results +// let (width, height) = ( +// image_object.width().unwrap().value, +// image_object.height().unwrap().value, +// ); + +// if width > 50.0 && height > 50.0 { +// if let Ok(image) = image_object.get_raw_image() { +// if let Ok(text) = self.image_parser.process_image(image) { +// if !text.is_empty() { +// let pdf_text = PDFText { +// text: Self::normalize_parsed_text(&text), +// likely_heading: false, +// }; +// pdf_texts.push(pdf_text); +// } +// } +// } +// } +// } +// _ => {} +// } +// } + +// // Drop parsed page numbers as text +// if !page_text.is_empty() && page_text != format!("{}", page_index + 1) { +// let pdf_text = PDFText { +// text: Self::normalize_parsed_text(&page_text), +// likely_heading: false, +// }; +// pdf_texts.push(pdf_text); +// } + +// page_text.clear(); + +// pdf_pages.push(PDFPage { +// page_number: page_index + 1, +// content: pdf_texts, +// }); + +// if std::env::var("DEBUG_VRKAI").is_ok() { +// let page_duration = page_start_time.elapsed(); +// println!("Page {} parsed in {:?}", page_index + 1, page_duration); +// } +// } + +// if !page_text.is_empty() { +// let pdf_text = PDFText { +// text: Self::normalize_parsed_text(&page_text), +// likely_heading: false, +// }; +// pdf_pages +// .last_mut() +// .unwrap_or(&mut PDFPage { +// page_number: 1, +// content: Vec::new(), +// }) +// .content +// .push(pdf_text); +// } + +// if std::env::var("DEBUG_VRKAI").is_ok() { +// let total_duration = start_time.elapsed(); +// println!("Total PDF parsed in {:?}", total_duration); +// } + +// Ok(pdf_pages) +// } + +// fn normalize_parsed_text(parsed_text: &str) -> String { +// let re_whitespaces = Regex::new(r"\s{2,}|\n").unwrap(); +// let re_word_breaks = Regex::new(r"\s*").unwrap(); + +// let normalized_text = re_whitespaces.replace_all(parsed_text, " "); +// let normalized_text = re_word_breaks.replace_all(&normalized_text, ""); +// let normalized_text = normalized_text.trim().to_string(); + +// normalized_text +// } +// } diff --git a/shinkai-libs/shinkai-ocr/src/pdf_parser_v2.rs b/shinkai-libs/shinkai-ocr/src/pdf_parser_v2.rs new file mode 100644 index 000000000..57d154862 --- /dev/null +++ b/shinkai-libs/shinkai-ocr/src/pdf_parser_v2.rs @@ -0,0 +1,354 @@ +use pdfium_render::prelude::*; +use regex::Regex; +use std::time::Instant; + +use crate::image_parser::ImageParser; + +pub struct PDFParser { + image_parser: ImageParser, + pdfium: Pdfium, +} + +#[derive(Debug)] +pub struct PDFDocument { + pub metadata: PDFMetadata, + pub pages: Vec, +} + +#[derive(Debug)] +pub struct PDFMetadata { + pub title: Option, + pub author: Option, + pub subject: Option, + pub keywords: Option, +} + +#[derive(Debug)] +pub struct PDFPage { + pub page_number: usize, + pub elements: Vec, +} + +#[derive(Debug)] +pub struct PDFElement { + pub element_type: PDFElementType, + pub metadata: ElementMetadata, + pub children: Vec, // Nested elements +} + +#[derive(Debug)] +pub enum PDFElementType { + Text(PDFText), + Image(PDFImage), + // Add more types as needed (e.g., Table, Line, etc.) +} + +#[derive(Debug)] +pub struct PDFText { + pub content: String, + pub likely_heading: bool, +} + +#[derive(Debug)] +pub struct PDFImage { + pub width: f32, + pub height: f32, + pub data: Vec, // Raw image data or a reference to the image +} + +#[derive(Debug)] +pub struct ElementMetadata { + pub page_number: usize, + pub object_id: usize, + pub position: (f32, f32), // (x, y) coordinates + pub font_size: Option, + pub font_weight: Option, + pub color: Option<(u8, u8, u8)>, // RGB color + pub italic: bool, + pub underline: bool, + // Add more styles as needed +} + +impl PDFParser { + pub fn new() -> anyhow::Result { + let image_parser = ImageParser::new()?; + + #[cfg(not(feature = "static"))] + let pdfium = { + let lib_path = match std::env::var("PDFIUM_DYNAMIC_LIB_PATH").ok() { + Some(lib_path) => lib_path, + None => { + #[cfg(target_os = "linux")] + let os = "linux"; + + #[cfg(target_os = "macos")] + let os = "mac"; + + #[cfg(target_os = "windows")] + let os = "win"; + + #[cfg(target_arch = "aarch64")] + let arch = "arm64"; + + #[cfg(target_arch = "x86_64")] + let arch = "x64"; + + format!("pdfium/{}-{}", os, arch) + } + }; + + // Look for the dynamic library in the specified path or fall back to the current directory. + let bindings = match Pdfium::bind_to_library(Pdfium::pdfium_platform_library_name_at_path(&lib_path)) { + Ok(bindings) => bindings, + Err(_) => Pdfium::bind_to_library(Pdfium::pdfium_platform_library_name_at_path("./"))?, + }; + + Pdfium::new(bindings) + }; + + #[cfg(feature = "static")] + let pdfium = Pdfium::new(Pdfium::bind_to_statically_linked_library().unwrap()); + + Ok(PDFParser { image_parser, pdfium }) + } + + pub fn process_pdf_file(&self, file_buffer: Vec) -> anyhow::Result { + let start_time = Instant::now(); + let document = self.pdfium.load_pdf_from_byte_vec(file_buffer, None)?; + + // Extract metadata + let metadata = self.extract_metadata(&document); + + let mut pdf_document = PDFDocument { + metadata, + pages: Vec::new(), + }; + + // Process each page + for (page_index, page) in document.pages().iter().enumerate() { + let page_start_time = Instant::now(); + let mut elements = Vec::new(); + + for (object_index, object) in page.objects().iter().enumerate() { + match object.object_type() { + PdfPageObjectType::Text => { + if let Ok(element) = self.parse_text_object(&object, page_index + 1, object_index) { + elements.push(element); + } + } + PdfPageObjectType::Image => { + if let Ok(element) = self.parse_image_object(&object, page_index + 1, object_index) { + elements.push(element); + } + } + // Handle other object types here + _ => {} + } + } + + // Build hierarchical relationships among elements + let hierarchical_elements = self.build_hierarchy(elements); + + pdf_document.pages.push(PDFPage { + page_number: page_index + 1, + elements: hierarchical_elements, + }); + + if std::env::var("DEBUG_VRKAI").is_ok() { + let page_duration = page_start_time.elapsed(); + println!("Page {} parsed in {:?}", page_index + 1, page_duration); + } + } + + if std::env::var("DEBUG_VRKAI").is_ok() { + let total_duration = start_time.elapsed(); + println!("Total PDF parsed in {:?}", total_duration); + } + + Ok(pdf_document) + } + + fn extract_metadata(&self, document: &PdfDocument) -> PDFMetadata { + let mut metadata = PDFMetadata { + title: None, + author: None, + subject: None, + keywords: None, + }; + + for tag in document.metadata().iter() { + match tag.tag_type() { + PdfDocumentMetadataTagType::Title => { + let title = tag.value(); + if !title.is_empty() { + metadata.title = Some(title.to_string()); + } + } + PdfDocumentMetadataTagType::Author => { + let author = tag.value(); + if !author.is_empty() { + metadata.author = Some(author.to_string()); + } + } + PdfDocumentMetadataTagType::Subject => { + let subject = tag.value(); + if !subject.is_empty() { + metadata.subject = Some(subject.to_string()); + } + } + PdfDocumentMetadataTagType::Keywords => { + let keywords = tag.value(); + if !keywords.is_empty() { + metadata.keywords = Some(keywords.to_string()); + } + } + _ => {} + } + } + + metadata + } + + fn parse_text_object( + &self, + object: &PdfPageObject, + page_number: usize, + object_id: usize, + ) -> anyhow::Result { + let text_object = object + .as_text_object() + .ok_or(anyhow::anyhow!("Not a text object"))?; + let text = text_object.text(); + + if text.is_empty() { + return Err(anyhow::anyhow!("Empty text")); + } + + let position = ( + text_object.get_translation().0.value, + text_object.get_translation().1.value, + ); + + let font_size = text_object.unscaled_font_size().value; + let font_weight = text_object.font().weight(); + let font_weight = match font_weight { + Ok(weight) => Some(weight), + Err(_) => None, + }; + + let color = None; // Remove the call to text_color and set color to None + + let italic = false; // Remove the call to is_italic and set italic to false + let underline = false; // Remove the call to is_underlined and set underline to false + + let likely_heading = self.determine_likely_heading(font_size, &font_weight, &text); + + let pdf_text = PDFText { + content: Self::normalize_parsed_text(&text), + likely_heading, + }; + + let metadata = ElementMetadata { + page_number, + object_id, + position, + font_size: Some(font_size), + font_weight, + color, + italic, + underline, + }; + + Ok(PDFElement { + element_type: PDFElementType::Text(pdf_text), + metadata, + children: Vec::new(), + }) + } + + fn parse_image_object( + &self, + object: &PdfPageObject, + page_number: usize, + object_id: usize, + ) -> anyhow::Result { + let image_object = object.as_image_object().ok_or(anyhow::anyhow!("Not an image object"))?; + + let width = image_object.width().unwrap_or(PdfPoints::ZERO).value; + let height = image_object.height().unwrap_or(PdfPoints::ZERO).value; + + // Optionally process the image to extract text or other data + let data = if let Ok(image) = image_object.get_raw_image() { + image.into_bytes() // Convert DynamicImage to Vec + } else { + Vec::new() + }; + + let pdf_image = PDFImage { width, height, data }; + + let position = ( + image_object.get_translation().0.value, + image_object.get_translation().1.value, + ); + + let color = None; // Images typically don't have a color in the same sense as text + let italic = false; + let underline = false; + + let metadata = ElementMetadata { + page_number, + object_id, + position, + font_size: None, + font_weight: None, + color, + italic, + underline, + }; + + Ok(PDFElement { + element_type: PDFElementType::Image(pdf_image), + metadata, + children: Vec::new(), + }) + } + + fn determine_likely_heading( + &self, + current_font_size: f32, + current_font_weight: &Option, + text: &str, + ) -> bool { + // Implement your logic to determine if the text is likely a heading + // For example, check if the font size is larger than a threshold and if it's bold + let is_bold = match current_font_weight { + Some(PdfFontWeight::Weight500) + | Some(PdfFontWeight::Weight600) + | Some(PdfFontWeight::Weight700Bold) + | Some(PdfFontWeight::Weight800) + | Some(PdfFontWeight::Weight900) => true, + Some(PdfFontWeight::Custom(weight)) => *weight >= 500, + _ => false, + }; + + current_font_size > 12.0 && is_bold && text.len() > 1 + } + + fn build_hierarchy(&self, elements: Vec) -> Vec { + // Implement logic to build a hierarchical tree from flat elements + // This could involve grouping elements based on positions, font sizes, etc. + // For simplicity, returning the elements as-is. You can enhance this as needed. + elements + } + + fn normalize_parsed_text(parsed_text: &str) -> String { + let re_whitespaces = Regex::new(r"\s{2,}|\n").unwrap(); + let re_word_breaks = Regex::new(r"\s*").unwrap(); + + let normalized_text = re_whitespaces.replace_all(parsed_text, " "); + let normalized_text = re_word_breaks.replace_all(&normalized_text, ""); + let normalized_text = normalized_text.trim().to_string(); + + normalized_text + } +} diff --git a/shinkai-libs/shinkai-ocr/src/pdf_to_md.rs b/shinkai-libs/shinkai-ocr/src/pdf_to_md.rs new file mode 100644 index 000000000..84d1cff76 --- /dev/null +++ b/shinkai-libs/shinkai-ocr/src/pdf_to_md.rs @@ -0,0 +1,118 @@ +use std::fs::{self, File}; +use std::io::Write; +use std::path::Path; + +use crate::pdf_parser_v2::{PDFDocument, PDFElement, PDFElementType, PDFImage, PDFPage}; + +pub struct MarkdownGenerator { + image_output_dir: String, +} + +impl MarkdownGenerator { + /// Creates a new MarkdownGenerator with the specified image output directory. + pub fn new(image_output_dir: String) -> anyhow::Result { + // Create the directory if it doesn't exist + fs::create_dir_all(&image_output_dir)?; + Ok(MarkdownGenerator { image_output_dir }) + } + + /// Converts a PDFDocument into a Markdown string. + pub fn to_markdown(&self, document: &PDFDocument) -> anyhow::Result { + let mut markdown = String::new(); + + // Add document metadata as front matter (optional) + if document.metadata.title.is_some() + || document.metadata.author.is_some() + || document.metadata.subject.is_some() + || document.metadata.keywords.is_some() + { + markdown.push_str("---\n"); + if let Some(title) = &document.metadata.title { + markdown.push_str(&format!("title: \"{}\"\n", title)); + } + if let Some(author) = &document.metadata.author { + markdown.push_str(&format!("author: \"{}\"\n", author)); + } + if let Some(subject) = &document.metadata.subject { + markdown.push_str(&format!("subject: \"{}\"\n", subject)); + } + if let Some(keywords) = &document.metadata.keywords { + markdown.push_str(&format!("keywords: \"{}\"\n", keywords)); + } + markdown.push_str("---\n\n"); + } + + // Process each page + for page in &document.pages { + markdown.push_str(&self.process_page(page)?); + markdown.push_str("\n\n---\n\n"); // Page separator + } + + Ok(markdown) + } + + /// Processes a single PDF page and converts it to Markdown. + fn process_page(&self, page: &PDFPage) -> anyhow::Result { + let mut markdown = String::new(); + + for element in &page.elements { + markdown.push_str(&self.process_element(element, 0)?); + markdown.push('\n'); + } + + Ok(markdown) + } + + /// Recursively processes a PDF element and its children, converting them to Markdown. + /// + /// `indent_level` is used to manage indentation for nested elements. + fn process_element(&self, element: &PDFElement, indent_level: usize) -> anyhow::Result { + let mut markdown = String::new(); + let indent = " ".repeat(indent_level); // 4 spaces per indent level + + match &element.element_type { + PDFElementType::Text(text) => { + if text.likely_heading { + // Determine heading level based on font size or other criteria + // For simplicity, we'll use Markdown's level 2 headings + markdown.push_str(&format!("{}## {}\n", indent, text.content)); + } else { + // Regular paragraph + markdown.push_str(&format!("{}{}\n", indent, text.content)); + } + } + PDFElementType::Image(image) => { + // Save the image and get its path + let image_filename = self.save_image(image)?; + // Reference the image in Markdown + markdown.push_str(&format!("{}![Image]({})\n", indent, image_filename)); + } + // Handle other element types (e.g., Table, Line) as needed + } + + // Process children recursively + for child in &element.children { + markdown.push_str(&self.process_element(child, indent_level + 1)?); + } + + Ok(markdown) + } + + /// Saves an image to the specified output directory and returns the relative path. + fn save_image(&self, image: &PDFImage) -> anyhow::Result { + // Generate a unique filename, e.g., image_1.png, image_2.png, etc. + // For simplicity, use a timestamp or a UUID. Here, we'll use a random UUID. + use uuid::Uuid; + + let uuid = Uuid::new_v4(); + let filename = format!("image_{}.png", uuid); + let filepath = Path::new(&self.image_output_dir).join(&filename); + + // Save the image data to the file + let mut file = File::create(&filepath)?; + file.write_all(&image.data)?; + + // Return the relative path to be used in Markdown + Ok(filepath.to_string_lossy().to_string()) + } +} diff --git a/shinkai-libs/shinkai-ocr/tests/pdf_parser_tests.rs b/shinkai-libs/shinkai-ocr/tests/pdf_parser_tests.rs index a52089e18..8a5dbe69b 100644 --- a/shinkai-libs/shinkai-ocr/tests/pdf_parser_tests.rs +++ b/shinkai-libs/shinkai-ocr/tests/pdf_parser_tests.rs @@ -1,38 +1,39 @@ -use shinkai_ocr::pdf_parser::PDFParser; +// // use shinkai_ocr::pdf_parser::PDFParser; -#[tokio::test] -async fn pdf_parsing() -> Result<(), Box> { - let file = std::fs::read("../../files/shinkai_intro.pdf")?; - let pdf_parser = PDFParser::new()?; - let parsed_pages = pdf_parser.process_pdf_file(file)?; +// #[tokio::test] +// async fn pdf_parsing() -> Result<(), Box> { +// let file = std::fs::read("../../files/shinkai_intro.pdf")?; +// let pdf_parser = PDFParser::new()?; +// let parsed_pages = pdf_parser.process_pdf_file(file)?; +// println!("Parsed pages: {:?}", parsed_pages); - assert_eq!( - parsed_pages.first().unwrap().content.first().unwrap().text, - "Shinkai Network Manifesto (Early Preview)" - ); +// assert_eq!( +// parsed_pages.first().unwrap().content.first().unwrap().text, +// "Shinkai Network Manifesto (Early Preview)" +// ); - Ok(()) -} +// Ok(()) +// } -// #[tokio::test] -// Note: needs fixing -async fn pdf_table_parsing() -> Result<(), Box> { - let file = std::fs::read("../../files/Shinkai_Table_Test_01.pdf")?; - let pdf_parser = PDFParser::new()?; - let parsed_pages = pdf_parser.process_pdf_file(file)?; +// // #[tokio::test] +// // Note: needs fixing +// async fn pdf_table_parsing() -> Result<(), Box> { +// let file = std::fs::read("../../files/Shinkai_Table_Test_01.pdf")?; +// let pdf_parser = PDFParser::new()?; +// let parsed_pages = pdf_parser.process_pdf_file(file)?; - // Print out the content of each page - for page in &parsed_pages { - println!("Page Number: {}", page.page_number); - for text in &page.content { - println!("Text: {}", text.text); - } - } +// // Print out the content of each page +// for page in &parsed_pages { +// println!("Page Number: {}", page.page_number); +// for text in &page.content { +// println!("Text: {}", text.text); +// } +// } - assert_eq!( - parsed_pages.first().unwrap().content.first().unwrap().text, - "Shinkai Network Manifesto (Early Preview)" - ); +// assert_eq!( +// parsed_pages.first().unwrap().content.first().unwrap().text, +// "Shinkai Network Manifesto (Early Preview)" +// ); - Ok(()) -} +// Ok(()) +// } diff --git a/shinkai-libs/shinkai-ocr/tests/pdf_parser_v2_tests.rs b/shinkai-libs/shinkai-ocr/tests/pdf_parser_v2_tests.rs new file mode 100644 index 000000000..e4713bfdb --- /dev/null +++ b/shinkai-libs/shinkai-ocr/tests/pdf_parser_v2_tests.rs @@ -0,0 +1,92 @@ +use shinkai_ocr::pdf_parser_v2::{PDFElementType, PDFParser}; +use shinkai_ocr::pdf_to_md::MarkdownGenerator; // Import the MarkdownGenerator + +use std::fs; +use std::io::Write; + +#[tokio::test] +async fn pdf_parsing() -> Result<(), Box> { + // Read the PDF file + let file = fs::read("../../files/shinkai_intro.pdf")?; + + // Initialize the PDF parser + let pdf_parser = PDFParser::new()?; + + // Process the PDF file + let parsed_document = pdf_parser.process_pdf_file(file)?; + + // Print the parsed document for debugging + println!("Parsed document: {:?}", parsed_document); + + // Initialize the Markdown generator with an output directory for images + let markdown_generator = MarkdownGenerator::new("output_images".to_string())?; + + // Generate markdown from the parsed document + let markdown = markdown_generator.to_markdown(&parsed_document)?; + + // Print the generated markdown to the console + println!("Generated Markdown:\n{}", markdown); + + // Assert the first page's first element's text content + if let Some(first_page) = parsed_document.pages.first() { + if let Some(first_element) = first_page.elements.first() { + if let PDFElementType::Text(text_element) = &first_element.element_type { + assert_eq!(text_element.content, "Shinkai Network Manifesto (Early Preview)"); + } else { + panic!("First element is not a text element"); + } + } else { + panic!("No elements found on the first page"); + } + } else { + panic!("No pages found in the parsed document"); + } + + Ok(()) +} + +#[tokio::test] +async fn pdf_parsing_from_local_file() -> Result<(), Box> { + // Path to the local PDF file + let local_file_path = "../../files/thinkos.pdf"; + + // Initialize the PDF parser + let pdf_parser = PDFParser::new()?; + + // Process the PDF file + let file = fs::read(local_file_path)?; + let parsed_document = pdf_parser.process_pdf_file(file)?; + + // Print the parsed document for debugging + println!("Parsed document: {:?}", parsed_document); + + // Initialize the Markdown generator with an output directory for images + let markdown_generator = MarkdownGenerator::new("output_images".to_string())?; + + // Generate markdown from the parsed document + let markdown = markdown_generator.to_markdown(&parsed_document)?; + + // Print the generated markdown to the console + println!("Generated Markdown:\n{}", markdown); + + // Save the generated markdown to a file called thinkos.md + let mut file = fs::File::create("thinkos.md")?; + file.write_all(markdown.as_bytes())?; + + // Assert the first page's first element's text content + if let Some(first_page) = parsed_document.pages.first() { + if let Some(first_element) = first_page.elements.first() { + if let PDFElementType::Text(text_element) = &first_element.element_type { + assert_eq!(text_element.content, "Think OS"); + } else { + panic!("First element is not a text element"); + } + } else { + panic!("No elements found on the first page"); + } + } else { + panic!("No pages found in the parsed document"); + } + + Ok(()) +} diff --git a/shinkai-libs/shinkai-ocr/thinkos.md b/shinkai-libs/shinkai-ocr/thinkos.md new file mode 100644 index 000000000..554312866 --- /dev/null +++ b/shinkai-libs/shinkai-ocr/thinkos.md @@ -0,0 +1,8668 @@ +Think OS + +A Brief Introduction to Operating Systems + +Version 0.7.4 + + + +--- + + + +--- + +Think OS + +A Brief Introduction to Operating Systems + +Version 0.7.4 + +Allen B. Downey + +Green Tea Press + +Needham, Massachusetts + + + +--- + +Copyright + +© + +2015 Allen B. Downey. + +Green Tea Press + +9 Washburn Ave + +Needham MA 02492 + +Permission is granted to copy, distribute, and/or modify this document under + +the terms of the Creative Commons Attribution-NonCommercial-ShareAlike + +4.0 International License, which is available at + +http://creativecommons. + +org/licenses/by-nc-sa/4.0/ + +. + +The L + +A + +T + +E + +X source for this book is available from + +http://greenteapress.com/ + +thinkos + +. + + + +--- + +## Preface + +In many computer science programs, Operating Systems is an advanced topic. + +By the time students take it, they know how to program in C, and they have + +probably taken a class in Computer Architecture. Usually the goal of the class + +is to expose students to the design and implementation of operating systems, + +with the implied assumption that some of them will do research in this area, + +or write part of an OS. + +This book is intended for a different audience, and it has different goals. I + +developed it for a class at Olin College called Software Systems. + +Most students taking this class learned to program in Python, so one of the + +goals is to help them learn C. For that part of the class, I use Griffiths and Grif + +fiths, + +Head First C + +, from O’Reilly Media. This book is meant to complement + +that one. + +Few of my students will ever write an operating system, but many of them + +will write low-level applications in C or work on embedded systems. My class + +includes material from operating systems, networks, databases, and embedded + +systems, but it emphasizes the topics programmers need to know. + +This book does not assume that you have studied Computer Architecture. As + +we go along, I will explain what we need. + +If this book is successful, it should give you a better understanding of what is + +happening when programs run, and what you can do to make them run better + +and faster. + +Chapter 1 explains some of the differences between compiled and interpreted + +languages, with some insight into how compilers work. Recommended reading: + +Head First C + +Chapter 1. + +Chapter 2 explains how the operating system uses processes to protect running + +programs from interfering with each other. + +Chapter 3 explains virtual memory and address translation. Recommended + +reading: + +Head First C + +Chapter 2. + + + +--- + +vi Chapter 0. Preface + +Chapter 4 is about file systems and data streams. Recommended reading: + +Head First C + +Chapter 3. + +Chapter 5 describes how numbers, letters, and other values are encoded, and + +presents the bitwise operators. + +Chapter 6 explains how to use dynamic memory management, and how it + +works. Recommended reading: + +Head First C + +Chapter 6. + +Chapter 7 is about caching and the memory hierarchy. + +Chapter 8 is about multitasking and scheduling. + +Chapter 9 is about POSIX threads and mutexes. Recommended reading: + +Head + +First C + +Chapter 12 and + +Little Book of Semaphores + +Chapters 1 and 2. + +Chapter 10 is about POSIX condition variables and the producer/consumer + +problem. Recommended reading: + +Little Book of Semaphores + +Chapters 3 and + +4. + +Chapter 11 is about using POSIX semaphores and implementing semaphores + +in C. + +## A note on this draft + +The current version of this book is an early draft. While I am working on the + +text, I have not yet included the figures. So there are a few places where, I’m + +sure, the explanation will be greatly improved when the figures are ready. + +## 0.1 Using the code + +Example code for this book is available from + +https://github.com/ + +AllenDowney/ThinkOS + +. Git is a version control system that allows you to + +keep track of the files that make up a project. A collection of files under + +Git’s control is called a + +repository + +. GitHub is a hosting service that provides + +storage for Git repositories and a convenient web interface. + +The GitHub homepage for my repository provides several ways to work with + +the code: + +ˆ + +You can create a copy of my repository on GitHub by pressing the + +Fork + +button. If you don’t already have a GitHub account, you’ll need to + +create one. After forking, you’ll have your own repository on GitHub + + + +--- + +0.1. Using the code vii + +that you can use to keep track of code you write while working on this + +book. Then you can clone the repo, which means that you copy the files + +to your computer. + +ˆ + +Or you could clone my repository. You don’t need a GitHub account to + +do this, but you won’t be able to write your changes back to GitHub. + +ˆ + +If you don’t want to use Git at all, you can download the files in a Zip + +file using the button in the lower-right corner of the GitHub page. + +## Contributor List + +If you have a suggestion or correction, please send email to + +downey@allendowney.com + +. If I make a change based on your feedback, + +I will add you to the contributor list (unless you ask to be omitted). + +If you include at least part of the sentence the error appears in, that makes it + +easy for me to search. Page and section numbers are fine, too, but not quite + +as easy to work with. Thanks! + +ˆ + +I am grateful to the students in Software Systems at Olin College, who tested + +an early draft of this book in Spring 2014. They corrected many errors and + +made many helpful suggestions. I appreciate their pioneering spirit! + +ˆ + +James P Giannoules spotted a copy-and-paste error. + +ˆ + +Andy Engle knows the difference between GB and GiB. + +ˆ + +Aashish Karki noted some broken syntax. + +Other people who found typos and errors include Jim Tyson, Donald Robertson, + +Jeremy Vermast, Yuzhong Huang, Ian Hill. + + + +--- + +viii Chapter 0. Preface + + + +--- + +## Contents + +Preface v + +0.1 Using the code . . . . . . . . . . . . . . . . . . . . . . . . . . + +vi + +1 Compilation 1 + +1.1 Compiled and interpreted languages . . . . . . . . . . . . . . + +1 + +1.2 Static types . . . . . . . . . . . . . . . . . . . . . . . . . . . + +1 + +1.3 The compilation process . . . . . . . . . . . . . . . . . . . . + +3 + +1.4 Object code . . . . . . . . . . . . . . . . . . . . . . . . . . . + +4 + +1.5 Assembly code . . . . . . . . . . . . . . . . . . . . . . . . . . + +5 + +1.6 Preprocessing . . . . . . . . . . . . . . . . . . . . . . . . . . + +6 + +1.7 Understanding errors . . . . . . . . . . . . . . . . . . . . . . + +6 + +2 Processes 9 + +2.1 Abstraction and virtualization . . . . . . . . . . . . . . . . . + +9 + +2.2 Isolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + +10 + +2.3 UNIX processes . . . . . . . . . . . . . . . . . . . . . . . . . + +12 + +3 Virtual memory 15 + +3.1 A bit of information theory . . . . . . . . . . . . . . . . . . . + +15 + +3.2 Memory and storage . . . . . . . . . . . . . . . . . . . . . . + +16 + +3.3 Address spaces . . . . . . . . . . . . . . . . . . . . . . . . . + +16 + + + +--- + +x Contents + +3.4 Memory segments . . . . . . . . . . . . . . . . . . . . . . . . + +17 + +3.5 Static local variables . . . . . . . . . . . . . . . . . . . . . . + +20 + +3.6 Address translation . . . . . . . . . . . . . . . . . . . . . . . + +20 + +4 Files and file systems 23 + +4.1 Disk performance . . . . . . . . . . . . . . . . . . . . . . . . + +25 + +4.2 Disk metadata . . . . . . . . . . . . . . . . . . . . . . . . . . + +27 + +4.3 Block allocation . . . . . . . . . . . . . . . . . . . . . . . . . + +28 + +4.4 Everything is a file? . . . . . . . . . . . . . . . . . . . . . . . + +28 + +5 More bits and bytes 31 + +5.1 Representing integers . . . . . . . . . . . . . . . . . . . . . . + +31 + +5.2 Bitwise operators . . . . . . . . . . . . . . . . . . . . . . . . + +32 + +5.3 Representing floating-point numbers . . . . . . . . . . . . . . + +33 + +5.4 Unions and memory errors . . . . . . . . . . . . . . . . . . . + +35 + +5.5 Representing strings . . . . . . . . . . . . . . . . . . . . . . . + +36 + +6 Memory management 39 + +6.1 Memory errors . . . . . . . . . . . . . . . . . . . . . . . . . . + +39 + +6.2 Memory leaks . . . . . . . . . . . . . . . . . . . . . . . . . . + +41 + +6.3 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . + +43 + +7 Caching 45 + +7.1 How programs run . . . . . . . . . . . . . . . . . . . . . . . + +45 + +7.2 Cache performance . . . . . . . . . . . . . . . . . . . . . . . + +47 + +7.3 Locality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + +47 + +7.4 Measuring cache performance . . . . . . . . . . . . . . . . . + +48 + +7.5 Programming for cache performance . . . . . . . . . . . . . . + +51 + +7.6 The memory hierarchy . . . . . . . . . . . . . . . . . . . . . + +52 + +7.7 Caching policy . . . . . . . . . . . . . . . . . . . . . . . . . . + +53 + +7.8 Paging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + +54 + + + +--- + +Contents xi + +8 Multitasking 57 + +8.1 Hardware state . . . . . . . . . . . . . . . . . . . . . . . . . + +58 + +8.2 Context switching . . . . . . . . . . . . . . . . . . . . . . . . + +58 + +8.3 The process life cycle . . . . . . . . . . . . . . . . . . . . . . + +59 + +8.4 Scheduling . . . . . . . . . . . . . . . . . . . . . . . . . . . . + +60 + +8.5 Real-time scheduling . . . . . . . . . . . . . . . . . . . . . . + +62 + +9 Threads 63 + +9.1 Creating threads . . . . . . . . . . . . . . . . . . . . . . . . + +64 + +9.2 Creating threads . . . . . . . . . . . . . . . . . . . . . . . . + +64 + +9.3 Joining threads . . . . . . . . . . . . . . . . . . . . . . . . . + +66 + +9.4 Synchronization errors . . . . . . . . . . . . . . . . . . . . . + +67 + +9.5 Mutex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + +69 + +10 Condition variables 71 + +10.1 The work queue . . . . . . . . . . . . . . . . . . . . . . . . . + +71 + +10.2 Producers and consumers . . . . . . . . . . . . . . . . . . . . + +74 + +10.3 Mutual exclusion . . . . . . . . . . . . . . . . . . . . . . . . + +75 + +10.4 Condition variables . . . . . . . . . . . . . . . . . . . . . . . + +77 + +10.5 Condition variable implementation . . . . . . . . . . . . . . + +80 + +11 Semaphores in C 81 + +11.1 POSIX Semaphores . . . . . . . . . . . . . . . . . . . . . . . + +81 + +11.2 Producers and consumers with semaphores . . . . . . . . . . + +83 + +11.3 Make your own semaphores . . . . . . . . . . . . . . . . . . + +85 + + + +--- + +xii Contents + + + +--- + +## Chapter 1 + +## Compilation + +## 1.1 Compiled and interpreted languages + +People often describe programming languages as either compiled or inter + +preted. “Compiled” means that programs are translated into machine lan + +guage and then executed by hardware; “interpreted” means that programs + +are read and executed by a software interpreter. Usually C is considered a + +compiled language and Python is considered an interpreted language. But the + +distinction is not always clear-cut. + +First, many languages can be either compiled or interpreted. For example, + +there are C interpreters and Python compilers. Second, there are languages + +like Java that use a hybrid approach, compiling programs into an intermediate + +language and then running the translated program in an interpreter. Java uses + +an intermediate language called Java bytecode, which is similar to machine + +language, but it is executed by a software interpreter, the Java virtual machine + +(JVM). + +So being compiled or interpreted is not an intrinsic characteristic of a lan + +guage; nevertheless, there are some general differences between compiled and + +interpreted languages. + +## 1.2 Static types + +Many interpreted languages support dynamic types, but compiled languages + +are usually limited to static types. In a statically-typed language, you can tell + + + +--- + +2 Chapter 1. Compilation + +by looking at the program what type each variable refers to. In a dynamically + +typed language, you don’t always know the type of a variable until the pro + +gram is running. In general, + +static + +refers to things that happen at compile + +time (while a program is being compiled), and + +dynamic + +refers to things that + +happen at run time (while a program is running). + +For example, in Python you can write a function like this: + +def add(x, y): + +return x + y + +Looking at this code, you can’t tell what type + +x + +and + +y + +will refer to at run + +time. This function might be called several times, each time with values with + +different types. Any values that support the addition operator will work; any + +other types will cause an exception or + +runtime error + +. + +In C you would write the same function like this: + +int add(int x, int y) { + +return x + y; + +} + +The first line of the function includes + +type declarations + +for the parameters + +and the return value: + +x + +and + +y + +are declared to be integers, which means that + +we can check at compile time whether the addition operator is legal for this + +type (it is). The return value is also declared to be an integer. + +Because of these declarations, when this function is called elsewhere in the + +program, the compiler can check whether the arguments provided have the + +right type, and whether the return value is used correctly. + +These checks happen before the program starts executing, so errors can be + +found earlier. More importantly, errors can be found in parts of the program + +that have never run. Furthermore, these checks don’t have to happen at run + +time, which is one of the reasons compiled languages generally run faster than + +interpreted languages. + +Declaring types at compile time also saves space. In dynamic languages, vari + +able names are stored in memory while the program runs, and they are of + +ten accessible by the program. For example, in Python the built-in function + +locals + +returns a dictionary that contains variable names and their values. + +Here’s an example in a Python interpreter: + +>>> x = 5 + +>>> print locals() + +{'x': 5, '__builtins__': , + +'__name__': '__main__', '__doc__': None, '__package__': None} + + + +--- + +1.3. The compilation process 3 + +This shows that the name of the variable is stored in memory while the program + +is running (along with some other values that are part of the default runtime + +environment). + +In compiled languages, variable names exist at compile-time but not at run + +time. The compiler chooses a location for each variable and records these + +locations as part of the compiled program. + +1 + +The location of a variable is + +called its + +address + +. At run time, the value of each variable is stored at its + +address, but the names of the variables are not stored at all (unless they are + +added by the compiler for purposes of debugging). + +## 1.3 The compilation process + +As a programmer, you should have a mental model of what happens during + +compilation. If you understand the process, it will help you interpret error + +messages, debug your code, and avoid common pitfalls. + +The steps of compilation are: + +1. + +Preprocessing: C is one of several languages that include + +preprocessing + +directives + +that take effect before the program is compiled. For example, + +the + +#include + +directive causes the source code from another file to be + +inserted at the location of the directive. + +2. + +Parsing: During parsing, the compiler reads the source code and builds + +an internal representation of the program, called an + +abstract syntax + +tree + +. Errors detected during this step are generally syntax errors. + +3. + +Static checking: The compiler checks whether variables and values have + +the right type, whether functions are called with the right number and + +type of arguments, etc. Errors detected during this step are sometimes + +called + +static semantic + +errors. + +4. + +Code generation: The compiler reads the internal representation of the + +program and generates machine code or byte code. + +5. + +Linking: If the program uses values and functions defined in a library, + +the compiler has to find the appropriate library and include the required + +code. + +1 + +This is a simplification; we will go into more detail later. + + + +--- + +4 Chapter 1. Compilation + +6. + +Optimization: At several points in the process, the compiler can trans + +form the program to generate code that runs faster or uses less space. + +Most optimizations are simple changes that eliminate obvious waste, but + +some compilers perform sophisticated analyses and transformations. + +Normally when you run + +gcc + +, it runs all of these steps and generates an exe + +cutable file. For example, here is a minimal C program: + +#include + +int main() + +{ + +printf("Hello World\n"); + +} + +If you save this code in a file called + +hello.c + +, you can compile and run it like + +this: + +$ gcc hello.c + +$ ./a.out + +By default, + +gcc + +stores the executable code in a file called + +a.out + +(which origi + +nally stood for “assembler output”). The second line runs the executable. The + +prefix + +./ + +tells the shell to look for it in the current directory. + +It is usually a good idea to use the + +-o + +flag to provide a better name for the + +executable: + +$ gcc hello.c -o hello + +$ ./hello + +## 1.4 Object code + +The + +-c + +flag tells + +gcc + +to compile the program and generate machine code, but + +not to link it or generate an executable: + +$ gcc hello.c -c + +The result is a file named + +hello.o + +, where the + +o + +stands for + +object code + +, which + +is the compiled program. Object code is not executable, but it can be linked + +into an executable. + +The UNIX command + +nm + +reads an object file and generates information about + +the names it defines and uses. For example: + +$ nm hello.o + +0000000000000000 T main + +U puts + + + +--- + +1.5. Assembly code 5 + +This output indicates that + +hello.o + +defines the name + +main + +and uses a function + +named + +puts + +, which stands for “put string”. In this example, + +gcc + +performs an + +optimization by replacing + +printf + +, which is a large and complicated function, + +with + +puts + +, which is relatively simple. + +You can control how much optimization + +gcc + +does with the + +-O + +flag. By default, + +it does very little optimization, which can make debugging easier. The option + +-O1 + +turns on the most common and safe optimizations. Higher numbers turn + +on additional optimizations that require longer compilation time. + +In theory, optimization should not change the behavior of the program, other + +than to speed it up. But if your program has a subtle bug, you might find that + +optimization makes the bug appear or disappear. It is usually a good idea to + +turn off optimization while you are developing new code. Once the program + +is working and passing appropriate tests, you can turn on optimization and + +confirm that the tests still pass. + +## 1.5 Assembly code + +Similar to the + +-c + +flag, the + +-S + +flag tells + +gcc + +to compile the program and generate + +assembly code, which is basically a human-readable form of machine code. + +$ gcc hello.c -S + +The result is a file named + +hello.s + +, which might look something like this: + +.file "hello.c" + +.section .rodata + +.LC0: + +.string "Hello World" + +.text + +.globl main + +.type main, @function + +main: + +.LFB0: + +.cfi_startproc + +pushq %rbp + +.cfi_def_cfa_offset 16 + +.cfi_offset 6, -16 + +movq %rsp, %rbp + +.cfi_def_cfa_register 6 + +movl $.LC0, %edi + +call puts + + + +--- + +6 Chapter 1. Compilation + +movl $0, %eax + +popq %rbp + +.cfi_def_cfa 7, 8 + +ret + +.cfi_endproc + +.LFE0: + +.size main, .-main + +.ident "GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3" + +.section .note.GNU-stack,"",@progbits + +gcc + +is usually configured to generate code for the machine you are running on, + +so for me it generates x86 assembly language, which runs on a wide variety + +of processors from Intel, AMD, and others. If you are running on a different + +architecture, you might see different code. + +## 1.6 Preprocessing + +Taking another step backward through the compilation process, you can use + +the + +-E + +flag to run the preprocessor only: + +$ gcc hello.c -E + +The result is the output from the preprocessor. In this example, it contains + +the included code from + +stdio.h + +, and all the files included from + +stdio.h + +, and + +all the files included from those files, and so on. On my machine, the total is + +more than 800 lines of code. Since almost every C program includes + +stdio.h + +, + +those 800 lines of code get compiled a lot. If, like many C programs, you also + +include + +stdlib.h + +, the result is more than 1800 lines of code. + +## 1.7 Understanding errors + +Now that we know the steps in the compilation process, it is easier to under + +stand error messages. For example, if there is an error in a + +#include + +directive, + +you’ll get a message from the preprocessor: + +hello.c:1:20: fatal error: stdioo.h: No such file or directory + +compilation terminated. + +If there’s a syntax error, you get a message from the compiler: + +hello.c: In function 'main': + +hello.c:6:1: error: expected ';' before '}' token + +If you use a function that’s not defined in any of the standard libraries, you + +get a message from the linker: + + + +--- + +1.7. Understanding errors 7 + +/tmp/cc7iAUbN.o: In function `main': + +hello.c:(.text+0xf): undefined reference to `printff' + +collect2: error: ld returned 1 exit status + +ld + +is the name of the UNIX linker, so named because “loading” is another + +step in the compilation process that is closely related to linking. + +Once the program starts, C does very little runtime checking, so there are + +only a few runtime errors you are likely to see. If you divide by zero, or + +perform another illegal floating-point operation, you will get a “Floating point + +exception.” And if you try to read or write an incorrect location in memory, + +you will get a “Segmentation fault.” + + + +--- + +8 Chapter 1. Compilation + + + +--- + +## Chapter 2 + +## Processes + +## 2.1 Abstraction and virtualization + +Before we talk about processes, I want to define a few words: + +ˆ + +Abstraction: An abstraction is a simplified representation of something + +complicated. For example, if you drive a car, you understand that when + +you turn the wheel left, the car goes left, and vice versa. Of course, + +the steering wheel is connected to a sequence of mechanical and (often) + +hydraulic systems that turn the wheels, and the wheels interact with + +the road in ways that can be complex, but as a driver, you normally + +don’t have to think about any of those details. You can get along very + +well with a simple mental model of steering. Your mental model is an + +abstraction. + +Similarly, when you use a web browser, you understand that when you + +click on a link, the browser displays the page the link refers to. The soft + +ware and network communication that make that possible are complex, + +but as a user, you don’t have to know the details. + +A large part of software engineering is designing abstractions like these + +that allow users and other programmers to use powerful and complicated + +systems without having to know about the details of their implementa + +tion. + +ˆ + +Virtualization: An important kind of abstraction is virtualization, which + +is the process of creating a desirable illusion. + +For example, many public libraries participate in inter-library collabora + +tions that allow them to borrow books from each other. When I request + + + +--- + +10 Chapter 2. Processes + +a book, sometimes the book is on the shelf at my local library, but other + +times it has to be transferred from another collection. Either way, I get + +a notification when it is available for pickup. I don’t need to know where + +it came from, and I don’t need to know which books my library has. As + +a whole, the system creates the illusion that my library has every book + +in the world. + +The collection physically located at my local library might be small, + +but the collection available to me virtually includes every book in the + +inter-library collaboration. + +As another example, most computers are only connected to one network, + +but that network is connected to others, and so on. What we call the + +Internet is a collection of networks and a set of protocols that forward + +packets from one network to the next. From the point of view of a user or + +programmer, the system behaves as if every computer on the Internet is + +connected to every other computer. The number of physical connections + +is small, but the number of virtual connections is very large. + +The word “virtual” is often used in the context of a virtual machine, which is + +software that creates the illusion of a dedicated computer running a particular + +operating system, when in reality the virtual machine might be running, along + +with many other virtual machines, on a computer running a different operating + +system. + +In the context of virtualization, we sometimes call what is really happening + +“physical”, and what is virtually happening either “logical” or “abstract.” + +## 2.2 Isolation + +One of the most important principles of engineering is isolation: when you + +are designing a system with multiple components, it is usually a good idea to + +isolate them from each other so that a change in one component doesn’t have + +undesired effects on other components. + +One of the most important goals of an operating system is to isolate each run + +ning program from the others so that programmers don’t have to think about + +every possible interaction. The software object that provides this isolation is + +a + +process + +. + +A process is a software object that represents a running program. I mean + +“software object” in the sense of object-oriented programming; in general, an + +object contains data and provides methods that operate on the data. A process + +is an object that contains the following data: + + + +--- + +2.2. Isolation 11 + +ˆ + +The text of the program, usually a sequence of machine language in + +structions. + +ˆ + +Data associated with the program, including static data (allocated at + +compile time) and dynamic data (allocated at run time). + +ˆ + +The state of any pending input/output operations. For example, if the + +process is waiting for data to be read from disk or for a packet to arrive + +on a network, the status of these operations is part of the process. + +ˆ + +The hardware state of the program, which includes data stored in regis + +ters, status information, and the program counter, which indicates which + +instruction is currently executing. + +Usually one process runs one program, but it is also possible for a process to + +load and run a new program. + +It is also possible, and common, to run the same program in more than one + +process. In that case, the processes share the same program text but generally + +have different data and hardware states. + +Most operating systems provide a fundamental set of capabilities to isolate + +processes from each other: + +ˆ + +Multitasking: Most operating systems have the ability to interrupt a + +running process at almost any time, save its hardware state, and then + +resume the process later. In general, programmers don’t have to think + +about these interruptions. The program behaves as if it is running con + +tinuously on a dedicated processor, except that the time between in + +structions is unpredictable. + +ˆ + +Virtual memory: Most operating systems create the illusion that each + +process has its own chunk of memory, isolated from all other processes. + +Again, programmers generally don’t have to think about how virtual + +memory works; they can proceed as if every program has a dedicated + +chunk of memory. + +ˆ + +Device abstraction: Processes running on the same computer share the + +disk drive, the network interface, the graphics card, and other hardware. + +If processes interacted with this hardware directly, without coordination, + +chaos would ensue. For example, network data intended for one process + +might be read by another. Or multiple processes might try to store data + +in the same location on a hard drive. It is up to the operating system + +to maintain order by providing appropriate abstractions. + + + +--- + +12 Chapter 2. Processes + +As a programmer, you don’t need to know much about how these capabilities + +are implemented. But if you are curious, you will find a lot of interesting + +things going on under the metaphorical hood. And if you know what’s going + +on, it can make you a better programmer. + +## 2.3 UNIX processes + +While I write this book, the process I am most aware of is my text editor, + +emacs. Every once in a while I switch to a terminal window, which is a + +window running a UNIX shell that provides a command-line interface. + +When I move the mouse, the window manager wakes up, sees that the mouse + +is over the terminal window, and wakes up the terminal. The terminal wakes + +up the shell. If I type + +make + +in the shell, it creates a new process to run + +Make, which creates another process to run LaTeX and then another process + +to display the results. + +If I need to look something up, I might switch to another desktop, which wakes + +up the window manager again. If I click on the icon for a web browser, the + +window manager creates a process to run the web browser. Some browsers, + +like Chrome, create a new process for each window and each tab. + +And those are just the processes I am aware of. At the same time there + +are many other processes running in the + +background + +. Many of them are + +performing operations related to the operating system. + +The UNIX command + +ps + +prints information about running processes. If you + +run it in a terminal, you might see something like this: + +PID TTY TIME CMD + +2687 pts/1 00:00:00 bash + +2801 pts/1 00:01:24 emacs + +24762 pts/1 00:00:00 ps + +The first column is the unique numerical process ID. The second column is + +the terminal that created the process; “TTY” stands for teletypewriter, which + +was the original mechanical terminal. + +The third column is the total processor time used by the process, in hours, + +minutes, and seconds. The last column is the name of the running program. + +In this example, + +bash + +is the name of the shell that interprets the commands I + +type in the terminal, emacs is my text editor, and ps is the program generating + +this output. + + + +--- + +2.3. UNIX processes 13 + +By default, + +ps + +lists only the processes associated with the current terminal. + +If you use the + +-e + +flag, you get every process (including processes belonging to + +other users, which is a security flaw, in my opinion). + +On my system there are currently 233 processes. Here are some of them: + +PID TTY TIME CMD + +1 ? 00:00:17 init + +2 ? 00:00:00 kthreadd + +3 ? 00:00:02 ksoftirqd/0 + +4 ? 00:00:00 kworker/0:0 + +8 ? 00:00:00 migration/0 + +9 ? 00:00:00 rcu_bh + +10 ? 00:00:16 rcu_sched + +47 ? 00:00:00 cpuset + +48 ? 00:00:00 khelper + +49 ? 00:00:00 kdevtmpfs + +50 ? 00:00:00 netns + +51 ? 00:00:00 bdi-default + +52 ? 00:00:00 kintegrityd + +53 ? 00:00:00 kblockd + +54 ? 00:00:00 ata_sff + +55 ? 00:00:00 khubd + +56 ? 00:00:00 md + +57 ? 00:00:00 devfreq_wq + +init + +is the first process created when the operating system starts. It creates + +many of the other processes, and then sits idle until the processes it created + +are done. + +kthreadd + +is a process the operating system uses to create new + +threads + +. We’ll + +talk more about threads later, but for now you can think of a thread as kind of + +a process. The + +k + +at the beginning stands for + +kernel + +, which is the part of the + +operating system responsible for core capabilities like creating threads. The + +extra + +d + +at the end stands for + +daemon + +, which is another name for processes like + +this that run in the background and provide operating system services. In this + +context, “daemon” is used in the sense of a helpful spirit, with no connotation + +of evil. + +Based on the name, you can infer that + +ksoftirqd + +is also a kernel daemon; + +specifically, it handles software interrupt requests, or “soft IRQ”. + +kworker + +is a worker process created by the kernel to do some kind of processing + +for the kernel. + + + +--- + +14 Chapter 2. Processes + +There are often multiple processes running these kernel services. On my system + +at the moment, there are 8 + +ksoftirqd + +processes and 35 + +kworker + +processes. + +I won’t go into more details about the other processes, but if you are interested + +you can search for more information about them. You should run + +ps + +on your + +system and compare your results to mine. + + + +--- + +## Chapter 3 + +## Virtual memory + +## 3.1 A bit of information theory + +A + +bit + +is a binary digit; it is also a unit of information. If you have one bit, + +you can specify one of two possibilities, usually written 0 and 1. If you have + +two bits, there are 4 possible combinations, 00, 01, 10, and 11. In general, if + +you have + +b + +bits, you can indicate one of 2 + +b + +values. A + +byte + +is 8 bits, so it can + +hold one of 256 values. + +Going in the other direction, suppose you want to store a letter of the alphabet. + +There are 26 letters, so how many bits do you need? With 4 bits, you can + +specify one of 16 values, so that’s not enough. With 5 bits, you can specify up + +to 32 values, so that’s enough for all the letters, with a few values left over. + +In general, if you want to specify one of + +N + +values, you should choose the + +smallest value of + +b + +so that 2 + +b + +≥ + +N + +. Taking the log base 2 of both sides yields + +b + +≥ + +log + +2 + +N + +. + +Suppose I flip a coin and tell you the outcome. I have given you one bit of + +information. If I roll a six-sided die and tell you the outcome, I have given you + +log + +2 + +6 bits of information. And in general, if the probability of the outcome is + +1 in + +N + +, then the outcome contains + +log + +2 + +N + +bits of information. + +Equivalently, if the probability of the outcome is + +p + +, then the information con + +tent is + +− + +log + +2 + +p + +. This quantity is called the + +self-information + +of the outcome. + +It measures how surprising the outcome is, which is why it is also called + +sur + +prisal + +. If your horse has only one chance in 16 of winning, and he wins, you + +get 4 bits of information (along with the payout). But if the favorite wins 75% + +of the time, the news of the win contains only 0.42 bits. + + + +--- + +16 Chapter 3. Virtual memory + +Intuitively, unexpected news carries a lot of information; conversely, if there + +is something you were already confident of, confirming it contributes only a + +small amount of information. + +For several topics in this book, we will need to be comfortable converting back + +and forth between the number of bits, + +b + +, and the number of values they can + +encode, + +N + += 2 + +b + +. + +## 3.2 Memory and storage + +While a process is running, most of its data is held in + +main memory + +, which + +is usually some kind of random access memory (RAM). On most current com + +puters, main memory is + +volatile + +, which means that when the computer shuts + +down, the contents of main memory are lost. A typical desktop computer has + +2–8 GiB of memory. GiB stands for “gibibyte,” which is 2 + +30 + +bytes. + +If the process reads and writes files, those files are usually stored on a hard + +disk drive (HDD) or solid state drive (SSD). These storage devices are + +non + +volatile + +, so they are used for long-term storage. Currently a typical desktop + +computer has a HDD with a capacity of 500 GB to 2 TB. GB stands for + +“gigabyte,” which is 10 + +9 + +bytes. TB stands for “terabyte,” which is 10 + +12 + +bytes. + +You might have noticed that I used the binary unit GiB for the size of main + +memory and the decimal units GB and TB for the size of the HDD. For + +historical and technical reasons, memory is measured in binary units, and + +disk drives are measured in decimal units. In this book I will be careful to + +distinguish binary and decimal units, but you should be aware that the word + +“gigabyte” and the abbreviation GB are often used ambiguously. + +In casual use, the term “memory” is sometimes used for HDDs and SSDs as + +well as RAM, but the properties of these devices are very different, so we will + +need to distinguish them. I will use + +storage + +to refer to HDDs and SSDs. + +## 3.3 Address spaces + +Each byte in main memory is specified by an integer + +physical address + +. The + +set of valid physical addresses is called the physical + +address space + +. It usually + +runs from 0 to + +N + +− + +1, where + +N + +is the size of main memory. On a system + +with 1 GiB of physical memory, the highest valid address is 2 + +30 + +− + +1, which is + +1,073,741,823 in decimal, or 0x3fff ffff in hexadecimal (the prefix 0x indicates + +a hexadecimal number). + + + +--- + +3.4. Memory segments 17 + +However, most operating systems provide + +virtual memory + +, which means + +that programs never deal with physical addresses, and don’t have to know + +how much physical memory is available. + +Instead, programs work with + +virtual addresses + +, which are numbered from 0 + +to + +M + +− + +1, where + +M + +is the number of valid virtual addresses. The size of the + +virtual address space is determined by the operating system and the hardware + +it runs on. + +You have probably heard people talk about 32-bit and 64-bit systems. These + +terms indicate the size of the registers, which is usually also the size of a virtual + +address. On a 32-bit system, virtual addresses are 32 bits, which means that + +the virtual address space runs from 0 to 0xffff ffff. The size of this address + +space is 2 + +32 + +bytes, or 4 GiB. + +On a 64-bit system, the size of the virtual address space is 2 + +64 + +bytes, or 2 + +4 + +· + +1024 + +6 + +bytes. That’s 16 exbibytes, which is about a billion times bigger than current + +physical memories. It might seem strange that a virtual address space can be + +so much bigger than physical memory, but we will see soon how that works. + +When a program reads and writes values in memory, it generates virtual ad + +dresses. The hardware, with help from the operating system, translates to + +physical addresses before accessing main memory. This translation is done on + +a per-process basis, so even if two processes generate the same virtual address, + +they would map to different locations in physical memory. + +Thus, virtual memory is one important way the operating system isolates + +processes from each other. In general, a process cannot access data belonging + +to another process, because there is no virtual address it can generate that + +maps to physical memory allocated to another process. + +## 3.4 Memory segments + +The data of a running process is organized into five segments: + +ˆ + +The + +code segment + +contains the program text; that is, the machine + +language instructions that make up the program. + +ˆ + +The + +static segment + +contains immutable values, like string literals. For + +example, if your program contains the string + +"Hello, World" + +, those + +characters will be stored in the static segment. + +ˆ + +The + +global segment + +contains global variables and local variables that + +are declared + +static + +. + + + +--- + +18 Chapter 3. Virtual memory + +ˆ + +The + +heap segment + +contains chunks of memory allocated at run time, + +most often by calling the C library function + +malloc + +. + +ˆ + +The + +stack segment + +contains the call stack, which is a sequence of stack + +frames. Each time a function is called, a stack frame is allocated to + +contain the parameters and local variables of the function. When the + +function completes, its stack frame is removed from the stack. + +The arrangement of these segments is determined partly by the compiler and + +partly by the operating system. The details vary from one system to another, + +but in the most common arrangement: + +ˆ + +The text segment is near the “bottom” of memory, that is, at addresses + +near 0. + +ˆ + +The static segment is often just above the text segment, that is, at higher + +addresses. + +ˆ + +The global segment is often just above the static segment. + +ˆ + +The heap is often above the global segment. As it expands, it grows up + +toward larger addresses. + +ˆ + +The stack is near the top of memory; that is, near the highest addresses + +in the virtual address space. As the stack expands, it grows down toward + +smaller addresses. + +To determine the layout of these segments on your system, try running this + +program, which is in + +aspace.c + +in the repository for this book (see Section 0.1). + +#include + +#include + +int global; + +int main () + +{ + +int local = 5; + +void *p = malloc(128); + +char *s = "Hello, World"; + +printf ("Address of main is %p\n", main); + +printf ("Address of global is %p\n", &global); + +printf ("Address of local is %p\n", &local); + + + +--- + +3.4. Memory segments 19 + +printf ("p points to %p\n", p); + +printf ("s points to %p\n", s); + +} + +main + +is the name of a function; when it is used as a variable, it refers to the + +address of the first machine language instruction in + +main + +, which we expect to + +be in the text segment. + +global + +is a global variable, so we expect it to be in the global segment. + +local + +is a local variable, so we expect it to be on the stack. + +s + +refers to a “string literal”, which is a string that appears as part of the + +program (as opposed to a string that is read from a file, input by a user, etc.). + +We expect the location of the string to be in the static segment (as opposed + +to the pointer, + +s + +, which is a local variable). + +p + +contains an address returned by + +malloc + +, which allocates space in the heap. + +“malloc” stands for “memory allocate.” + +The format sequence + +%p + +tells + +printf + +to format each address as a “pointer”, + +so it displays the results in hexadecimal. + +When I run this program, the output looks like this (I added spaces to make + +it easier to read): + +Address of main is 0x 40057d + +Address of global is 0x 60104c + +Address of local is 0x7ffe6085443c + +p points to 0x 16c3010 + +s points to 0x 4006a4 + +As expected, the address of + +main + +is the lowest, followed by the location of the + +string literal. The location of + +global + +is next, then the address + +p + +points to. + +The address of + +local + +is much bigger. + +The largest address has 12 hexadecimal digits. Each hex digit corresponds + +to 4 bits, so it is a 48-bit address. That suggests that the usable part of the + +virtual address space is 2 + +48 + +bytes. + +As an exercise, run this program on your computer and compare your results + +to mine. Add a second call to + +malloc + +and check whether the heap on your + +system grows up (toward larger addresses). Add a function that prints the + +address of a local variable, and check whether the stack grows down. + + + +--- + +20 Chapter 3. Virtual memory + +Figure 3.1: Diagram of the address translation process. + +## 3.5 Static local variables + +Local variables on the stack are sometimes called + +automatic + +, because they + +are allocated automatically when a function is called, and freed automatically + +when the function returns. + +In C there is another kind of local variable, called + +static + +, which is allocated + +in the global segment. It is initialized when the program starts and keeps its + +value from one function call to the next. + +For example, the following function keeps track of how many times it has been + +called. + +int times_called() + +{ + +static int counter = 0; + +counter++; + +return counter; + +} + +The keyword + +static + +indicates that + +counter + +is a static local variable. The + +initialization happens only once, when the program starts. + +If you add this function to + +aspace.c + +you can confirm that + +counter + +is allocated + +in the global segment along with global variables, not in the stack. + +## 3.6 Address translation + +How does a virtual address (VA) get translated to a physical address (PA)? + +The basic mechanism is simple, but a simple implementation would be too + +slow and take too much space. So actual implementations are a bit more + +complicated. + + + +--- + +3.6. Address translation 21 + +Most processors provide a memory management unit (MMU) that sits between + +the CPU and main memory. The MMU performs fast translation between VAs + +and PAs. + +1. + +When a program reads or writes a variable, the CPU generates a VA. + +2. + +The MMU splits the VA into two parts, called the page number and the + +offset. A “page” is a chunk of memory; the size of a page depends on + +the operating system and the hardware, but common sizes are 1–4 KiB. + +3. + +The MMU looks up the page number in the translation lookaside buffer + +(TLB) and gets the corresponding physical page number. Then it com + +bines the physical page number with the offset to produce a PA. + +4. + +The PA is passed to main memory, which reads or writes the given + +location. + +The TLB contains cached copies of data from the page table (which is stored + +in kernel memory). The page table contains the mapping from virtual page + +numbers to physical page numbers. Since each process has its own page table, + +the TLB has to make sure it only uses entries from the page table of the + +process that’s running. + +Figure 3.1 shows a diagram of this process. To see how it all works, suppose + +that the VA is 32 bits and the physical memory is 1 GiB, divided into 1 KiB + +pages. + +ˆ + +Since 1 GiB is 2 + +30 + +bytes and 1 KiB is 2 + +10 + +bytes, there are 2 + +20 + +physical + +pages, sometimes called “frames.” + +ˆ + +The size of the virtual address space is 2 + +32 + +B and the size of a page is + +2 + +10 + +B, so there are 2 + +22 + +virtual pages. + +ˆ + +The size of the offset is determined by the page size. In this example the + +page size is 2 + +10 + +B, so it takes 10 bits to specify a byte on a page. + +ˆ + +If a VA is 32 bits and the offset is 10 bits, the remaining 22 bits make + +up the virtual page number. + +ˆ + +Since there are 2 + +20 + +physical pages, each physical page number is 20 bits. + +Adding in the 10 bit offset, the resulting PAs are 30 bits. + +So far this all seems feasible. But let’s think about how big a page table might + +have to be. The simplest implementation of a page table is an array with one + +entry for each virtual page. Each entry would contain a physical page number, + + + +--- + +22 Chapter 3. Virtual memory + +which is 20 bits in this example, plus some additional information about each + +frame. So we expect 3–4 bytes per entry. But with 2 + +22 + +virtual pages, the page + +table would require 2 + +24 + +bytes, or 16 MiB. + +And since we need a page table for each process, a system running 256 processes + +would need 2 + +32 + +bytes, or 4 GiB, just for page tables! And that’s just with 32-bit + +virtual addresses. With 48- or 64-bit VAs, the numbers are ridiculous. + +Fortunately, we don’t actually need that much space, because most processes + +don’t use even a small fraction of their virtual address space. And if a process + +doesn’t use a virtual page, we don’t need an entry in the page table for it. + +Another way to say the same thing is that page tables are “sparse”, which + +implies that the simple implementation, an array of page table entries, is a bad + +idea. Fortunately, there are several good implementations for sparse arrays. + +One option is a multilevel page table, which is what many operating systems, + +including Linux, use. Another option is an associative table, where each entry + +includes both the virtual page number and the physical page number. Search + +ing an associative table can be slow in software, but in hardware we can search + +the entire table in parallel, so associative arrays are often used to represent + +the page table entries in the TLB. + +You can read more about these implementations at + +http://en.wikipedia. + +org/wiki/Page_table + +; you might find the details interesting. But the fun + +damental idea is that page tables are sparse, so we have to choose a good + +implementation for sparse arrays. + +I mentioned earlier that the operating system can interrupt a running process, + +save its state, and then run another process. This mechanism is called a + +context switch + +. Since each process has its own page table, the operating + +system has to work with the MMU to make sure each process gets the right + +page table. In older machines, the page table information in the MMU had + +to be replaced during every context switch, which was expensive. In newer + +systems, each page table entry in the MMU includes the process ID, so page + +tables from multiple processes can be in the MMU at the same time. + + + +--- + +## Chapter 4 + +## Files and file systems + +When a process completes (or crashes), any data stored in main memory is + +lost. But data stored on a hard disk drive (HDD) or solid state drive (SSD) + +is “persistent;” that is, it survives after the process completes, even if the + +computer shuts down. + +Hard disk drives are complicated. Data is stored in blocks, which are laid out + +in sectors, which make up tracks, which are arranged in concentric circles on + +platters. + +Solid state drives are simpler in one sense, because blocks are numbered se + +quentially, but they raise a different complication: each block can be written + +a limited number of times before it becomes unreliable. + +As a programmer, you don’t want to deal with these complications. What you + +want is an appropriate abstraction of persistent storage hardware. The most + +common abstraction is called a “file system.” + +Abstractly: + +ˆ + +A “file system” is a mapping from each file’s name to its contents. If + +you think of the names as keys, and the contents as values, a file system + +is a kind of key-value database (see + +https://en.wikipedia.org/wiki/ + +Key-value_database + +). + +ˆ + +A “file” is a sequence of bytes. + +File names are usually strings, and they are usually “hierarchical”; that is, the + +string specifies a path from a top-level directory (or folder), through a series + +of subdirectories, to a specific file. + + + +--- + +24 Chapter 4. Files and file systems + +The primary difference between the abstraction and the underlying mechanism + +is that files are byte-based and persistent storage is block-based. The operating + +system translates byte-based file operations in the C library into block-based + +operations on storage devices. Typical block sizes are 1–8 KiB. + +For example, the following code opens a file and reads the first byte: + +FILE *fp = fopen("/home/downey/file.txt", "r"); + +char c = fgetc(fp); + +fclose(fp); + +When this code runs: + +1. + +fopen + +uses the filename to find the top-level directory, called + +/ + +, the + +subdirectory + +home + +, and the sub-subdirectory + +downey + +. + +2. + +It finds the file named + +file.txt + +and “opens” it for reading, which means + +it creates a data structure that represents the file being read. Among + +other things, this data structure keeps track of how much of the file has + +been read, called the “file position”. + +In DOS, this data structure is called a File Control Block, but I want + +to avoid that term because in UNIX it means something else. In UNIX, + +there seems to be no good name for it. It is an entry in the open file + +table, so I will call it an OpenFileTableEntry. + +3. + +When we call + +fgetc + +, the operating system checks whether the next char + +acter of the file is already in memory. If so, it reads the next character, + +advances the file position, and returns the result. + +4. + +If the next character is not in memory, the operating system issues an + +I/O request to get the next block. Disk drives are slow, so a process + +waiting for a block from disk is usually interrupted so another process + +can run until the data arrives. + +5. + +When the I/O operation is complete, the new block of data is stored in + +memory, and the process resumes. It reads the first character and stores + +it as a local variable. + +6. + +When the process closes the file, the operating system completes or can + +cels any pending operations, removes data stored in memory, and frees + +the OpenFileTableEntry. + +The process for writing a file is similar, but there are some additional steps. + +Here is an example that opens a file for writing and changes the first character. + + + +--- + +4.1. Disk performance 25 + +FILE *fp = fopen("/home/downey/file.txt", "w"); + +fputc('b', fp); + +fclose(fp); + +When this code runs: + +1. + +Again, + +fopen + +uses the filename to find the file. If it does not already + +exist, it creates a new file and adds an entry in the parent directory, + +/home/downey + +. + +2. + +The operating system creates an OpenFileTableEntry that indicates that + +the file is open for writing, and sets the file position to 0. + +3. + +fputc + +attempts to write (or re-write) the first byte of the file. If the + +file already exists, the operating system has to load the first block into + +memory. Otherwise it allocates a new block in memory and requests a + +new block on disk. + +4. + +After the block in memory is modified, it might not be copied back to + +the disk right away. In general, data written to a file is “buffered”, which + +means it is stored in memory and only written to disk when there is at + +least one block to write. + +5. + +When the file is closed, any buffered data is written to disk and the + +OpenFileTableEntry is freed. + +To summarize, the C library provides the abstraction of a file system that + +maps from file names to streams of bytes. This abstraction is built on top of + +storage devices that are actually organized in blocks. + +## 4.1 Disk performance + +I mentioned earlier that disk drives are slow. On current HDDs, the + +average time to read a block from disk to memory might be 5–25 + +ms (see + +https://en.wikipedia.org/wiki/Hard_disk_drive_performance_ + +characteristics + +). SSDs are faster, taking 25 + +µ + +s to read a 4 KiB block and + +250 + +µ + +s to write one (see + +http://en.wikipedia.org/wiki/Ssd#Controller + +). + +To put these numbers in perspective, let’s compare them to the clock cycle of + +the CPU. A processor with clock rate 2 GHz completes one clock cycle every + +0.5 ns. The time to get a byte from memory to the CPU is typically around + +100 ns. If the processor completes one instruction per clock cycle, it would + +complete 200 instructions while waiting for a byte from memory. + + + +--- + +26 Chapter 4. Files and file systems + +In one microsecond, it would complete 2000 instructions, so while waiting 25 + +µ + +s for a byte from an SSD, it would complete 50,000. + +In one millisecond, it would complete 2,000,000 instructions, so while waiting + +20 ms for a byte from a HDD, it might complete 40 million. If there’s nothing + +for the CPU to do while it waits, it would be idle. That’s why the operating + +system generally switches to another process while it is waiting for data from + +disk. + +The gap in performance between main memory and persistent storage is one + +of the major challenges of computer system design. Operating systems and + +hardware provide several features intended to “fill in” this gap: + +ˆ + +Block transfers: The time it takes to load a single byte from disk is 5– + +25 ms. By comparison, the additional time to load an 8 KiB block is + +negligible. So systems generally try to read large blocks each time they + +access the disk. + +ˆ + +Prefetching: Sometimes the operating system can predict that a process + +will read a block and start loading it before it is requested. For example, + +if you open a file and read the first block, there is a good chance you + +will go on to read the second block. The operating system might start + +loading additional blocks before they are requested. + +ˆ + +Buffering: As I mentioned, when you write a file, the operating system + +stores the data in memory and only writes it to disk later. If you modify + +the block several times while it is in memory, the system only has to + +write it to disk once. + +ˆ + +Caching: If a process has used a block recently, it is likely to use it again + +soon. If the operating system keeps a copy of the block in memory, it + +can handle future requests at memory speed. + +Some of these features are also implemented in hardware. For example, some + +disk drives provide a cache that stores recently-used blocks, and many disk + +drives read more than one block at a time, even if only one is requested. + +These mechanisms generally improve the performance of programs, but they + +don’t change the behavior. Usually programmers don’t have to think about + +them, with two exceptions: (1) if the performance of a program is unexpectedly + +bad, you might have to know something about these mechanisms to diagnose + +the problem, and (2) when data is buffered, it can be harder to debug a + +program. For example, if a program prints a value and then crashes, the value + +might not appear, because it might be in a buffer. Similarly, if a program + +writes data to disk and then the computer loses power, the data might be lost + +if it is in a cache and not yet on disk. + + + +--- + +4.2. Disk metadata 27 + +## 4.2 Disk metadata + +The blocks that make up a file might be arranged contiguously on disk, and file + +system performance is generally better if they are, but most operating systems + +don’t require contiguous allocation. They are free to place a block anywhere + +on disk, and they use various data structures to keep track of them. + +In many UNIX file systems, that data structure is called an “inode,” which + +stands for “index node”. More generally, information about files, including + +the location of their blocks, is called “metadata”. (The content of the file is + +data, so information about the file is data about data, hence “meta”.) + +Since inodes reside on disk along with the rest of the data, they are designed + +to fit neatly into disk blocks. A UNIX inode contains information about a + +file, including the user ID of the file owner; permission flags indicating who + +is allowed to read, write, or execute it; and timestamps that indicate when it + +was last modified and accessed. In addition, it contains block numbers for the + +first 12 blocks that make up the file. + +If the block size is 8 KiB, the first 12 blocks make up 96 KiB. On most systems, + +that’s big enough for a large majority of files, but it’s definitely not big enough + +for all of them. That’s why the inode also contains a pointer to an “indirection + +block”, which contains nothing but pointers to other blocks. + +The number of pointers in an indirection block depends on the sizes of the + +blocks and the block numbers, but it is often 1024. With 1024 block numbers + +and 8 KiB blocks, an indirection block can address 8 MiB. That’s big enough + +for all but the largest files, but still not big enough for all. + +That’s why the inode also contains a pointer to a “double indirection block”, + +which contains pointers to indirection blocks. With 1024 indirection blocks, + +we can address 8 GiB. + +And if that’s not big enough, there is (finally) a triple indirection block, which + +contains pointers to double indirection blocks, yielding a maximum file size of + +8 TiB. When UNIX inodes were designed, that seemed big enough to serve for + +a long time. But that was a long time ago. + +As an alternative to indirection blocks, some files systems, like FAT, use a File + +Allocation Table that contains one entry for each block, called a “cluster” in + +this context. A root directory contains a pointer to the first cluster in each file. + +The FAT entry for each cluster points to the next cluster in the file, similar to + +a linked list. For more details, see + +http://en.wikipedia.org/wiki/File_ + +Allocation_Table + +. + + + +--- + +28 Chapter 4. Files and file systems + +## 4.3 Block allocation + +File systems have to keep track of which blocks belong to each file; they also + +have to keep track of which blocks are available for use. When a new file is + +created, the file system finds an available block and allocates it. When a file + +is deleted, the file system makes its blocks available for re-allocation. + +The goals of the block allocation system are: + +ˆ + +Speed: Allocating and freeing blocks should be fast. + +ˆ + +Minimal space overhead: The data structures used by the allocator + +should be small, leaving as much space as possible for data. + +ˆ + +Minimal fragmentation: If some blocks are left unused, or some are only + +partially used, the unused space is called “fragmentation”. + +ˆ + +Maximum contiguity: Data that is likely to be used at the same time + +should be physically contiguous, if possible, to improve performance. + +It is hard to design a file system that achieves all of these goals, especially + +since file system performance depends on “workload characteristics” like file + +sizes, access patterns, etc. A file system that is well tuned for one workload + +might not perform as well for another. + +For this reason, most operating systems support several kinds of file systems, + +and file system design is an active area of research and development. In the + +last decade, Linux systems have migrated from ext2, which was a conventional + +UNIX file system, to ext3, a “journaling” file system intended to improve speed + +and contiguity, and more recently to ext4, which can handle larger files and + +file systems. Within the next few years, there might be another migration to + +the B-tree file system, Btrfs. + +## 4.4 Everything is a file? + +The file abstraction is really a “stream of bytes” abstraction, which turns out + +to be useful for many things, not just file systems. + +One example is the UNIX pipe, which is a simple form of inter-process com + +munication. Processes can be set up so that output from one process is taken + +as input into another process. For the first process, the pipe behaves like a + +file open for writing, so it can use C library functions like + +fputs + +and + +fprintf + +. + + + +--- + +4.4. Everything is a file? 29 + +For the second process, the pipe behaves like a file open for reading, so it uses + +fgets + +and + +fscanf + +. + +Network communication also uses the stream of bytes abstraction. A UNIX + +socket is a data structure that represents a communication channel between + +processes on different computers (usually). Again, processes can read data + +from and write data to a socket using “file” handling functions. + +Reusing the file abstraction makes life easier for programmers, since they only + +have to learn one API (application program interface). It also makes programs + +more versatile, since a program intended to work with files can also work with + +data coming from pipes and other sources. + + + +--- + +30 Chapter 4. Files and file systems + + + +--- + +## Chapter 5 + +## More bits and bytes + +## 5.1 Representing integers + +You probably know that computers represent numbers in base 2, also known + +as binary. For positive numbers, the binary representation is straightforward; + +for example, the representation for 5 + +10 + +is + +b + +101. + +For negative numbers, the most obvious representation uses a sign bit to in + +dicate whether a number is positive or negative. But there is another repre + +sentation, called “two’s complement” that is much more common because it + +is easier to work with in hardware. + +To find the two’s complement of a negative number, + +− + +x + +, find the binary rep + +resentation of + +x + +, flip all the bits, and add 1. For example, to represent + +− + +5 + +10 + +, + +start with the representation of 5 + +10 + +, which is + +b + +00000101 if we write the 8-bit + +version. Flipping all the bits and adding 1 yields + +b + +11111011. + +In two’s complement, the leftmost bit acts like a sign bit; it is 0 for positive + +numbers and 1 for negative numbers. + +To convert from an 8-bit number to 16-bits, we have to add more 0’s for a + +positive number and add 1’s for a negative number. In effect, we have to copy + +the sign bit into the new bits. This process is called “sign extension”. + +In C all integer types are signed (able to represent positive and negative num + +bers) unless you declare them + +unsigned + +. The difference, and the reason this + +declaration is important, is that operations on unsigned integers don’t use sign + +extension. + + + +--- + +32 Chapter 5. More bits and bytes + +## 5.2 Bitwise operators + +People learning C are sometimes confused about the bitwise operators + +& + +and + +| + +. These operators treat integers as bit vectors and compute logical operations + +on corresponding bits. + +For example, + +& + +computes the AND operation, which yields 1 if both operands + +are 1, and 0 otherwise. Here is an example of + +& + +applied to two 4-bit numbers: + +1100 + +& 1010 + +---- + +1000 + +In C, this means that the expression + +12 & 10 + +has the value 8. + +Similarly, + +| + +computes the OR operation, which yields 1 if either operand is 1, + +and 0 otherwise. + +1100 + +| 1010 + +---- + +1110 + +So the expression + +12 | 10 + +has the value 14. + +Finally, + +^ + +computes the XOR operation, which yields 1 if either operand is 1, + +but not both. + +1100 + +^ 1010 + +---- + +0110 + +So the expression + +12 ^ 10 + +has the value 6. + +Most commonly, + +& + +is used to clear a set of bits from a bit vector, + +| + +is used to + +set bits, and + +^ + +is used to flip, or “toggle” bits. Here are the details: + +Clearing bits + +: For any value + +x + +, + +x + +&0 is 0, and + +x + +&1 is + +x + +. So if you AND a + +vector with 3, it selects only the two rightmost bits, and sets the rest to 0. + +xxxx + +& 0011 + +---- + +00xx + + + +--- + +5.3. Representing floating-point numbers 33 + +In this context, the value 3 is called a “mask” because it selects some bits and + +masks the rest. + +Setting bits + +: Similarly, for any + +x + +, + +x + +| + +0 is x, and + +x + +| + +1 is 1. So if you OR a vector + +with 3, it sets the rightmost bits, and leaves the rest alone: + +xxxx + +| 0011 + +---- + +xx11 + +Toggling bits + +: Finally, if you XOR a vector with 3, it flips the rightmost bits + +and leaves the rest alone. As an exercise, see if you can compute the two’s + +complement of 12 using + +^ + +. Hint: what’s the two’s complement representation + +of -1? + +C also provides shift operators, + +<< + +and + +>> + +, which shift bits left and right. Each + +left shift doubles a number, so + +5 << 1 + +is 10, and + +5 << 2 + +is 20. Each right shift + +divides by two (rounding down), so + +5 >> 1 + +is 2 and + +2 >> 1 + +is 1. + +## 5.3 Representing floating-point numbers + +Floating-point numbers are represented using the binary version of scientific + +notation. In decimal notation, large numbers are written as the product of a + +coefficient and 10 raised to an exponent. For example, the speed of light in + +m/s is approximately 2 + +. + +998 + +· + +10 + +8 + +. + +Most computers use the IEEE standard for floating-point arithmetic. The C + +type + +float + +usually corresponds to the 32-bit IEEE standard; + +double + +usually + +corresponds to the 64-bit standard. + +In the 32-bit standard, the leftmost bit is the sign bit, + +s + +. The next 8 bits + +are the exponent, + +q + +, and the last 23 bits are the coefficient, + +c + +. The value of a + +floating-point number is + +( + +− + +1) + +s + +c + +· + +2 + +q + +Well, that’s almost correct, but there’s one more wrinkle. Floating-point num + +bers are usually normalized so that there is one digit before the point. For + +example, in base 10, we prefer 2 + +. + +998 + +· + +10 + +8 + +rather than 2998 + +· + +10 + +5 + +or any other + +equivalent expression. In base 2, a normalized number always has the digit 1 + +before the binary point. Since the digit in this location is always 1, we can + +save space by leaving it out of the representation. + + + +--- + +34 Chapter 5. More bits and bytes + +For example, the integer representation of 13 + +10 + +is + +b + +1101. In floating point, + +that’s 1 + +. + +101 + +· + +2 + +3 + +, so the exponent is 3 and the part of the coefficient that would + +be stored is 101 (followed by 20 zeros). + +Well, that’s almost correct, but there’s one more wrinkle. The exponent is + +stored with a “bias”. In the 32-bit standard, the bias is 127, so the exponent + +3 would be stored as 130. + +To pack and unpack floating-point numbers in C, we can use a union and + +bitwise operations. Here’s an example: + +union { + +float f; + +unsigned int u; + +} p; + +p.f = -13.0; + +unsigned int sign = (p.u >> 31) & 1; + +unsigned int exp = (p.u >> 23) & 0xff; + +unsigned int coef_mask = (1 << 23) - 1; + +unsigned int coef = p.u & coef_mask; + +printf("%d\n", sign); + +printf("%d\n", exp); + +printf("0x%x\n", coef); + +This code is in + +float.c + +in the repository for this book (see Section 0.1). + +The union allows us to store a floating-point value using + +p.f + +and then read it + +as an unsigned integer using + +p.u + +. + +To get the sign bit, we shift the bits to the right 31 places and then use a 1-bit + +mask to select only the rightmost bit. + +To get the exponent, we shift the bits 23 places, then select the rightmost 8 + +bits (the hexadecimal value + +0xff + +has eight 1’s). + +To get the coefficient, we need to extract the 23 rightmost bits and ignore the + +rest. We do that by making a mask with 1s in the 23 rightmost places and 0s + +on the left. The easiest way to do that is by shifting 1 to the left by 23 places + +and then subtracting 1. + +The output of this program is: + +1 + + + +--- + +5.4. Unions and memory errors 35 + +130 + +0x500000 + +As expected, the sign bit for a negative number is 1. The exponent is 130, + +including the bias. And the coefficient, which I printed in hexadecimal, is 101 + +followed by 20 zeros. + +As an exercise, try assembling or disassembling a + +double + +, which uses the 64-bit + +standard. See + +http://en.wikipedia.org/wiki/IEEE_floating_point + +. + +## 5.4 Unions and memory errors + +There are two common uses of C unions. One, which we saw in the previous + +section, is to access the binary representation of data. Another is to store + +heterogeneous data. For example, you could use a union to represent a number + +that might be an integer, float, complex, or rational number. + +However, unions are error-prone. It is up to you, as the programmer, to keep + +track of what type of data is in the union; if you write a floating-point value + +and then interpret it as an integer, the result is usually nonsense. + +Actually, the same thing can happen if you read a location in memory incor + +rectly. One way that can happen is if you read past the end of an array. + +To see what happens, I’ll start with a function that allocates an array on the + +stack and fills it with the numbers from 0 to 99. + +void f1() { + +int i; + +int array[100]; + +for (i=0; i<100; i++) { + +array[i] = i; + +} + +} + +Next I’ll define a function that creates a smaller array and deliberately accesses + +elements before the beginning and after the end: + +void f2() { + +int x = 17; + +int array[10]; + +int y = 123; + +printf("%d\n", array[-2]); + + + +--- + +36 Chapter 5. More bits and bytes + +printf("%d\n", array[-1]); + +printf("%d\n", array[10]); + +printf("%d\n", array[11]); + +} + +If I call + +f1 + +and then + +f2 + +, I get these results: + +17 + +123 + +98 + +99 + +The details here depend on the compiler, which arranges variables on the stack. + +From these results, we can infer that the compiler put + +x + +and + +y + +next to each + +other, “below” the array (at a lower address). And when we read past the + +array, it looks like we are getting values that were left on the stack by the + +previous function call. + +In this example, all of the variables are integers, so it is relatively easy to figure + +out what is going on. But in general when you read beyond the bounds of an + +array, the values you read might have any type. For example, if I change + +f1 + +to make an array of floats, the results are: + +17 + +123 + +1120141312 + +1120272384 + +The latter two values are what you get if you interpret a floating-point value + +as an integer. If you encountered this output while debugging, you would have + +a hard time figuring out what’s going on. + +## 5.5 Representing strings + +Related issues sometimes come up with strings. First, remember that C strings + +are null-terminated. When you allocate space for a string, don’t forget the + +extra byte at the end. + +Also, the letters + +and numbers + +in C strings are encoded in ASCII. The ASCII + +codes for the digits “0” through “9” are 48 through 57, + +not + +0 through 9. The + +ASCII code 0 is the NUL character that marks the end of a string. And the + +ASCII codes 1 through 9 are special characters used in some communication + +protocols. ASCII code 7 is a bell; on some terminals, printing it makes a + +sound. + + + +--- + +5.5. Representing strings 37 + +The ASCII code for the letter “A” is 65; the code for “a” is 97. Here are those + +codes in binary: + +65 = b0100 0001 + +97 = b0110 0001 + +A careful observer will notice that they differ by a single bit. And this pattern + +holds for the rest of the letters; the sixth bit (counting from the right) acts as + +a “case bit”, 0 for upper-case letters and 1 for lower case letters. + +As an exercise, write a function that takes a string and converts from lower + +case to upper-case by flipping the sixth bit. As a challenge, you can make a + +faster version by reading the string 32 or 64 bits at a time, rather than one + +character at a time. This optimization is made easier if the length of the string + +is a multiple of 4 or 8 bytes. + +If you read past the end of a string, you are likely to see strange characters. + +Conversely, if you write a string and then accidentally read it as an int or float, + +the results will be hard to interpret. + +For example, if you run: + +char array[] = "allen"; + +float *p = array; + +printf("%f\n", *p); + +You will find that the ASCII representation of the first 8 characters + +of my name, interpreted as a double-precision floating point number, is + +69779713878800585457664. + + + +--- + +38 Chapter 5. More bits and bytes + + + +--- + +## Chapter 6 + +## Memory management + +C provides 4 functions for dynamic memory allocation: + +ˆ + +malloc + +, which takes an integer size, in bytes, and returns a pointer to + +a newly-allocated chunk of memory with (at least) the given size. If it + +can’t satisfy the request, it returns the special pointer value NULL. + +ˆ + +calloc + +, which is the same as + +malloc + +except that it also clears the newly + +allocated chunk; that is, it sets all bytes in the chunk to 0. + +ˆ + +free + +, which takes a pointer to a previously allocated chunk and deallo + +cates it; that is, it makes the space available for future allocation. + +ˆ + +realloc + +, which takes a pointer to a previously allocated chunk and a + +new size. It allocates a chunk of memory with the new size, copies data + +from the old chunk to the new, frees the old chunk, and returns a pointer + +to the new chunk. + +This API is notoriously error-prone and unforgiving. Memory management is + +one of the most challenging parts of designing large software systems, which + +is why most modern languages provide higher-level memory management fea + +tures like garbage collection. + +## 6.1 Memory errors + +The C memory management API is a bit like Jasper Beardly, a minor charac + +ter on the animated television program + +The Simpsons + +; in a few episodes, he + +appears as a strict substitute teacher who imposes corporal punishment — a + +“paddlin”’ — for all infractions. + + + +--- + +40 Chapter 6. Memory management + +Here are some of things a program can do that deserve a paddling: + +ˆ + +If you access (read or write) any chunk that has not been allocated, + +that’s a paddling. + +ˆ + +If you free an allocated chunk and then access it, that’s a paddling. + +ˆ + +If you try to free a chunk that has not been allocated, that’s a paddling. + +ˆ + +If you free the same chunk more than once, that’s a paddling. + +ˆ + +If you call + +realloc + +with a chunk that was not allocated, or was allocated + +and then freed, that’s a paddling. + +It might not sound difficult to follow these rules, but in a large program a chunk + +of memory might be allocated in one part of the program, used in several other + +parts, and freed in yet another part. So changes in one part of the program + +can require changes in many other parts. + +Also, there might be many aliases, or references to the same allocated chunk, + +in different parts of the program. The chunk should not be freed until all + +references to the chunk are no longer in use. Getting this right often requires + +careful analysis across all parts of the program, which is difficult and contrary + +to fundamental principles of good software engineering. + +Ideally, every function that allocates memory should include, as part of the + +documented interface, information about how that memory is supposed to + +be freed. Mature libraries often do this well, but in the real world, software + +engineering practice often falls short of this ideal. + +To make matters worse, memory errors can be difficult to find because the + +symptoms are unpredictable. For example: + +ˆ + +If you read a value from an unallocated chunk, the system + +might + +detect + +the error, trigger a runtime error called a “segmentation fault”, and stop + +the program. Or, the program might read unallocated memory without + +detecting the error; in that case, the value it gets is whatever happened + +to be stored at the accessed location, which is unpredictable, and might + +be different each time the program runs. + +ˆ + +If you write a value to an unallocated chunk, and don’t get a segmenta + +tion fault, things are even worse. After you write a value to an invalid + +location, a long time might pass before it is read and causes problems. + +At that point it will be very difficult to find the source of the problem. + + + +--- + +6.2. Memory leaks 41 + +And things can be even worse than that! One of the most common problems + +with C-style memory management is that the data structures used to imple + +ment + +malloc + +and + +free + +(which we will see soon) are often stored along with the + +allocated chunks. So if you accidentally write past the end of a dynamically + +allocated chunk, you are likely to mangle these data structures. The system + +usually won’t detect the problem until later, when you call + +malloc + +or + +free + +, + +and those functions fail in some inscrutable way. + +One conclusion you should draw from this is that safe memory management + +requires design and discipline. If you write a library or module that allocates + +memory, you should also provide an interface to free it, and memory manage + +ment should be part of the API design from the beginning. + +If you use a library that allocates memory, you should be disciplined in your + +use of the API. For example, if the library provides functions to allocate and + +deallocate storage, you should use those functions and not, for example, call + +free + +on a chunk you did not + +malloc + +. And you should avoid keeping multiple + +references to the same chunk in different parts of your program. + +Often there is a trade-off between safe memory management and performance. + +For example, the most common source of memory errors is writing beyond the + +bounds of an array. The obvious remedy for this problem is bounds checking; + +that is, every access to the array should check whether the index is out of + +bounds. High-level libraries that provide array-like structures usually perform + +bounds checking. But C arrays and most low-level libraries do not. + +## 6.2 Memory leaks + +There is one more memory error that may or may not deserve a paddling. If + +you allocate a chunk of memory and never free it, that’s a “memory leak”. + +For some programs, memory leaks are ok. For example, if your program + +allocates memory, performs computations on it, and then exits, it is probably + +not necessary to free the allocated memory. When the program exits, all of its + +memory is deallocated by the operating system. Freeing memory immediately + +before exiting might feel more responsible, but it is mostly a waste of time. + +But if a program runs for a long time and leaks memory, its total memory use + +will increase indefinitely. At that point, a few things might happen: + +ˆ + +At some point, the system runs out of physical memory. On systems + +without virtual memory, the next call to + +malloc + +will fail, returning + +NULL. + + + +--- + +42 Chapter 6. Memory management + +ˆ + +On systems with virtual memory, the operating system can move another + +process’s pages from memory to disk and then allocate more space to the + +leaking process. I explain this mechanism in Section 7.8. + +ˆ + +There might be a limit on the amount of space a single process can + +allocate; beyond that, + +malloc + +returns NULL. + +ˆ + +Eventually, a process might fill its virtual address space (or the usable + +part). After that, there are no more addresses to allocate, so + +malloc + +returns NULL. + +If + +malloc + +returns NULL, but you persist and access the chunk you think you + +allocated, you get a segmentation fault. For this reason, it is considered good + +style to check the result from + +malloc + +before using it. One option is to add a + +condition like this after every + +malloc + +call: + +void *p = malloc(size); + +if (p == NULL) { + +perror("malloc failed"); + +exit(-1); + +} + +perror + +is declared in + +stdio.h + +; it prints an error message and additional in + +formation about the last error that occurred. + +exit + +, which is declared in + +stdlib.h + +, causes the process to terminate. The + +argument is a status code that indicates how the process terminated. By + +convention, status code 0 indicates normal termination and -1 indicates an + +error condition. Sometimes other codes are used to indicate different error + +conditions. + +Error-checking code can be a nuisance, and it makes programs harder to read. + +You can mitigate these problems by wrapping library function calls and their + +error-checking code in your own functions. For example, here is a + +malloc + +wrapper that checks the return value. + +void *check_malloc(int size) + +{ + +void *p = malloc (size); + +if (p == NULL) { + +perror("malloc failed"); + +exit(-1); + +} + +return p; + +} + + + +--- + +6.3. Implementation 43 + +Because memory management is so difficult, most large programs, like web + +browsers, leak memory. To see which programs on your system are using the + +most memory, you can use the UNIX utilities + +ps + +and + +top + +. + +## 6.3 Implementation + +When a process starts, the system allocates space for the text segment and + +statically allocated data, space for the stack, and space for the heap, which + +contains dynamically allocated data. + +Not all programs allocate data dynamically, so the initial size of the heap + +might be small or zero. Initially the heap contains only one free chunk. + +When + +malloc + +is called, it checks whether it can find a free chunk that’s big + +enough. If not, it has to request more memory from the system. The function + +that does that is + +sbrk + +, which sets the “program break”, which you can think + +of as a pointer to the end of the heap. + +When + +sbrk + +is called, the OS allocates new pages of physical memory, updates + +the process’s page table, and sets the program break. + +In theory, a program could call + +sbrk + +directly (without using + +malloc + +) and + +manage the heap itself. But + +malloc + +is easier to use and, for most memory-use + +patterns, it runs fast and uses memory efficiently. + +To implement the memory management API (that is, the functions + +malloc + +, + +free + +, + +calloc + +, and + +realloc + +), most Linux systems use + +ptmalloc + +, which is + +based on + +dlmalloc + +, written by Doug Lea. A short paper that describes key + +elements of the implementation is available at + +http://gee.cs.oswego.edu/ + +dl/html/malloc.html + +. + +For programmers, the most important elements to be aware of are: + +ˆ + +The run time of + +malloc + +does not usually depend on the size of the chunk, + +but might depend on how many free chunks there are. + +free + +is usually + +fast, regardless of the number of free chunks. Because + +calloc + +clears + +every byte in the chunk, the run time depends on chunk size (as well as + +the number of free chunks). + +realloc + +is sometimes fast, if the new size is smaller than the current + +size, or if space is available to expand the existing chunk. If not, it has + +to copy data from the old chunk to the new; in that case, the run time + +depends on the size of the old chunk. + + + +--- + +44 Chapter 6. Memory management + +ˆ + +Boundary tags: When + +malloc + +allocates a chunk, it adds space at the + +beginning and end to store information about the chunk, including its + +size and the state (allocated or free). These bits of data are called + +“boundary tags”. Using these tags, + +malloc + +can get from any chunk + +to the previous chunk and the next chunk in memory. In addition, free + +chunks are chained into a doubly-linked list; each free chunk contains + +pointers to the next and previous chunks in the “free list”. + +The boundary tags and free list pointers make up + +malloc + +’s internal data + +structures. These data structures are interspersed with program data, + +so it is easy for a program error to damage them. + +ˆ + +Space overhead: Boundary tags and free list pointers take up space. + +The minimum chunk size on most systems is 16 bytes. So for very small + +chunks, + +malloc + +is not space efficient. If your program requires large + +numbers of small structures, it might be more efficient to allocate them + +in arrays. + +ˆ + +Fragmentation: If you allocate and free chunks with varied sizes, the + +heap will tend to become fragmented. That is, the free space might be + +broken into many small pieces. Fragmentation wastes space; it also slows + +the program down by making memory caches less effective. + +ˆ + +Binning and caching: The free list is sorted by size into bins, so when + +malloc + +searches for a chunk with a particular size, it knows what bin + +to search in. If you free a chunk and then immediately allocate a chunk + +with the same size, + +malloc + +will usually be fast. + + + +--- + +## Chapter 7 + +## Caching + +## 7.1 How programs run + +In order to understand caching, you have to understand how computers execute + +programs. For a deep understanding of this topic, you should study computer + +architecture. My goal in this chapter is to provide a simple model of program + +execution. + +When a program starts, the code (or text) is usually on a hard disk or solid + +state drive. The operating system creates a new process to run the program, + +then the “loader” copies the text from storage into main memory and starts + +the program by calling + +main + +. + +While the program is running, most of its data is stored in main memory, but + +some of the data is in registers, which are small units of memory on the CPU. + +These registers include: + +ˆ + +The program counter, or PC, which contains the address (in memory) + +of the next instruction in the program. + +ˆ + +The instruction register, or IR, which contains the machine code instruc + +tion currently executing. + +ˆ + +The stack pointer, or SP, which contains the address of the stack frame + +for the current function, which contains its parameters and local vari + +ables. + +ˆ + +General-purpose registers that hold the data the program is currently + +working with. + + + +--- + +46 Chapter 7. Caching + +ˆ + +A status register, or flag register, that contains information about the + +current computation. For example, the flag register usually contains a + +bit that is set if the result of the previous operation was zero. + +When a program is running, the CPU executes the following steps, called the + +“instruction cycle”: + +ˆ + +Fetch: The next instruction is fetched from memory and stored in the + +instruction register. + +ˆ + +Decode: Part of the CPU, called the “control unit”, decodes the instruc + +tion and sends signals to the other parts of the CPU. + +ˆ + +Execute: Signals from the control unit cause the appropriate computa + +tion to occur. + +Most computers can execute a few hundred different instructions, called the + +“instruction set”. But most instructions fall into a few general categories: + +ˆ + +Load: Transfers a value from memory to a register. + +ˆ + +Arithmetic/logic: Loads operands from registers, performs a mathemat + +ical operation, and stores the result in a register. + +ˆ + +Store: Transfers a value from a register to memory. + +ˆ + +Jump/branch: Changes the program counter, causing the flow of execu + +tion to jump to another location in the program. Branches are usually + +conditional, which means that they check a flag in the flag register and + +jump only if it is set. + +Some instructions sets, including the ubiquitous x86, provide instructions that + +combine a load and an arithmetic operation. + +During each instruction cycle, one instruction is read from the program text. In + +addition, about half of the instructions in a typical program load or store data. + +And therein lies one of the fundamental problems of computer architecture: + +the “memory bottleneck”. + +In current computers, a typical core is capable of executing an instruction in + +less than 1 ns. But the time it takes to transfer data to and from memory is + +about 100 ns. If the CPU has to wait 100 ns to fetch the next instruction, and + +another 100 ns to load data, it would complete instructions 200 times slower + +than what’s theoretically possible. For many computations, memory is the + +speed limiting factor, not the CPU. + + + +--- + +7.2. Cache performance 47 + +## 7.2 Cache performance + +The solution to this problem, or at least a partial solution, is caching. A + +“cache” is a small, fast memory that is physically close to the CPU, usually + +on the same chip. + +Actually, current computers typically have several levels of cache: the Level 1 + +cache, which is the smallest and fastest, might be 1–2 MiB with a access times + +near 1 ns; the Level 2 cache might have access times near 4 ns, and the Level + +3 might take 16 ns. + +When the CPU loads a value from memory, it stores a copy in the cache. If + +the same value is loaded again, the CPU gets the cached copy and doesn’t + +have to wait for memory. + +Eventually the cache gets full. Then, in order to bring something new in, we + +have to kick something out. So if the CPU loads a value and then loads it + +again much later, it might not be in cache any more. + +The performance of many programs is limited by the effectiveness of the cache. + +If the instructions and data needed by the CPU are usually in cache, the + +program can run close to the full speed of the CPU. If the CPU frequently + +needs data that are not in cache, the program is limited by the speed of + +memory. + +The cache “hit rate”, + +h + +, is the fraction of memory accesses that find data in + +cache; the “miss rate”, + +m + +, is the fraction of memory accesses that have to go + +to memory. If the time to process a cache hit is + +T + +h + +and the time for a cache + +miss is + +T + +m + +, the average time for each memory access is + +hT + +h + ++ + +mT + +m + +Equivalently, we could define the “miss penalty” as the extra time to process + +a cache miss, + +T + +p + += + +T + +m + +− + +T + +h + +. Then the average access time is + +T + +h + ++ + +mT + +p + +When the miss rate is low, the average access time can be close to + +T + +h + +. That + +is, the program can perform as if memory ran at cache speeds. + +## 7.3 Locality + +When a program reads a byte for the first time, the cache usually loads a + +“block” or “line” of data that includes the requested byte and some of its + + + +--- + +48 Chapter 7. Caching + +neighbors. If the program goes on to read one of the neighbors, it will already + +be in cache. + +As an example, suppose the block size is 64 B; you read a string with length + +64, and the first byte of the string happens to fall at the beginning of a block. + +When you load the first byte, you incur a miss penalty, but after that the rest + +of the string will be in cache. After reading the whole string, the hit rate will + +be 63/64, about 98%. If the string spans two blocks, you would incur 2 miss + +penalties. But even then the hit rate would be 62/64, or almost 97%. If you + +then read the same string again, the hit rate would be 100%. + +On the other hand, if the program jumps around unpredictably, reading data + +from scattered locations in memory, and seldom accessing the same location + +twice, cache performance would be poor. + +The tendency of a program to use the same data more than once is called + +“temporal locality”. The tendency to use data in nearby locations is called + +“spatial locality”. Fortunately, many programs naturally display both kinds + +of locality: + +ˆ + +Most programs contain blocks of code with no jumps or branches. Within + +these blocks, instructions run sequentially, so the access pattern has + +spatial locality. + +ˆ + +In a loop, programs execute the same instructions many times, so the + +access pattern has temporal locality. + +ˆ + +The result of one instruction is often used immediately as an operand of + +the next instruction, so the data access pattern has temporal locality. + +ˆ + +When a program executes a function, its parameters and local variables + +are stored together on the stack; accessing these values has spatial local + +ity. + +ˆ + +One of the most common processing patterns is to read or write the + +elements of an array sequentially; this pattern also has spatial locality. + +The next section explores the relationship between a program’s access pattern + +and cache performance. + +## 7.4 Measuring cache performance + +When I was a graduate student at U.C. Berkeley I was a teaching assistant + +for Computer Architecture with Brian Harvey. One of my favorite exercises + + + +--- + +7.4. Measuring cache performance 49 + +involved a program that iterates through an array and measures the average + +time to read and write an element. By varying the size of the array, it is + +possible to infer the size of the cache, the block size, and some other attributes. + +My modified version of this program is in the + +cache + +directory of the repository + +for this book (see Section 0.1). + +The important part of the program is this loop: + +iters = 0; + +do { + +sec0 = get_seconds(); + +for (index = 0; index < limit; index += stride) + +array[index] = array[index] + 1; + +iters = iters + 1; + +sec = sec + (get_seconds() - sec0); + +} while (sec < 0.1); + +The inner + +for + +loop traverses the array. + +limit + +determines how much of the + +array it traverses; + +stride + +determines how many elements it skips over. For + +example, if + +limit + +is 16 and + +stride + +is 4, the loop would access elements 0, 4, + +8, and 12. + +sec + +keeps track of the total CPU time used by the inner loop. The outer loop + +runs until + +sec + +exceeds 0.1 seconds, which is long enough that we can compute + +the average time with sufficient precision. + +get_seconds + +uses the system call + +clock_gettime + +, converts to seconds, and + +returns the result as a + +double + +: + +double get_seconds(){ + +struct timespec ts; + +clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + +return ts.tv_sec + ts.tv_nsec / 1e9; + +} + +To isolate the time to access the elements of the array, the program runs a + +second loop that is almost identical except that the inner loop doesn’t touch + +the array; it always increments the same variable: + +iters2 = 0; + +do { + +sec0 = get_seconds(); + + + +--- + +50 Chapter 7. Caching + +Figure 7.1: Average miss penalty as a function of array size and stride. + +for (index = 0; index < limit; index += stride) + +temp = temp + index; + +iters2 = iters2 + 1; + +sec = sec - (get_seconds() - sec0); + +} while (iters2 < iters); + +The second loop runs the same number of iterations as the first. After each + +iteration, it + +subtracts + +the elapsed time from + +sec + +. When the loop completes, + +sec + +contains the total time for all array accesses, minus the total time it took + +to increment + +temp + +. This difference is the total miss penalty incurred by all + +accesses. Finally, we divide by the number of accesses to get the average miss + +penalty per access, in ns: + +sec * 1e9 / iters / limit * stride + +If you compile and run + +cache.c + +you should see output like this: + +Size: 4096 Stride: 8 read+write: 0.8633 ns + +Size: 4096 Stride: 16 read+write: 0.7023 ns + +Size: 4096 Stride: 32 read+write: 0.7105 ns + +Size: 4096 Stride: 64 read+write: 0.7058 ns + +If you have Python and + +matplotlib + +installed, you can use + +graph_data.py + +to + +graph the results. Figure 7.1 shows the results when I ran it on a Dell Optiplex + +7010. Notice that the array size and stride are reported in bytes, not number + +of array elements. + +Take a minute to consider this graph, and see what you can infer about the + +cache. Here are some things to think about: + + + +--- + +7.5. Programming for cache performance 51 + +ˆ + +The program reads through the array many times, so it has plenty of + +temporal locality. If the entire array fits in cache, we expect the average + +miss penalty to be near 0. + +ˆ + +When the stride is 4 bytes, we read every element of the array, so the + +program has plenty of spatial locality. If the block size is big enough to + +contain 64 elements, for example, the hit rate would be 63/64, even if + +the array does not fit in cache. + +ˆ + +If the stride is equal to the block size (or greater), the spatial locality is + +effectively zero, because each time we read a block, we only access one + +element. In that case we expect to see the maximum miss penalty. + +In summary, we expect good cache performance if the array is smaller than + +the cache size + +or + +if the stride is smaller than the block size. Performance only + +degrades if the array is bigger than the cache + +and + +the stride is large. + +In Figure 7.1, cache performance is good, for all strides, as long as the array + +is less than 2 + +22 + +B. We can infer that the cache size is near 4 MiB; in fact, + +according to the specs, it is 3 MiB. + +When the stride is 8, 16, or 32 B, cache performance is good. At 64 B it starts + +to degrade, and for larger strides the average miss penalty is about 9 ns. We + +can infer that the block size near 128 B. + +Many processors use “multi-level caches” that include a small, fast cache and + +a bigger, slower cache. In this example, it looks like the miss penalty increases + +a little when the array size is bigger than 2 + +14 + +B, so it’s possible that this + +processor also has a 16 KB cache with an access time less than 1 ns. + +## 7.5 Programming for cache performance + +Memory caching is implemented in hardware, so most of the time programmers + +don’t need to know much about it. But if you know how caches work, you can + +write programs that use them more effectively. + +For example, if you are working with a large array, it might be faster to traverse + +the array once, performing several operations with each element, rather than + +traversing the array several times. + +If you are working with a 2-D array, it might be stored as an array of rows. + +If you traverse through the elements, it would be faster to go row-wise, with + +stride equal to the element size, rather than column-wise, with stride equal to + +the row length. + + + +--- + +52 Chapter 7. Caching + +Linked data structures don’t always exhibit spatial locality, because the nodes + +aren’t necessarily contiguous in memory. But if you allocate many nodes at + +the same time, they are usually co-located in the heap. Or, even better, if you + +allocate an array of nodes all at once, you know they will be contiguous. + +Recursive strategies like mergesort often have good cache behavior because + +they break big arrays into smaller pieces and then work with the pieces. Some + +times these algorithms can be tuned to take advantage of cache behavior. + +For applications where performance is critical, it is possible to design algo + +rithms tailored to the size of the cache, the block size, and other hardware + +characterstics. Algorithms like that are called “cache-aware”. The obvious + +drawback of cache-aware algorithms is that they are hardware-specific. + +## 7.6 The memory hierarchy + +At some point during this chapter, a question like the following might have + +occurred to you: “If caches are so much faster than main memory, why not + +make a really big cache and forget about memory?” + +Without going too far into computer architecture, there are two reasons: elec + +tronics and economics. Caches are fast because they are small and close to + +the CPU, which minimizes delays due to capacitance and signal propagation. + +If you make a cache big, it will be slower. + +Also, caches take up space on the processor chip, and bigger chips are more + +expensive. Main memory is usually dynamic random-access memory (DRAM), + +which uses only one transistor and one capacitor per bit, so it is possible to pack + +more memory into the same amount of space. But this way of implementing + +memory is slower than the way caches are implemented. + +Also main memory is usually packaged in a dual in-line memory module + +(DIMM) that includes 16 or more chips. Several small chips are cheaper than + +one big one. + +The trade-off between speed, size, and cost is the fundamental reason for + +caching. If there were one memory technology that was fast, big, and cheap, + +we wouldn’t need anything else. + +The same principle applies to storage as well as memory. Solid state drives + +(SSD) are fast, but they are more expensive than hard drives (HDD), so they + +tend to be smaller. Tape drives are even slower than hard drives, but they can + +store large amounts of data relatively cheaply. + + + +--- + +7.7. Caching policy 53 + +The following table shows typical access times, sizes, and costs for each of + +these technologies. + +Device + +Access + +Typical + +Cost + +time + +size + +Register + +0.5 ns + +256 B + +? + +Cache + +1 ns + +2 MiB + +? + +DRAM + +100 ns + +4 GiB + +$ + +10 / GiB + +SSD + +10 + +µ + +s + +100 GiB + +$ + +1 / GiB + +HDD + +5 ms + +500 GiB + +$ + +0.25 / GiB + +Tape + +minutes + +1–2 TiB + +$ + +0.02 / GiB + +The number and size of registers depends on details of the architecture. Cur + +rent computers have about 32 general-purpose registers, each storing one + +“word”. On a 32-bit computer, a word is 32 bits or 4 B. On a 64-bit computer, + +a word is 64 bits or 8 B. So the total size of the register file is 100–300 B. + +The cost of registers and caches is hard to quantify. They contribute to the + +cost of the chips they are on, but consumers don’t see that cost directly. + +For the other numbers in the table, I looked at the specifications for typical + +hardware for sale from online computer hardware stores. By the time you read + +this, these numbers will be obsolete, but they give you an idea of what the + +performance and cost gaps looked like at one point in time. + +These technologies make up the “memory hierarchy” (note that this use of + +“memory” also includes storage). Each level of the hierarchy is bigger and + +slower than the one above it. And in some sense, each level acts as a cache for + +the one below it. You can think of main memory as a cache for programs and + +data that are stored permanently on SSDs and HHDs. And if you are working + +with very large datasets stored on tape, you could use hard drives to cache + +one subset of the data at a time. + +## 7.7 Caching policy + +The memory hierarchy suggests a framework for thinking about caching. At + +every level of the hierarchy, we have to address four fundamental questions of + +caching: + +ˆ + +Who moves data up and down the hierarchy? At the top of the hierarchy, + +register allocation is usually done by the compiler. Hardware on the CPU + +handles the memory cache. Users implicitly move data from storage to + + + +--- + +54 Chapter 7. Caching + +memory when they execute programs and open files. But the operating + +system also moves data back and forth between memory and storage. At + +the bottom of the hierarchy, administrators move data explicitly between + +disk and tape. + +ˆ + +What gets moved? In general, block sizes are small at the top of the + +hierarchy and bigger at the bottom. In a memory cache, a typical block + +size is 128 B. Pages in memory might be 4 KiB, but when the operating + +system reads a file from disk, it might read 10s or 100s of blocks at a + +time. + +ˆ + +When does data get moved? In the most basic cache, data gets moved + +into cache when it is used for the first time. But many caches use some + +kind of “prefetching”, meaning that data is loaded before it is explicitly + +requested. We have already seen one form of prefetching: loading an + +entire block when only part of it is requested. + +ˆ + +Where in the cache does the data go? When the cache is full, we can’t + +bring anything in without kicking something out. Ideally, we want to + +keep data that will be used again soon and replace data that won’t. + +The answers to these questions make up the “cache policy”. Near the top of + +the hierarchy, cache policies tend to be simple because they have to be fast + +and they are implemented in hardware. Near the bottom of the hierarchy, + +there is more time to make decisions, and well-designed policies can make a + +big difference. + +Most cache policies are based on the principle that history repeats itself; if we + +have information about the recent past, we can use it to predict the immediate + +future. For example, if a block of data has been used recently, we expect it to + +be used again soon. This principle suggests a replacement policy called “least + +recently used,” or LRU, which removes from the cache a block of data that has + +not been used recently. For more on this topic, see + +http://en.wikipedia. + +org/wiki/Cache_algorithms + +. + +## 7.8 Paging + +In systems with virtual memory, the operating system can move pages back + +and forth between memory and storage. As I mentioned in Section 6.2, this + +mechanism is called “paging” or sometimes “swapping”. + +Here’s how the process works: + + + +--- + +7.8. Paging 55 + +1. + +Suppose Process A calls + +malloc + +to allocate a chunk. If there is no free + +space in the heap with the requested size, + +malloc + +calls + +sbrk + +to ask the + +operating system for more memory. + +2. + +If there is a free page in physical memory, the operating system adds it + +to the page table for Process A, creating a new range of valid virtual + +addresses. + +3. + +If there are no free pages, the paging system chooses a “victim page” + +belonging to Process B. It copies the contents of the victim page from + +memory to disk, then it modifies the page table for Process B to indicate + +that this page is “swapped out”. + +4. + +Once the data from Process B is written, the page can be reallocated + +to Process A. To prevent Process A from reading Process B’s data, the + +page should be cleared. + +5. + +At this point the call to + +sbrk + +can return, giving + +malloc + +additional space + +in the heap. Then + +malloc + +allocates the requested chunk and returns. + +Process A can resume. + +6. + +When Process A completes, or is interrupted, the scheduler might allow + +Process B to resume. When Process B accesses a page that has been + +swapped out, the memory management unit notices that the page is + +“invalid” and causes an interrupt. + +7. + +When the operating system handles the interrupt, it sees that the page + +is swapped out, so it transfers the page back from disk to memory. + +8. + +Once the page is swapped in, Process B can resume. + +When paging works well, it can greatly improve the utilization of physical + +memory, allowing more processes to run in less space. Here’s why: + +ˆ + +Most processes don’t use all of their allocated memory. Many parts of + +the text segment are never executed, or execute once and never again. + +Those pages can be swapped out without causing any problems. + +ˆ + +If a program leaks memory, it might leave allocated space behind and + +never access it again. By swapping those pages out, the operating system + +can effectively plug the leak. + +ˆ + +On most systems, there are processes like daemons that sit idle most of + +the time and only occasionally “wake up” to respond to events. While + +they are idle, these processes can be swapped out. + + + +--- + +56 Chapter 7. Caching + +ˆ + +A user might have many windows open, but only a few are active at a + +time. The inactive processes can be swapped out. + +ˆ + +Also, there might be many processes running the same program. These + +processes can share the same text and static segments, avoiding the need + +to keep multiple copies in physical memory. + +If you add up the total memory allocated to all processes, it can greatly exceed + +the size of physical memory, and yet the system can still behave well. + +Up to a point. + +When a process accesses a page that’s swapped out, it has to get the data back + +from disk, which can take several milliseconds. The delay is often noticeable. + +If you leave a window idle for a long time and then switch back to it, it + +might start slowly, and you might hear the disk drive working while pages are + +swapped in. + +Occasional delays like that might be acceptable, but if you have too many + +processes using too much space, they start to interfere with each other. When + +Process A runs, it evicts the pages Process B needs. Then when B runs, it + +evicts the pages A needs. When this happens, both processes slow to a crawl + +and the system can become unresponsive. This scenario is called “thrashing”. + +In theory, operating systems could avoid thrashing by detecting an increase in + +paging and blocking or killing processes until the system is responsive again. + +But as far as I can tell, most systems don’t do this, or don’t do it well; it is + +often left to users to limit their use of physical memory or try to recover when + +thrashing occurs. + + + +--- + +## Chapter 8 + +## Multitasking + +In many current systems, the CPU contains multiple cores, which means it can + +run several processes at the same time. In addition, each core is capable of + +“multitasking”, which means it can switch from one process to another quickly, + +creating the illusion that many processes are running at the same time. + +The part of the operating system that implements multitasking is the “kernel”. + +In a nut or seed, the kernel is the innermost part, surrounded by a shell. In + +an operating system, the kernel is the lowest level of software, surrounded by + +several other layers, including an interface called a “shell.” Computer scientists + +love extended metaphors. + +At its most basic, the kernel’s job is to handle interrupts. An “interrupt” is an + +event that stops the normal instruction cycle and causes the flow of execution + +to jump to a special section of code called an “interrupt handler”. + +A + +hardware interrupt + +is caused when a device sends a signal to the CPU. + +For example, a network interface might cause an interrupt when a packet of + +data arrives, or a disk drive might cause an interrupt when a data transfer + +is complete. Most systems also have timers that cause interrupts at regular + +intervals, or after an elapsed time. + +A + +software interrupt + +is caused by a running program. For example, if an + +instruction cannot complete for some reason, it might trigger an interrupt so + +the condition can be handled by the operating system. Some floating-point + +errors, like division by zero, are handled using interrupts. + +When a program needs to access a hardware device, it makes a + +system call + +, + +which is similar to a function call, except that instead of jumping to the + +beginning of the function, it executes a special instruction that triggers an + + + +--- + +58 Chapter 8. Multitasking + +interrupt, causing the flow of execution to jump to the kernel. The kernel + +reads the parameters of the system call, performs the requested operation, + +and then resumes the interrupted process. + +## 8.1 Hardware state + +Handling interrupts requires cooperation between hardware and software. + +When an interrupt occurs, there might be several instructions running on + +the CPU, data stored in registers, and other + +hardware state + +. + +Usually the hardware is responsible for bringing the CPU to a consistent state; + +for example, every instruction should either complete or behave as if it never + +started. No instruction should be left half complete. Also, the hardware is + +responsible for saving the program counter (PC), so the kernel knows where + +to resume. + +Then, usually, it is the responsibility of the interrupt handler to save the rest + +of the hardware state before it does anything that might modify it, and then + +restore the saved state before the interrupted process resumes. + +Here is an outline of this sequence of events: + +1. + +When the interrupt occurs, the hardware saves the program counter in + +a special register and jumps to the appropriate interrupt handler. + +2. + +The interrupt handler stores the program counter and the status register + +in memory, along with the contents of any data registers it plans to use. + +3. + +The interrupt handler runs whatever code is needed to handle the inter + +rupt. + +4. + +Then it restores the contents of the saved registers. Finally, it restores + +the program counter of the interrupted process, which has the effect of + +jumping back to the interrupted instruction. + +If this mechanism works correctly, there is generally no way for the interrupted + +process to know there was an interrupt, unless it detects the change in time + +between instructions. + +## 8.2 Context switching + +Interrupt handlers can be fast because they don’t have to save the entire + +hardware state; they only have to save registers they are planning to use. + + + +--- + +8.3. The process life cycle 59 + +But when an interrupt occurs, the kernel does not always resume the inter + +rupted process. It has the option of switching to another process. This mech + +anism is called a “context switch”. + +In general, the kernel doesn’t know which registers a process will use, so it has + +to save all of them. Also, when it switches to a new process, it might have + +to clear data stored in the memory management unit (see Section 3.6). And + +after the context switch, it might take some time for the new process to load + +data into the cache. For these reasons, context switches are relatively slow, on + +the order of thousands of cycles, or a few microseconds. + +In a multi-tasking system, each process is allowed to run for a short period of + +time called a “time slice” or “quantum”. During a context switch, the kernel + +sets a hardware timer that causes an interrupt at the end of the time slice. + +When the interrupt occurs, the kernel can switch to another process or allow + +the interrupted process to resume. The part of the operating system that + +makes this decision is the “scheduler”. + +## 8.3 The process life cycle + +When a process is created, the operating system allocates a data structure + +that contains information about the process, called a “process control block” + +or PCB. Among other things, the PCB keeps track of the process state, which + +is one of: + +ˆ + +Running, if the process is currently running on a core. + +ˆ + +Ready, if the process could be running, but isn’t, usually because there + +are more runnable processes than cores. + +ˆ + +Blocked, if the process cannot run because it is waiting for a future event + +like network communication or a disk read. + +ˆ + +Done, if the process has completed, but has exit status information that + +has not been read yet. + +Here are the events that cause a process to transition from one state to another: + +ˆ + +A process is created when the running program executes a system call + +like + +fork + +. At the end of the system call, the new process is usually ready. + +Then the scheduler might resume the original process (the “parent”) or + +start the new process (the “child”). + + + +--- + +60 Chapter 8. Multitasking + +ˆ + +When a process is started or resumed by the scheduler, its state changes + +from ready to running. + +ˆ + +When a process is interrupted and the scheduler chooses not to let it + +resume, its state changes from running to ready. + +ˆ + +If a process executes a system call that cannot complete immediately, + +like a disk request, it becomes blocked and the scheduler usually chooses + +another process. + +ˆ + +When an operation like a disk request completes, it causes an interrupt. + +The interrupt handler figures out which process was waiting for the re + +quest and switches its state from blocked to ready. Then the scheduler + +may or may not choose to resume the unblocked process. + +ˆ + +When a process calls + +exit + +, the interrupt handler stores the exit code in + +the PCB and changes the process’s state to done. + +## 8.4 Scheduling + +As we saw in Section 2.3 there might be hundreds of processes on a computer, + +but usually most of them are blocked. Most of the time, there are only a few + +processes that are ready or running. When an interrupt occurs, the scheduler + +decides which process to start or resume. + +On a workstation or laptop, the primary goal of the scheduler is to minimize + +response time; that is, the computer should respond quickly to user actions. + +Response time is also important on a server, but in addition the scheduler + +might try to maximize throughput, which is the number of requests that com + +plete per unit of time. + +Usually the scheduler doesn’t have much information about what processes + +are doing, so its decisions are based on a few heuristics: + +ˆ + +Processes might be limited by different resources. A process that does + +a lot of computation is probably CPU-bound, which means that its run + +time depends on how much CPU time it gets. A process that reads data + +from a network or disk might be I/O-bound, which means that it would + +run faster if data input and output went faster, but would not run faster + +with more CPU time. Finally, a process that interacts with the user is + +probably blocked, most of the time, waiting for user actions. + +The operating system can sometimes classify processes based on their + +past behavior, and schedule them accordingly. For example, when an + + + +--- + +8.4. Scheduling 61 + +interactive process is unblocked, it should probably run immediately, + +because a user is probably waiting for a reply. On the other hand, a + +CPU-bound process that has been running for a long time might be less + +time-sensitive. + +ˆ + +If a process is likely to run for a short time and then make a blocking + +request, it should probably run immediately, for two reasons: (1) if the + +request takes some time to complete, we should start it as soon as pos + +sible, and (2) it is better for a long-running process to wait for a short + +one, rather than the other way around. + +As an analogy, suppose you are making an apple pie. The crust takes + +5 minutes to prepare, but then it has to chill for half an hour. It takes + +20 minutes to prepare the filling. If you prepare the crust first, you can + +prepare the filling while the crust is chilling, and you can finish the pie in + +35 minutes. If you prepare the filling first, the process takes 55 minutes. + +Most schedulers use some form of priority-based scheduling, where each process + +has a priority that can be adjusted up or down over time. When the scheduler + +runs, it chooses the runnable process with the highest priority. + +Here are some of the factors that determine a process’s priority: + +ˆ + +A process usually starts with a relatively high priority so it starts running + +quickly. + +ˆ + +If a process makes a request and blocks before its time slice is complete, + +it is more likely to be interactive or I/O-bound, so its priority should go + +up. + +ˆ + +If a process runs for an entire time slice, it is more likely to be long + +running and CPU-bound, so its priority should go down. + +ˆ + +If a task blocks for a long time and then becomes ready, it should get a + +priority boost so it can respond to whatever it was waiting for. + +ˆ + +If process A is blocked waiting for process B, for example if they are + +connected by a pipe, the priority of process B should go up. + +ˆ + +The system call + +nice + +allows a process to decrease (but not increase) its + +own priority, allowing programmers to pass explicit information to the + +scheduler. + +For most systems running normal workloads, scheduling algorithms don’t have + +a substantial effect on performance. Simple scheduling policies are usually + +good enough. + + + +--- + +62 Chapter 8. Multitasking + +## 8.5 Real-time scheduling + +However, for programs that interact with the real world, scheduling can be + +very important. For example, a program that reads data from sensors and + +controls motors might have to complete recurring tasks at some minimum fre + +quency and react to external events with some maximum response time. These + +requirements are often expressed in terms of “tasks” that must be completed + +before “deadlines”. + +Scheduling tasks to meet deadlines is called “real-time scheduling”. For some + +applications, a general-purpose operating system like Linux can be modified + +to handle real-time scheduling. These modifications might include: + +ˆ + +Providing richer APIs for controlling task priorities. + +ˆ + +Modifying the scheduler to guarantee that the process with highest pri + +ority runs within a fixed amount of time. + +ˆ + +Reorganizing interrupt handlers to guarantee a maximum completion + +time. + +ˆ + +Modifying locks and other synchronization mechanisms (coming up in + +the next chapter) to allow a high-priority task to preempt a lower-priority + +task. + +ˆ + +Choosing an implementation of dynamic memory allocation that guar + +antees a maximum completion time. + +For more demanding applications, especially in domains where real-time re + +sponse is a matter of life and death, “real-time operating systems” provide + +specialized capabilities, often with much simpler designs than general purpose + +operating systems. + + + +--- + +## Chapter 9 + +## Threads + +When I mentioned threads in Section 2.3, I said that a thread is a kind of + +process. Now I will provide a more careful explanation. + +When you create a process, the operating system creates a new address space, + +which includes the text segment, static segment, and heap; it also creates + +a new “thread of execution”, which includes the program counter and other + +hardware state, and the call stack. + +The processes we have seen so far are “single-threaded”, which means that only + +one thread of execution runs in each address space. In this chapter, you will + +learn about “multi-threaded” processes that have multiple threads running in + +the same address space. + +Within a single process, all threads share the same text segment, so they run + +the same code. But different threads often run different parts of the code. + +And they share the same static segment, so if one thread changes a global + +variable, other threads see the change. They also share the heap, so threads + +can share dynamically-allocated chunks. + +But each thread has its own stack, so threads can call functions without inter + +fering with each other. Usually threads don’t access each other’s local variables + +(and sometimes they can’t). + +The example code for this chapter is in the repository for this book, in a + +directory named + +counter + +. For information on downloading this code, see + +Section 0.1. + + + +--- + +64 Chapter 9. Threads + +## 9.1 Creating threads + +The most popular threading standard used with C is POSIX Threads, or + +Pthreads for short. The POSIX standard defines a thread model and an + +interface for creating and controlling threads. Most versions of UNIX provide + +an implementation of Pthreads. + +Using Pthreads is like using most C libraries: + +ˆ + +You include headers files at the beginning of your program. + +ˆ + +You write code that calls functions defined by Pthreads. + +ˆ + +When you compile the program, you link it with the Pthread library. + +For my examples, I include the following headers: + +#include + +#include + +#include + +#include + +The first two are standard; the third is for Pthreads and the fourth is for + +semaphores. To compile with the Pthread library in + +gcc + +, you can use the + +-l + +option on the command line: + +gcc -g -O2 -o array array.c -lpthread + +This compiles a source file named + +array.c + +with debugging info and opti + +mization, links with the Pthread library, and generates an executable named + +array + +. + +## 9.2 Creating threads + +The Pthread function that creates threads is called + +pthread_create + +. The + +following function shows how to use it: + +pthread_t make_thread(void *(*entry)(void *), Shared *shared) + +{ + +int n; + +pthread_t thread; + +n = pthread_create(&thread, NULL, entry, (void *)shared); + +if (n != 0) { + +perror("pthread_create failed"); + + + +--- + +9.2. Creating threads 65 + +exit(-1); + +} + +return thread; + +} + +make_thread + +is a wrapper I wrote to make + +pthread_create + +easier to use, and + +to provide error-checking. + +The return type from + +pthread_create + +is + +pthread_t + +, which you can think of + +as an id or “handle” for the new thread. + +If + +pthread + +create + +succeeds, it returns 0 and + +make_thread + +returns the handle + +of the new thread. If an error occurs, + +pthread + +create + +returns an error code + +and + +make_thread + +prints an error message and exits. + +The parameters of + +make_thread + +take some explaining. Starting with the sec + +ond, + +Shared + +is a structure I defined to contain values shared between threads. + +The following + +typedef + +statement creates the new type: + +typedef struct { + +int counter; + +} Shared; + +In this case, the only shared variable is + +counter + +. + +make + +shared + +allocates space + +for a + +Shared + +structure and initializes the contents: + +Shared *make_shared() + +{ + +Shared *shared = check_malloc(sizeof (Shared)); + +shared->counter = 0; + +return shared; + +} + +Now that we have a shared data structure, let’s get back to + +make_thread + +. + +The first parameter is a pointer to a function that takes a + +void + +pointer and + +returns a + +void + +pointer. If the syntax for declaring this type makes your eyes + +bleed, you are not alone. Anyway, the purpose of this parameter is to specify + +the function where the execution of the new thread will begin. By convention, + +this function is named + +entry + +: + +void *entry(void *arg) + +{ + +Shared *shared = (Shared *) arg; + +child_code(shared); + +pthread_exit(NULL); + +} + + + +--- + +66 Chapter 9. Threads + +The parameter of + +entry + +has to be declared as a + +void + +pointer, but in this + +program we know that it is really a pointer to a + +Shared + +structure, so we can + +typecast it accordingly and then pass it along to + +child + +code + +, which does the + +real work. + +As a simple example, + +child_code + +prints the value of the shared counter and + +increments it. + +void child_code(Shared *shared) + +{ + +printf("counter = %d\n", shared->counter); + +shared->counter++; + +} + +When + +child + +code + +returns, + +entry + +invokes + +pthread_exit + +which can be used to + +pass a value to the thread that joins with this thread. In this case, the child + +has nothing to say, so we pass + +NULL + +. + +Finally, here is the code that creates the child threads: + +int i; + +pthread_t child[NUM_CHILDREN]; + +Shared *shared = make_shared(1000000); + +for (i=0; imutex); + +printf("counter = %d\n", shared->counter); + +shared->counter++; + +mutex_unlock(shared->mutex); + +} + +Before any thread can access + +counter + +, it has to “lock” the mutex, which + +has the effect of barring all other threads. Suppose Thread A has locked the + +mutex and is in the middle of + +child_code + +. If Thread B arrives and executes + +mutex_lock + +, it blocks. + +When Thread A is done, it executes + +mutex_unlock + +, which allows Thread B to + +proceed. In effect, the threads line up to execute + +child_code + +one at a time, + + + +--- + +9.5. Mutex 69 + +so they can’t interfere with each other. When I run this code with 5 children, + +I get: + +counter = 0 + +counter = 1 + +counter = 2 + +counter = 3 + +counter = 4 + +And that satisfies the requirements. In order for this solution to work, I have + +to add the Mutex to the Shared struct: + +typedef struct { + +int counter; + +Mutex *mutex; + +} Shared; + +And initialize it in + +make_shared + +Shared *make_shared(int end) + +{ + +Shared *shared = check_malloc(sizeof(Shared)); + +shared->counter = 0; + +shared->mutex = make_mutex(); //-- this line is new + +return shared; + +} + +The code in this section is in + +counter_mutex.c + +. The definition of + +Mutex + +is in + +mutex.c + +, which I explain in the next section. + +## 9.5 Mutex + +My definition of + +Mutex + +is a wrapper for a type called + +pthread_mutex_t + +, which + +is defined in the POSIX threads API. + +To create a POSIX mutex, you have to allocate space for a + +pthread_mutex_t + +type and then call + +pthread_mutex_init + +. + +One of the problems with this API is that + +pthread_mutex_t + +behaves like a + +structure, so if you pass it as an argument, it makes a copy, which makes the + +mutex behave incorrectly. To avoid that, you have to pass + +pthread_mutex_t + +by address. + +My code makes it easier to get that right. It defines a type, + +Mutex + +, which is + +just a more readable name for + +pthread_mutex_t + +: + + + +--- + +70 Chapter 9. Threads + +#include + +typedef pthread_mutex_t Mutex; + +Then it defines + +make_mutex + +, which allocates space and initializes the mutex: + +Mutex *make_mutex() + +{ + +Mutex *mutex = check_malloc(sizeof(Mutex)); + +int n = pthread_mutex_init(mutex, NULL); + +if (n != 0) perror_exit("make_lock failed"); + +return mutex; + +} + +The return value is a pointer, which you can pass around as an argument + +without causing unwanted copying. + +The functions to lock and unlock the mutex are simple wrappers for POSIX + +functions: + +void mutex_lock(Mutex *mutex) + +{ + +int n = pthread_mutex_lock(mutex); + +if (n != 0) perror_exit("lock failed"); + +} + +void mutex_unlock(Mutex *mutex) + +{ + +int n = pthread_mutex_unlock(mutex); + +if (n != 0) perror_exit("unlock failed"); + +} + +This code is in + +mutex.c + +and the header file + +mutex.h + +. + + + +--- + +## Chapter 10 + +## Condition variables + +Many simple synchronization problems can be solved using mutexes as shown + +in the previous chapter. In this chapter I introduce a bigger challenge, the + +well-known “Producer-Consumer problem”, and a new tool to solve it, the + +condition variable. + +## 10.1 The work queue + +In some multi-threaded programs, threads are organized to perform different + +tasks. Often they communicate with each other using a queue, where some + +threads, called “producers”, put data into the queue and other threads, called + +“consumers”, take data out. + +For example, in applications with a graphical user interface, there might be + +one thread that runs the GUI, responding to user events, and another thread + +that processes user requests. In that case, the GUI thread might put requests + +into a queue and the “back end” thread might take requests out and process + +them. + +To support this organization, we need a queue implementation that is “thread + +safe”, which means that both threads (or more than two) can access the queue + +at the same time. And we need to handle the special cases when the queue is + +empty and, if the size of the queue is bounded, when the queue is full. + +I’ll start with a simple queue that is not thread safe, then we’ll see what goes + +wrong and fix it. The code for this example is in the repository for this book, + +in a folder called + +queue + +. The file + +queue.c + +contains a basic implementation of + +a circular buffer, which you can read about at + +https://en.wikipedia.org/ + +wiki/Circular_buffer + +. + + + +--- + +72 Chapter 10. Condition variables + +Here’s the structure definition: + +typedef struct { + +int *array; + +int length; + +int next_in; + +int next_out; + +} Queue; + +array + +is the array that contains the elements of the queue. For this example + +the elements are ints, but more generally they would be structures that contain + +user events, items of work, etc. + +length + +is the length of the array. + +next_in + +is an index into the array that + +indices where the next element should be added; similarly, + +next_out + +is the + +index of the next element that should be removed. + +make_queue + +allocates space for this structure and initializes the fields: + +Queue *make_queue(int length) + +{ + +Queue *queue = (Queue *) malloc(sizeof(Queue)); + +queue->length = length + 1; + +queue->array = (int *) malloc(length * sizeof(int)); + +queue->next_in = 0; + +queue->next_out = 0; + +return queue; + +} + +The initial value for + +next_out + +needs some explaining. Since the queue is + +initially empty, there is no next element to remove, so + +next_out + +is invalid. + +Setting + +next_out == next_in + +is a special case that indicates that the queue + +is empty, so we can write: + +int queue_empty(Queue *queue) + +{ + +return (queue->next_in == queue->next_out); + +} + +Now we can add elements to the queue using + +queue_push + +: + +void queue_push(Queue *queue, int item) { + +if (queue_full(queue)) { + +perror_exit("queue is full"); + +} + +queue->array[queue->next_in] = item; + + + +--- + +10.1. The work queue 73 + +queue->next_in = queue_incr(queue, queue->next_in); + +} + +If the queue is full, + +queue_push + +prints an error message and exits. I will + +explain + +queue_full + +soon. + +If the queue is not full, + +queue_push + +inserts the new element and then incre + +ments + +next_in + +using + +queue_incr + +: + +int queue_incr(Queue *queue, int i) + +{ + +return (i+1) % queue->length; + +} + +When the index, + +i + +, gets to the end of the array, it wraps around to 0. And + +that’s where we run into a tricky part. If we keep adding elements to the + +queue, eventually + +next_in + +wraps around and catches up with + +next_out + +. But + +if + +next_in == next_out + +, we would incorrectly conclude that the queue was + +empty. + +To avoid that, we define another special case to indicate that the queue is full: + +int queue_full(Queue *queue) + +{ + +return (queue_incr(queue, queue->next_in) == queue->next_out); + +} + +If incrementing + +next_in + +lands on + +next_out + +, that means we can’t add another + +element without making the queue seem empty. So we stop one element before + +the “end” (keeping in mind that the end of the queue can be anywhere, not + +necessarily the end of the array). + +Now we can write + +queue_pop + +, which removes and returns the next element + +from the queue: + +int queue_pop(Queue *queue) { + +if (queue_empty(queue)) { + +perror_exit("queue is empty"); + +} + +int item = queue->array[queue->next_out]; + +queue->next_out = queue_incr(queue, queue->next_out); + +return item; + +} + +If you try to pop from an empty queue, + +queue_pop + +prints an error message + +and exits. + + + +--- + +74 Chapter 10. Condition variables + +## 10.2 Producers and consumers + +Now let’s make some threads to access this queue. Here’s the producer code: + +void *producer_entry(void *arg) { + +Shared *shared = (Shared *) arg; + +for (int i=0; iqueue, i); + +} + +pthread_exit(NULL); + +} + +Here’s the consumer code: + +void *consumer_entry(void *arg) { + +int item; + +Shared *shared = (Shared *) arg; + +for (int i=0; iqueue); + +printf("consuming item %d\n", item); + +} + +pthread_exit(NULL); + +} + +Here’s the parent code that starts the threads and waits for them + +pthread_t child[NUM_CHILDREN]; + +Shared *shared = make_shared(); + +child[0] = make_thread(producer_entry, shared); + +child[1] = make_thread(consumer_entry, shared); + +for (int i=0; iqueue = make_queue(QUEUE_LENGTH); + +return shared; + +} + +The code we have so far is a good starting place, but it has several problems: + +ˆ + +Access to the queue is not thread safe. Different threads could access + +array + +, + +next_in + +, and + +next_out + +at the same time and leave the queue in + +a broken, “inconsistent” state. + +ˆ + +If the consumer is scheduled first, it finds the queue empty, print an error + +message, and exits. We would rather have the consumer block until the + +queue is not empty. Similarly, we would like the producer to block if the + +queue is full. + +In the next section, we solve the first problem with a + +Mutex + +. In the following + +section, we solve the second problem with condition variables. + +## 10.3 Mutual exclusion + +We can make the queue thread safe with a mutex. This version of the code is + +in + +queue_mutex.c + +. + +First we add a + +Mutex + +pointer to the queue structure: + +typedef struct { + +int *array; + +int length; + +int next_in; + +int next_out; + +Mutex *mutex; //-- this line is new + +} Queue; + +And initialize the + +Mutex + +in + +make_queue + +: + +Queue *make_queue(int length) { + +Queue *queue = (Queue *) malloc(sizeof(Queue)); + +queue->length = length; + +queue->array = (int *) malloc(length * sizeof(int)); + +queue->next_in = 0; + +queue->next_out = 0; + +queue->mutex = make_mutex(); //-- new + +return queue; + +} + + + +--- + +76 Chapter 10. Condition variables + +Next we add synchronization code to + +queue_push + +: + +void queue_push(Queue *queue, int item) { + +mutex_lock(queue->mutex); //-- new + +if (queue_full(queue)) { + +mutex_unlock(queue->mutex); //-- new + +perror_exit("queue is full"); + +} + +queue->array[queue->next_in] = item; + +queue->next_in = queue_incr(queue, queue->next_in); + +mutex_unlock(queue->mutex); //-- new + +} + +Before checking whether the queue is full, we have to lock the + +Mutex + +. If the + +queue is full, we have to unlock the + +Mutex + +before exiting; otherwise the thread + +would leave it locked and no other threads could proceed. + +The synchronization code for + +queue_pop + +is similar: + +int queue_pop(Queue *queue) { + +mutex_lock(queue->mutex); + +if (queue_empty(queue)) { + +mutex_unlock(queue->mutex); + +perror_exit("queue is empty"); + +} + +int item = queue->array[queue->next_out]; + +queue->next_out = queue_incr(queue, queue->next_out); + +mutex_unlock(queue->mutex); + +return item; + +} + +Note that the other + +Queue + +functions, + +queue_full + +, + +queue_empty + +, and + +queue_incr + +do not try to lock the mutex. Any thread that calls these functions + +is required to lock the mutex first; this requirement is part of the documented + +interface for these functions. + +With this additional code, the queue is thread safe; if you run it, you should + +not see any synchronization errors. But it is likely that the consumer will exit + +at some point because the queue is empty, or the producer will exit because + +the queue is full, or both. + +The next step is to add condition variables. + + + +--- + +10.4. Condition variables 77 + +## 10.4 Condition variables + +A condition variable is a data structure associated with a condition; it allows + +threads to block until the condition becomes true. For example, + +thread_pop + +might want check whether the queue is empty and, if so, wait for a condition + +like “queue not empty”. + +Similarly, + +thread_push + +might want to check whether the queue is full and, if + +so, block until it is not full. + +I’ll handle the first condition here, and you will have a chance to handle the + +second condition as an exercise. + +First we add a condition variable to the + +Queue + +structure: + +typedef struct { + +int *array; + +int length; + +int next_in; + +int next_out; + +Mutex *mutex; + +Cond *nonempty; //-- new + +} Queue; + +And initialize it in + +make_queue + +: + +Queue *make_queue(int length) + +{ + +Queue *queue = (Queue *) malloc(sizeof(Queue)); + +queue->length = length; + +queue->array = (int *) malloc(length * sizeof(int)); + +queue->next_in = 0; + +queue->next_out = 0; + +queue->mutex = make_mutex(); + +queue->nonempty = make_cond(); //-- new + +return queue; + +} + +Now in + +queue_pop + +, if we find the queue empty, we don’t exit; instead we use + +the condition variable to block: + +int queue_pop(Queue *queue) { + +mutex_lock(queue->mutex); + +while (queue_empty(queue)) { + +cond_wait(queue->nonempty, queue->mutex); //-- new + +} + + + +--- + +78 Chapter 10. Condition variables + +int item = queue->array[queue->next_out]; + +queue->next_out = queue_incr(queue, queue->next_out); + +mutex_unlock(queue->mutex); + +cond_signal(queue->nonfull); //-- new + +return item; + +} + +cond_wait + +is complicated, so let’s take it slow. The first argument is the + +condition variable; in this case, the condition we are waiting for is “queue not + +empty”. The second argument is the mutex that protects the queue. + +When the thread that locked the mutex calls + +cond_wait + +, it unlocks the mutex + +and then blocks. This is important. If + +cond_wait + +did not unlock the mutex + +before blocking, no other thread would be able to access the queue, no more + +items could be added, and the queue would always be empty. + +So while the consumer is blocked on + +nonempty + +, the producer can run. Let’s + +see what happens when the producer runs + +queue_push + +: + +void queue_push(Queue *queue, int item) { + +mutex_lock(queue->mutex); + +if (queue_full(queue)) { + +mutex_unlock(queue->mutex); + +perror_exit("queue is full"); + +} + +queue->array[queue->next_in] = item; + +queue->next_in = queue_incr(queue, queue->next_in); + +mutex_unlock(queue->mutex); + +cond_signal(queue->nonempty); //-- new + +} + +Just as before, + +queue_push + +locks the + +Mutex + +and checks whether the queue is + +full. Assuming it is not, + +queue_push + +adds a new element to the queue and + +then unlocks the + +Mutex + +. + +But before returning, it does one more thing: it “signals” the condition variable + +nonempty + +. + +Signalling a condition variable usually indicates that the condition is true. If + +there are no threads waiting on the condition variable, the signal has no effect. + +If there are threads waiting on the condition variable, one of them gets un + +blocked and resumes execution of + +cond_wait + +. But before the awakened thread + +can return from + +cond_wait + +, it has to wait for and lock the + +Mutex + +, again. + +Now go back to + +queue_pop + +and see what happens when the thread returns + +from + +cond_wait + +. It loops back to the top of the while loop and checks the + + + +--- + +10.4. Condition variables 79 + +condition again. I’ll explain why in just a second, but for now let’s assume + +that the condition is true; that is, the queue is not empty. + +When the consumer thread exits the while loop, we know two things: (1) the + +condition is true, so there is at least one item in the queue, and (2) the + +Mutex + +is locked, so it is safe to access the queue. + +After removing an item, + +queue_pop + +unlocks the mutex and returns. + +In the next section I’ll show you how my + +Cond + +code works, but first I want to + +answer two frequently-asked questions: + +ˆ + +Why is + +cond_wait + +inside a while loop rather than an if statement; that + +is, why do we have to check the condition again after returning from + +cond_wait + +? + +The primary reason you have to re-check the condition is the possibility + +of an intercepted signal. Suppose Thread A is waiting on + +nonempty + +. + +Thread B adds an item to the queue and signals + +nonempty + +. Thread A + +wakes up an tries to lock the mutex, but before it gets the chance, Evil + +Thread C swoops in, locks the mutex, pops the item from the queue, + +and unlocks the mutex. Now the queue is empty again, but Thread A is + +not blocked any more. Thread A could lock the mutex and returns from + +cond_wait + +. If Thread A does not check the condition again, it would try + +to pop an element from an empty queue, and probably cause an error. + +ˆ + +The other question that comes up when people learn about condition + +variables is “How does the condition variable know what condition it is + +associated with?” + +This question is understandable because there is no explicit connection + +between a + +Cond + +structure and the condition it relates to. The connection + +is implicit in the way it is used. + +Here’s one way to think of it: the condition associated with a Cond is + +the thing that is false when you call + +cond_wait + +and true when you call + +cond_signal + +. + +Because threads have to check the condition when they return from + +cond_wait + +, + +it is not strictly necessary to call + +cond_signal + +only when the condition is + +true. If you have reason to think the condition + +might + +be true, you could call + +cond_signal + +as a suggestion that now is a good time to check. + + + +--- + +80 Chapter 10. Condition variables + +## 10.5 Condition variable implementation + +The Cond structure I used in the previous section is a wrapper for a type + +called + +pthread_cond_t + +, which is defined in the POSIX threads API. It is very + +similar to Mutex, which is a wrapper for + +pthread_mutex_t + +. Both wrappers + +are defined in + +utils.c + +and + +utils.h + +. + +Here’s the typedef: + +typedef pthread_cond_t Cond; + +make_cond + +allocates space, initializes the condition variable, and returns a + +pointer: + +Cond *make_cond() { + +Cond *cond = check_malloc(sizeof(Cond)); + +int n = pthread_cond_init(cond, NULL); + +if (n != 0) perror_exit("make_cond failed"); + +return cond; + +} + +And here are the wrappers for + +cond_wait + +and + +cond_signal + +. + +void cond_wait(Cond *cond, Mutex *mutex) { + +int n = pthread_cond_wait(cond, mutex); + +if (n != 0) perror_exit("cond_wait failed"); + +} + +void cond_signal(Cond *cond) { + +int n = pthread_cond_signal(cond); + +if (n != 0) perror_exit("cond_signal failed"); + +} + +At this point there should be nothing too surprising there. + + + +--- + +## Chapter 11 + +## Semaphores in C + +Semaphores are a good way to learn about synchronization, but they are not + +as widely used, in practice, as mutexes and condition variables. + +Nevertheless, there are some synchronization problems that can be solved sim + +ply with semaphores, yielding solutions that are more demonstrably correct. + +This chapter presents a C API for working with semaphores and my code for + +making it easier to work with. And it presents a final challenge: can you write + +an implementation of a semaphore using mutexes and condition variables? + +The code for this chapter is in directory + +semaphore + +in the repository for this + +book (see Section 0.1). + +## 11.1 POSIX Semaphores + +A semaphore is a data structure used to help threads work together without + +interfering with each other. + +The POSIX standard specifies an interface for semaphores; it is not part of + +Pthreads, but most UNIXes that implement Pthreads also provide semaphores. + +POSIX semaphores have type + +sem + +t + +. As usual, I put a wrapper around + +sem + +t + +to make it easier to use. The interface is defined in + +sem.h + +: + +typedef sem_t Semaphore; + +Semaphore *make_semaphore(int value); + +void semaphore_wait(Semaphore *sem); + +void semaphore_signal(Semaphore *sem); + + + +--- + +82 Chapter 11. Semaphores in C + +Semaphore + +is a synonym for + +sem_t + +, but I find it more readable, and the capital + +letter reminds me to treat it like an object and pass it by pointer. + +The implementation of these functions is in + +sem.c + +: + +Semaphore *make_semaphore(int value) + +{ + +Semaphore *sem = check_malloc(sizeof(Semaphore)); + +int n = sem_init(sem, 0, value); + +if (n != 0) perror_exit("sem_init failed"); + +return sem; + +} + +make + +semaphore + +takes the initial value of the semaphore as a parameter. + +It allocates space for a Semaphore, initializes it, and returns a pointer to + +Semaphore + +. + +sem + +init + +returns 0 if it succeeds and -1 if anything goes wrong. One nice thing + +about using wrapper functions is that you can encapsulate the error-checking + +code, which makes the code that uses these functions more readable. + +Here is the implementation of + +semaphore_wait + +: + +void semaphore_wait(Semaphore *sem) + +{ + +int n = sem_wait(sem); + +if (n != 0) perror_exit("sem_wait failed"); + +} + +And here is + +semaphore_signal + +: + +void semaphore_signal(Semaphore *sem) + +{ + +int n = sem_post(sem); + +if (n != 0) perror_exit("sem_post failed"); + +} + +I prefer to call this operation “signal” rather than “post”, although both terms + +are common. + +Here’s an example that shows how to use a semaphore as a mutex: + +Semaphore *mutex = make_semaphore(1); + +semaphore_wait(mutex); + +// protected code goes here + +semaphore_signal(mutex); + + + +--- + +11.2. Producers and consumers with semaphores 83 + +When you use a semaphore as a mutex, you usually initialize it to 1 to indicate + +that the mutex is unlocked; that is, one thread can pass the semaphore without + +blocking. + +Here I am using the variable name + +mutex + +to indicate that the semaphore is + +being used as a mutex. But remember that the behavior of a semaphore is not + +the same as a Pthread mutex. + +## 11.2 Producers and consumers with + +## semaphores + +Using these semaphore wrapper functions, we can write a solution to the + +Producer-Consumer problem from Section 10.2. The code in this section is + +in + +queue_sem.c + +. + +Here’s the new definition of + +Queue + +, replacing the mutex and condition variables + +with semaphores: + +typedef struct { + +int *array; + +int length; + +int next_in; + +int next_out; + +Semaphore *mutex; //-- new + +Semaphore *items; //-- new + +Semaphore *spaces; //-- new + +} Queue; + +And here’s the new version of + +make_queue + +: + +Queue *make_queue(int length) + +{ + +Queue *queue = (Queue *) malloc(sizeof(Queue)); + +queue->length = length; + +queue->array = (int *) malloc(length * sizeof(int)); + +queue->next_in = 0; + +queue->next_out = 0; + +queue->mutex = make_semaphore(1); + +queue->items = make_semaphore(0); + +queue->spaces = make_semaphore(length-1); + +return queue; + +} + + + +--- + +84 Chapter 11. Semaphores in C + +mutex + +is used to guarantee exclusive access to the queue; the initial value is 1, + +so the mutex is initially unlocked. + +items + +is the number of items in the queue, which is also the number of con + +sumer threads that can execute + +queue_pop + +without blocking. Initially there + +are no items in the queue. + +spaces + +is the number of empty spaces in the queue, which is the number of + +producer threads that can execute + +queue_push + +without blocking. Initially the + +number of spaces is the capacity of the queue, which is + +length-1 + +, as explained + +in Section 10.1. + +Here is the new version of + +queue_push + +, which is run by producer threads: + +void queue_push(Queue *queue, int item) { + +semaphore_wait(queue->spaces); + +semaphore_wait(queue->mutex); + +queue->array[queue->next_in] = item; + +queue->next_in = queue_incr(queue, queue->next_in); + +semaphore_signal(queue->mutex); + +semaphore_signal(queue->items); + +} + +Notice that + +queue_push + +doesn’t have to call + +queue_full + +any more; instead, + +the semaphore keeps track of how many spaces are available and blocks pro + +ducers if the queue is full. + +Here is the new version of + +queue_pop + +: + +int queue_pop(Queue *queue) { + +semaphore_wait(queue->items); + +semaphore_wait(queue->mutex); + +int item = queue->array[queue->next_out]; + +queue->next_out = queue_incr(queue, queue->next_out); + +semaphore_signal(queue->mutex); + +semaphore_signal(queue->spaces); + +return item; + +} + +This solution is explained, using pseudo-code, in Chapter 4 of + +The Little Book + +of Semaphores + +. + + + +--- + +11.3. Make your own semaphores 85 + +Using the code in the repository for this book, you should be able to compile + +and run this solution like this: + +$ make queue_sem + +$ ./queue_sem + +## 11.3 Make your own semaphores + +Any problem that can be solved with semaphores can also be solved with + +condition variables and mutexes. We can prove that’s true by using condition + +variables and mutexes to implement a semaphore. + +Before you go on, you might want to try this as an exercise: write func + +tions that implement the semaphore API in + +sem.h + +using using condition vari + +ables and mutexes. In the repository for this book, you’ll find my solution in + +mysem_soln.c + +and + +mysem_soln.h + +. + +If you have trouble getting started, you can use the following structure defini + +tion, from my solution, as a hint: + +typedef struct { + +int value, wakeups; + +Mutex *mutex; + +Cond *cond; + +} Semaphore; + +value + +is the value of the semaphore. + +wakeups + +counts the number of pending + +signals; that is, the number of threads that have been woken but have not + +yet resumed execution. The reason for wakeups is to make sure that our + +semaphores have Property 3, described in + +The Little Book of Semaphores + +. + +mutex + +provides exclusive access to + +value + +and + +wakeups + +; + +cond + +is the condition + +variable threads wait on if they wait on the semaphore. + +Here is the initialization code for this structure: + +Semaphore *make_semaphore(int value) + +{ + +Semaphore *semaphore = check_malloc(sizeof(Semaphore)); + +semaphore->value = value; + +semaphore->wakeups = 0; + +semaphore->mutex = make_mutex(); + +semaphore->cond = make_cond(); + +return semaphore; + +} + + + +--- + +86 Chapter 11. Semaphores in C + +## 11.3.1 Semaphore implementation + +Here is my implementation of semaphores using POSIX mutexes and condition + +variables: + +void semaphore_wait(Semaphore *semaphore) + +{ + +mutex_lock(semaphore->mutex); + +semaphore->value--; + +if (semaphore->value < 0) { + +do { + +cond_wait(semaphore->cond, semaphore->mutex); + +} while (semaphore->wakeups < 1); + +semaphore->wakeups--; + +} + +mutex_unlock(semaphore->mutex); + +} + +When a thread waits on the semaphore, it has to lock the mutex before it + +decrements + +value + +. If the value of the semaphore becomes negative, the thread + +blocks until a “wakeup” is available. While it is blocked, the mutex is unlocked, + +so another thread can signal. + +Here is the code for + +semaphore_signal + +: + +void semaphore_signal(Semaphore *semaphore) + +{ + +mutex_lock(semaphore->mutex); + +semaphore->value++; + +if (semaphore->value <= 0) { + +semaphore->wakeups++; + +cond_signal(semaphore->cond); + +} + +mutex_unlock(semaphore->mutex); + +} + +Again, a thread has to lock the mutex before it increments + +value + +. If the + +semaphore was negative, that means threads are waiting, so the signalling + +thread increments + +wakeups + +and signals the condition variable. + +At this point one of the waiting threads might wake up, but the mutex is still + +locked until the signalling thread unlocks it. + +At that point, one of the waiting threads returns from + +cond_wait + +and checks + + + +--- + +11.3. Make your own semaphores 87 + +whether a wakeup is still available. If not, it loops and waits on the condition + +variable again. If so, it decrements + +wakeups + +, unlocks the mutex, and exits. + +One thing about this solution that might not be obvious is the use of a + +do...while + +loop. Can you figure out why it is not a more conventional + +while + +loop? What would go wrong? + +The problem is that with a + +while + +loop this implementation would not have + +Property 3. It would be possible for a thread to signal and then run around + +and catch its own signal. + +With the + +do...while + +loop, it is guaranteed + +1 + +that when a thread signals, one + +of the waiting threads will get the signal, even if the signalling thread runs + +around and gets the mutex before one of the waiting threads resumes. + +1 + +Well, almost. It turns out that a well-timed spurious wakeup (see + +http://en. + +wikipedia.org/wiki/Spurious_wakeup + +) can violate this guarantee. + + + +--- + From 377e542689a62388d862c307fc793d153a052d95 Mon Sep 17 00:00:00 2001 From: Nico Arqueros <1622112+nicarq@users.noreply.github.com> Date: Sun, 22 Sep 2024 17:30:35 -0500 Subject: [PATCH 2/2] drawing (but incorrectly) --- shinkai-libs/shinkai-ocr/src/pdf_parser_v2.rs | 61 +- .../shinkai-ocr/tests/pdf_parser_v2_tests.rs | 60 +- shinkai-libs/shinkai-ocr/thinkos.md | 8668 ----------------- 3 files changed, 114 insertions(+), 8675 deletions(-) delete mode 100644 shinkai-libs/shinkai-ocr/thinkos.md diff --git a/shinkai-libs/shinkai-ocr/src/pdf_parser_v2.rs b/shinkai-libs/shinkai-ocr/src/pdf_parser_v2.rs index 57d154862..c97b77645 100644 --- a/shinkai-libs/shinkai-ocr/src/pdf_parser_v2.rs +++ b/shinkai-libs/shinkai-ocr/src/pdf_parser_v2.rs @@ -1,9 +1,18 @@ +use image::{Rgba, RgbaImage}; use pdfium_render::prelude::*; use regex::Regex; use std::time::Instant; use crate::image_parser::ImageParser; +/* +TODO: + +- [ ] Remove page number from element metadata +- [ ] Remove top level heading + +*/ + pub struct PDFParser { image_parser: ImageParser, pdfium: Pdfium, @@ -215,9 +224,7 @@ impl PDFParser { page_number: usize, object_id: usize, ) -> anyhow::Result { - let text_object = object - .as_text_object() - .ok_or(anyhow::anyhow!("Not a text object"))?; + let text_object = object.as_text_object().ok_or(anyhow::anyhow!("Not a text object"))?; let text = text_object.text(); if text.is_empty() { @@ -351,4 +358,52 @@ impl PDFParser { normalized_text } + + // + pub fn mark_text_position_in_pdf( + &self, + input_path: &str, + output_path: &str, + page_number: usize, + position: (f32, f32), + ) -> Result<(), Box> { + eprintln!("Position: {:?}", position); + let document = self.pdfium.load_pdf_from_file(input_path, None)?; + + let page_index: u16 = (page_number - 1).try_into().unwrap(); + let page = document.pages().get(page_index)?; + + let render_config = PdfRenderConfig::new().set_target_width(2000).set_maximum_height(2000); + + let rendered_page = page.render_with_config(&render_config)?.as_image(); + + let mut image = rendered_page.into_rgba8(); + + Self::draw_translucent_rectangle(&mut image, position.0 as u32, position.1 as u32, 10, 25)?; + + image.save(output_path)?; + + Ok(()) + } + + // Add the helper function outside the impl block + fn draw_translucent_rectangle( + image: &mut RgbaImage, + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), Box> { + let rect_color = Rgba([255, 0, 0, 128]); // Red color with 50% opacity + + for i in x..x + width { + for j in y..y + height { + if i < image.width() && j < image.height() { + image.put_pixel(i, j, rect_color); + } + } + } + + Ok(()) + } } diff --git a/shinkai-libs/shinkai-ocr/tests/pdf_parser_v2_tests.rs b/shinkai-libs/shinkai-ocr/tests/pdf_parser_v2_tests.rs index e4713bfdb..af42a5653 100644 --- a/shinkai-libs/shinkai-ocr/tests/pdf_parser_v2_tests.rs +++ b/shinkai-libs/shinkai-ocr/tests/pdf_parser_v2_tests.rs @@ -1,4 +1,7 @@ -use shinkai_ocr::pdf_parser_v2::{PDFElementType, PDFParser}; +use image::{Rgba, RgbaImage}; +use pdfium_render::pdfium::Pdfium; +use pdfium_render::prelude::{PdfPageObjects, PdfRenderConfig}; +use shinkai_ocr::pdf_parser_v2::{PDFDocument, PDFElementType, PDFParser}; use shinkai_ocr::pdf_to_md::MarkdownGenerator; // Import the MarkdownGenerator use std::fs; @@ -27,6 +30,24 @@ async fn pdf_parsing() -> Result<(), Box> { // Print the generated markdown to the console println!("Generated Markdown:\n{}", markdown); + // Search for the text "At several points in the process" + if let Some((page_number, position)) = find_text_position(&parsed_document, "At several points in the process") { + println!( + "Found 'At several points in the process' on page {} at position: {:?}", + page_number, position + ); + + // Mark the text position in the PDF and save as an image + pdf_parser.mark_text_position_in_pdf( + "../../files/shinkai_intro.pdf", + "../../files/shinkai_intro_marked.png", + page_number, + position + )?; + } else { + println!("Text 'At several points in the process' not found"); + } + // Assert the first page's first element's text content if let Some(first_page) = parsed_document.pages.first() { if let Some(first_element) = first_page.elements.first() { @@ -45,6 +66,19 @@ async fn pdf_parsing() -> Result<(), Box> { Ok(()) } +fn find_text_position(document: &PDFDocument, search_text: &str) -> Option<(usize, (f32, f32))> { + for page in &document.pages { + for element in &page.elements { + if let PDFElementType::Text(text_element) = &element.element_type { + if text_element.content.contains(search_text) { + return Some((page.page_number, element.metadata.position)); + } + } + } + } + None +} + #[tokio::test] async fn pdf_parsing_from_local_file() -> Result<(), Box> { // Path to the local PDF file @@ -58,7 +92,7 @@ async fn pdf_parsing_from_local_file() -> Result<(), Box> let parsed_document = pdf_parser.process_pdf_file(file)?; // Print the parsed document for debugging - println!("Parsed document: {:?}", parsed_document); + eprintln!("Parsed document: {:?}", parsed_document.metadata); // Initialize the Markdown generator with an output directory for images let markdown_generator = MarkdownGenerator::new("output_images".to_string())?; @@ -67,12 +101,30 @@ async fn pdf_parsing_from_local_file() -> Result<(), Box> let markdown = markdown_generator.to_markdown(&parsed_document)?; // Print the generated markdown to the console - println!("Generated Markdown:\n{}", markdown); + eprintln!("Markdown generated"); // Save the generated markdown to a file called thinkos.md - let mut file = fs::File::create("thinkos.md")?; + let mut file = fs::File::create("../../files/thinkos.md")?; file.write_all(markdown.as_bytes())?; + // Search for the text "At several points in the process" + if let Some((page_number, position)) = find_text_position(&parsed_document, "At several points in the process") { + eprintln!( + "Found 'At several points in the process' on page {} at position: {:?}", + page_number, position + ); + + // Mark the text position in the PDF and save as an image + pdf_parser.mark_text_position_in_pdf( + "../../files/thinkos.pdf", + "../../files/thinkos_marked.png", + page_number, + position + )?; + } else { + println!("Text 'At several points in the process' not found"); + } + // Assert the first page's first element's text content if let Some(first_page) = parsed_document.pages.first() { if let Some(first_element) = first_page.elements.first() { diff --git a/shinkai-libs/shinkai-ocr/thinkos.md b/shinkai-libs/shinkai-ocr/thinkos.md deleted file mode 100644 index 554312866..000000000 --- a/shinkai-libs/shinkai-ocr/thinkos.md +++ /dev/null @@ -1,8668 +0,0 @@ -Think OS - -A Brief Introduction to Operating Systems - -Version 0.7.4 - - - ---- - - - ---- - -Think OS - -A Brief Introduction to Operating Systems - -Version 0.7.4 - -Allen B. Downey - -Green Tea Press - -Needham, Massachusetts - - - ---- - -Copyright - -© - -2015 Allen B. Downey. - -Green Tea Press - -9 Washburn Ave - -Needham MA 02492 - -Permission is granted to copy, distribute, and/or modify this document under - -the terms of the Creative Commons Attribution-NonCommercial-ShareAlike - -4.0 International License, which is available at - -http://creativecommons. - -org/licenses/by-nc-sa/4.0/ - -. - -The L - -A - -T - -E - -X source for this book is available from - -http://greenteapress.com/ - -thinkos - -. - - - ---- - -## Preface - -In many computer science programs, Operating Systems is an advanced topic. - -By the time students take it, they know how to program in C, and they have - -probably taken a class in Computer Architecture. Usually the goal of the class - -is to expose students to the design and implementation of operating systems, - -with the implied assumption that some of them will do research in this area, - -or write part of an OS. - -This book is intended for a different audience, and it has different goals. I - -developed it for a class at Olin College called Software Systems. - -Most students taking this class learned to program in Python, so one of the - -goals is to help them learn C. For that part of the class, I use Griffiths and Grif - -fiths, - -Head First C - -, from O’Reilly Media. This book is meant to complement - -that one. - -Few of my students will ever write an operating system, but many of them - -will write low-level applications in C or work on embedded systems. My class - -includes material from operating systems, networks, databases, and embedded - -systems, but it emphasizes the topics programmers need to know. - -This book does not assume that you have studied Computer Architecture. As - -we go along, I will explain what we need. - -If this book is successful, it should give you a better understanding of what is - -happening when programs run, and what you can do to make them run better - -and faster. - -Chapter 1 explains some of the differences between compiled and interpreted - -languages, with some insight into how compilers work. Recommended reading: - -Head First C - -Chapter 1. - -Chapter 2 explains how the operating system uses processes to protect running - -programs from interfering with each other. - -Chapter 3 explains virtual memory and address translation. Recommended - -reading: - -Head First C - -Chapter 2. - - - ---- - -vi Chapter 0. Preface - -Chapter 4 is about file systems and data streams. Recommended reading: - -Head First C - -Chapter 3. - -Chapter 5 describes how numbers, letters, and other values are encoded, and - -presents the bitwise operators. - -Chapter 6 explains how to use dynamic memory management, and how it - -works. Recommended reading: - -Head First C - -Chapter 6. - -Chapter 7 is about caching and the memory hierarchy. - -Chapter 8 is about multitasking and scheduling. - -Chapter 9 is about POSIX threads and mutexes. Recommended reading: - -Head - -First C - -Chapter 12 and - -Little Book of Semaphores - -Chapters 1 and 2. - -Chapter 10 is about POSIX condition variables and the producer/consumer - -problem. Recommended reading: - -Little Book of Semaphores - -Chapters 3 and - -4. - -Chapter 11 is about using POSIX semaphores and implementing semaphores - -in C. - -## A note on this draft - -The current version of this book is an early draft. While I am working on the - -text, I have not yet included the figures. So there are a few places where, I’m - -sure, the explanation will be greatly improved when the figures are ready. - -## 0.1 Using the code - -Example code for this book is available from - -https://github.com/ - -AllenDowney/ThinkOS - -. Git is a version control system that allows you to - -keep track of the files that make up a project. A collection of files under - -Git’s control is called a - -repository - -. GitHub is a hosting service that provides - -storage for Git repositories and a convenient web interface. - -The GitHub homepage for my repository provides several ways to work with - -the code: - -ˆ - -You can create a copy of my repository on GitHub by pressing the - -Fork - -button. If you don’t already have a GitHub account, you’ll need to - -create one. After forking, you’ll have your own repository on GitHub - - - ---- - -0.1. Using the code vii - -that you can use to keep track of code you write while working on this - -book. Then you can clone the repo, which means that you copy the files - -to your computer. - -ˆ - -Or you could clone my repository. You don’t need a GitHub account to - -do this, but you won’t be able to write your changes back to GitHub. - -ˆ - -If you don’t want to use Git at all, you can download the files in a Zip - -file using the button in the lower-right corner of the GitHub page. - -## Contributor List - -If you have a suggestion or correction, please send email to - -downey@allendowney.com - -. If I make a change based on your feedback, - -I will add you to the contributor list (unless you ask to be omitted). - -If you include at least part of the sentence the error appears in, that makes it - -easy for me to search. Page and section numbers are fine, too, but not quite - -as easy to work with. Thanks! - -ˆ - -I am grateful to the students in Software Systems at Olin College, who tested - -an early draft of this book in Spring 2014. They corrected many errors and - -made many helpful suggestions. I appreciate their pioneering spirit! - -ˆ - -James P Giannoules spotted a copy-and-paste error. - -ˆ - -Andy Engle knows the difference between GB and GiB. - -ˆ - -Aashish Karki noted some broken syntax. - -Other people who found typos and errors include Jim Tyson, Donald Robertson, - -Jeremy Vermast, Yuzhong Huang, Ian Hill. - - - ---- - -viii Chapter 0. Preface - - - ---- - -## Contents - -Preface v - -0.1 Using the code . . . . . . . . . . . . . . . . . . . . . . . . . . - -vi - -1 Compilation 1 - -1.1 Compiled and interpreted languages . . . . . . . . . . . . . . - -1 - -1.2 Static types . . . . . . . . . . . . . . . . . . . . . . . . . . . - -1 - -1.3 The compilation process . . . . . . . . . . . . . . . . . . . . - -3 - -1.4 Object code . . . . . . . . . . . . . . . . . . . . . . . . . . . - -4 - -1.5 Assembly code . . . . . . . . . . . . . . . . . . . . . . . . . . - -5 - -1.6 Preprocessing . . . . . . . . . . . . . . . . . . . . . . . . . . - -6 - -1.7 Understanding errors . . . . . . . . . . . . . . . . . . . . . . - -6 - -2 Processes 9 - -2.1 Abstraction and virtualization . . . . . . . . . . . . . . . . . - -9 - -2.2 Isolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - -10 - -2.3 UNIX processes . . . . . . . . . . . . . . . . . . . . . . . . . - -12 - -3 Virtual memory 15 - -3.1 A bit of information theory . . . . . . . . . . . . . . . . . . . - -15 - -3.2 Memory and storage . . . . . . . . . . . . . . . . . . . . . . - -16 - -3.3 Address spaces . . . . . . . . . . . . . . . . . . . . . . . . . - -16 - - - ---- - -x Contents - -3.4 Memory segments . . . . . . . . . . . . . . . . . . . . . . . . - -17 - -3.5 Static local variables . . . . . . . . . . . . . . . . . . . . . . - -20 - -3.6 Address translation . . . . . . . . . . . . . . . . . . . . . . . - -20 - -4 Files and file systems 23 - -4.1 Disk performance . . . . . . . . . . . . . . . . . . . . . . . . - -25 - -4.2 Disk metadata . . . . . . . . . . . . . . . . . . . . . . . . . . - -27 - -4.3 Block allocation . . . . . . . . . . . . . . . . . . . . . . . . . - -28 - -4.4 Everything is a file? . . . . . . . . . . . . . . . . . . . . . . . - -28 - -5 More bits and bytes 31 - -5.1 Representing integers . . . . . . . . . . . . . . . . . . . . . . - -31 - -5.2 Bitwise operators . . . . . . . . . . . . . . . . . . . . . . . . - -32 - -5.3 Representing floating-point numbers . . . . . . . . . . . . . . - -33 - -5.4 Unions and memory errors . . . . . . . . . . . . . . . . . . . - -35 - -5.5 Representing strings . . . . . . . . . . . . . . . . . . . . . . . - -36 - -6 Memory management 39 - -6.1 Memory errors . . . . . . . . . . . . . . . . . . . . . . . . . . - -39 - -6.2 Memory leaks . . . . . . . . . . . . . . . . . . . . . . . . . . - -41 - -6.3 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . - -43 - -7 Caching 45 - -7.1 How programs run . . . . . . . . . . . . . . . . . . . . . . . - -45 - -7.2 Cache performance . . . . . . . . . . . . . . . . . . . . . . . - -47 - -7.3 Locality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - -47 - -7.4 Measuring cache performance . . . . . . . . . . . . . . . . . - -48 - -7.5 Programming for cache performance . . . . . . . . . . . . . . - -51 - -7.6 The memory hierarchy . . . . . . . . . . . . . . . . . . . . . - -52 - -7.7 Caching policy . . . . . . . . . . . . . . . . . . . . . . . . . . - -53 - -7.8 Paging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - -54 - - - ---- - -Contents xi - -8 Multitasking 57 - -8.1 Hardware state . . . . . . . . . . . . . . . . . . . . . . . . . - -58 - -8.2 Context switching . . . . . . . . . . . . . . . . . . . . . . . . - -58 - -8.3 The process life cycle . . . . . . . . . . . . . . . . . . . . . . - -59 - -8.4 Scheduling . . . . . . . . . . . . . . . . . . . . . . . . . . . . - -60 - -8.5 Real-time scheduling . . . . . . . . . . . . . . . . . . . . . . - -62 - -9 Threads 63 - -9.1 Creating threads . . . . . . . . . . . . . . . . . . . . . . . . - -64 - -9.2 Creating threads . . . . . . . . . . . . . . . . . . . . . . . . - -64 - -9.3 Joining threads . . . . . . . . . . . . . . . . . . . . . . . . . - -66 - -9.4 Synchronization errors . . . . . . . . . . . . . . . . . . . . . - -67 - -9.5 Mutex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - -69 - -10 Condition variables 71 - -10.1 The work queue . . . . . . . . . . . . . . . . . . . . . . . . . - -71 - -10.2 Producers and consumers . . . . . . . . . . . . . . . . . . . . - -74 - -10.3 Mutual exclusion . . . . . . . . . . . . . . . . . . . . . . . . - -75 - -10.4 Condition variables . . . . . . . . . . . . . . . . . . . . . . . - -77 - -10.5 Condition variable implementation . . . . . . . . . . . . . . - -80 - -11 Semaphores in C 81 - -11.1 POSIX Semaphores . . . . . . . . . . . . . . . . . . . . . . . - -81 - -11.2 Producers and consumers with semaphores . . . . . . . . . . - -83 - -11.3 Make your own semaphores . . . . . . . . . . . . . . . . . . - -85 - - - ---- - -xii Contents - - - ---- - -## Chapter 1 - -## Compilation - -## 1.1 Compiled and interpreted languages - -People often describe programming languages as either compiled or inter - -preted. “Compiled” means that programs are translated into machine lan - -guage and then executed by hardware; “interpreted” means that programs - -are read and executed by a software interpreter. Usually C is considered a - -compiled language and Python is considered an interpreted language. But the - -distinction is not always clear-cut. - -First, many languages can be either compiled or interpreted. For example, - -there are C interpreters and Python compilers. Second, there are languages - -like Java that use a hybrid approach, compiling programs into an intermediate - -language and then running the translated program in an interpreter. Java uses - -an intermediate language called Java bytecode, which is similar to machine - -language, but it is executed by a software interpreter, the Java virtual machine - -(JVM). - -So being compiled or interpreted is not an intrinsic characteristic of a lan - -guage; nevertheless, there are some general differences between compiled and - -interpreted languages. - -## 1.2 Static types - -Many interpreted languages support dynamic types, but compiled languages - -are usually limited to static types. In a statically-typed language, you can tell - - - ---- - -2 Chapter 1. Compilation - -by looking at the program what type each variable refers to. In a dynamically - -typed language, you don’t always know the type of a variable until the pro - -gram is running. In general, - -static - -refers to things that happen at compile - -time (while a program is being compiled), and - -dynamic - -refers to things that - -happen at run time (while a program is running). - -For example, in Python you can write a function like this: - -def add(x, y): - -return x + y - -Looking at this code, you can’t tell what type - -x - -and - -y - -will refer to at run - -time. This function might be called several times, each time with values with - -different types. Any values that support the addition operator will work; any - -other types will cause an exception or - -runtime error - -. - -In C you would write the same function like this: - -int add(int x, int y) { - -return x + y; - -} - -The first line of the function includes - -type declarations - -for the parameters - -and the return value: - -x - -and - -y - -are declared to be integers, which means that - -we can check at compile time whether the addition operator is legal for this - -type (it is). The return value is also declared to be an integer. - -Because of these declarations, when this function is called elsewhere in the - -program, the compiler can check whether the arguments provided have the - -right type, and whether the return value is used correctly. - -These checks happen before the program starts executing, so errors can be - -found earlier. More importantly, errors can be found in parts of the program - -that have never run. Furthermore, these checks don’t have to happen at run - -time, which is one of the reasons compiled languages generally run faster than - -interpreted languages. - -Declaring types at compile time also saves space. In dynamic languages, vari - -able names are stored in memory while the program runs, and they are of - -ten accessible by the program. For example, in Python the built-in function - -locals - -returns a dictionary that contains variable names and their values. - -Here’s an example in a Python interpreter: - ->>> x = 5 - ->>> print locals() - -{'x': 5, '__builtins__': , - -'__name__': '__main__', '__doc__': None, '__package__': None} - - - ---- - -1.3. The compilation process 3 - -This shows that the name of the variable is stored in memory while the program - -is running (along with some other values that are part of the default runtime - -environment). - -In compiled languages, variable names exist at compile-time but not at run - -time. The compiler chooses a location for each variable and records these - -locations as part of the compiled program. - -1 - -The location of a variable is - -called its - -address - -. At run time, the value of each variable is stored at its - -address, but the names of the variables are not stored at all (unless they are - -added by the compiler for purposes of debugging). - -## 1.3 The compilation process - -As a programmer, you should have a mental model of what happens during - -compilation. If you understand the process, it will help you interpret error - -messages, debug your code, and avoid common pitfalls. - -The steps of compilation are: - -1. - -Preprocessing: C is one of several languages that include - -preprocessing - -directives - -that take effect before the program is compiled. For example, - -the - -#include - -directive causes the source code from another file to be - -inserted at the location of the directive. - -2. - -Parsing: During parsing, the compiler reads the source code and builds - -an internal representation of the program, called an - -abstract syntax - -tree - -. Errors detected during this step are generally syntax errors. - -3. - -Static checking: The compiler checks whether variables and values have - -the right type, whether functions are called with the right number and - -type of arguments, etc. Errors detected during this step are sometimes - -called - -static semantic - -errors. - -4. - -Code generation: The compiler reads the internal representation of the - -program and generates machine code or byte code. - -5. - -Linking: If the program uses values and functions defined in a library, - -the compiler has to find the appropriate library and include the required - -code. - -1 - -This is a simplification; we will go into more detail later. - - - ---- - -4 Chapter 1. Compilation - -6. - -Optimization: At several points in the process, the compiler can trans - -form the program to generate code that runs faster or uses less space. - -Most optimizations are simple changes that eliminate obvious waste, but - -some compilers perform sophisticated analyses and transformations. - -Normally when you run - -gcc - -, it runs all of these steps and generates an exe - -cutable file. For example, here is a minimal C program: - -#include - -int main() - -{ - -printf("Hello World\n"); - -} - -If you save this code in a file called - -hello.c - -, you can compile and run it like - -this: - -$ gcc hello.c - -$ ./a.out - -By default, - -gcc - -stores the executable code in a file called - -a.out - -(which origi - -nally stood for “assembler output”). The second line runs the executable. The - -prefix - -./ - -tells the shell to look for it in the current directory. - -It is usually a good idea to use the - --o - -flag to provide a better name for the - -executable: - -$ gcc hello.c -o hello - -$ ./hello - -## 1.4 Object code - -The - --c - -flag tells - -gcc - -to compile the program and generate machine code, but - -not to link it or generate an executable: - -$ gcc hello.c -c - -The result is a file named - -hello.o - -, where the - -o - -stands for - -object code - -, which - -is the compiled program. Object code is not executable, but it can be linked - -into an executable. - -The UNIX command - -nm - -reads an object file and generates information about - -the names it defines and uses. For example: - -$ nm hello.o - -0000000000000000 T main - -U puts - - - ---- - -1.5. Assembly code 5 - -This output indicates that - -hello.o - -defines the name - -main - -and uses a function - -named - -puts - -, which stands for “put string”. In this example, - -gcc - -performs an - -optimization by replacing - -printf - -, which is a large and complicated function, - -with - -puts - -, which is relatively simple. - -You can control how much optimization - -gcc - -does with the - --O - -flag. By default, - -it does very little optimization, which can make debugging easier. The option - --O1 - -turns on the most common and safe optimizations. Higher numbers turn - -on additional optimizations that require longer compilation time. - -In theory, optimization should not change the behavior of the program, other - -than to speed it up. But if your program has a subtle bug, you might find that - -optimization makes the bug appear or disappear. It is usually a good idea to - -turn off optimization while you are developing new code. Once the program - -is working and passing appropriate tests, you can turn on optimization and - -confirm that the tests still pass. - -## 1.5 Assembly code - -Similar to the - --c - -flag, the - --S - -flag tells - -gcc - -to compile the program and generate - -assembly code, which is basically a human-readable form of machine code. - -$ gcc hello.c -S - -The result is a file named - -hello.s - -, which might look something like this: - -.file "hello.c" - -.section .rodata - -.LC0: - -.string "Hello World" - -.text - -.globl main - -.type main, @function - -main: - -.LFB0: - -.cfi_startproc - -pushq %rbp - -.cfi_def_cfa_offset 16 - -.cfi_offset 6, -16 - -movq %rsp, %rbp - -.cfi_def_cfa_register 6 - -movl $.LC0, %edi - -call puts - - - ---- - -6 Chapter 1. Compilation - -movl $0, %eax - -popq %rbp - -.cfi_def_cfa 7, 8 - -ret - -.cfi_endproc - -.LFE0: - -.size main, .-main - -.ident "GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3" - -.section .note.GNU-stack,"",@progbits - -gcc - -is usually configured to generate code for the machine you are running on, - -so for me it generates x86 assembly language, which runs on a wide variety - -of processors from Intel, AMD, and others. If you are running on a different - -architecture, you might see different code. - -## 1.6 Preprocessing - -Taking another step backward through the compilation process, you can use - -the - --E - -flag to run the preprocessor only: - -$ gcc hello.c -E - -The result is the output from the preprocessor. In this example, it contains - -the included code from - -stdio.h - -, and all the files included from - -stdio.h - -, and - -all the files included from those files, and so on. On my machine, the total is - -more than 800 lines of code. Since almost every C program includes - -stdio.h - -, - -those 800 lines of code get compiled a lot. If, like many C programs, you also - -include - -stdlib.h - -, the result is more than 1800 lines of code. - -## 1.7 Understanding errors - -Now that we know the steps in the compilation process, it is easier to under - -stand error messages. For example, if there is an error in a - -#include - -directive, - -you’ll get a message from the preprocessor: - -hello.c:1:20: fatal error: stdioo.h: No such file or directory - -compilation terminated. - -If there’s a syntax error, you get a message from the compiler: - -hello.c: In function 'main': - -hello.c:6:1: error: expected ';' before '}' token - -If you use a function that’s not defined in any of the standard libraries, you - -get a message from the linker: - - - ---- - -1.7. Understanding errors 7 - -/tmp/cc7iAUbN.o: In function `main': - -hello.c:(.text+0xf): undefined reference to `printff' - -collect2: error: ld returned 1 exit status - -ld - -is the name of the UNIX linker, so named because “loading” is another - -step in the compilation process that is closely related to linking. - -Once the program starts, C does very little runtime checking, so there are - -only a few runtime errors you are likely to see. If you divide by zero, or - -perform another illegal floating-point operation, you will get a “Floating point - -exception.” And if you try to read or write an incorrect location in memory, - -you will get a “Segmentation fault.” - - - ---- - -8 Chapter 1. Compilation - - - ---- - -## Chapter 2 - -## Processes - -## 2.1 Abstraction and virtualization - -Before we talk about processes, I want to define a few words: - -ˆ - -Abstraction: An abstraction is a simplified representation of something - -complicated. For example, if you drive a car, you understand that when - -you turn the wheel left, the car goes left, and vice versa. Of course, - -the steering wheel is connected to a sequence of mechanical and (often) - -hydraulic systems that turn the wheels, and the wheels interact with - -the road in ways that can be complex, but as a driver, you normally - -don’t have to think about any of those details. You can get along very - -well with a simple mental model of steering. Your mental model is an - -abstraction. - -Similarly, when you use a web browser, you understand that when you - -click on a link, the browser displays the page the link refers to. The soft - -ware and network communication that make that possible are complex, - -but as a user, you don’t have to know the details. - -A large part of software engineering is designing abstractions like these - -that allow users and other programmers to use powerful and complicated - -systems without having to know about the details of their implementa - -tion. - -ˆ - -Virtualization: An important kind of abstraction is virtualization, which - -is the process of creating a desirable illusion. - -For example, many public libraries participate in inter-library collabora - -tions that allow them to borrow books from each other. When I request - - - ---- - -10 Chapter 2. Processes - -a book, sometimes the book is on the shelf at my local library, but other - -times it has to be transferred from another collection. Either way, I get - -a notification when it is available for pickup. I don’t need to know where - -it came from, and I don’t need to know which books my library has. As - -a whole, the system creates the illusion that my library has every book - -in the world. - -The collection physically located at my local library might be small, - -but the collection available to me virtually includes every book in the - -inter-library collaboration. - -As another example, most computers are only connected to one network, - -but that network is connected to others, and so on. What we call the - -Internet is a collection of networks and a set of protocols that forward - -packets from one network to the next. From the point of view of a user or - -programmer, the system behaves as if every computer on the Internet is - -connected to every other computer. The number of physical connections - -is small, but the number of virtual connections is very large. - -The word “virtual” is often used in the context of a virtual machine, which is - -software that creates the illusion of a dedicated computer running a particular - -operating system, when in reality the virtual machine might be running, along - -with many other virtual machines, on a computer running a different operating - -system. - -In the context of virtualization, we sometimes call what is really happening - -“physical”, and what is virtually happening either “logical” or “abstract.” - -## 2.2 Isolation - -One of the most important principles of engineering is isolation: when you - -are designing a system with multiple components, it is usually a good idea to - -isolate them from each other so that a change in one component doesn’t have - -undesired effects on other components. - -One of the most important goals of an operating system is to isolate each run - -ning program from the others so that programmers don’t have to think about - -every possible interaction. The software object that provides this isolation is - -a - -process - -. - -A process is a software object that represents a running program. I mean - -“software object” in the sense of object-oriented programming; in general, an - -object contains data and provides methods that operate on the data. A process - -is an object that contains the following data: - - - ---- - -2.2. Isolation 11 - -ˆ - -The text of the program, usually a sequence of machine language in - -structions. - -ˆ - -Data associated with the program, including static data (allocated at - -compile time) and dynamic data (allocated at run time). - -ˆ - -The state of any pending input/output operations. For example, if the - -process is waiting for data to be read from disk or for a packet to arrive - -on a network, the status of these operations is part of the process. - -ˆ - -The hardware state of the program, which includes data stored in regis - -ters, status information, and the program counter, which indicates which - -instruction is currently executing. - -Usually one process runs one program, but it is also possible for a process to - -load and run a new program. - -It is also possible, and common, to run the same program in more than one - -process. In that case, the processes share the same program text but generally - -have different data and hardware states. - -Most operating systems provide a fundamental set of capabilities to isolate - -processes from each other: - -ˆ - -Multitasking: Most operating systems have the ability to interrupt a - -running process at almost any time, save its hardware state, and then - -resume the process later. In general, programmers don’t have to think - -about these interruptions. The program behaves as if it is running con - -tinuously on a dedicated processor, except that the time between in - -structions is unpredictable. - -ˆ - -Virtual memory: Most operating systems create the illusion that each - -process has its own chunk of memory, isolated from all other processes. - -Again, programmers generally don’t have to think about how virtual - -memory works; they can proceed as if every program has a dedicated - -chunk of memory. - -ˆ - -Device abstraction: Processes running on the same computer share the - -disk drive, the network interface, the graphics card, and other hardware. - -If processes interacted with this hardware directly, without coordination, - -chaos would ensue. For example, network data intended for one process - -might be read by another. Or multiple processes might try to store data - -in the same location on a hard drive. It is up to the operating system - -to maintain order by providing appropriate abstractions. - - - ---- - -12 Chapter 2. Processes - -As a programmer, you don’t need to know much about how these capabilities - -are implemented. But if you are curious, you will find a lot of interesting - -things going on under the metaphorical hood. And if you know what’s going - -on, it can make you a better programmer. - -## 2.3 UNIX processes - -While I write this book, the process I am most aware of is my text editor, - -emacs. Every once in a while I switch to a terminal window, which is a - -window running a UNIX shell that provides a command-line interface. - -When I move the mouse, the window manager wakes up, sees that the mouse - -is over the terminal window, and wakes up the terminal. The terminal wakes - -up the shell. If I type - -make - -in the shell, it creates a new process to run - -Make, which creates another process to run LaTeX and then another process - -to display the results. - -If I need to look something up, I might switch to another desktop, which wakes - -up the window manager again. If I click on the icon for a web browser, the - -window manager creates a process to run the web browser. Some browsers, - -like Chrome, create a new process for each window and each tab. - -And those are just the processes I am aware of. At the same time there - -are many other processes running in the - -background - -. Many of them are - -performing operations related to the operating system. - -The UNIX command - -ps - -prints information about running processes. If you - -run it in a terminal, you might see something like this: - -PID TTY TIME CMD - -2687 pts/1 00:00:00 bash - -2801 pts/1 00:01:24 emacs - -24762 pts/1 00:00:00 ps - -The first column is the unique numerical process ID. The second column is - -the terminal that created the process; “TTY” stands for teletypewriter, which - -was the original mechanical terminal. - -The third column is the total processor time used by the process, in hours, - -minutes, and seconds. The last column is the name of the running program. - -In this example, - -bash - -is the name of the shell that interprets the commands I - -type in the terminal, emacs is my text editor, and ps is the program generating - -this output. - - - ---- - -2.3. UNIX processes 13 - -By default, - -ps - -lists only the processes associated with the current terminal. - -If you use the - --e - -flag, you get every process (including processes belonging to - -other users, which is a security flaw, in my opinion). - -On my system there are currently 233 processes. Here are some of them: - -PID TTY TIME CMD - -1 ? 00:00:17 init - -2 ? 00:00:00 kthreadd - -3 ? 00:00:02 ksoftirqd/0 - -4 ? 00:00:00 kworker/0:0 - -8 ? 00:00:00 migration/0 - -9 ? 00:00:00 rcu_bh - -10 ? 00:00:16 rcu_sched - -47 ? 00:00:00 cpuset - -48 ? 00:00:00 khelper - -49 ? 00:00:00 kdevtmpfs - -50 ? 00:00:00 netns - -51 ? 00:00:00 bdi-default - -52 ? 00:00:00 kintegrityd - -53 ? 00:00:00 kblockd - -54 ? 00:00:00 ata_sff - -55 ? 00:00:00 khubd - -56 ? 00:00:00 md - -57 ? 00:00:00 devfreq_wq - -init - -is the first process created when the operating system starts. It creates - -many of the other processes, and then sits idle until the processes it created - -are done. - -kthreadd - -is a process the operating system uses to create new - -threads - -. We’ll - -talk more about threads later, but for now you can think of a thread as kind of - -a process. The - -k - -at the beginning stands for - -kernel - -, which is the part of the - -operating system responsible for core capabilities like creating threads. The - -extra - -d - -at the end stands for - -daemon - -, which is another name for processes like - -this that run in the background and provide operating system services. In this - -context, “daemon” is used in the sense of a helpful spirit, with no connotation - -of evil. - -Based on the name, you can infer that - -ksoftirqd - -is also a kernel daemon; - -specifically, it handles software interrupt requests, or “soft IRQ”. - -kworker - -is a worker process created by the kernel to do some kind of processing - -for the kernel. - - - ---- - -14 Chapter 2. Processes - -There are often multiple processes running these kernel services. On my system - -at the moment, there are 8 - -ksoftirqd - -processes and 35 - -kworker - -processes. - -I won’t go into more details about the other processes, but if you are interested - -you can search for more information about them. You should run - -ps - -on your - -system and compare your results to mine. - - - ---- - -## Chapter 3 - -## Virtual memory - -## 3.1 A bit of information theory - -A - -bit - -is a binary digit; it is also a unit of information. If you have one bit, - -you can specify one of two possibilities, usually written 0 and 1. If you have - -two bits, there are 4 possible combinations, 00, 01, 10, and 11. In general, if - -you have - -b - -bits, you can indicate one of 2 - -b - -values. A - -byte - -is 8 bits, so it can - -hold one of 256 values. - -Going in the other direction, suppose you want to store a letter of the alphabet. - -There are 26 letters, so how many bits do you need? With 4 bits, you can - -specify one of 16 values, so that’s not enough. With 5 bits, you can specify up - -to 32 values, so that’s enough for all the letters, with a few values left over. - -In general, if you want to specify one of - -N - -values, you should choose the - -smallest value of - -b - -so that 2 - -b - -≥ - -N - -. Taking the log base 2 of both sides yields - -b - -≥ - -log - -2 - -N - -. - -Suppose I flip a coin and tell you the outcome. I have given you one bit of - -information. If I roll a six-sided die and tell you the outcome, I have given you - -log - -2 - -6 bits of information. And in general, if the probability of the outcome is - -1 in - -N - -, then the outcome contains - -log - -2 - -N - -bits of information. - -Equivalently, if the probability of the outcome is - -p - -, then the information con - -tent is - -− - -log - -2 - -p - -. This quantity is called the - -self-information - -of the outcome. - -It measures how surprising the outcome is, which is why it is also called - -sur - -prisal - -. If your horse has only one chance in 16 of winning, and he wins, you - -get 4 bits of information (along with the payout). But if the favorite wins 75% - -of the time, the news of the win contains only 0.42 bits. - - - ---- - -16 Chapter 3. Virtual memory - -Intuitively, unexpected news carries a lot of information; conversely, if there - -is something you were already confident of, confirming it contributes only a - -small amount of information. - -For several topics in this book, we will need to be comfortable converting back - -and forth between the number of bits, - -b - -, and the number of values they can - -encode, - -N - -= 2 - -b - -. - -## 3.2 Memory and storage - -While a process is running, most of its data is held in - -main memory - -, which - -is usually some kind of random access memory (RAM). On most current com - -puters, main memory is - -volatile - -, which means that when the computer shuts - -down, the contents of main memory are lost. A typical desktop computer has - -2–8 GiB of memory. GiB stands for “gibibyte,” which is 2 - -30 - -bytes. - -If the process reads and writes files, those files are usually stored on a hard - -disk drive (HDD) or solid state drive (SSD). These storage devices are - -non - -volatile - -, so they are used for long-term storage. Currently a typical desktop - -computer has a HDD with a capacity of 500 GB to 2 TB. GB stands for - -“gigabyte,” which is 10 - -9 - -bytes. TB stands for “terabyte,” which is 10 - -12 - -bytes. - -You might have noticed that I used the binary unit GiB for the size of main - -memory and the decimal units GB and TB for the size of the HDD. For - -historical and technical reasons, memory is measured in binary units, and - -disk drives are measured in decimal units. In this book I will be careful to - -distinguish binary and decimal units, but you should be aware that the word - -“gigabyte” and the abbreviation GB are often used ambiguously. - -In casual use, the term “memory” is sometimes used for HDDs and SSDs as - -well as RAM, but the properties of these devices are very different, so we will - -need to distinguish them. I will use - -storage - -to refer to HDDs and SSDs. - -## 3.3 Address spaces - -Each byte in main memory is specified by an integer - -physical address - -. The - -set of valid physical addresses is called the physical - -address space - -. It usually - -runs from 0 to - -N - -− - -1, where - -N - -is the size of main memory. On a system - -with 1 GiB of physical memory, the highest valid address is 2 - -30 - -− - -1, which is - -1,073,741,823 in decimal, or 0x3fff ffff in hexadecimal (the prefix 0x indicates - -a hexadecimal number). - - - ---- - -3.4. Memory segments 17 - -However, most operating systems provide - -virtual memory - -, which means - -that programs never deal with physical addresses, and don’t have to know - -how much physical memory is available. - -Instead, programs work with - -virtual addresses - -, which are numbered from 0 - -to - -M - -− - -1, where - -M - -is the number of valid virtual addresses. The size of the - -virtual address space is determined by the operating system and the hardware - -it runs on. - -You have probably heard people talk about 32-bit and 64-bit systems. These - -terms indicate the size of the registers, which is usually also the size of a virtual - -address. On a 32-bit system, virtual addresses are 32 bits, which means that - -the virtual address space runs from 0 to 0xffff ffff. The size of this address - -space is 2 - -32 - -bytes, or 4 GiB. - -On a 64-bit system, the size of the virtual address space is 2 - -64 - -bytes, or 2 - -4 - -· - -1024 - -6 - -bytes. That’s 16 exbibytes, which is about a billion times bigger than current - -physical memories. It might seem strange that a virtual address space can be - -so much bigger than physical memory, but we will see soon how that works. - -When a program reads and writes values in memory, it generates virtual ad - -dresses. The hardware, with help from the operating system, translates to - -physical addresses before accessing main memory. This translation is done on - -a per-process basis, so even if two processes generate the same virtual address, - -they would map to different locations in physical memory. - -Thus, virtual memory is one important way the operating system isolates - -processes from each other. In general, a process cannot access data belonging - -to another process, because there is no virtual address it can generate that - -maps to physical memory allocated to another process. - -## 3.4 Memory segments - -The data of a running process is organized into five segments: - -ˆ - -The - -code segment - -contains the program text; that is, the machine - -language instructions that make up the program. - -ˆ - -The - -static segment - -contains immutable values, like string literals. For - -example, if your program contains the string - -"Hello, World" - -, those - -characters will be stored in the static segment. - -ˆ - -The - -global segment - -contains global variables and local variables that - -are declared - -static - -. - - - ---- - -18 Chapter 3. Virtual memory - -ˆ - -The - -heap segment - -contains chunks of memory allocated at run time, - -most often by calling the C library function - -malloc - -. - -ˆ - -The - -stack segment - -contains the call stack, which is a sequence of stack - -frames. Each time a function is called, a stack frame is allocated to - -contain the parameters and local variables of the function. When the - -function completes, its stack frame is removed from the stack. - -The arrangement of these segments is determined partly by the compiler and - -partly by the operating system. The details vary from one system to another, - -but in the most common arrangement: - -ˆ - -The text segment is near the “bottom” of memory, that is, at addresses - -near 0. - -ˆ - -The static segment is often just above the text segment, that is, at higher - -addresses. - -ˆ - -The global segment is often just above the static segment. - -ˆ - -The heap is often above the global segment. As it expands, it grows up - -toward larger addresses. - -ˆ - -The stack is near the top of memory; that is, near the highest addresses - -in the virtual address space. As the stack expands, it grows down toward - -smaller addresses. - -To determine the layout of these segments on your system, try running this - -program, which is in - -aspace.c - -in the repository for this book (see Section 0.1). - -#include - -#include - -int global; - -int main () - -{ - -int local = 5; - -void *p = malloc(128); - -char *s = "Hello, World"; - -printf ("Address of main is %p\n", main); - -printf ("Address of global is %p\n", &global); - -printf ("Address of local is %p\n", &local); - - - ---- - -3.4. Memory segments 19 - -printf ("p points to %p\n", p); - -printf ("s points to %p\n", s); - -} - -main - -is the name of a function; when it is used as a variable, it refers to the - -address of the first machine language instruction in - -main - -, which we expect to - -be in the text segment. - -global - -is a global variable, so we expect it to be in the global segment. - -local - -is a local variable, so we expect it to be on the stack. - -s - -refers to a “string literal”, which is a string that appears as part of the - -program (as opposed to a string that is read from a file, input by a user, etc.). - -We expect the location of the string to be in the static segment (as opposed - -to the pointer, - -s - -, which is a local variable). - -p - -contains an address returned by - -malloc - -, which allocates space in the heap. - -“malloc” stands for “memory allocate.” - -The format sequence - -%p - -tells - -printf - -to format each address as a “pointer”, - -so it displays the results in hexadecimal. - -When I run this program, the output looks like this (I added spaces to make - -it easier to read): - -Address of main is 0x 40057d - -Address of global is 0x 60104c - -Address of local is 0x7ffe6085443c - -p points to 0x 16c3010 - -s points to 0x 4006a4 - -As expected, the address of - -main - -is the lowest, followed by the location of the - -string literal. The location of - -global - -is next, then the address - -p - -points to. - -The address of - -local - -is much bigger. - -The largest address has 12 hexadecimal digits. Each hex digit corresponds - -to 4 bits, so it is a 48-bit address. That suggests that the usable part of the - -virtual address space is 2 - -48 - -bytes. - -As an exercise, run this program on your computer and compare your results - -to mine. Add a second call to - -malloc - -and check whether the heap on your - -system grows up (toward larger addresses). Add a function that prints the - -address of a local variable, and check whether the stack grows down. - - - ---- - -20 Chapter 3. Virtual memory - -Figure 3.1: Diagram of the address translation process. - -## 3.5 Static local variables - -Local variables on the stack are sometimes called - -automatic - -, because they - -are allocated automatically when a function is called, and freed automatically - -when the function returns. - -In C there is another kind of local variable, called - -static - -, which is allocated - -in the global segment. It is initialized when the program starts and keeps its - -value from one function call to the next. - -For example, the following function keeps track of how many times it has been - -called. - -int times_called() - -{ - -static int counter = 0; - -counter++; - -return counter; - -} - -The keyword - -static - -indicates that - -counter - -is a static local variable. The - -initialization happens only once, when the program starts. - -If you add this function to - -aspace.c - -you can confirm that - -counter - -is allocated - -in the global segment along with global variables, not in the stack. - -## 3.6 Address translation - -How does a virtual address (VA) get translated to a physical address (PA)? - -The basic mechanism is simple, but a simple implementation would be too - -slow and take too much space. So actual implementations are a bit more - -complicated. - - - ---- - -3.6. Address translation 21 - -Most processors provide a memory management unit (MMU) that sits between - -the CPU and main memory. The MMU performs fast translation between VAs - -and PAs. - -1. - -When a program reads or writes a variable, the CPU generates a VA. - -2. - -The MMU splits the VA into two parts, called the page number and the - -offset. A “page” is a chunk of memory; the size of a page depends on - -the operating system and the hardware, but common sizes are 1–4 KiB. - -3. - -The MMU looks up the page number in the translation lookaside buffer - -(TLB) and gets the corresponding physical page number. Then it com - -bines the physical page number with the offset to produce a PA. - -4. - -The PA is passed to main memory, which reads or writes the given - -location. - -The TLB contains cached copies of data from the page table (which is stored - -in kernel memory). The page table contains the mapping from virtual page - -numbers to physical page numbers. Since each process has its own page table, - -the TLB has to make sure it only uses entries from the page table of the - -process that’s running. - -Figure 3.1 shows a diagram of this process. To see how it all works, suppose - -that the VA is 32 bits and the physical memory is 1 GiB, divided into 1 KiB - -pages. - -ˆ - -Since 1 GiB is 2 - -30 - -bytes and 1 KiB is 2 - -10 - -bytes, there are 2 - -20 - -physical - -pages, sometimes called “frames.” - -ˆ - -The size of the virtual address space is 2 - -32 - -B and the size of a page is - -2 - -10 - -B, so there are 2 - -22 - -virtual pages. - -ˆ - -The size of the offset is determined by the page size. In this example the - -page size is 2 - -10 - -B, so it takes 10 bits to specify a byte on a page. - -ˆ - -If a VA is 32 bits and the offset is 10 bits, the remaining 22 bits make - -up the virtual page number. - -ˆ - -Since there are 2 - -20 - -physical pages, each physical page number is 20 bits. - -Adding in the 10 bit offset, the resulting PAs are 30 bits. - -So far this all seems feasible. But let’s think about how big a page table might - -have to be. The simplest implementation of a page table is an array with one - -entry for each virtual page. Each entry would contain a physical page number, - - - ---- - -22 Chapter 3. Virtual memory - -which is 20 bits in this example, plus some additional information about each - -frame. So we expect 3–4 bytes per entry. But with 2 - -22 - -virtual pages, the page - -table would require 2 - -24 - -bytes, or 16 MiB. - -And since we need a page table for each process, a system running 256 processes - -would need 2 - -32 - -bytes, or 4 GiB, just for page tables! And that’s just with 32-bit - -virtual addresses. With 48- or 64-bit VAs, the numbers are ridiculous. - -Fortunately, we don’t actually need that much space, because most processes - -don’t use even a small fraction of their virtual address space. And if a process - -doesn’t use a virtual page, we don’t need an entry in the page table for it. - -Another way to say the same thing is that page tables are “sparse”, which - -implies that the simple implementation, an array of page table entries, is a bad - -idea. Fortunately, there are several good implementations for sparse arrays. - -One option is a multilevel page table, which is what many operating systems, - -including Linux, use. Another option is an associative table, where each entry - -includes both the virtual page number and the physical page number. Search - -ing an associative table can be slow in software, but in hardware we can search - -the entire table in parallel, so associative arrays are often used to represent - -the page table entries in the TLB. - -You can read more about these implementations at - -http://en.wikipedia. - -org/wiki/Page_table - -; you might find the details interesting. But the fun - -damental idea is that page tables are sparse, so we have to choose a good - -implementation for sparse arrays. - -I mentioned earlier that the operating system can interrupt a running process, - -save its state, and then run another process. This mechanism is called a - -context switch - -. Since each process has its own page table, the operating - -system has to work with the MMU to make sure each process gets the right - -page table. In older machines, the page table information in the MMU had - -to be replaced during every context switch, which was expensive. In newer - -systems, each page table entry in the MMU includes the process ID, so page - -tables from multiple processes can be in the MMU at the same time. - - - ---- - -## Chapter 4 - -## Files and file systems - -When a process completes (or crashes), any data stored in main memory is - -lost. But data stored on a hard disk drive (HDD) or solid state drive (SSD) - -is “persistent;” that is, it survives after the process completes, even if the - -computer shuts down. - -Hard disk drives are complicated. Data is stored in blocks, which are laid out - -in sectors, which make up tracks, which are arranged in concentric circles on - -platters. - -Solid state drives are simpler in one sense, because blocks are numbered se - -quentially, but they raise a different complication: each block can be written - -a limited number of times before it becomes unreliable. - -As a programmer, you don’t want to deal with these complications. What you - -want is an appropriate abstraction of persistent storage hardware. The most - -common abstraction is called a “file system.” - -Abstractly: - -ˆ - -A “file system” is a mapping from each file’s name to its contents. If - -you think of the names as keys, and the contents as values, a file system - -is a kind of key-value database (see - -https://en.wikipedia.org/wiki/ - -Key-value_database - -). - -ˆ - -A “file” is a sequence of bytes. - -File names are usually strings, and they are usually “hierarchical”; that is, the - -string specifies a path from a top-level directory (or folder), through a series - -of subdirectories, to a specific file. - - - ---- - -24 Chapter 4. Files and file systems - -The primary difference between the abstraction and the underlying mechanism - -is that files are byte-based and persistent storage is block-based. The operating - -system translates byte-based file operations in the C library into block-based - -operations on storage devices. Typical block sizes are 1–8 KiB. - -For example, the following code opens a file and reads the first byte: - -FILE *fp = fopen("/home/downey/file.txt", "r"); - -char c = fgetc(fp); - -fclose(fp); - -When this code runs: - -1. - -fopen - -uses the filename to find the top-level directory, called - -/ - -, the - -subdirectory - -home - -, and the sub-subdirectory - -downey - -. - -2. - -It finds the file named - -file.txt - -and “opens” it for reading, which means - -it creates a data structure that represents the file being read. Among - -other things, this data structure keeps track of how much of the file has - -been read, called the “file position”. - -In DOS, this data structure is called a File Control Block, but I want - -to avoid that term because in UNIX it means something else. In UNIX, - -there seems to be no good name for it. It is an entry in the open file - -table, so I will call it an OpenFileTableEntry. - -3. - -When we call - -fgetc - -, the operating system checks whether the next char - -acter of the file is already in memory. If so, it reads the next character, - -advances the file position, and returns the result. - -4. - -If the next character is not in memory, the operating system issues an - -I/O request to get the next block. Disk drives are slow, so a process - -waiting for a block from disk is usually interrupted so another process - -can run until the data arrives. - -5. - -When the I/O operation is complete, the new block of data is stored in - -memory, and the process resumes. It reads the first character and stores - -it as a local variable. - -6. - -When the process closes the file, the operating system completes or can - -cels any pending operations, removes data stored in memory, and frees - -the OpenFileTableEntry. - -The process for writing a file is similar, but there are some additional steps. - -Here is an example that opens a file for writing and changes the first character. - - - ---- - -4.1. Disk performance 25 - -FILE *fp = fopen("/home/downey/file.txt", "w"); - -fputc('b', fp); - -fclose(fp); - -When this code runs: - -1. - -Again, - -fopen - -uses the filename to find the file. If it does not already - -exist, it creates a new file and adds an entry in the parent directory, - -/home/downey - -. - -2. - -The operating system creates an OpenFileTableEntry that indicates that - -the file is open for writing, and sets the file position to 0. - -3. - -fputc - -attempts to write (or re-write) the first byte of the file. If the - -file already exists, the operating system has to load the first block into - -memory. Otherwise it allocates a new block in memory and requests a - -new block on disk. - -4. - -After the block in memory is modified, it might not be copied back to - -the disk right away. In general, data written to a file is “buffered”, which - -means it is stored in memory and only written to disk when there is at - -least one block to write. - -5. - -When the file is closed, any buffered data is written to disk and the - -OpenFileTableEntry is freed. - -To summarize, the C library provides the abstraction of a file system that - -maps from file names to streams of bytes. This abstraction is built on top of - -storage devices that are actually organized in blocks. - -## 4.1 Disk performance - -I mentioned earlier that disk drives are slow. On current HDDs, the - -average time to read a block from disk to memory might be 5–25 - -ms (see - -https://en.wikipedia.org/wiki/Hard_disk_drive_performance_ - -characteristics - -). SSDs are faster, taking 25 - -µ - -s to read a 4 KiB block and - -250 - -µ - -s to write one (see - -http://en.wikipedia.org/wiki/Ssd#Controller - -). - -To put these numbers in perspective, let’s compare them to the clock cycle of - -the CPU. A processor with clock rate 2 GHz completes one clock cycle every - -0.5 ns. The time to get a byte from memory to the CPU is typically around - -100 ns. If the processor completes one instruction per clock cycle, it would - -complete 200 instructions while waiting for a byte from memory. - - - ---- - -26 Chapter 4. Files and file systems - -In one microsecond, it would complete 2000 instructions, so while waiting 25 - -µ - -s for a byte from an SSD, it would complete 50,000. - -In one millisecond, it would complete 2,000,000 instructions, so while waiting - -20 ms for a byte from a HDD, it might complete 40 million. If there’s nothing - -for the CPU to do while it waits, it would be idle. That’s why the operating - -system generally switches to another process while it is waiting for data from - -disk. - -The gap in performance between main memory and persistent storage is one - -of the major challenges of computer system design. Operating systems and - -hardware provide several features intended to “fill in” this gap: - -ˆ - -Block transfers: The time it takes to load a single byte from disk is 5– - -25 ms. By comparison, the additional time to load an 8 KiB block is - -negligible. So systems generally try to read large blocks each time they - -access the disk. - -ˆ - -Prefetching: Sometimes the operating system can predict that a process - -will read a block and start loading it before it is requested. For example, - -if you open a file and read the first block, there is a good chance you - -will go on to read the second block. The operating system might start - -loading additional blocks before they are requested. - -ˆ - -Buffering: As I mentioned, when you write a file, the operating system - -stores the data in memory and only writes it to disk later. If you modify - -the block several times while it is in memory, the system only has to - -write it to disk once. - -ˆ - -Caching: If a process has used a block recently, it is likely to use it again - -soon. If the operating system keeps a copy of the block in memory, it - -can handle future requests at memory speed. - -Some of these features are also implemented in hardware. For example, some - -disk drives provide a cache that stores recently-used blocks, and many disk - -drives read more than one block at a time, even if only one is requested. - -These mechanisms generally improve the performance of programs, but they - -don’t change the behavior. Usually programmers don’t have to think about - -them, with two exceptions: (1) if the performance of a program is unexpectedly - -bad, you might have to know something about these mechanisms to diagnose - -the problem, and (2) when data is buffered, it can be harder to debug a - -program. For example, if a program prints a value and then crashes, the value - -might not appear, because it might be in a buffer. Similarly, if a program - -writes data to disk and then the computer loses power, the data might be lost - -if it is in a cache and not yet on disk. - - - ---- - -4.2. Disk metadata 27 - -## 4.2 Disk metadata - -The blocks that make up a file might be arranged contiguously on disk, and file - -system performance is generally better if they are, but most operating systems - -don’t require contiguous allocation. They are free to place a block anywhere - -on disk, and they use various data structures to keep track of them. - -In many UNIX file systems, that data structure is called an “inode,” which - -stands for “index node”. More generally, information about files, including - -the location of their blocks, is called “metadata”. (The content of the file is - -data, so information about the file is data about data, hence “meta”.) - -Since inodes reside on disk along with the rest of the data, they are designed - -to fit neatly into disk blocks. A UNIX inode contains information about a - -file, including the user ID of the file owner; permission flags indicating who - -is allowed to read, write, or execute it; and timestamps that indicate when it - -was last modified and accessed. In addition, it contains block numbers for the - -first 12 blocks that make up the file. - -If the block size is 8 KiB, the first 12 blocks make up 96 KiB. On most systems, - -that’s big enough for a large majority of files, but it’s definitely not big enough - -for all of them. That’s why the inode also contains a pointer to an “indirection - -block”, which contains nothing but pointers to other blocks. - -The number of pointers in an indirection block depends on the sizes of the - -blocks and the block numbers, but it is often 1024. With 1024 block numbers - -and 8 KiB blocks, an indirection block can address 8 MiB. That’s big enough - -for all but the largest files, but still not big enough for all. - -That’s why the inode also contains a pointer to a “double indirection block”, - -which contains pointers to indirection blocks. With 1024 indirection blocks, - -we can address 8 GiB. - -And if that’s not big enough, there is (finally) a triple indirection block, which - -contains pointers to double indirection blocks, yielding a maximum file size of - -8 TiB. When UNIX inodes were designed, that seemed big enough to serve for - -a long time. But that was a long time ago. - -As an alternative to indirection blocks, some files systems, like FAT, use a File - -Allocation Table that contains one entry for each block, called a “cluster” in - -this context. A root directory contains a pointer to the first cluster in each file. - -The FAT entry for each cluster points to the next cluster in the file, similar to - -a linked list. For more details, see - -http://en.wikipedia.org/wiki/File_ - -Allocation_Table - -. - - - ---- - -28 Chapter 4. Files and file systems - -## 4.3 Block allocation - -File systems have to keep track of which blocks belong to each file; they also - -have to keep track of which blocks are available for use. When a new file is - -created, the file system finds an available block and allocates it. When a file - -is deleted, the file system makes its blocks available for re-allocation. - -The goals of the block allocation system are: - -ˆ - -Speed: Allocating and freeing blocks should be fast. - -ˆ - -Minimal space overhead: The data structures used by the allocator - -should be small, leaving as much space as possible for data. - -ˆ - -Minimal fragmentation: If some blocks are left unused, or some are only - -partially used, the unused space is called “fragmentation”. - -ˆ - -Maximum contiguity: Data that is likely to be used at the same time - -should be physically contiguous, if possible, to improve performance. - -It is hard to design a file system that achieves all of these goals, especially - -since file system performance depends on “workload characteristics” like file - -sizes, access patterns, etc. A file system that is well tuned for one workload - -might not perform as well for another. - -For this reason, most operating systems support several kinds of file systems, - -and file system design is an active area of research and development. In the - -last decade, Linux systems have migrated from ext2, which was a conventional - -UNIX file system, to ext3, a “journaling” file system intended to improve speed - -and contiguity, and more recently to ext4, which can handle larger files and - -file systems. Within the next few years, there might be another migration to - -the B-tree file system, Btrfs. - -## 4.4 Everything is a file? - -The file abstraction is really a “stream of bytes” abstraction, which turns out - -to be useful for many things, not just file systems. - -One example is the UNIX pipe, which is a simple form of inter-process com - -munication. Processes can be set up so that output from one process is taken - -as input into another process. For the first process, the pipe behaves like a - -file open for writing, so it can use C library functions like - -fputs - -and - -fprintf - -. - - - ---- - -4.4. Everything is a file? 29 - -For the second process, the pipe behaves like a file open for reading, so it uses - -fgets - -and - -fscanf - -. - -Network communication also uses the stream of bytes abstraction. A UNIX - -socket is a data structure that represents a communication channel between - -processes on different computers (usually). Again, processes can read data - -from and write data to a socket using “file” handling functions. - -Reusing the file abstraction makes life easier for programmers, since they only - -have to learn one API (application program interface). It also makes programs - -more versatile, since a program intended to work with files can also work with - -data coming from pipes and other sources. - - - ---- - -30 Chapter 4. Files and file systems - - - ---- - -## Chapter 5 - -## More bits and bytes - -## 5.1 Representing integers - -You probably know that computers represent numbers in base 2, also known - -as binary. For positive numbers, the binary representation is straightforward; - -for example, the representation for 5 - -10 - -is - -b - -101. - -For negative numbers, the most obvious representation uses a sign bit to in - -dicate whether a number is positive or negative. But there is another repre - -sentation, called “two’s complement” that is much more common because it - -is easier to work with in hardware. - -To find the two’s complement of a negative number, - -− - -x - -, find the binary rep - -resentation of - -x - -, flip all the bits, and add 1. For example, to represent - -− - -5 - -10 - -, - -start with the representation of 5 - -10 - -, which is - -b - -00000101 if we write the 8-bit - -version. Flipping all the bits and adding 1 yields - -b - -11111011. - -In two’s complement, the leftmost bit acts like a sign bit; it is 0 for positive - -numbers and 1 for negative numbers. - -To convert from an 8-bit number to 16-bits, we have to add more 0’s for a - -positive number and add 1’s for a negative number. In effect, we have to copy - -the sign bit into the new bits. This process is called “sign extension”. - -In C all integer types are signed (able to represent positive and negative num - -bers) unless you declare them - -unsigned - -. The difference, and the reason this - -declaration is important, is that operations on unsigned integers don’t use sign - -extension. - - - ---- - -32 Chapter 5. More bits and bytes - -## 5.2 Bitwise operators - -People learning C are sometimes confused about the bitwise operators - -& - -and - -| - -. These operators treat integers as bit vectors and compute logical operations - -on corresponding bits. - -For example, - -& - -computes the AND operation, which yields 1 if both operands - -are 1, and 0 otherwise. Here is an example of - -& - -applied to two 4-bit numbers: - -1100 - -& 1010 - ----- - -1000 - -In C, this means that the expression - -12 & 10 - -has the value 8. - -Similarly, - -| - -computes the OR operation, which yields 1 if either operand is 1, - -and 0 otherwise. - -1100 - -| 1010 - ----- - -1110 - -So the expression - -12 | 10 - -has the value 14. - -Finally, - -^ - -computes the XOR operation, which yields 1 if either operand is 1, - -but not both. - -1100 - -^ 1010 - ----- - -0110 - -So the expression - -12 ^ 10 - -has the value 6. - -Most commonly, - -& - -is used to clear a set of bits from a bit vector, - -| - -is used to - -set bits, and - -^ - -is used to flip, or “toggle” bits. Here are the details: - -Clearing bits - -: For any value - -x - -, - -x - -&0 is 0, and - -x - -&1 is - -x - -. So if you AND a - -vector with 3, it selects only the two rightmost bits, and sets the rest to 0. - -xxxx - -& 0011 - ----- - -00xx - - - ---- - -5.3. Representing floating-point numbers 33 - -In this context, the value 3 is called a “mask” because it selects some bits and - -masks the rest. - -Setting bits - -: Similarly, for any - -x - -, - -x - -| - -0 is x, and - -x - -| - -1 is 1. So if you OR a vector - -with 3, it sets the rightmost bits, and leaves the rest alone: - -xxxx - -| 0011 - ----- - -xx11 - -Toggling bits - -: Finally, if you XOR a vector with 3, it flips the rightmost bits - -and leaves the rest alone. As an exercise, see if you can compute the two’s - -complement of 12 using - -^ - -. Hint: what’s the two’s complement representation - -of -1? - -C also provides shift operators, - -<< - -and - ->> - -, which shift bits left and right. Each - -left shift doubles a number, so - -5 << 1 - -is 10, and - -5 << 2 - -is 20. Each right shift - -divides by two (rounding down), so - -5 >> 1 - -is 2 and - -2 >> 1 - -is 1. - -## 5.3 Representing floating-point numbers - -Floating-point numbers are represented using the binary version of scientific - -notation. In decimal notation, large numbers are written as the product of a - -coefficient and 10 raised to an exponent. For example, the speed of light in - -m/s is approximately 2 - -. - -998 - -· - -10 - -8 - -. - -Most computers use the IEEE standard for floating-point arithmetic. The C - -type - -float - -usually corresponds to the 32-bit IEEE standard; - -double - -usually - -corresponds to the 64-bit standard. - -In the 32-bit standard, the leftmost bit is the sign bit, - -s - -. The next 8 bits - -are the exponent, - -q - -, and the last 23 bits are the coefficient, - -c - -. The value of a - -floating-point number is - -( - -− - -1) - -s - -c - -· - -2 - -q - -Well, that’s almost correct, but there’s one more wrinkle. Floating-point num - -bers are usually normalized so that there is one digit before the point. For - -example, in base 10, we prefer 2 - -. - -998 - -· - -10 - -8 - -rather than 2998 - -· - -10 - -5 - -or any other - -equivalent expression. In base 2, a normalized number always has the digit 1 - -before the binary point. Since the digit in this location is always 1, we can - -save space by leaving it out of the representation. - - - ---- - -34 Chapter 5. More bits and bytes - -For example, the integer representation of 13 - -10 - -is - -b - -1101. In floating point, - -that’s 1 - -. - -101 - -· - -2 - -3 - -, so the exponent is 3 and the part of the coefficient that would - -be stored is 101 (followed by 20 zeros). - -Well, that’s almost correct, but there’s one more wrinkle. The exponent is - -stored with a “bias”. In the 32-bit standard, the bias is 127, so the exponent - -3 would be stored as 130. - -To pack and unpack floating-point numbers in C, we can use a union and - -bitwise operations. Here’s an example: - -union { - -float f; - -unsigned int u; - -} p; - -p.f = -13.0; - -unsigned int sign = (p.u >> 31) & 1; - -unsigned int exp = (p.u >> 23) & 0xff; - -unsigned int coef_mask = (1 << 23) - 1; - -unsigned int coef = p.u & coef_mask; - -printf("%d\n", sign); - -printf("%d\n", exp); - -printf("0x%x\n", coef); - -This code is in - -float.c - -in the repository for this book (see Section 0.1). - -The union allows us to store a floating-point value using - -p.f - -and then read it - -as an unsigned integer using - -p.u - -. - -To get the sign bit, we shift the bits to the right 31 places and then use a 1-bit - -mask to select only the rightmost bit. - -To get the exponent, we shift the bits 23 places, then select the rightmost 8 - -bits (the hexadecimal value - -0xff - -has eight 1’s). - -To get the coefficient, we need to extract the 23 rightmost bits and ignore the - -rest. We do that by making a mask with 1s in the 23 rightmost places and 0s - -on the left. The easiest way to do that is by shifting 1 to the left by 23 places - -and then subtracting 1. - -The output of this program is: - -1 - - - ---- - -5.4. Unions and memory errors 35 - -130 - -0x500000 - -As expected, the sign bit for a negative number is 1. The exponent is 130, - -including the bias. And the coefficient, which I printed in hexadecimal, is 101 - -followed by 20 zeros. - -As an exercise, try assembling or disassembling a - -double - -, which uses the 64-bit - -standard. See - -http://en.wikipedia.org/wiki/IEEE_floating_point - -. - -## 5.4 Unions and memory errors - -There are two common uses of C unions. One, which we saw in the previous - -section, is to access the binary representation of data. Another is to store - -heterogeneous data. For example, you could use a union to represent a number - -that might be an integer, float, complex, or rational number. - -However, unions are error-prone. It is up to you, as the programmer, to keep - -track of what type of data is in the union; if you write a floating-point value - -and then interpret it as an integer, the result is usually nonsense. - -Actually, the same thing can happen if you read a location in memory incor - -rectly. One way that can happen is if you read past the end of an array. - -To see what happens, I’ll start with a function that allocates an array on the - -stack and fills it with the numbers from 0 to 99. - -void f1() { - -int i; - -int array[100]; - -for (i=0; i<100; i++) { - -array[i] = i; - -} - -} - -Next I’ll define a function that creates a smaller array and deliberately accesses - -elements before the beginning and after the end: - -void f2() { - -int x = 17; - -int array[10]; - -int y = 123; - -printf("%d\n", array[-2]); - - - ---- - -36 Chapter 5. More bits and bytes - -printf("%d\n", array[-1]); - -printf("%d\n", array[10]); - -printf("%d\n", array[11]); - -} - -If I call - -f1 - -and then - -f2 - -, I get these results: - -17 - -123 - -98 - -99 - -The details here depend on the compiler, which arranges variables on the stack. - -From these results, we can infer that the compiler put - -x - -and - -y - -next to each - -other, “below” the array (at a lower address). And when we read past the - -array, it looks like we are getting values that were left on the stack by the - -previous function call. - -In this example, all of the variables are integers, so it is relatively easy to figure - -out what is going on. But in general when you read beyond the bounds of an - -array, the values you read might have any type. For example, if I change - -f1 - -to make an array of floats, the results are: - -17 - -123 - -1120141312 - -1120272384 - -The latter two values are what you get if you interpret a floating-point value - -as an integer. If you encountered this output while debugging, you would have - -a hard time figuring out what’s going on. - -## 5.5 Representing strings - -Related issues sometimes come up with strings. First, remember that C strings - -are null-terminated. When you allocate space for a string, don’t forget the - -extra byte at the end. - -Also, the letters - -and numbers - -in C strings are encoded in ASCII. The ASCII - -codes for the digits “0” through “9” are 48 through 57, - -not - -0 through 9. The - -ASCII code 0 is the NUL character that marks the end of a string. And the - -ASCII codes 1 through 9 are special characters used in some communication - -protocols. ASCII code 7 is a bell; on some terminals, printing it makes a - -sound. - - - ---- - -5.5. Representing strings 37 - -The ASCII code for the letter “A” is 65; the code for “a” is 97. Here are those - -codes in binary: - -65 = b0100 0001 - -97 = b0110 0001 - -A careful observer will notice that they differ by a single bit. And this pattern - -holds for the rest of the letters; the sixth bit (counting from the right) acts as - -a “case bit”, 0 for upper-case letters and 1 for lower case letters. - -As an exercise, write a function that takes a string and converts from lower - -case to upper-case by flipping the sixth bit. As a challenge, you can make a - -faster version by reading the string 32 or 64 bits at a time, rather than one - -character at a time. This optimization is made easier if the length of the string - -is a multiple of 4 or 8 bytes. - -If you read past the end of a string, you are likely to see strange characters. - -Conversely, if you write a string and then accidentally read it as an int or float, - -the results will be hard to interpret. - -For example, if you run: - -char array[] = "allen"; - -float *p = array; - -printf("%f\n", *p); - -You will find that the ASCII representation of the first 8 characters - -of my name, interpreted as a double-precision floating point number, is - -69779713878800585457664. - - - ---- - -38 Chapter 5. More bits and bytes - - - ---- - -## Chapter 6 - -## Memory management - -C provides 4 functions for dynamic memory allocation: - -ˆ - -malloc - -, which takes an integer size, in bytes, and returns a pointer to - -a newly-allocated chunk of memory with (at least) the given size. If it - -can’t satisfy the request, it returns the special pointer value NULL. - -ˆ - -calloc - -, which is the same as - -malloc - -except that it also clears the newly - -allocated chunk; that is, it sets all bytes in the chunk to 0. - -ˆ - -free - -, which takes a pointer to a previously allocated chunk and deallo - -cates it; that is, it makes the space available for future allocation. - -ˆ - -realloc - -, which takes a pointer to a previously allocated chunk and a - -new size. It allocates a chunk of memory with the new size, copies data - -from the old chunk to the new, frees the old chunk, and returns a pointer - -to the new chunk. - -This API is notoriously error-prone and unforgiving. Memory management is - -one of the most challenging parts of designing large software systems, which - -is why most modern languages provide higher-level memory management fea - -tures like garbage collection. - -## 6.1 Memory errors - -The C memory management API is a bit like Jasper Beardly, a minor charac - -ter on the animated television program - -The Simpsons - -; in a few episodes, he - -appears as a strict substitute teacher who imposes corporal punishment — a - -“paddlin”’ — for all infractions. - - - ---- - -40 Chapter 6. Memory management - -Here are some of things a program can do that deserve a paddling: - -ˆ - -If you access (read or write) any chunk that has not been allocated, - -that’s a paddling. - -ˆ - -If you free an allocated chunk and then access it, that’s a paddling. - -ˆ - -If you try to free a chunk that has not been allocated, that’s a paddling. - -ˆ - -If you free the same chunk more than once, that’s a paddling. - -ˆ - -If you call - -realloc - -with a chunk that was not allocated, or was allocated - -and then freed, that’s a paddling. - -It might not sound difficult to follow these rules, but in a large program a chunk - -of memory might be allocated in one part of the program, used in several other - -parts, and freed in yet another part. So changes in one part of the program - -can require changes in many other parts. - -Also, there might be many aliases, or references to the same allocated chunk, - -in different parts of the program. The chunk should not be freed until all - -references to the chunk are no longer in use. Getting this right often requires - -careful analysis across all parts of the program, which is difficult and contrary - -to fundamental principles of good software engineering. - -Ideally, every function that allocates memory should include, as part of the - -documented interface, information about how that memory is supposed to - -be freed. Mature libraries often do this well, but in the real world, software - -engineering practice often falls short of this ideal. - -To make matters worse, memory errors can be difficult to find because the - -symptoms are unpredictable. For example: - -ˆ - -If you read a value from an unallocated chunk, the system - -might - -detect - -the error, trigger a runtime error called a “segmentation fault”, and stop - -the program. Or, the program might read unallocated memory without - -detecting the error; in that case, the value it gets is whatever happened - -to be stored at the accessed location, which is unpredictable, and might - -be different each time the program runs. - -ˆ - -If you write a value to an unallocated chunk, and don’t get a segmenta - -tion fault, things are even worse. After you write a value to an invalid - -location, a long time might pass before it is read and causes problems. - -At that point it will be very difficult to find the source of the problem. - - - ---- - -6.2. Memory leaks 41 - -And things can be even worse than that! One of the most common problems - -with C-style memory management is that the data structures used to imple - -ment - -malloc - -and - -free - -(which we will see soon) are often stored along with the - -allocated chunks. So if you accidentally write past the end of a dynamically - -allocated chunk, you are likely to mangle these data structures. The system - -usually won’t detect the problem until later, when you call - -malloc - -or - -free - -, - -and those functions fail in some inscrutable way. - -One conclusion you should draw from this is that safe memory management - -requires design and discipline. If you write a library or module that allocates - -memory, you should also provide an interface to free it, and memory manage - -ment should be part of the API design from the beginning. - -If you use a library that allocates memory, you should be disciplined in your - -use of the API. For example, if the library provides functions to allocate and - -deallocate storage, you should use those functions and not, for example, call - -free - -on a chunk you did not - -malloc - -. And you should avoid keeping multiple - -references to the same chunk in different parts of your program. - -Often there is a trade-off between safe memory management and performance. - -For example, the most common source of memory errors is writing beyond the - -bounds of an array. The obvious remedy for this problem is bounds checking; - -that is, every access to the array should check whether the index is out of - -bounds. High-level libraries that provide array-like structures usually perform - -bounds checking. But C arrays and most low-level libraries do not. - -## 6.2 Memory leaks - -There is one more memory error that may or may not deserve a paddling. If - -you allocate a chunk of memory and never free it, that’s a “memory leak”. - -For some programs, memory leaks are ok. For example, if your program - -allocates memory, performs computations on it, and then exits, it is probably - -not necessary to free the allocated memory. When the program exits, all of its - -memory is deallocated by the operating system. Freeing memory immediately - -before exiting might feel more responsible, but it is mostly a waste of time. - -But if a program runs for a long time and leaks memory, its total memory use - -will increase indefinitely. At that point, a few things might happen: - -ˆ - -At some point, the system runs out of physical memory. On systems - -without virtual memory, the next call to - -malloc - -will fail, returning - -NULL. - - - ---- - -42 Chapter 6. Memory management - -ˆ - -On systems with virtual memory, the operating system can move another - -process’s pages from memory to disk and then allocate more space to the - -leaking process. I explain this mechanism in Section 7.8. - -ˆ - -There might be a limit on the amount of space a single process can - -allocate; beyond that, - -malloc - -returns NULL. - -ˆ - -Eventually, a process might fill its virtual address space (or the usable - -part). After that, there are no more addresses to allocate, so - -malloc - -returns NULL. - -If - -malloc - -returns NULL, but you persist and access the chunk you think you - -allocated, you get a segmentation fault. For this reason, it is considered good - -style to check the result from - -malloc - -before using it. One option is to add a - -condition like this after every - -malloc - -call: - -void *p = malloc(size); - -if (p == NULL) { - -perror("malloc failed"); - -exit(-1); - -} - -perror - -is declared in - -stdio.h - -; it prints an error message and additional in - -formation about the last error that occurred. - -exit - -, which is declared in - -stdlib.h - -, causes the process to terminate. The - -argument is a status code that indicates how the process terminated. By - -convention, status code 0 indicates normal termination and -1 indicates an - -error condition. Sometimes other codes are used to indicate different error - -conditions. - -Error-checking code can be a nuisance, and it makes programs harder to read. - -You can mitigate these problems by wrapping library function calls and their - -error-checking code in your own functions. For example, here is a - -malloc - -wrapper that checks the return value. - -void *check_malloc(int size) - -{ - -void *p = malloc (size); - -if (p == NULL) { - -perror("malloc failed"); - -exit(-1); - -} - -return p; - -} - - - ---- - -6.3. Implementation 43 - -Because memory management is so difficult, most large programs, like web - -browsers, leak memory. To see which programs on your system are using the - -most memory, you can use the UNIX utilities - -ps - -and - -top - -. - -## 6.3 Implementation - -When a process starts, the system allocates space for the text segment and - -statically allocated data, space for the stack, and space for the heap, which - -contains dynamically allocated data. - -Not all programs allocate data dynamically, so the initial size of the heap - -might be small or zero. Initially the heap contains only one free chunk. - -When - -malloc - -is called, it checks whether it can find a free chunk that’s big - -enough. If not, it has to request more memory from the system. The function - -that does that is - -sbrk - -, which sets the “program break”, which you can think - -of as a pointer to the end of the heap. - -When - -sbrk - -is called, the OS allocates new pages of physical memory, updates - -the process’s page table, and sets the program break. - -In theory, a program could call - -sbrk - -directly (without using - -malloc - -) and - -manage the heap itself. But - -malloc - -is easier to use and, for most memory-use - -patterns, it runs fast and uses memory efficiently. - -To implement the memory management API (that is, the functions - -malloc - -, - -free - -, - -calloc - -, and - -realloc - -), most Linux systems use - -ptmalloc - -, which is - -based on - -dlmalloc - -, written by Doug Lea. A short paper that describes key - -elements of the implementation is available at - -http://gee.cs.oswego.edu/ - -dl/html/malloc.html - -. - -For programmers, the most important elements to be aware of are: - -ˆ - -The run time of - -malloc - -does not usually depend on the size of the chunk, - -but might depend on how many free chunks there are. - -free - -is usually - -fast, regardless of the number of free chunks. Because - -calloc - -clears - -every byte in the chunk, the run time depends on chunk size (as well as - -the number of free chunks). - -realloc - -is sometimes fast, if the new size is smaller than the current - -size, or if space is available to expand the existing chunk. If not, it has - -to copy data from the old chunk to the new; in that case, the run time - -depends on the size of the old chunk. - - - ---- - -44 Chapter 6. Memory management - -ˆ - -Boundary tags: When - -malloc - -allocates a chunk, it adds space at the - -beginning and end to store information about the chunk, including its - -size and the state (allocated or free). These bits of data are called - -“boundary tags”. Using these tags, - -malloc - -can get from any chunk - -to the previous chunk and the next chunk in memory. In addition, free - -chunks are chained into a doubly-linked list; each free chunk contains - -pointers to the next and previous chunks in the “free list”. - -The boundary tags and free list pointers make up - -malloc - -’s internal data - -structures. These data structures are interspersed with program data, - -so it is easy for a program error to damage them. - -ˆ - -Space overhead: Boundary tags and free list pointers take up space. - -The minimum chunk size on most systems is 16 bytes. So for very small - -chunks, - -malloc - -is not space efficient. If your program requires large - -numbers of small structures, it might be more efficient to allocate them - -in arrays. - -ˆ - -Fragmentation: If you allocate and free chunks with varied sizes, the - -heap will tend to become fragmented. That is, the free space might be - -broken into many small pieces. Fragmentation wastes space; it also slows - -the program down by making memory caches less effective. - -ˆ - -Binning and caching: The free list is sorted by size into bins, so when - -malloc - -searches for a chunk with a particular size, it knows what bin - -to search in. If you free a chunk and then immediately allocate a chunk - -with the same size, - -malloc - -will usually be fast. - - - ---- - -## Chapter 7 - -## Caching - -## 7.1 How programs run - -In order to understand caching, you have to understand how computers execute - -programs. For a deep understanding of this topic, you should study computer - -architecture. My goal in this chapter is to provide a simple model of program - -execution. - -When a program starts, the code (or text) is usually on a hard disk or solid - -state drive. The operating system creates a new process to run the program, - -then the “loader” copies the text from storage into main memory and starts - -the program by calling - -main - -. - -While the program is running, most of its data is stored in main memory, but - -some of the data is in registers, which are small units of memory on the CPU. - -These registers include: - -ˆ - -The program counter, or PC, which contains the address (in memory) - -of the next instruction in the program. - -ˆ - -The instruction register, or IR, which contains the machine code instruc - -tion currently executing. - -ˆ - -The stack pointer, or SP, which contains the address of the stack frame - -for the current function, which contains its parameters and local vari - -ables. - -ˆ - -General-purpose registers that hold the data the program is currently - -working with. - - - ---- - -46 Chapter 7. Caching - -ˆ - -A status register, or flag register, that contains information about the - -current computation. For example, the flag register usually contains a - -bit that is set if the result of the previous operation was zero. - -When a program is running, the CPU executes the following steps, called the - -“instruction cycle”: - -ˆ - -Fetch: The next instruction is fetched from memory and stored in the - -instruction register. - -ˆ - -Decode: Part of the CPU, called the “control unit”, decodes the instruc - -tion and sends signals to the other parts of the CPU. - -ˆ - -Execute: Signals from the control unit cause the appropriate computa - -tion to occur. - -Most computers can execute a few hundred different instructions, called the - -“instruction set”. But most instructions fall into a few general categories: - -ˆ - -Load: Transfers a value from memory to a register. - -ˆ - -Arithmetic/logic: Loads operands from registers, performs a mathemat - -ical operation, and stores the result in a register. - -ˆ - -Store: Transfers a value from a register to memory. - -ˆ - -Jump/branch: Changes the program counter, causing the flow of execu - -tion to jump to another location in the program. Branches are usually - -conditional, which means that they check a flag in the flag register and - -jump only if it is set. - -Some instructions sets, including the ubiquitous x86, provide instructions that - -combine a load and an arithmetic operation. - -During each instruction cycle, one instruction is read from the program text. In - -addition, about half of the instructions in a typical program load or store data. - -And therein lies one of the fundamental problems of computer architecture: - -the “memory bottleneck”. - -In current computers, a typical core is capable of executing an instruction in - -less than 1 ns. But the time it takes to transfer data to and from memory is - -about 100 ns. If the CPU has to wait 100 ns to fetch the next instruction, and - -another 100 ns to load data, it would complete instructions 200 times slower - -than what’s theoretically possible. For many computations, memory is the - -speed limiting factor, not the CPU. - - - ---- - -7.2. Cache performance 47 - -## 7.2 Cache performance - -The solution to this problem, or at least a partial solution, is caching. A - -“cache” is a small, fast memory that is physically close to the CPU, usually - -on the same chip. - -Actually, current computers typically have several levels of cache: the Level 1 - -cache, which is the smallest and fastest, might be 1–2 MiB with a access times - -near 1 ns; the Level 2 cache might have access times near 4 ns, and the Level - -3 might take 16 ns. - -When the CPU loads a value from memory, it stores a copy in the cache. If - -the same value is loaded again, the CPU gets the cached copy and doesn’t - -have to wait for memory. - -Eventually the cache gets full. Then, in order to bring something new in, we - -have to kick something out. So if the CPU loads a value and then loads it - -again much later, it might not be in cache any more. - -The performance of many programs is limited by the effectiveness of the cache. - -If the instructions and data needed by the CPU are usually in cache, the - -program can run close to the full speed of the CPU. If the CPU frequently - -needs data that are not in cache, the program is limited by the speed of - -memory. - -The cache “hit rate”, - -h - -, is the fraction of memory accesses that find data in - -cache; the “miss rate”, - -m - -, is the fraction of memory accesses that have to go - -to memory. If the time to process a cache hit is - -T - -h - -and the time for a cache - -miss is - -T - -m - -, the average time for each memory access is - -hT - -h - -+ - -mT - -m - -Equivalently, we could define the “miss penalty” as the extra time to process - -a cache miss, - -T - -p - -= - -T - -m - -− - -T - -h - -. Then the average access time is - -T - -h - -+ - -mT - -p - -When the miss rate is low, the average access time can be close to - -T - -h - -. That - -is, the program can perform as if memory ran at cache speeds. - -## 7.3 Locality - -When a program reads a byte for the first time, the cache usually loads a - -“block” or “line” of data that includes the requested byte and some of its - - - ---- - -48 Chapter 7. Caching - -neighbors. If the program goes on to read one of the neighbors, it will already - -be in cache. - -As an example, suppose the block size is 64 B; you read a string with length - -64, and the first byte of the string happens to fall at the beginning of a block. - -When you load the first byte, you incur a miss penalty, but after that the rest - -of the string will be in cache. After reading the whole string, the hit rate will - -be 63/64, about 98%. If the string spans two blocks, you would incur 2 miss - -penalties. But even then the hit rate would be 62/64, or almost 97%. If you - -then read the same string again, the hit rate would be 100%. - -On the other hand, if the program jumps around unpredictably, reading data - -from scattered locations in memory, and seldom accessing the same location - -twice, cache performance would be poor. - -The tendency of a program to use the same data more than once is called - -“temporal locality”. The tendency to use data in nearby locations is called - -“spatial locality”. Fortunately, many programs naturally display both kinds - -of locality: - -ˆ - -Most programs contain blocks of code with no jumps or branches. Within - -these blocks, instructions run sequentially, so the access pattern has - -spatial locality. - -ˆ - -In a loop, programs execute the same instructions many times, so the - -access pattern has temporal locality. - -ˆ - -The result of one instruction is often used immediately as an operand of - -the next instruction, so the data access pattern has temporal locality. - -ˆ - -When a program executes a function, its parameters and local variables - -are stored together on the stack; accessing these values has spatial local - -ity. - -ˆ - -One of the most common processing patterns is to read or write the - -elements of an array sequentially; this pattern also has spatial locality. - -The next section explores the relationship between a program’s access pattern - -and cache performance. - -## 7.4 Measuring cache performance - -When I was a graduate student at U.C. Berkeley I was a teaching assistant - -for Computer Architecture with Brian Harvey. One of my favorite exercises - - - ---- - -7.4. Measuring cache performance 49 - -involved a program that iterates through an array and measures the average - -time to read and write an element. By varying the size of the array, it is - -possible to infer the size of the cache, the block size, and some other attributes. - -My modified version of this program is in the - -cache - -directory of the repository - -for this book (see Section 0.1). - -The important part of the program is this loop: - -iters = 0; - -do { - -sec0 = get_seconds(); - -for (index = 0; index < limit; index += stride) - -array[index] = array[index] + 1; - -iters = iters + 1; - -sec = sec + (get_seconds() - sec0); - -} while (sec < 0.1); - -The inner - -for - -loop traverses the array. - -limit - -determines how much of the - -array it traverses; - -stride - -determines how many elements it skips over. For - -example, if - -limit - -is 16 and - -stride - -is 4, the loop would access elements 0, 4, - -8, and 12. - -sec - -keeps track of the total CPU time used by the inner loop. The outer loop - -runs until - -sec - -exceeds 0.1 seconds, which is long enough that we can compute - -the average time with sufficient precision. - -get_seconds - -uses the system call - -clock_gettime - -, converts to seconds, and - -returns the result as a - -double - -: - -double get_seconds(){ - -struct timespec ts; - -clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); - -return ts.tv_sec + ts.tv_nsec / 1e9; - -} - -To isolate the time to access the elements of the array, the program runs a - -second loop that is almost identical except that the inner loop doesn’t touch - -the array; it always increments the same variable: - -iters2 = 0; - -do { - -sec0 = get_seconds(); - - - ---- - -50 Chapter 7. Caching - -Figure 7.1: Average miss penalty as a function of array size and stride. - -for (index = 0; index < limit; index += stride) - -temp = temp + index; - -iters2 = iters2 + 1; - -sec = sec - (get_seconds() - sec0); - -} while (iters2 < iters); - -The second loop runs the same number of iterations as the first. After each - -iteration, it - -subtracts - -the elapsed time from - -sec - -. When the loop completes, - -sec - -contains the total time for all array accesses, minus the total time it took - -to increment - -temp - -. This difference is the total miss penalty incurred by all - -accesses. Finally, we divide by the number of accesses to get the average miss - -penalty per access, in ns: - -sec * 1e9 / iters / limit * stride - -If you compile and run - -cache.c - -you should see output like this: - -Size: 4096 Stride: 8 read+write: 0.8633 ns - -Size: 4096 Stride: 16 read+write: 0.7023 ns - -Size: 4096 Stride: 32 read+write: 0.7105 ns - -Size: 4096 Stride: 64 read+write: 0.7058 ns - -If you have Python and - -matplotlib - -installed, you can use - -graph_data.py - -to - -graph the results. Figure 7.1 shows the results when I ran it on a Dell Optiplex - -7010. Notice that the array size and stride are reported in bytes, not number - -of array elements. - -Take a minute to consider this graph, and see what you can infer about the - -cache. Here are some things to think about: - - - ---- - -7.5. Programming for cache performance 51 - -ˆ - -The program reads through the array many times, so it has plenty of - -temporal locality. If the entire array fits in cache, we expect the average - -miss penalty to be near 0. - -ˆ - -When the stride is 4 bytes, we read every element of the array, so the - -program has plenty of spatial locality. If the block size is big enough to - -contain 64 elements, for example, the hit rate would be 63/64, even if - -the array does not fit in cache. - -ˆ - -If the stride is equal to the block size (or greater), the spatial locality is - -effectively zero, because each time we read a block, we only access one - -element. In that case we expect to see the maximum miss penalty. - -In summary, we expect good cache performance if the array is smaller than - -the cache size - -or - -if the stride is smaller than the block size. Performance only - -degrades if the array is bigger than the cache - -and - -the stride is large. - -In Figure 7.1, cache performance is good, for all strides, as long as the array - -is less than 2 - -22 - -B. We can infer that the cache size is near 4 MiB; in fact, - -according to the specs, it is 3 MiB. - -When the stride is 8, 16, or 32 B, cache performance is good. At 64 B it starts - -to degrade, and for larger strides the average miss penalty is about 9 ns. We - -can infer that the block size near 128 B. - -Many processors use “multi-level caches” that include a small, fast cache and - -a bigger, slower cache. In this example, it looks like the miss penalty increases - -a little when the array size is bigger than 2 - -14 - -B, so it’s possible that this - -processor also has a 16 KB cache with an access time less than 1 ns. - -## 7.5 Programming for cache performance - -Memory caching is implemented in hardware, so most of the time programmers - -don’t need to know much about it. But if you know how caches work, you can - -write programs that use them more effectively. - -For example, if you are working with a large array, it might be faster to traverse - -the array once, performing several operations with each element, rather than - -traversing the array several times. - -If you are working with a 2-D array, it might be stored as an array of rows. - -If you traverse through the elements, it would be faster to go row-wise, with - -stride equal to the element size, rather than column-wise, with stride equal to - -the row length. - - - ---- - -52 Chapter 7. Caching - -Linked data structures don’t always exhibit spatial locality, because the nodes - -aren’t necessarily contiguous in memory. But if you allocate many nodes at - -the same time, they are usually co-located in the heap. Or, even better, if you - -allocate an array of nodes all at once, you know they will be contiguous. - -Recursive strategies like mergesort often have good cache behavior because - -they break big arrays into smaller pieces and then work with the pieces. Some - -times these algorithms can be tuned to take advantage of cache behavior. - -For applications where performance is critical, it is possible to design algo - -rithms tailored to the size of the cache, the block size, and other hardware - -characterstics. Algorithms like that are called “cache-aware”. The obvious - -drawback of cache-aware algorithms is that they are hardware-specific. - -## 7.6 The memory hierarchy - -At some point during this chapter, a question like the following might have - -occurred to you: “If caches are so much faster than main memory, why not - -make a really big cache and forget about memory?” - -Without going too far into computer architecture, there are two reasons: elec - -tronics and economics. Caches are fast because they are small and close to - -the CPU, which minimizes delays due to capacitance and signal propagation. - -If you make a cache big, it will be slower. - -Also, caches take up space on the processor chip, and bigger chips are more - -expensive. Main memory is usually dynamic random-access memory (DRAM), - -which uses only one transistor and one capacitor per bit, so it is possible to pack - -more memory into the same amount of space. But this way of implementing - -memory is slower than the way caches are implemented. - -Also main memory is usually packaged in a dual in-line memory module - -(DIMM) that includes 16 or more chips. Several small chips are cheaper than - -one big one. - -The trade-off between speed, size, and cost is the fundamental reason for - -caching. If there were one memory technology that was fast, big, and cheap, - -we wouldn’t need anything else. - -The same principle applies to storage as well as memory. Solid state drives - -(SSD) are fast, but they are more expensive than hard drives (HDD), so they - -tend to be smaller. Tape drives are even slower than hard drives, but they can - -store large amounts of data relatively cheaply. - - - ---- - -7.7. Caching policy 53 - -The following table shows typical access times, sizes, and costs for each of - -these technologies. - -Device - -Access - -Typical - -Cost - -time - -size - -Register - -0.5 ns - -256 B - -? - -Cache - -1 ns - -2 MiB - -? - -DRAM - -100 ns - -4 GiB - -$ - -10 / GiB - -SSD - -10 - -µ - -s - -100 GiB - -$ - -1 / GiB - -HDD - -5 ms - -500 GiB - -$ - -0.25 / GiB - -Tape - -minutes - -1–2 TiB - -$ - -0.02 / GiB - -The number and size of registers depends on details of the architecture. Cur - -rent computers have about 32 general-purpose registers, each storing one - -“word”. On a 32-bit computer, a word is 32 bits or 4 B. On a 64-bit computer, - -a word is 64 bits or 8 B. So the total size of the register file is 100–300 B. - -The cost of registers and caches is hard to quantify. They contribute to the - -cost of the chips they are on, but consumers don’t see that cost directly. - -For the other numbers in the table, I looked at the specifications for typical - -hardware for sale from online computer hardware stores. By the time you read - -this, these numbers will be obsolete, but they give you an idea of what the - -performance and cost gaps looked like at one point in time. - -These technologies make up the “memory hierarchy” (note that this use of - -“memory” also includes storage). Each level of the hierarchy is bigger and - -slower than the one above it. And in some sense, each level acts as a cache for - -the one below it. You can think of main memory as a cache for programs and - -data that are stored permanently on SSDs and HHDs. And if you are working - -with very large datasets stored on tape, you could use hard drives to cache - -one subset of the data at a time. - -## 7.7 Caching policy - -The memory hierarchy suggests a framework for thinking about caching. At - -every level of the hierarchy, we have to address four fundamental questions of - -caching: - -ˆ - -Who moves data up and down the hierarchy? At the top of the hierarchy, - -register allocation is usually done by the compiler. Hardware on the CPU - -handles the memory cache. Users implicitly move data from storage to - - - ---- - -54 Chapter 7. Caching - -memory when they execute programs and open files. But the operating - -system also moves data back and forth between memory and storage. At - -the bottom of the hierarchy, administrators move data explicitly between - -disk and tape. - -ˆ - -What gets moved? In general, block sizes are small at the top of the - -hierarchy and bigger at the bottom. In a memory cache, a typical block - -size is 128 B. Pages in memory might be 4 KiB, but when the operating - -system reads a file from disk, it might read 10s or 100s of blocks at a - -time. - -ˆ - -When does data get moved? In the most basic cache, data gets moved - -into cache when it is used for the first time. But many caches use some - -kind of “prefetching”, meaning that data is loaded before it is explicitly - -requested. We have already seen one form of prefetching: loading an - -entire block when only part of it is requested. - -ˆ - -Where in the cache does the data go? When the cache is full, we can’t - -bring anything in without kicking something out. Ideally, we want to - -keep data that will be used again soon and replace data that won’t. - -The answers to these questions make up the “cache policy”. Near the top of - -the hierarchy, cache policies tend to be simple because they have to be fast - -and they are implemented in hardware. Near the bottom of the hierarchy, - -there is more time to make decisions, and well-designed policies can make a - -big difference. - -Most cache policies are based on the principle that history repeats itself; if we - -have information about the recent past, we can use it to predict the immediate - -future. For example, if a block of data has been used recently, we expect it to - -be used again soon. This principle suggests a replacement policy called “least - -recently used,” or LRU, which removes from the cache a block of data that has - -not been used recently. For more on this topic, see - -http://en.wikipedia. - -org/wiki/Cache_algorithms - -. - -## 7.8 Paging - -In systems with virtual memory, the operating system can move pages back - -and forth between memory and storage. As I mentioned in Section 6.2, this - -mechanism is called “paging” or sometimes “swapping”. - -Here’s how the process works: - - - ---- - -7.8. Paging 55 - -1. - -Suppose Process A calls - -malloc - -to allocate a chunk. If there is no free - -space in the heap with the requested size, - -malloc - -calls - -sbrk - -to ask the - -operating system for more memory. - -2. - -If there is a free page in physical memory, the operating system adds it - -to the page table for Process A, creating a new range of valid virtual - -addresses. - -3. - -If there are no free pages, the paging system chooses a “victim page” - -belonging to Process B. It copies the contents of the victim page from - -memory to disk, then it modifies the page table for Process B to indicate - -that this page is “swapped out”. - -4. - -Once the data from Process B is written, the page can be reallocated - -to Process A. To prevent Process A from reading Process B’s data, the - -page should be cleared. - -5. - -At this point the call to - -sbrk - -can return, giving - -malloc - -additional space - -in the heap. Then - -malloc - -allocates the requested chunk and returns. - -Process A can resume. - -6. - -When Process A completes, or is interrupted, the scheduler might allow - -Process B to resume. When Process B accesses a page that has been - -swapped out, the memory management unit notices that the page is - -“invalid” and causes an interrupt. - -7. - -When the operating system handles the interrupt, it sees that the page - -is swapped out, so it transfers the page back from disk to memory. - -8. - -Once the page is swapped in, Process B can resume. - -When paging works well, it can greatly improve the utilization of physical - -memory, allowing more processes to run in less space. Here’s why: - -ˆ - -Most processes don’t use all of their allocated memory. Many parts of - -the text segment are never executed, or execute once and never again. - -Those pages can be swapped out without causing any problems. - -ˆ - -If a program leaks memory, it might leave allocated space behind and - -never access it again. By swapping those pages out, the operating system - -can effectively plug the leak. - -ˆ - -On most systems, there are processes like daemons that sit idle most of - -the time and only occasionally “wake up” to respond to events. While - -they are idle, these processes can be swapped out. - - - ---- - -56 Chapter 7. Caching - -ˆ - -A user might have many windows open, but only a few are active at a - -time. The inactive processes can be swapped out. - -ˆ - -Also, there might be many processes running the same program. These - -processes can share the same text and static segments, avoiding the need - -to keep multiple copies in physical memory. - -If you add up the total memory allocated to all processes, it can greatly exceed - -the size of physical memory, and yet the system can still behave well. - -Up to a point. - -When a process accesses a page that’s swapped out, it has to get the data back - -from disk, which can take several milliseconds. The delay is often noticeable. - -If you leave a window idle for a long time and then switch back to it, it - -might start slowly, and you might hear the disk drive working while pages are - -swapped in. - -Occasional delays like that might be acceptable, but if you have too many - -processes using too much space, they start to interfere with each other. When - -Process A runs, it evicts the pages Process B needs. Then when B runs, it - -evicts the pages A needs. When this happens, both processes slow to a crawl - -and the system can become unresponsive. This scenario is called “thrashing”. - -In theory, operating systems could avoid thrashing by detecting an increase in - -paging and blocking or killing processes until the system is responsive again. - -But as far as I can tell, most systems don’t do this, or don’t do it well; it is - -often left to users to limit their use of physical memory or try to recover when - -thrashing occurs. - - - ---- - -## Chapter 8 - -## Multitasking - -In many current systems, the CPU contains multiple cores, which means it can - -run several processes at the same time. In addition, each core is capable of - -“multitasking”, which means it can switch from one process to another quickly, - -creating the illusion that many processes are running at the same time. - -The part of the operating system that implements multitasking is the “kernel”. - -In a nut or seed, the kernel is the innermost part, surrounded by a shell. In - -an operating system, the kernel is the lowest level of software, surrounded by - -several other layers, including an interface called a “shell.” Computer scientists - -love extended metaphors. - -At its most basic, the kernel’s job is to handle interrupts. An “interrupt” is an - -event that stops the normal instruction cycle and causes the flow of execution - -to jump to a special section of code called an “interrupt handler”. - -A - -hardware interrupt - -is caused when a device sends a signal to the CPU. - -For example, a network interface might cause an interrupt when a packet of - -data arrives, or a disk drive might cause an interrupt when a data transfer - -is complete. Most systems also have timers that cause interrupts at regular - -intervals, or after an elapsed time. - -A - -software interrupt - -is caused by a running program. For example, if an - -instruction cannot complete for some reason, it might trigger an interrupt so - -the condition can be handled by the operating system. Some floating-point - -errors, like division by zero, are handled using interrupts. - -When a program needs to access a hardware device, it makes a - -system call - -, - -which is similar to a function call, except that instead of jumping to the - -beginning of the function, it executes a special instruction that triggers an - - - ---- - -58 Chapter 8. Multitasking - -interrupt, causing the flow of execution to jump to the kernel. The kernel - -reads the parameters of the system call, performs the requested operation, - -and then resumes the interrupted process. - -## 8.1 Hardware state - -Handling interrupts requires cooperation between hardware and software. - -When an interrupt occurs, there might be several instructions running on - -the CPU, data stored in registers, and other - -hardware state - -. - -Usually the hardware is responsible for bringing the CPU to a consistent state; - -for example, every instruction should either complete or behave as if it never - -started. No instruction should be left half complete. Also, the hardware is - -responsible for saving the program counter (PC), so the kernel knows where - -to resume. - -Then, usually, it is the responsibility of the interrupt handler to save the rest - -of the hardware state before it does anything that might modify it, and then - -restore the saved state before the interrupted process resumes. - -Here is an outline of this sequence of events: - -1. - -When the interrupt occurs, the hardware saves the program counter in - -a special register and jumps to the appropriate interrupt handler. - -2. - -The interrupt handler stores the program counter and the status register - -in memory, along with the contents of any data registers it plans to use. - -3. - -The interrupt handler runs whatever code is needed to handle the inter - -rupt. - -4. - -Then it restores the contents of the saved registers. Finally, it restores - -the program counter of the interrupted process, which has the effect of - -jumping back to the interrupted instruction. - -If this mechanism works correctly, there is generally no way for the interrupted - -process to know there was an interrupt, unless it detects the change in time - -between instructions. - -## 8.2 Context switching - -Interrupt handlers can be fast because they don’t have to save the entire - -hardware state; they only have to save registers they are planning to use. - - - ---- - -8.3. The process life cycle 59 - -But when an interrupt occurs, the kernel does not always resume the inter - -rupted process. It has the option of switching to another process. This mech - -anism is called a “context switch”. - -In general, the kernel doesn’t know which registers a process will use, so it has - -to save all of them. Also, when it switches to a new process, it might have - -to clear data stored in the memory management unit (see Section 3.6). And - -after the context switch, it might take some time for the new process to load - -data into the cache. For these reasons, context switches are relatively slow, on - -the order of thousands of cycles, or a few microseconds. - -In a multi-tasking system, each process is allowed to run for a short period of - -time called a “time slice” or “quantum”. During a context switch, the kernel - -sets a hardware timer that causes an interrupt at the end of the time slice. - -When the interrupt occurs, the kernel can switch to another process or allow - -the interrupted process to resume. The part of the operating system that - -makes this decision is the “scheduler”. - -## 8.3 The process life cycle - -When a process is created, the operating system allocates a data structure - -that contains information about the process, called a “process control block” - -or PCB. Among other things, the PCB keeps track of the process state, which - -is one of: - -ˆ - -Running, if the process is currently running on a core. - -ˆ - -Ready, if the process could be running, but isn’t, usually because there - -are more runnable processes than cores. - -ˆ - -Blocked, if the process cannot run because it is waiting for a future event - -like network communication or a disk read. - -ˆ - -Done, if the process has completed, but has exit status information that - -has not been read yet. - -Here are the events that cause a process to transition from one state to another: - -ˆ - -A process is created when the running program executes a system call - -like - -fork - -. At the end of the system call, the new process is usually ready. - -Then the scheduler might resume the original process (the “parent”) or - -start the new process (the “child”). - - - ---- - -60 Chapter 8. Multitasking - -ˆ - -When a process is started or resumed by the scheduler, its state changes - -from ready to running. - -ˆ - -When a process is interrupted and the scheduler chooses not to let it - -resume, its state changes from running to ready. - -ˆ - -If a process executes a system call that cannot complete immediately, - -like a disk request, it becomes blocked and the scheduler usually chooses - -another process. - -ˆ - -When an operation like a disk request completes, it causes an interrupt. - -The interrupt handler figures out which process was waiting for the re - -quest and switches its state from blocked to ready. Then the scheduler - -may or may not choose to resume the unblocked process. - -ˆ - -When a process calls - -exit - -, the interrupt handler stores the exit code in - -the PCB and changes the process’s state to done. - -## 8.4 Scheduling - -As we saw in Section 2.3 there might be hundreds of processes on a computer, - -but usually most of them are blocked. Most of the time, there are only a few - -processes that are ready or running. When an interrupt occurs, the scheduler - -decides which process to start or resume. - -On a workstation or laptop, the primary goal of the scheduler is to minimize - -response time; that is, the computer should respond quickly to user actions. - -Response time is also important on a server, but in addition the scheduler - -might try to maximize throughput, which is the number of requests that com - -plete per unit of time. - -Usually the scheduler doesn’t have much information about what processes - -are doing, so its decisions are based on a few heuristics: - -ˆ - -Processes might be limited by different resources. A process that does - -a lot of computation is probably CPU-bound, which means that its run - -time depends on how much CPU time it gets. A process that reads data - -from a network or disk might be I/O-bound, which means that it would - -run faster if data input and output went faster, but would not run faster - -with more CPU time. Finally, a process that interacts with the user is - -probably blocked, most of the time, waiting for user actions. - -The operating system can sometimes classify processes based on their - -past behavior, and schedule them accordingly. For example, when an - - - ---- - -8.4. Scheduling 61 - -interactive process is unblocked, it should probably run immediately, - -because a user is probably waiting for a reply. On the other hand, a - -CPU-bound process that has been running for a long time might be less - -time-sensitive. - -ˆ - -If a process is likely to run for a short time and then make a blocking - -request, it should probably run immediately, for two reasons: (1) if the - -request takes some time to complete, we should start it as soon as pos - -sible, and (2) it is better for a long-running process to wait for a short - -one, rather than the other way around. - -As an analogy, suppose you are making an apple pie. The crust takes - -5 minutes to prepare, but then it has to chill for half an hour. It takes - -20 minutes to prepare the filling. If you prepare the crust first, you can - -prepare the filling while the crust is chilling, and you can finish the pie in - -35 minutes. If you prepare the filling first, the process takes 55 minutes. - -Most schedulers use some form of priority-based scheduling, where each process - -has a priority that can be adjusted up or down over time. When the scheduler - -runs, it chooses the runnable process with the highest priority. - -Here are some of the factors that determine a process’s priority: - -ˆ - -A process usually starts with a relatively high priority so it starts running - -quickly. - -ˆ - -If a process makes a request and blocks before its time slice is complete, - -it is more likely to be interactive or I/O-bound, so its priority should go - -up. - -ˆ - -If a process runs for an entire time slice, it is more likely to be long - -running and CPU-bound, so its priority should go down. - -ˆ - -If a task blocks for a long time and then becomes ready, it should get a - -priority boost so it can respond to whatever it was waiting for. - -ˆ - -If process A is blocked waiting for process B, for example if they are - -connected by a pipe, the priority of process B should go up. - -ˆ - -The system call - -nice - -allows a process to decrease (but not increase) its - -own priority, allowing programmers to pass explicit information to the - -scheduler. - -For most systems running normal workloads, scheduling algorithms don’t have - -a substantial effect on performance. Simple scheduling policies are usually - -good enough. - - - ---- - -62 Chapter 8. Multitasking - -## 8.5 Real-time scheduling - -However, for programs that interact with the real world, scheduling can be - -very important. For example, a program that reads data from sensors and - -controls motors might have to complete recurring tasks at some minimum fre - -quency and react to external events with some maximum response time. These - -requirements are often expressed in terms of “tasks” that must be completed - -before “deadlines”. - -Scheduling tasks to meet deadlines is called “real-time scheduling”. For some - -applications, a general-purpose operating system like Linux can be modified - -to handle real-time scheduling. These modifications might include: - -ˆ - -Providing richer APIs for controlling task priorities. - -ˆ - -Modifying the scheduler to guarantee that the process with highest pri - -ority runs within a fixed amount of time. - -ˆ - -Reorganizing interrupt handlers to guarantee a maximum completion - -time. - -ˆ - -Modifying locks and other synchronization mechanisms (coming up in - -the next chapter) to allow a high-priority task to preempt a lower-priority - -task. - -ˆ - -Choosing an implementation of dynamic memory allocation that guar - -antees a maximum completion time. - -For more demanding applications, especially in domains where real-time re - -sponse is a matter of life and death, “real-time operating systems” provide - -specialized capabilities, often with much simpler designs than general purpose - -operating systems. - - - ---- - -## Chapter 9 - -## Threads - -When I mentioned threads in Section 2.3, I said that a thread is a kind of - -process. Now I will provide a more careful explanation. - -When you create a process, the operating system creates a new address space, - -which includes the text segment, static segment, and heap; it also creates - -a new “thread of execution”, which includes the program counter and other - -hardware state, and the call stack. - -The processes we have seen so far are “single-threaded”, which means that only - -one thread of execution runs in each address space. In this chapter, you will - -learn about “multi-threaded” processes that have multiple threads running in - -the same address space. - -Within a single process, all threads share the same text segment, so they run - -the same code. But different threads often run different parts of the code. - -And they share the same static segment, so if one thread changes a global - -variable, other threads see the change. They also share the heap, so threads - -can share dynamically-allocated chunks. - -But each thread has its own stack, so threads can call functions without inter - -fering with each other. Usually threads don’t access each other’s local variables - -(and sometimes they can’t). - -The example code for this chapter is in the repository for this book, in a - -directory named - -counter - -. For information on downloading this code, see - -Section 0.1. - - - ---- - -64 Chapter 9. Threads - -## 9.1 Creating threads - -The most popular threading standard used with C is POSIX Threads, or - -Pthreads for short. The POSIX standard defines a thread model and an - -interface for creating and controlling threads. Most versions of UNIX provide - -an implementation of Pthreads. - -Using Pthreads is like using most C libraries: - -ˆ - -You include headers files at the beginning of your program. - -ˆ - -You write code that calls functions defined by Pthreads. - -ˆ - -When you compile the program, you link it with the Pthread library. - -For my examples, I include the following headers: - -#include - -#include - -#include - -#include - -The first two are standard; the third is for Pthreads and the fourth is for - -semaphores. To compile with the Pthread library in - -gcc - -, you can use the - --l - -option on the command line: - -gcc -g -O2 -o array array.c -lpthread - -This compiles a source file named - -array.c - -with debugging info and opti - -mization, links with the Pthread library, and generates an executable named - -array - -. - -## 9.2 Creating threads - -The Pthread function that creates threads is called - -pthread_create - -. The - -following function shows how to use it: - -pthread_t make_thread(void *(*entry)(void *), Shared *shared) - -{ - -int n; - -pthread_t thread; - -n = pthread_create(&thread, NULL, entry, (void *)shared); - -if (n != 0) { - -perror("pthread_create failed"); - - - ---- - -9.2. Creating threads 65 - -exit(-1); - -} - -return thread; - -} - -make_thread - -is a wrapper I wrote to make - -pthread_create - -easier to use, and - -to provide error-checking. - -The return type from - -pthread_create - -is - -pthread_t - -, which you can think of - -as an id or “handle” for the new thread. - -If - -pthread - -create - -succeeds, it returns 0 and - -make_thread - -returns the handle - -of the new thread. If an error occurs, - -pthread - -create - -returns an error code - -and - -make_thread - -prints an error message and exits. - -The parameters of - -make_thread - -take some explaining. Starting with the sec - -ond, - -Shared - -is a structure I defined to contain values shared between threads. - -The following - -typedef - -statement creates the new type: - -typedef struct { - -int counter; - -} Shared; - -In this case, the only shared variable is - -counter - -. - -make - -shared - -allocates space - -for a - -Shared - -structure and initializes the contents: - -Shared *make_shared() - -{ - -Shared *shared = check_malloc(sizeof (Shared)); - -shared->counter = 0; - -return shared; - -} - -Now that we have a shared data structure, let’s get back to - -make_thread - -. - -The first parameter is a pointer to a function that takes a - -void - -pointer and - -returns a - -void - -pointer. If the syntax for declaring this type makes your eyes - -bleed, you are not alone. Anyway, the purpose of this parameter is to specify - -the function where the execution of the new thread will begin. By convention, - -this function is named - -entry - -: - -void *entry(void *arg) - -{ - -Shared *shared = (Shared *) arg; - -child_code(shared); - -pthread_exit(NULL); - -} - - - ---- - -66 Chapter 9. Threads - -The parameter of - -entry - -has to be declared as a - -void - -pointer, but in this - -program we know that it is really a pointer to a - -Shared - -structure, so we can - -typecast it accordingly and then pass it along to - -child - -code - -, which does the - -real work. - -As a simple example, - -child_code - -prints the value of the shared counter and - -increments it. - -void child_code(Shared *shared) - -{ - -printf("counter = %d\n", shared->counter); - -shared->counter++; - -} - -When - -child - -code - -returns, - -entry - -invokes - -pthread_exit - -which can be used to - -pass a value to the thread that joins with this thread. In this case, the child - -has nothing to say, so we pass - -NULL - -. - -Finally, here is the code that creates the child threads: - -int i; - -pthread_t child[NUM_CHILDREN]; - -Shared *shared = make_shared(1000000); - -for (i=0; imutex); - -printf("counter = %d\n", shared->counter); - -shared->counter++; - -mutex_unlock(shared->mutex); - -} - -Before any thread can access - -counter - -, it has to “lock” the mutex, which - -has the effect of barring all other threads. Suppose Thread A has locked the - -mutex and is in the middle of - -child_code - -. If Thread B arrives and executes - -mutex_lock - -, it blocks. - -When Thread A is done, it executes - -mutex_unlock - -, which allows Thread B to - -proceed. In effect, the threads line up to execute - -child_code - -one at a time, - - - ---- - -9.5. Mutex 69 - -so they can’t interfere with each other. When I run this code with 5 children, - -I get: - -counter = 0 - -counter = 1 - -counter = 2 - -counter = 3 - -counter = 4 - -And that satisfies the requirements. In order for this solution to work, I have - -to add the Mutex to the Shared struct: - -typedef struct { - -int counter; - -Mutex *mutex; - -} Shared; - -And initialize it in - -make_shared - -Shared *make_shared(int end) - -{ - -Shared *shared = check_malloc(sizeof(Shared)); - -shared->counter = 0; - -shared->mutex = make_mutex(); //-- this line is new - -return shared; - -} - -The code in this section is in - -counter_mutex.c - -. The definition of - -Mutex - -is in - -mutex.c - -, which I explain in the next section. - -## 9.5 Mutex - -My definition of - -Mutex - -is a wrapper for a type called - -pthread_mutex_t - -, which - -is defined in the POSIX threads API. - -To create a POSIX mutex, you have to allocate space for a - -pthread_mutex_t - -type and then call - -pthread_mutex_init - -. - -One of the problems with this API is that - -pthread_mutex_t - -behaves like a - -structure, so if you pass it as an argument, it makes a copy, which makes the - -mutex behave incorrectly. To avoid that, you have to pass - -pthread_mutex_t - -by address. - -My code makes it easier to get that right. It defines a type, - -Mutex - -, which is - -just a more readable name for - -pthread_mutex_t - -: - - - ---- - -70 Chapter 9. Threads - -#include - -typedef pthread_mutex_t Mutex; - -Then it defines - -make_mutex - -, which allocates space and initializes the mutex: - -Mutex *make_mutex() - -{ - -Mutex *mutex = check_malloc(sizeof(Mutex)); - -int n = pthread_mutex_init(mutex, NULL); - -if (n != 0) perror_exit("make_lock failed"); - -return mutex; - -} - -The return value is a pointer, which you can pass around as an argument - -without causing unwanted copying. - -The functions to lock and unlock the mutex are simple wrappers for POSIX - -functions: - -void mutex_lock(Mutex *mutex) - -{ - -int n = pthread_mutex_lock(mutex); - -if (n != 0) perror_exit("lock failed"); - -} - -void mutex_unlock(Mutex *mutex) - -{ - -int n = pthread_mutex_unlock(mutex); - -if (n != 0) perror_exit("unlock failed"); - -} - -This code is in - -mutex.c - -and the header file - -mutex.h - -. - - - ---- - -## Chapter 10 - -## Condition variables - -Many simple synchronization problems can be solved using mutexes as shown - -in the previous chapter. In this chapter I introduce a bigger challenge, the - -well-known “Producer-Consumer problem”, and a new tool to solve it, the - -condition variable. - -## 10.1 The work queue - -In some multi-threaded programs, threads are organized to perform different - -tasks. Often they communicate with each other using a queue, where some - -threads, called “producers”, put data into the queue and other threads, called - -“consumers”, take data out. - -For example, in applications with a graphical user interface, there might be - -one thread that runs the GUI, responding to user events, and another thread - -that processes user requests. In that case, the GUI thread might put requests - -into a queue and the “back end” thread might take requests out and process - -them. - -To support this organization, we need a queue implementation that is “thread - -safe”, which means that both threads (or more than two) can access the queue - -at the same time. And we need to handle the special cases when the queue is - -empty and, if the size of the queue is bounded, when the queue is full. - -I’ll start with a simple queue that is not thread safe, then we’ll see what goes - -wrong and fix it. The code for this example is in the repository for this book, - -in a folder called - -queue - -. The file - -queue.c - -contains a basic implementation of - -a circular buffer, which you can read about at - -https://en.wikipedia.org/ - -wiki/Circular_buffer - -. - - - ---- - -72 Chapter 10. Condition variables - -Here’s the structure definition: - -typedef struct { - -int *array; - -int length; - -int next_in; - -int next_out; - -} Queue; - -array - -is the array that contains the elements of the queue. For this example - -the elements are ints, but more generally they would be structures that contain - -user events, items of work, etc. - -length - -is the length of the array. - -next_in - -is an index into the array that - -indices where the next element should be added; similarly, - -next_out - -is the - -index of the next element that should be removed. - -make_queue - -allocates space for this structure and initializes the fields: - -Queue *make_queue(int length) - -{ - -Queue *queue = (Queue *) malloc(sizeof(Queue)); - -queue->length = length + 1; - -queue->array = (int *) malloc(length * sizeof(int)); - -queue->next_in = 0; - -queue->next_out = 0; - -return queue; - -} - -The initial value for - -next_out - -needs some explaining. Since the queue is - -initially empty, there is no next element to remove, so - -next_out - -is invalid. - -Setting - -next_out == next_in - -is a special case that indicates that the queue - -is empty, so we can write: - -int queue_empty(Queue *queue) - -{ - -return (queue->next_in == queue->next_out); - -} - -Now we can add elements to the queue using - -queue_push - -: - -void queue_push(Queue *queue, int item) { - -if (queue_full(queue)) { - -perror_exit("queue is full"); - -} - -queue->array[queue->next_in] = item; - - - ---- - -10.1. The work queue 73 - -queue->next_in = queue_incr(queue, queue->next_in); - -} - -If the queue is full, - -queue_push - -prints an error message and exits. I will - -explain - -queue_full - -soon. - -If the queue is not full, - -queue_push - -inserts the new element and then incre - -ments - -next_in - -using - -queue_incr - -: - -int queue_incr(Queue *queue, int i) - -{ - -return (i+1) % queue->length; - -} - -When the index, - -i - -, gets to the end of the array, it wraps around to 0. And - -that’s where we run into a tricky part. If we keep adding elements to the - -queue, eventually - -next_in - -wraps around and catches up with - -next_out - -. But - -if - -next_in == next_out - -, we would incorrectly conclude that the queue was - -empty. - -To avoid that, we define another special case to indicate that the queue is full: - -int queue_full(Queue *queue) - -{ - -return (queue_incr(queue, queue->next_in) == queue->next_out); - -} - -If incrementing - -next_in - -lands on - -next_out - -, that means we can’t add another - -element without making the queue seem empty. So we stop one element before - -the “end” (keeping in mind that the end of the queue can be anywhere, not - -necessarily the end of the array). - -Now we can write - -queue_pop - -, which removes and returns the next element - -from the queue: - -int queue_pop(Queue *queue) { - -if (queue_empty(queue)) { - -perror_exit("queue is empty"); - -} - -int item = queue->array[queue->next_out]; - -queue->next_out = queue_incr(queue, queue->next_out); - -return item; - -} - -If you try to pop from an empty queue, - -queue_pop - -prints an error message - -and exits. - - - ---- - -74 Chapter 10. Condition variables - -## 10.2 Producers and consumers - -Now let’s make some threads to access this queue. Here’s the producer code: - -void *producer_entry(void *arg) { - -Shared *shared = (Shared *) arg; - -for (int i=0; iqueue, i); - -} - -pthread_exit(NULL); - -} - -Here’s the consumer code: - -void *consumer_entry(void *arg) { - -int item; - -Shared *shared = (Shared *) arg; - -for (int i=0; iqueue); - -printf("consuming item %d\n", item); - -} - -pthread_exit(NULL); - -} - -Here’s the parent code that starts the threads and waits for them - -pthread_t child[NUM_CHILDREN]; - -Shared *shared = make_shared(); - -child[0] = make_thread(producer_entry, shared); - -child[1] = make_thread(consumer_entry, shared); - -for (int i=0; iqueue = make_queue(QUEUE_LENGTH); - -return shared; - -} - -The code we have so far is a good starting place, but it has several problems: - -ˆ - -Access to the queue is not thread safe. Different threads could access - -array - -, - -next_in - -, and - -next_out - -at the same time and leave the queue in - -a broken, “inconsistent” state. - -ˆ - -If the consumer is scheduled first, it finds the queue empty, print an error - -message, and exits. We would rather have the consumer block until the - -queue is not empty. Similarly, we would like the producer to block if the - -queue is full. - -In the next section, we solve the first problem with a - -Mutex - -. In the following - -section, we solve the second problem with condition variables. - -## 10.3 Mutual exclusion - -We can make the queue thread safe with a mutex. This version of the code is - -in - -queue_mutex.c - -. - -First we add a - -Mutex - -pointer to the queue structure: - -typedef struct { - -int *array; - -int length; - -int next_in; - -int next_out; - -Mutex *mutex; //-- this line is new - -} Queue; - -And initialize the - -Mutex - -in - -make_queue - -: - -Queue *make_queue(int length) { - -Queue *queue = (Queue *) malloc(sizeof(Queue)); - -queue->length = length; - -queue->array = (int *) malloc(length * sizeof(int)); - -queue->next_in = 0; - -queue->next_out = 0; - -queue->mutex = make_mutex(); //-- new - -return queue; - -} - - - ---- - -76 Chapter 10. Condition variables - -Next we add synchronization code to - -queue_push - -: - -void queue_push(Queue *queue, int item) { - -mutex_lock(queue->mutex); //-- new - -if (queue_full(queue)) { - -mutex_unlock(queue->mutex); //-- new - -perror_exit("queue is full"); - -} - -queue->array[queue->next_in] = item; - -queue->next_in = queue_incr(queue, queue->next_in); - -mutex_unlock(queue->mutex); //-- new - -} - -Before checking whether the queue is full, we have to lock the - -Mutex - -. If the - -queue is full, we have to unlock the - -Mutex - -before exiting; otherwise the thread - -would leave it locked and no other threads could proceed. - -The synchronization code for - -queue_pop - -is similar: - -int queue_pop(Queue *queue) { - -mutex_lock(queue->mutex); - -if (queue_empty(queue)) { - -mutex_unlock(queue->mutex); - -perror_exit("queue is empty"); - -} - -int item = queue->array[queue->next_out]; - -queue->next_out = queue_incr(queue, queue->next_out); - -mutex_unlock(queue->mutex); - -return item; - -} - -Note that the other - -Queue - -functions, - -queue_full - -, - -queue_empty - -, and - -queue_incr - -do not try to lock the mutex. Any thread that calls these functions - -is required to lock the mutex first; this requirement is part of the documented - -interface for these functions. - -With this additional code, the queue is thread safe; if you run it, you should - -not see any synchronization errors. But it is likely that the consumer will exit - -at some point because the queue is empty, or the producer will exit because - -the queue is full, or both. - -The next step is to add condition variables. - - - ---- - -10.4. Condition variables 77 - -## 10.4 Condition variables - -A condition variable is a data structure associated with a condition; it allows - -threads to block until the condition becomes true. For example, - -thread_pop - -might want check whether the queue is empty and, if so, wait for a condition - -like “queue not empty”. - -Similarly, - -thread_push - -might want to check whether the queue is full and, if - -so, block until it is not full. - -I’ll handle the first condition here, and you will have a chance to handle the - -second condition as an exercise. - -First we add a condition variable to the - -Queue - -structure: - -typedef struct { - -int *array; - -int length; - -int next_in; - -int next_out; - -Mutex *mutex; - -Cond *nonempty; //-- new - -} Queue; - -And initialize it in - -make_queue - -: - -Queue *make_queue(int length) - -{ - -Queue *queue = (Queue *) malloc(sizeof(Queue)); - -queue->length = length; - -queue->array = (int *) malloc(length * sizeof(int)); - -queue->next_in = 0; - -queue->next_out = 0; - -queue->mutex = make_mutex(); - -queue->nonempty = make_cond(); //-- new - -return queue; - -} - -Now in - -queue_pop - -, if we find the queue empty, we don’t exit; instead we use - -the condition variable to block: - -int queue_pop(Queue *queue) { - -mutex_lock(queue->mutex); - -while (queue_empty(queue)) { - -cond_wait(queue->nonempty, queue->mutex); //-- new - -} - - - ---- - -78 Chapter 10. Condition variables - -int item = queue->array[queue->next_out]; - -queue->next_out = queue_incr(queue, queue->next_out); - -mutex_unlock(queue->mutex); - -cond_signal(queue->nonfull); //-- new - -return item; - -} - -cond_wait - -is complicated, so let’s take it slow. The first argument is the - -condition variable; in this case, the condition we are waiting for is “queue not - -empty”. The second argument is the mutex that protects the queue. - -When the thread that locked the mutex calls - -cond_wait - -, it unlocks the mutex - -and then blocks. This is important. If - -cond_wait - -did not unlock the mutex - -before blocking, no other thread would be able to access the queue, no more - -items could be added, and the queue would always be empty. - -So while the consumer is blocked on - -nonempty - -, the producer can run. Let’s - -see what happens when the producer runs - -queue_push - -: - -void queue_push(Queue *queue, int item) { - -mutex_lock(queue->mutex); - -if (queue_full(queue)) { - -mutex_unlock(queue->mutex); - -perror_exit("queue is full"); - -} - -queue->array[queue->next_in] = item; - -queue->next_in = queue_incr(queue, queue->next_in); - -mutex_unlock(queue->mutex); - -cond_signal(queue->nonempty); //-- new - -} - -Just as before, - -queue_push - -locks the - -Mutex - -and checks whether the queue is - -full. Assuming it is not, - -queue_push - -adds a new element to the queue and - -then unlocks the - -Mutex - -. - -But before returning, it does one more thing: it “signals” the condition variable - -nonempty - -. - -Signalling a condition variable usually indicates that the condition is true. If - -there are no threads waiting on the condition variable, the signal has no effect. - -If there are threads waiting on the condition variable, one of them gets un - -blocked and resumes execution of - -cond_wait - -. But before the awakened thread - -can return from - -cond_wait - -, it has to wait for and lock the - -Mutex - -, again. - -Now go back to - -queue_pop - -and see what happens when the thread returns - -from - -cond_wait - -. It loops back to the top of the while loop and checks the - - - ---- - -10.4. Condition variables 79 - -condition again. I’ll explain why in just a second, but for now let’s assume - -that the condition is true; that is, the queue is not empty. - -When the consumer thread exits the while loop, we know two things: (1) the - -condition is true, so there is at least one item in the queue, and (2) the - -Mutex - -is locked, so it is safe to access the queue. - -After removing an item, - -queue_pop - -unlocks the mutex and returns. - -In the next section I’ll show you how my - -Cond - -code works, but first I want to - -answer two frequently-asked questions: - -ˆ - -Why is - -cond_wait - -inside a while loop rather than an if statement; that - -is, why do we have to check the condition again after returning from - -cond_wait - -? - -The primary reason you have to re-check the condition is the possibility - -of an intercepted signal. Suppose Thread A is waiting on - -nonempty - -. - -Thread B adds an item to the queue and signals - -nonempty - -. Thread A - -wakes up an tries to lock the mutex, but before it gets the chance, Evil - -Thread C swoops in, locks the mutex, pops the item from the queue, - -and unlocks the mutex. Now the queue is empty again, but Thread A is - -not blocked any more. Thread A could lock the mutex and returns from - -cond_wait - -. If Thread A does not check the condition again, it would try - -to pop an element from an empty queue, and probably cause an error. - -ˆ - -The other question that comes up when people learn about condition - -variables is “How does the condition variable know what condition it is - -associated with?” - -This question is understandable because there is no explicit connection - -between a - -Cond - -structure and the condition it relates to. The connection - -is implicit in the way it is used. - -Here’s one way to think of it: the condition associated with a Cond is - -the thing that is false when you call - -cond_wait - -and true when you call - -cond_signal - -. - -Because threads have to check the condition when they return from - -cond_wait - -, - -it is not strictly necessary to call - -cond_signal - -only when the condition is - -true. If you have reason to think the condition - -might - -be true, you could call - -cond_signal - -as a suggestion that now is a good time to check. - - - ---- - -80 Chapter 10. Condition variables - -## 10.5 Condition variable implementation - -The Cond structure I used in the previous section is a wrapper for a type - -called - -pthread_cond_t - -, which is defined in the POSIX threads API. It is very - -similar to Mutex, which is a wrapper for - -pthread_mutex_t - -. Both wrappers - -are defined in - -utils.c - -and - -utils.h - -. - -Here’s the typedef: - -typedef pthread_cond_t Cond; - -make_cond - -allocates space, initializes the condition variable, and returns a - -pointer: - -Cond *make_cond() { - -Cond *cond = check_malloc(sizeof(Cond)); - -int n = pthread_cond_init(cond, NULL); - -if (n != 0) perror_exit("make_cond failed"); - -return cond; - -} - -And here are the wrappers for - -cond_wait - -and - -cond_signal - -. - -void cond_wait(Cond *cond, Mutex *mutex) { - -int n = pthread_cond_wait(cond, mutex); - -if (n != 0) perror_exit("cond_wait failed"); - -} - -void cond_signal(Cond *cond) { - -int n = pthread_cond_signal(cond); - -if (n != 0) perror_exit("cond_signal failed"); - -} - -At this point there should be nothing too surprising there. - - - ---- - -## Chapter 11 - -## Semaphores in C - -Semaphores are a good way to learn about synchronization, but they are not - -as widely used, in practice, as mutexes and condition variables. - -Nevertheless, there are some synchronization problems that can be solved sim - -ply with semaphores, yielding solutions that are more demonstrably correct. - -This chapter presents a C API for working with semaphores and my code for - -making it easier to work with. And it presents a final challenge: can you write - -an implementation of a semaphore using mutexes and condition variables? - -The code for this chapter is in directory - -semaphore - -in the repository for this - -book (see Section 0.1). - -## 11.1 POSIX Semaphores - -A semaphore is a data structure used to help threads work together without - -interfering with each other. - -The POSIX standard specifies an interface for semaphores; it is not part of - -Pthreads, but most UNIXes that implement Pthreads also provide semaphores. - -POSIX semaphores have type - -sem - -t - -. As usual, I put a wrapper around - -sem - -t - -to make it easier to use. The interface is defined in - -sem.h - -: - -typedef sem_t Semaphore; - -Semaphore *make_semaphore(int value); - -void semaphore_wait(Semaphore *sem); - -void semaphore_signal(Semaphore *sem); - - - ---- - -82 Chapter 11. Semaphores in C - -Semaphore - -is a synonym for - -sem_t - -, but I find it more readable, and the capital - -letter reminds me to treat it like an object and pass it by pointer. - -The implementation of these functions is in - -sem.c - -: - -Semaphore *make_semaphore(int value) - -{ - -Semaphore *sem = check_malloc(sizeof(Semaphore)); - -int n = sem_init(sem, 0, value); - -if (n != 0) perror_exit("sem_init failed"); - -return sem; - -} - -make - -semaphore - -takes the initial value of the semaphore as a parameter. - -It allocates space for a Semaphore, initializes it, and returns a pointer to - -Semaphore - -. - -sem - -init - -returns 0 if it succeeds and -1 if anything goes wrong. One nice thing - -about using wrapper functions is that you can encapsulate the error-checking - -code, which makes the code that uses these functions more readable. - -Here is the implementation of - -semaphore_wait - -: - -void semaphore_wait(Semaphore *sem) - -{ - -int n = sem_wait(sem); - -if (n != 0) perror_exit("sem_wait failed"); - -} - -And here is - -semaphore_signal - -: - -void semaphore_signal(Semaphore *sem) - -{ - -int n = sem_post(sem); - -if (n != 0) perror_exit("sem_post failed"); - -} - -I prefer to call this operation “signal” rather than “post”, although both terms - -are common. - -Here’s an example that shows how to use a semaphore as a mutex: - -Semaphore *mutex = make_semaphore(1); - -semaphore_wait(mutex); - -// protected code goes here - -semaphore_signal(mutex); - - - ---- - -11.2. Producers and consumers with semaphores 83 - -When you use a semaphore as a mutex, you usually initialize it to 1 to indicate - -that the mutex is unlocked; that is, one thread can pass the semaphore without - -blocking. - -Here I am using the variable name - -mutex - -to indicate that the semaphore is - -being used as a mutex. But remember that the behavior of a semaphore is not - -the same as a Pthread mutex. - -## 11.2 Producers and consumers with - -## semaphores - -Using these semaphore wrapper functions, we can write a solution to the - -Producer-Consumer problem from Section 10.2. The code in this section is - -in - -queue_sem.c - -. - -Here’s the new definition of - -Queue - -, replacing the mutex and condition variables - -with semaphores: - -typedef struct { - -int *array; - -int length; - -int next_in; - -int next_out; - -Semaphore *mutex; //-- new - -Semaphore *items; //-- new - -Semaphore *spaces; //-- new - -} Queue; - -And here’s the new version of - -make_queue - -: - -Queue *make_queue(int length) - -{ - -Queue *queue = (Queue *) malloc(sizeof(Queue)); - -queue->length = length; - -queue->array = (int *) malloc(length * sizeof(int)); - -queue->next_in = 0; - -queue->next_out = 0; - -queue->mutex = make_semaphore(1); - -queue->items = make_semaphore(0); - -queue->spaces = make_semaphore(length-1); - -return queue; - -} - - - ---- - -84 Chapter 11. Semaphores in C - -mutex - -is used to guarantee exclusive access to the queue; the initial value is 1, - -so the mutex is initially unlocked. - -items - -is the number of items in the queue, which is also the number of con - -sumer threads that can execute - -queue_pop - -without blocking. Initially there - -are no items in the queue. - -spaces - -is the number of empty spaces in the queue, which is the number of - -producer threads that can execute - -queue_push - -without blocking. Initially the - -number of spaces is the capacity of the queue, which is - -length-1 - -, as explained - -in Section 10.1. - -Here is the new version of - -queue_push - -, which is run by producer threads: - -void queue_push(Queue *queue, int item) { - -semaphore_wait(queue->spaces); - -semaphore_wait(queue->mutex); - -queue->array[queue->next_in] = item; - -queue->next_in = queue_incr(queue, queue->next_in); - -semaphore_signal(queue->mutex); - -semaphore_signal(queue->items); - -} - -Notice that - -queue_push - -doesn’t have to call - -queue_full - -any more; instead, - -the semaphore keeps track of how many spaces are available and blocks pro - -ducers if the queue is full. - -Here is the new version of - -queue_pop - -: - -int queue_pop(Queue *queue) { - -semaphore_wait(queue->items); - -semaphore_wait(queue->mutex); - -int item = queue->array[queue->next_out]; - -queue->next_out = queue_incr(queue, queue->next_out); - -semaphore_signal(queue->mutex); - -semaphore_signal(queue->spaces); - -return item; - -} - -This solution is explained, using pseudo-code, in Chapter 4 of - -The Little Book - -of Semaphores - -. - - - ---- - -11.3. Make your own semaphores 85 - -Using the code in the repository for this book, you should be able to compile - -and run this solution like this: - -$ make queue_sem - -$ ./queue_sem - -## 11.3 Make your own semaphores - -Any problem that can be solved with semaphores can also be solved with - -condition variables and mutexes. We can prove that’s true by using condition - -variables and mutexes to implement a semaphore. - -Before you go on, you might want to try this as an exercise: write func - -tions that implement the semaphore API in - -sem.h - -using using condition vari - -ables and mutexes. In the repository for this book, you’ll find my solution in - -mysem_soln.c - -and - -mysem_soln.h - -. - -If you have trouble getting started, you can use the following structure defini - -tion, from my solution, as a hint: - -typedef struct { - -int value, wakeups; - -Mutex *mutex; - -Cond *cond; - -} Semaphore; - -value - -is the value of the semaphore. - -wakeups - -counts the number of pending - -signals; that is, the number of threads that have been woken but have not - -yet resumed execution. The reason for wakeups is to make sure that our - -semaphores have Property 3, described in - -The Little Book of Semaphores - -. - -mutex - -provides exclusive access to - -value - -and - -wakeups - -; - -cond - -is the condition - -variable threads wait on if they wait on the semaphore. - -Here is the initialization code for this structure: - -Semaphore *make_semaphore(int value) - -{ - -Semaphore *semaphore = check_malloc(sizeof(Semaphore)); - -semaphore->value = value; - -semaphore->wakeups = 0; - -semaphore->mutex = make_mutex(); - -semaphore->cond = make_cond(); - -return semaphore; - -} - - - ---- - -86 Chapter 11. Semaphores in C - -## 11.3.1 Semaphore implementation - -Here is my implementation of semaphores using POSIX mutexes and condition - -variables: - -void semaphore_wait(Semaphore *semaphore) - -{ - -mutex_lock(semaphore->mutex); - -semaphore->value--; - -if (semaphore->value < 0) { - -do { - -cond_wait(semaphore->cond, semaphore->mutex); - -} while (semaphore->wakeups < 1); - -semaphore->wakeups--; - -} - -mutex_unlock(semaphore->mutex); - -} - -When a thread waits on the semaphore, it has to lock the mutex before it - -decrements - -value - -. If the value of the semaphore becomes negative, the thread - -blocks until a “wakeup” is available. While it is blocked, the mutex is unlocked, - -so another thread can signal. - -Here is the code for - -semaphore_signal - -: - -void semaphore_signal(Semaphore *semaphore) - -{ - -mutex_lock(semaphore->mutex); - -semaphore->value++; - -if (semaphore->value <= 0) { - -semaphore->wakeups++; - -cond_signal(semaphore->cond); - -} - -mutex_unlock(semaphore->mutex); - -} - -Again, a thread has to lock the mutex before it increments - -value - -. If the - -semaphore was negative, that means threads are waiting, so the signalling - -thread increments - -wakeups - -and signals the condition variable. - -At this point one of the waiting threads might wake up, but the mutex is still - -locked until the signalling thread unlocks it. - -At that point, one of the waiting threads returns from - -cond_wait - -and checks - - - ---- - -11.3. Make your own semaphores 87 - -whether a wakeup is still available. If not, it loops and waits on the condition - -variable again. If so, it decrements - -wakeups - -, unlocks the mutex, and exits. - -One thing about this solution that might not be obvious is the use of a - -do...while - -loop. Can you figure out why it is not a more conventional - -while - -loop? What would go wrong? - -The problem is that with a - -while - -loop this implementation would not have - -Property 3. It would be possible for a thread to signal and then run around - -and catch its own signal. - -With the - -do...while - -loop, it is guaranteed - -1 - -that when a thread signals, one - -of the waiting threads will get the signal, even if the signalling thread runs - -around and gets the mutex before one of the waiting threads resumes. - -1 - -Well, almost. It turns out that a well-timed spurious wakeup (see - -http://en. - -wikipedia.org/wiki/Spurious_wakeup - -) can violate this guarantee. - - - ---- -