Index: ossp-pkg/pth/.cvsignore RCS File: /v/ossp/cvs/ossp-pkg/pth/.cvsignore,v rcsdiff -q -kk '-r1.21' '-r1.22' -u '/v/ossp/cvs/ossp-pkg/pth/.cvsignore,v' 2>/dev/null --- .cvsignore 2002/11/03 09:59:32 1.21 +++ .cvsignore 2006/06/12 18:02:51 1.22 @@ -39,3 +39,7 @@ test_uctx test_sig test_std +rse-pmt.aux +rse-pmt.dvi +rse-pmt.eps +rse-pmt.log Index: ossp-pkg/pth/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/pth/ChangeLog,v rcsdiff -q -kk '-r1.645' '-r1.646' -u '/v/ossp/cvs/ossp-pkg/pth/ChangeLog,v' 2>/dev/null --- ChangeLog 2006/06/08 17:56:20 1.645 +++ ChangeLog 2006/06/12 18:02:51 1.646 @@ -19,6 +19,14 @@ / __/ | |_| | __|_____(_)___/_________________________________________________________ + Changes between 2.0.7 and 2.0.9 (07-Jun-2006 to 12-Jun-2006) + + *) Added LaTeX sources of USENIX paper (rse-pmt.tex, rse-pmt.fig) + to source tree and add Makefile targets for re-generating outputs + (rse-pmt.ps, rse-pmt.pdf). This way all GNU Pth related material + is finally part of the same distribution. + [Ralf S. Engelschall] + Changes between 2.0.6 and 2.0.7 (22-Nov-2005 to 08-Jun-2006) *) Upgraded build environment from GNU shtool 2.0.3 to 2.0.6 Index: ossp-pkg/pth/Makefile.in RCS File: /v/ossp/cvs/ossp-pkg/pth/Makefile.in,v rcsdiff -q -kk '-r1.156' '-r1.157' -u '/v/ossp/cvs/ossp-pkg/pth/Makefile.in,v' 2>/dev/null --- Makefile.in 2006/06/08 17:54:51 1.156 +++ Makefile.in 2006/06/12 18:02:52 1.157 @@ -73,6 +73,10 @@ POD2MAN = pod2man GDB = gdb PERL = perl +FIG2DEV = fig2dev +LATEX = latex +DVIPS = dvips +GS = gs ## ## ____ TARGET DEFINITIONS _________________________________________ @@ -214,6 +218,19 @@ test_pthread: test_pthread.o test_common.o libpthread.la $(LIBTOOL) --mode=link --quiet $(CC) $(LDFLAGS) -o test_pthread test_pthread.o test_common.o libpthread.la $(LIBS) +# build paper +rse-pmt.eps: rse-pmt.fig + $(FIG2DEV) -L eps -F rse-pmt.fig rse-pmt.eps +rse-pmt.aux: rse-pmt.tex rse-pmt.eps + $(LATEX) rse-pmt.tex +rse-pmt.dvi: rse-pmt.tex rse-pmt.eps rse-pmt.aux + $(LATEX) rse-pmt.tex +rse-pmt.ps: rse-pmt.dvi + $(DVIPS) -o rse-pmt.ps rse-pmt.dvi +rse-pmt.pdf: rse-pmt.ps + $(GS) -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 \ + -sOutputFile=rse-pmt.pdf -c .setpdfwrite -f rse-pmt.ps + # install the package install: all-for-install @$(MAKE) $(MKFLAGS) install-dirs install-pth @INSTALL_PTHREAD@ @@ -298,11 +315,14 @@ $(RM) pthread-config pthread.h $(RM) config.log config.cache config.status $(RM) libtool + $(RM) rse-pmt.aux rse-pmt.log + $(RM) rse-pmt.eps rse-pmt.dvi $(RM) *.bak *~ # clean the source tree by removing really all generate stuff realclean: distclean $(RM) $(TARGET_MANS) + $(RM) rse-pmt.ps ./devtool autoclean # give hints what to do as the next step Index: ossp-pkg/pth/rse-pmt.fig RCS File: /v/ossp/cvs/ossp-pkg/pth/rse-pmt.fig,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/pth/rse-pmt.fig,v' | diff -u /dev/null - -L'ossp-pkg/pth/rse-pmt.fig' 2>/dev/null --- ossp-pkg/pth/rse-pmt.fig +++ - 2024-05-09 08:33:06.746148585 +0200 @@ -0,0 +1,211 @@ +#FIG 3.2 +Landscape +Center +Metric +Letter +100.00 +Single +-2 +1200 2 +6 735 690 945 900 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 930 885 750 885 750 705 930 705 930 885 +4 0 7 50 0 2 10 0.0000 4 105 75 810 840 1\001 +-6 +6 990 675 1215 900 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 1185 885 1005 885 1005 705 1185 705 1185 885 +4 0 7 50 0 2 10 0.0000 4 105 75 1065 840 2\001 +-6 +6 990 1170 1200 1380 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 1185 1365 1005 1365 1005 1185 1185 1185 1185 1365 +4 0 7 50 0 2 10 0.0000 4 105 75 1065 1320 6\001 +-6 +6 1260 1485 1470 1695 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 1455 1680 1275 1680 1275 1500 1455 1500 1455 1680 +4 0 7 50 0 2 10 0.0000 4 105 75 1335 1635 7\001 +-6 +6 1995 1485 2205 1695 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 2190 1680 2010 1680 2010 1500 2190 1500 2190 1680 +4 0 7 50 0 2 10 0.0000 4 105 75 2070 1635 8\001 +-6 +6 1980 495 2205 720 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 2190 705 2010 705 2010 525 2190 525 2190 705 +4 0 7 50 0 2 10 0.0000 4 105 75 2070 660 4\001 +-6 +6 1305 540 1530 765 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 1500 750 1320 750 1320 570 1500 570 1500 750 +4 0 7 50 0 2 10 0.0000 4 105 75 1380 705 3\001 +-6 +6 3060 870 3270 1080 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 3255 1065 3075 1065 3075 885 3255 885 3255 1065 +4 0 7 50 0 2 10 0.0000 4 105 75 3135 1020 5\001 +-6 +6 1995 2085 2205 2295 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 2190 2280 2010 2280 2010 2100 2190 2100 2190 2280 +4 0 7 50 0 2 10 0.0000 4 105 75 2070 2235 9\001 +-6 +6 1995 2625 2205 2835 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 2190 2820 2010 2820 2010 2640 2190 2640 2190 2820 +4 0 7 50 0 2 10 0.0000 4 105 150 2040 2775 13\001 +-6 +6 3030 2490 3240 2700 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 3225 2685 3045 2685 3045 2505 3225 2505 3225 2685 +4 0 7 50 0 2 10 0.0000 4 105 150 3068 2640 10\001 +-6 +6 1500 3210 1710 3420 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 1695 3405 1515 3405 1515 3225 1695 3225 1695 3405 +4 0 7 50 0 2 10 0.0000 4 105 150 1545 3360 14\001 +-6 +6 3300 2490 3510 2700 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 3495 2685 3315 2685 3315 2505 3495 2505 3495 2685 +4 0 7 50 0 2 10 0.0000 4 105 150 3337 2640 11\001 +-6 +6 3030 2745 3240 2955 +2 4 0 2 0 -1 100 0 20 0.000 0 0 2 0 0 5 + 3225 2940 3045 2940 3045 2760 3225 2760 3225 2940 +4 0 7 50 0 2 10 0.0000 4 105 150 3068 2895 12\001 +-6 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 630 270 1890 270 1890 3600 630 3600 630 270 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2340 270 3600 270 3600 1800 2340 1800 2340 270 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2340 2070 3600 2070 3600 3600 2340 3600 2340 2070 +2 1 2 1 0 7 50 0 -1 1.000 0 0 -1 0 0 6 + 1980 810 2025 720 2070 900 2115 720 2160 900 2205 810 +2 1 2 1 0 7 50 0 -1 1.000 0 0 7 0 0 6 + 1980 1170 2014 1081 2059 1261 2104 1081 2149 1261 2205 1170 +2 1 0 2 0 7 50 0 -1 0.000 0 0 -1 1 0 7 + 1 1 1.00 60.00 120.00 + 1260 4586 1980 4593 1980 3690 450 3690 450 630 990 630 + 1260 630 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 1 1 1.00 60.00 120.00 + 1260 630 1260 810 1980 810 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 2205 810 2970 810 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 2970 810 2970 1170 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 1 2 + 1 1 1.00 60.00 120.00 + 2205 1170 2970 1170 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 1 2 + 1 1 1.00 60.00 120.00 + 1260 1170 1980 1170 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 1260 1440 2970 1440 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2 + 1260 1170 1260 1440 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 1 0 5 + 1 1 1.00 60.00 120.00 + 2970 1440 2970 1890 2250 1890 2250 2520 2970 2520 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 2 + 2970 2520 2970 2883 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 2970 2891 1245 2883 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 1 0 5 + 1 1 1.00 60.00 120.00 + 1260 2880 1260 3150 2070 3150 2062 4773 1245 4781 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 1 1 1.00 60.00 120.00 + 450 4050 1260 4050 1260 4586 +2 1 0 2 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 1252 4773 1260 5220 +2 1 2 2 0 7 50 0 -1 3.000 0 1 7 1 0 5 + 1 1 1.00 60.00 120.00 + 2970 3150 2970 3690 2250 3690 2250 4230 2970 4230 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 + 630 6300 1890 6300 1890 7290 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 1 1 1.00 60.00 120.00 + 1 1 1.00 60.00 120.00 + 3690 6300 3690 7560 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2340 6300 3600 6300 3600 7560 2340 7560 2340 6300 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 630 3780 1890 3780 1890 6120 630 6120 630 3780 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2340 3780 3600 3780 3600 6120 2340 6120 2340 3780 +2 1 2 2 0 7 50 0 -1 3.000 0 1 7 1 0 4 + 1 1 1.00 60.00 120.00 + 1260 5220 2160 5220 2160 3150 2970 3150 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 630 6300 630 7380 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 630 6570 900 6300 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 630 6840 1170 6300 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 630 7110 1440 6300 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 630 7380 1710 6300 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 810 7470 1890 6435 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 1080 7515 1890 6750 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 1665 7245 1890 7020 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 2340 6570 2610 6300 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 2340 6840 2925 6300 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 2340 7110 3240 6300 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 2340 7380 3510 6300 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 2520 7560 3600 6570 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 2880 7560 3600 6930 +2 1 0 1 0 7 50 0 -1 0.000 0 1 -1 0 0 2 + 3240 7560 3600 7245 +2 1 2 2 0 7 50 0 -1 3.000 0 1 7 1 0 2 + 1 1 1.00 60.00 120.00 + 2970 4230 2970 5310 +2 1 2 2 0 7 50 0 -1 3.000 0 1 7 1 0 2 + 1 1 1.00 60.00 120.00 + 2970 5310 1260 5310 +2 1 2 2 0 7 50 0 -1 3.000 0 1 7 1 0 3 + 1 1 1.00 60.00 120.00 + 2970 5580 2970 5670 1260 5670 +2 1 2 2 0 7 50 0 -1 3.000 0 1 7 1 0 3 + 1 1 1.00 60.00 120.00 + 1260 5670 1260 5940 360 5940 +2 1 2 2 0 7 50 0 -1 3.000 0 1 7 1 0 3 + 1 1 1.00 60.00 120.00 + 1260 5355 1260 5580 2970 5580 +3 2 0 1 0 7 50 0 -1 0.000 0 0 0 4 + 630 7380 1035 7515 1530 7290 1890 7290 + 0.000 -1.000 -1.000 0.000 +4 0 0 50 0 2 10 0.0000 4 150 525 2430 6480 sk_addr\001 +4 0 0 50 0 2 10 0.0000 4 120 705 720 6480 main stack\001 +4 0 0 50 0 2 10 0.0000 4 120 330 720 3960 main\001 +4 0 0 50 0 2 10 0.0000 4 150 1005 2430 3960 sf_addr(sf_arg)\001 +4 0 0 50 0 2 10 0.0000 4 150 825 2430 2250 mctx_create\001 +4 0 0 50 0 2 10 0.0000 4 150 825 2430 450 mctx_create\001 +4 0 0 50 0 2 10 0.0000 4 150 825 720 450 mctx_create\001 +4 0 0 50 0 2 10 0.0000 4 150 390 3150 2250 _boot\001 +4 0 0 50 0 2 10 0.0000 4 165 810 2790 585 _trampoline\001 +4 0 0 50 0 2 10 1.5708 4 165 465 3870 7110 sk_size\001 +4 0 0 50 0 2 10 0.0000 4 165 810 1350 5175 mctx_switch\001 +4 0 0 50 0 2 10 0.0000 4 165 810 2385 5445 mctx_switch\001 +4 0 0 50 0 2 10 0.0000 4 165 810 1350 5535 mctx_switch\001 +4 0 0 50 0 2 10 0.0000 4 165 810 2385 5805 mctx_switch\001 +4 0 0 50 0 2 10 0.0000 4 150 825 1305 4725 mctx_create\001 Index: ossp-pkg/pth/rse-pmt.pdf RCS File: /v/ossp/cvs/ossp-pkg/pth/rse-pmt.pdf,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/pth/rse-pmt.pdf,v' | diff -u /dev/null - -L'ossp-pkg/pth/rse-pmt.pdf' 2>/dev/null Binary files ossp-pkg/pth/rse-pmt.pdf and - differ Index: ossp-pkg/pth/rse-pmt.ps RCS File: /v/ossp/cvs/ossp-pkg/pth/rse-pmt.ps,v co -q -kk -p'1.9' '/v/ossp/cvs/ossp-pkg/pth/rse-pmt.ps,v' | diff -u /dev/null - -L'ossp-pkg/pth/rse-pmt.ps' 2>/dev/null --- ossp-pkg/pth/rse-pmt.ps +++ - 2024-05-09 08:33:06.751580976 +0200 @@ -0,0 +1,3070 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.95a Copyright 2005 Radical Eye Software +%%Title: rse-pmt.dvi +%%Pages: 11 +%%PageOrder: Ascend +%%BoundingBox: 0 0 595 842 +%%DocumentFonts: Times-Bold Times-Roman Times-Italic Helvetica-Bold +%%+ Courier CMSY9 Times-BoldItalic Courier-Bold Courier-BoldOblique +%%+ CMSY8 CMMI10 CMSY10 CMR10 Helvetica +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -o rse-pmt.ps rse-pmt.dvi +%DVIPSParameters: dpi=1200 +%DVIPSSource: TeX output 2006.06.12:1951 +%%BeginProcSet: tex.pro 0 0 +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S +/BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy +setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask +restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc 0 0 +% File 8r.enc TeX Base 1 Encoding Revision 2.0 2002-10-30 +% +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry, +% W. Schmidt, P. Lehman", +% version = "2.0", +% date = "30 October 2002", +% filename = "8r.enc", +% email = "tex-fonts@@tug.org", +% docstring = "This is the encoding vector for Type1 and TrueType +% fonts to be used with TeX. This file is part of the +% PSNFSS bundle, version 9" +% @} +% +% The idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard encoding, ISO Latin 1, Windows ANSI including the euro symbol, +% MacRoman, and some extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% These are /dotlessj /ff /ffi /ffl. +% +% (4) hyphen appears twice for compatibility with both ASCII and Windows. +% +% (5) /Euro was assigned to 128, as in Windows ANSI +% +% (6) Missing characters from MacRoman encoding incorporated as follows: +% +% PostScript MacRoman TeXBase1 +% -------------- -------------- -------------- +% /notequal 173 0x16 +% /infinity 176 0x17 +% /lessequal 178 0x18 +% /greaterequal 179 0x19 +% /partialdiff 182 0x1A +% /summation 183 0x1B +% /product 184 0x1C +% /pi 185 0x1D +% /integral 186 0x81 +% /Omega 189 0x8D +% /radical 195 0x8E +% /approxequal 197 0x8F +% /Delta 198 0x9D +% /lozenge 215 0x9E +% +/TeXBase1Encoding [ +% 0x00 + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef /breve + /minus /.notdef /Zcaron /zcaron +% 0x10 + /caron /dotlessi /dotlessj /ff + /ffi /ffl /notequal /infinity + /lessequal /greaterequal /partialdiff /summation + /product /pi /grave /quotesingle +% 0x20 + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus + /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three + /four /five /six /seven + /eight /nine /colon /semicolon + /less /equal /greater /question +% 0x40 + /at /A /B /C + /D /E /F /G + /H /I /J /K + /L /M /N /O +% 0x50 + /P /Q /R /S + /T /U /V /W + /X /Y /Z /bracketleft + /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c + /d /e /f /g + /h /i /j /k + /l /m /n /o +% 0x70 + /p /q /r /s + /t /u /v /w + /x /y /z /braceleft + /bar /braceright /asciitilde /.notdef +% 0x80 + /Euro /integral /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /Omega /radical /approxequal +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /Delta /lozenge /Ydieresis +% 0xA0 + /.notdef /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot /hyphen /registered /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde + /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + + +%%EndProcSet +%%BeginProcSet: texps.pro 0 0 +%! +TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 +index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 +ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ +pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get +div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type +/nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end +definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup +sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll +mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ +exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} +forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def +end + +%%EndProcSet +%%BeginProcSet: special.pro 0 0 +%! +TeXDict begin/SDict 200 dict N SDict begin/@SpecialDefaults{/hs 612 N +/vs 792 N/ho 0 N/vo 0 N/hsc 1 N/vsc 1 N/ang 0 N/CLIP 0 N/rwiSeen false N +/rhiSeen false N/letter{}N/note{}N/a4{}N/legal{}N}B/@scaleunit 100 N +/@hscale{@scaleunit div/hsc X}B/@vscale{@scaleunit div/vsc X}B/@hsize{ +/hs X/CLIP 1 N}B/@vsize{/vs X/CLIP 1 N}B/@clip{/CLIP 2 N}B/@hoffset{/ho +X}B/@voffset{/vo X}B/@angle{/ang X}B/@rwi{10 div/rwi X/rwiSeen true N}B +/@rhi{10 div/rhi X/rhiSeen true N}B/@llx{/llx X}B/@lly{/lly X}B/@urx{ +/urx X}B/@ury{/ury X}B/magscale true def end/@MacSetUp{userdict/md known +{userdict/md get type/dicttype eq{userdict begin md length 10 add md +maxlength ge{/md md dup length 20 add dict copy def}if end md begin +/letter{}N/note{}N/legal{}N/od{txpose 1 0 mtx defaultmatrix dtransform S +atan/pa X newpath clippath mark{transform{itransform moveto}}{transform{ +itransform lineto}}{6 -2 roll transform 6 -2 roll transform 6 -2 roll +transform{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll +curveto}}{{closepath}}pathforall newpath counttomark array astore/gc xdf +pop ct 39 0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack} +if}N/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 +-1 scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 +get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip +yflip not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub +neg 0 TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{ +noflips{TR pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop +90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get +neg sub neg TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr +1 get neg sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr +2 get ppr 0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 +-1 roll add 2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S +TR}if}N/cp{pop pop showpage pm restore}N end}if}if}N/normalscale{ +Resolution 72 div VResolution 72 div neg scale magscale{DVImag dup scale +}if 0 setgray}N/psfts{S 65781.76 div N}N/startTexFig{/psf$SavedState +save N userdict maxlength dict begin/magscale true def normalscale +currentpoint TR/psf$ury psfts/psf$urx psfts/psf$lly psfts/psf$llx psfts +/psf$y psfts/psf$x psfts currentpoint/psf$cy X/psf$cx X/psf$sx psf$x +psf$urx psf$llx sub div N/psf$sy psf$y psf$ury psf$lly sub div N psf$sx +psf$sy scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub +TR/showpage{}N/erasepage{}N/setpagedevice{pop}N/copypage{}N/p 3 def +@MacSetUp}N/doclip{psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll +newpath 4 copy 4 2 roll moveto 6 -1 roll S lineto S lineto S lineto +closepath clip newpath moveto}N/endTexFig{end psf$SavedState restore}N +/@beginspecial{SDict begin/SpecialSave save N gsave normalscale +currentpoint TR @SpecialDefaults count/ocount X/dcount countdictstack N} +N/@setspecial{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs +neg 0 rlineto closepath clip}if ho vo TR hsc vsc scale ang rotate +rwiSeen{rwi urx llx sub div rhiSeen{rhi ury lly sub div}{dup}ifelse +scale llx neg lly neg TR}{rhiSeen{rhi ury lly sub div dup scale llx neg +lly neg TR}if}ifelse CLIP 2 eq{newpath llx lly moveto urx lly lineto urx +ury lineto llx ury lineto closepath clip}if/showpage{}N/erasepage{}N +/setpagedevice{pop}N/copypage{}N newpath}N/@endspecial{count ocount sub{ +pop}repeat countdictstack dcount sub{end}repeat grestore SpecialSave +restore end}N/@defspecial{SDict begin}N/@fedspecial{end}B/li{lineto}B +/rl{rlineto}B/rc{rcurveto}B/np{/SaveX currentpoint/SaveY X N 1 +setlinecap newpath}N/st{stroke SaveX SaveY moveto}N/fil{fill SaveX SaveY +moveto}N/ellipse{/endangle X/startangle X/yrad X/xrad X/savematrix +matrix currentmatrix N TR xrad yrad scale 0 0 1 startangle endangle arc +savematrix setmatrix}N end + +%%EndProcSet +%%BeginProcSet: color.pro 0 0 +%! +TeXDict begin/setcmykcolor where{pop}{/setcmykcolor{dup 10 eq{pop +setrgbcolor}{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll +}repeat setrgbcolor pop}ifelse}B}ifelse/TeXcolorcmyk{setcmykcolor}def +/TeXcolorrgb{setrgbcolor}def/TeXcolorgrey{setgray}def/TeXcolorgray{ +setgray}def/TeXcolorhsb{sethsbcolor}def/currentcmykcolor where{pop}{ +/currentcmykcolor{currentrgbcolor 10}B}ifelse/DC{exch dup userdict exch +known{pop pop}{X}ifelse}B/GreenYellow{0.15 0 0.69 0 setcmykcolor}DC +/Yellow{0 0 1 0 setcmykcolor}DC/Goldenrod{0 0.10 0.84 0 setcmykcolor}DC +/Dandelion{0 0.29 0.84 0 setcmykcolor}DC/Apricot{0 0.32 0.52 0 +setcmykcolor}DC/Peach{0 0.50 0.70 0 setcmykcolor}DC/Melon{0 0.46 0.50 0 +setcmykcolor}DC/YellowOrange{0 0.42 1 0 setcmykcolor}DC/Orange{0 0.61 +0.87 0 setcmykcolor}DC/BurntOrange{0 0.51 1 0 setcmykcolor}DC +/Bittersweet{0 0.75 1 0.24 setcmykcolor}DC/RedOrange{0 0.77 0.87 0 +setcmykcolor}DC/Mahogany{0 0.85 0.87 0.35 setcmykcolor}DC/Maroon{0 0.87 +0.68 0.32 setcmykcolor}DC/BrickRed{0 0.89 0.94 0.28 setcmykcolor}DC/Red{ +0 1 1 0 setcmykcolor}DC/OrangeRed{0 1 0.50 0 setcmykcolor}DC/RubineRed{ +0 1 0.13 0 setcmykcolor}DC/WildStrawberry{0 0.96 0.39 0 setcmykcolor}DC +/Salmon{0 0.53 0.38 0 setcmykcolor}DC/CarnationPink{0 0.63 0 0 +setcmykcolor}DC/Magenta{0 1 0 0 setcmykcolor}DC/VioletRed{0 0.81 0 0 +setcmykcolor}DC/Rhodamine{0 0.82 0 0 setcmykcolor}DC/Mulberry{0.34 0.90 +0 0.02 setcmykcolor}DC/RedViolet{0.07 0.90 0 0.34 setcmykcolor}DC +/Fuchsia{0.47 0.91 0 0.08 setcmykcolor}DC/Lavender{0 0.48 0 0 +setcmykcolor}DC/Thistle{0.12 0.59 0 0 setcmykcolor}DC/Orchid{0.32 0.64 0 +0 setcmykcolor}DC/DarkOrchid{0.40 0.80 0.20 0 setcmykcolor}DC/Purple{ +0.45 0.86 0 0 setcmykcolor}DC/Plum{0.50 1 0 0 setcmykcolor}DC/Violet{ +0.79 0.88 0 0 setcmykcolor}DC/RoyalPurple{0.75 0.90 0 0 setcmykcolor}DC +/BlueViolet{0.86 0.91 0 0.04 setcmykcolor}DC/Periwinkle{0.57 0.55 0 0 +setcmykcolor}DC/CadetBlue{0.62 0.57 0.23 0 setcmykcolor}DC +/CornflowerBlue{0.65 0.13 0 0 setcmykcolor}DC/MidnightBlue{0.98 0.13 0 +0.43 setcmykcolor}DC/NavyBlue{0.94 0.54 0 0 setcmykcolor}DC/RoyalBlue{1 +0.50 0 0 setcmykcolor}DC/Blue{1 1 0 0 setcmykcolor}DC/Cerulean{0.94 0.11 +0 0 setcmykcolor}DC/Cyan{1 0 0 0 setcmykcolor}DC/ProcessBlue{0.96 0 0 0 +setcmykcolor}DC/SkyBlue{0.62 0 0.12 0 setcmykcolor}DC/Turquoise{0.85 0 +0.20 0 setcmykcolor}DC/TealBlue{0.86 0 0.34 0.02 setcmykcolor}DC +/Aquamarine{0.82 0 0.30 0 setcmykcolor}DC/BlueGreen{0.85 0 0.33 0 +setcmykcolor}DC/Emerald{1 0 0.50 0 setcmykcolor}DC/JungleGreen{0.99 0 +0.52 0 setcmykcolor}DC/SeaGreen{0.69 0 0.50 0 setcmykcolor}DC/Green{1 0 +1 0 setcmykcolor}DC/ForestGreen{0.91 0 0.88 0.12 setcmykcolor}DC +/PineGreen{0.92 0 0.59 0.25 setcmykcolor}DC/LimeGreen{0.50 0 1 0 +setcmykcolor}DC/YellowGreen{0.44 0 0.74 0 setcmykcolor}DC/SpringGreen{ +0.26 0 0.76 0 setcmykcolor}DC/OliveGreen{0.64 0 0.95 0.40 setcmykcolor} +DC/RawSienna{0 0.72 1 0.45 setcmykcolor}DC/Sepia{0 0.83 1 0.70 +setcmykcolor}DC/Brown{0 0.81 1 0.60 setcmykcolor}DC/Tan{0.14 0.42 0.56 0 +setcmykcolor}DC/Gray{0 0 0 0.50 setcmykcolor}DC/Black{0 0 0 1 +setcmykcolor}DC/White{0 0 0 0 setcmykcolor}DC end + +%%EndProcSet +%%BeginFont: CMR10 +%!PS-AdobeFont-1.1: CMR10 1.00B +%%CreationDate: 1992 Feb 19 19:54:52 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.00B) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMR10) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle 0 def +/isFixedPitch false def +end readonly def +/FontName /CMR10 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 43 /plus put +dup 50 /two put +readonly def +/FontBBox{-251 -250 1009 969}readonly def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 +016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 +9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F +D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 +469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 +2BDBF16FBC7512FAA308A093FE5CF7158F1163BC1F3352E22A1452E73FECA8A4 +87100FB1FFC4C8AF409B2067537220E605DA0852CA49839E1386AF9D7A1A455F +D1F017CE45884D76EF2CB9BC5821FD25365DDEA6E45F332B5F68A44AD8A530F0 +92A36FAC8D27F9087AFEEA2096F839A2BC4B937F24E080EF7C0F9374A18D565C +295A05210DB96A23175AC59A9BD0147A310EF49C551A417E0A22703F94FF7B75 +409A5D417DA6730A69E310FA6A4229FC7E4F620B0FC4C63C50E99E179EB51E4C +4BC45217722F1E8E40F1E1428E792EAFE05C5A50D38C52114DFCD24D54027CBF +2512DD116F0463DE4052A7AD53B641A27E81E481947884CE35661B49153FA19E +0A2A860C7B61558671303DE6AE06A80E4E450E17067676E6BBB42A9A24ACBC3E +B0CA7B7A3BFEA84FED39CCFB6D545BB2BCC49E5E16976407AB9D94556CD4F008 +24EF579B6800B6DC3AAF840B3FC6822872368E3B4274DD06CA36AF8F6346C11B +43C772CC242F3B212C4BD7018D71A1A74C9A94ED0093A5FB6557F4E0751047AF +D72098ECA301B8AE68110F983796E581F106144951DF5B750432A230FDA3B575 +5A38B5E7972AABC12306A01A99FCF8189D71B8DBF49550BAEA9CF1B97CBFC7CC +96498ECC938B1A1710B670657DE923A659DB8757147B140A48067328E7E3F9C3 +7D1888B284904301450CE0BC15EEEA00E48CCD6388F3FC3C8578EF9A20A0E06E +4F7ADDAF0E7D1E182D115BF1AD931977325AD391E72E2B13CC108E3726C11099 +E2000623188AAAC9F3E233EB253BDD8B0A4759A66A113E066238B0086AC1B634 +5ABFF90E4B5ED3FA69C22541981B2BFC9710AEF6B50A8BB53431C7B4D380D721 +639E005D6B4688EE16BFF48443E7C9E5FB5BC5883E271CB034289232A0694CCE +12A5A2637485FB47BC281A2129E040DE629890E13430C788F3860C1EC52C8DE4 +581DE90A40BF466BD3EFF7D03E7B33CF5DF9BD038D5E27602FC07D387B1115BF +843776E976022FA3DDDB1132F32935428D0B14D9F2835F2E774363ECA0E7BA0B +D9B4A0083A8D751A82644167C763874FB86DAB03BDECC3EEC2243CCDB104DD94 +24FC1731E5C449F475E53B73D92814059370688B9E8252D0402188058A8214B1 +9D409DD944A2F2EA0BF8559353B2F7690C0C23386C54B813FD74D541BD12A6BC +167FC46065D5EC82F71315F8BD967DB8272042F5D9818E7A0F616870A39B7071 +29E50828BA48B9D82755F09DA2B6F56C414AF14B7CBD6BE39AFCF681709D2471 +652FB14F114FDA3F8141CABABE595D1DD69D1C4A9AE8F491BD3D7DE3B8F7C3ED +9759358B5EBE0C8B3402A9A2025A82639708D9596A8087ED8F601A152A518A37 +A6D73278AF9A487F55091DBB148299C853FA5012A3C4522B206B89356C0F6067 +0BA3EE71F3B36B7EE3E5AFDD3224E93A8BAD1F64E272417647158942C682700C +3BC5E0995E2EE30DB8BF9469F0995FAF1A82 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +%%BeginFont: CMSY10 +%!PS-AdobeFont-1.1: CMSY10 1.0 +%%CreationDate: 1991 Aug 15 07:20:57 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.0) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMSY10) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.035 def +/isFixedPitch false def +end readonly def +/FontName /CMSY10 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 2 /multiply put +readonly def +/FontBBox{-29 -960 1116 775}readonly def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 +7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 +A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 +E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A +221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A +27D1663E0B62F461F6E40A5D6676D1D12B51E641C1D4E8E2771864FC104F8CBF +5B78EC1D88228725F1C453A678F58A7E1B7BD7CA700717D288EB8DA1F57C4F09 +0ABF1D42C5DDD0C384C7E22F8F8047BE1D4C1CC8E33368FB1AC82B4E96146730 +DE3302B2E6B819CB6AE455B1AF3187FFE8071AA57EF8A6616B9CB7941D44EC7A +71A7BB3DF755178D7D2E4BB69859EFA4BBC30BD6BB1531133FD4D9438FF99F09 +4ECC068A324D75B5F696B8688EEB2F17E5ED34CCD6D047A4E3806D000C199D7C +515DB70A8D4F6146FE068DC1E5DE8BC5703711DA090312BA3FC00A08C453C609 +C627A8B149D71F3155BFBF5A359E54EFE40EB6AAF7344F336BBDFA5241D39DFD +19DFE4F1B56DCAAEA84D9290E81FFAD8472517CB517C9F8D04EAF8E87A58341D +57386FF17BF29235356C3F85FE85CCB75DFBD407A6B76C198356415768FE0D58 +0F0E0665E6B2EFC269256FCE0146C415E35D900293555D8B6CB2AA451586E477 +93461FAF0803AE54B9FEE351771B08F9F7D564B5F50CB4E660298DECF4DC0F67 +0A4DA5738D89F708019CDFF9443964830B406748B60EF34EA35EDA7DF1C05A1E +A385C5DE4B171FCD735AA0C41E54B09D133E48FCAA3A75F1B05C2AD4CD792534 +4160FCF0C48076AD3174E1A970FD9A285EB251E016B2739E373B43F17A1D50BC +02FB2383DACFF35A5503EE8D0C8147908BFF5FA0D9D06F243AA8B4FFFCD8FF4E +ED02BC +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +%%BeginFont: CMMI10 +%!PS-AdobeFont-1.1: CMMI10 1.100 +%%CreationDate: 1996 Jul 23 07:53:57 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.100) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMMI10) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.04 def +/isFixedPitch false def +end readonly def +/FontName /CMMI10 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 65 /A put +dup 78 /N put +readonly def +/FontBBox{-32 -250 1048 750}readonly def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE +3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B +532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 +B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B +986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE +D919C2DDD26BDC0D99398B9F4D03D5993DFC0930297866E1CD0A319B6B1FD958 +9E394A533A081C36D456A09920001A3D2199583EB9B84B4DEE08E3D12939E321 +990CD249827D9648574955F61BAAA11263A91B6C3D47A5190165B0C25ABF6D3E +6EC187E4B05182126BB0D0323D943170B795255260F9FD25F2248D04F45DFBFB +DEF7FF8B19BFEF637B210018AE02572B389B3F76282BEB29CC301905D388C721 +59616893E774413F48DE0B408BC66DCE3FE17CB9F84D205839D58014D6A88823 +D9320AE93AF96D97A02C4D5A2BB2B8C7925C4578003959C46E3CE1A2F0EAC4BF +8B9B325E46435BDE60BC54D72BC8ACB5C0A34413AC87045DC7B84646A324B808 +6FD8E34217213E131C3B1510415CE45420688ED9C1D27890EC68BD7C1235FAF9 +1DAB3A369DD2FC3BE5CF9655C7B7EDA7361D7E05E5831B6B8E2EEC542A7B38EE +03BE4BAC6079D038ACB3C7C916279764547C2D51976BABA94BA9866D79F13909 +95AA39B0F03103A07CBDF441B8C5669F729020AF284B7FF52A29C6255FCAACF1 +74109050FBA2602E72593FBCBFC26E726EE4AEF97B7632BC4F5F353B5C67FED2 +3EA752A4A57B8F7FEFF1D7341D895F0A3A0BE1D8E3391970457A967EFF84F6D8 +47750B1145B8CC5BD96EE7AA99DDC9E06939E383BDA41175233D58AD263EBF19 +AFC0E2F840512D321166547B306C592B8A01E1FA2564B9A26DAC14256414E4C8 +42616728D918C74D13C349F4186EC7B9708B86467425A6FDB3A396562F7EE4D8 +40B43621744CF8A23A6E532649B66C2A0002DD04F8F39618E4F572819DD34837 +B5A08E643FDCA1505AF6A1FA3DDFD1FA758013CAED8ACDDBBB334D664DFF5B53 +95601766777978D01677B8D19E1B10A078432D2884BB6250F980A231AC216383 +1FD449E6C47B12C66F68D19F77E672D207E4454D4FE979040A5CF8D0F31FFB88 +13B824C3B5675933EDB05D3EC1687024F38F3B9480096C8CC3EE5E51CF75AF22 +92119E844810F5AC882300FFEA881FD9AF30B3641171C15D4B40C088C7A480C4 +F0168D1AF719EED16E7F34DFE59E505E5FAAD4DD1E30918D3C06CA3C03CD6A0A +AC440A7238E59139C4338BC398EAC55D68593D60981A5FA1DD2222D78164340F +C25F5DF2D37EFC9E90F29B44C626410F740734D57C9E463156B7656BB48F8785 +18DF94463376E831A865D0A529AB562572F3B37E65CCF7715C1E69DBDE368CE6 +5F25C19753DB0D9F25243B703FC683ACC9E35B6643ADC727183649C2EC1927D1 +129B93DB94672FA19C9613EAD3B19579B8824BD0D86AD70D89002D44D8328072 +BFAE543FCF6BD9A3008DAE7E8E9393EA1672F420FE2E1EF2C49B3532A2642A75 +5E1C88B645E99840EBD742881CB6844BA155BD73FDDB923D73895EE2703514C1 +5F90371E51BC6A3B252072591921AD07155E1837DFACD9DC3154BBB63DE6FAB4 +1867218FE229C1676867B720ED9AFE1C0070DCC3647B01475464C3B8E8414050 +488CB48C1A123A49CC016DF43EE649BAE5E00C37DABD7653BC8A18F79F31B926 +F0859F043831331AB3DBFB4DC923454C09C29C8049BFBA71BD7FE5EA5B1DFA4C +736D775FDF529F6F99785219D4298E9823771433504E2AA8B0A92EB7D9F433C5 +D6406B17D9C03F4DB0277ED4001E1E3D1A537AABB336F651 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +%%BeginFont: CMSY8 +%!PS-AdobeFont-1.1: CMSY8 1.0 +%%CreationDate: 1991 Aug 15 07:22:10 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.0) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMSY8) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.035 def +/isFixedPitch false def +end readonly def +/FontName /CMSY8 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 2 /multiply put +readonly def +/FontBBox{-30 -955 1185 779}readonly def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 +7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 +A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 +E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A +221A37D9A807DD01161779DDE7D5FC1B2109839E5B52DFBB2A7C1B5D8E7E8AA0 +5B10EA43D6A8ED61AF5B23D49920D8F79DAB6A59062134D84AC0100187A6CD1F +80F5DDD9D222ACB1C23326A7656A635C4A241CCD32CBFDF8363206B8AA36E107 +1477F5496111E055C7491002AFF272E46ECC46422F0380D093284870022523FB +DA1716CC4F2E2CCAD5F173FCBE6EDDB874AD255CD5E5C0F86214393FCB5F5C20 +9C3C2BB5886E36FC3CCC21483C3AC193485A46E9D22BD7201894E4D45ADD9BF1 +CC5CF6A5010B5654AC0BE0DA903DB563B13840BA3015F72E51E3BC80156388BA +F83C7D393392BCBC227771CDCB976E93302531886DDA73EBC9178917EFD0C20B +133F1E59A6DB3811BD410DC83AA75BE26D4E754A02DD0075D7A793D8C4B499A2 +BC8E8A5316CB716ADB46D95C7B12CA61DD83222233C8DDFA7CDE7D9A6ADE5D37 +DCAD7CA36C274C9844CCFFEDA502BBBDB60FAE578D00B89137526796A1EBEAE8 +F896D9A1F6DA099B80ABF69047F70A59D086D90DEE48A18606D68FF1B98B671E +AED376EEE1EB099004C5343B1D473F845D60C9BCDBB19DA77E0DDDB032052DDB +48629F27A39B5CC68A4A2A285D09356A9BC085EF39D03B96F073FFF0F63AEDDE +0CA7918F4534E6DDC108A93CAEFA2775CB07C30D5D5A108FBBDC5E909F110BB6 +89474C11CD76FBC6E9CDA58775C49840E2903429597CBA68253CC92E62FDB847 +1D8D9A975D2D7B6E2DD6F3B68F6562C54D091FC926FE5410DE5D9A8C0A73AB17 +333450D9 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +%%BeginFont: CMSY9 +%!PS-AdobeFont-1.1: CMSY9 1.0 +%%CreationDate: 1991 Aug 15 07:22:27 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.0) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMSY9) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.035 def +/isFixedPitch false def +end readonly def +/FontName /CMSY9 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 21 /greaterequal put +dup 102 /braceleft put +dup 103 /braceright put +dup 110 /backslash put +readonly def +/FontBBox{-30 -958 1146 777}readonly def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 +7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 +A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 +E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A +221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A +27D1663E0B62F461F6E40A5D6676D0037D33F24E2FAC2B0009AD3C8350CDF8CC +65BCA87979C36D14CB552E9A985E48BE4E88ECA16DF418749AF04FDD2B0E1380 +D281BB2476BB45FF30946B247DFD7F57305FA87E50CA338121C71CDFDF927A9C +77FF14CB4A1D6D80356FB1171ED38C37702350497B44E42CE31DB2F493807DAA +15B887C671199A54C4C1294BC520F5538C15556BC43C9F62342B121C6DCD6C5F +491DA47FF360201EE21C08A781ED0589A6DF91B99FE118B9B29E4F068672E52F +1A06C514D91C4C937D4E642503392B1CD1B984B04B674C2977A634F63B35677E +9196FFC0F57806BBA111603CDED14B3FD9D537343B83693A57CE39EF70A3F289 +CAA584C8ADC703D35922D286242575D4A249B19BBF483DF303D802B5D2FA278F +BA6E3C852733048FD342AE39CCC9F4D8809C846471E751597EBD521EFE368858 +ADC4CA646D35FF65C797EF775445747B6510960FECCAD9A2EF0B76500EA0C069 +B8E8AFA16D099299FE092A97E2FDF483A39FCCACFFF3DF10D4C3CC0D78BB7413 +DDB69644F0305FD1158CDB96AC4432BFB81DB1259B8AC16982694149276336C4 +659FFC384078BAF79749E72CD873E8B4B99D3D928F624CB6A1FEEE07199E5274 +213F60F9902597D145C52DABC5AD44616A8B0894DB47F6F2A07F585BDCE050AE +9F159401B65219C9695CFF122C9CBE743839A29060B2B33A6B0CBDD41516F448 +09A8795098237D1805168A35D8E20F1B211A580B2F051572F44E76EC01A7BAE3 +66CE505B13C828AF4FAF0EDC9BCD96A014E86993552839DBCFDD88BF84285CE0 +BFB2CC6AB9AC3308C2438E1E5E9EB2F7727CDCB4A71BB83F1D70F15436712730 +75BD1B40CC9B7FBEFA20B4F3BDA5E68C540D6FC8AF1CA3A30E1FBA7FA7D8E011 +2AC2F960786C810642986594F3BB8A33838381FE47D436A485E95DC3C391B251 +9C43A85A8D8EAB0E5D5B978ECD8BF0D117D61C3CA57D46BE354513F6DA278B51 +FFD5C2E3B25F900BAE47C5D006366E513742409500B32AED625A4B2AC1F4E3F4 +8A7D6153C2C6D994804A1E3834E8623F2BC29752B9069BA80C10E9EE8A60E32A +8259CE68944FBB6FB47FACF129FBA781E0D1B7B46481BC05B34482901C8A6770 +4D3101B75317FB04E90DFEF394C7A8329D24CC4CA261A339D4B3F4193BD2A5A4 +13A1DCDC60A4A685B0F99D8CFC00F944F1D21FC0E0BAC319D36747AA47C156B6 +CCD69E3F7AADB801BDFCF16833FCF141FCF33CCACEAF6DA099724DF56FA14CC2 +163379669D980643E0BF8B9F2CAA7AB5AE55171A1D6686C28F658B223D039FBB +47A47BFE8FF5907BBBBBE8EC56D2538ADD4ACABA19648592741C5F74F1F1D01F +ACB7B023997973E5BC4961990DFA539A16E7764CA2DE4167C2F4F18EAC1D68BD +E82B66A38CCA217C10C2A03C4679 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +TeXDict begin 39139632 55387786 1000 1200 1200 (rse-pmt.dvi) +@start /Fa 165[73 86 1[113 86 86 73 66 80 86 66 86 86 +106 73 86 47 40 86 86 66 73 86 80 80 86 65[{ +TeXBase1Encoding ReEncodeFont}25 119.552 /Times-Roman +rf /Fb 140[75 50 12[83 101[{TeXBase1Encoding ReEncodeFont}3 +149.44 /Helvetica rf /Fc 205[83 6[129 43[{}2 166.044 +/CMR10 rf /Fd 253[129 2[{}1 166.044 /CMSY10 rf /Fe 177[133 +12[125 65[{}2 166.044 /CMMI10 rf /Ff 253[110 2[{}1 132.835 +/CMSY8 rf /Fg 135[90 3[90 6[90 9[90 99[{TeXBase1Encoding ReEncodeFont}4 +149.44 /Courier-BoldOblique rf /Fh 135[80 80 2[80 80 +2[80 80 80 80 80 80 80 80 80 80 1[80 1[80 1[80 12[80 +1[80 1[80 80 80 4[80 1[80 25[80 45[{TeXBase1Encoding ReEncodeFont}25 +132.835 /Courier rf /Fi 133[90 90 1[90 90 90 90 90 90 +1[90 90 90 1[90 2[90 90 1[90 90 90 90 1[90 1[90 59[90 +35[{TeXBase1Encoding ReEncodeFont}21 149.44 /Courier-Bold +rf /Fj 133[58 66 75 100 66 83 42 58 58 1[75 75 83 116 +42 75 42 42 83 75 50 66 75 66 75 75 50 11[91 83 24[50 +75 75 75 75 75 75 75 75 75 75 1[37 6[50 116 35[83 2[{ +TeXBase1Encoding ReEncodeFont}43 149.44 /Times-BoldItalic +rf /Fk 103[90 29[90 90 90 90 90 90 90 90 90 1[90 90 90 +90 90 90 90 90 90 90 90 90 90 90 90 90 1[90 9[90 90 90 +90 2[90 90 90 90 90 1[90 90 90 90 90 90 90 90 90 2[90 +90 1[90 9[90 90 90 90 90 90 1[90 90 90 1[90 4[90 33[{ +TeXBase1Encoding ReEncodeFont}59 149.44 /Courier rf /Fl +135[59 3[37 1[52 1[66 66 66 96 37 59 1[37 66 2[59 1[59 +1[66 11[96 1[66 2[81 1[89 111 5[96 3[89 81 19[33 46[{ +TeXBase1Encoding ReEncodeFont}23 132.835 /Times-Italic +rf /Fm 134[66 66 96 66 66 37 52 44 1[66 66 66 103 37 +66 37 37 66 66 44 59 66 59 66 59 3[44 1[44 2[96 125 96 +96 81 74 89 1[74 96 96 118 81 96 1[44 96 96 74 81 96 +89 89 96 6[37 66 66 66 66 66 66 66 66 66 66 37 33 44 +33 2[44 44 37[74 2[{TeXBase1Encoding ReEncodeFont}66 +132.835 /Times-Roman rf /Fn 134[66 66 96 66 74 44 52 +59 1[74 66 74 111 37 1[44 37 74 66 44 59 74 59 74 66 +12[89 74 2[81 103 8[81 4[96 6[44 66 66 3[66 66 66 66 +66 1[33 4[44 44 40[{TeXBase1Encoding ReEncodeFont}40 +132.835 /Times-Bold rf /Fo 145[77 6[77 77 80[119 21[{}4 +149.44 /CMSY9 rf /Fp 135[100 100 100 100 100 100 100 +1[100 100 100 100 100 100 100 100 100 100 100 100 100 +100 100 100 7[100 1[100 100 100 100 100 100 1[100 100 +100 2[100 1[100 100 100 1[100 1[100 1[100 12[100 2[100 +2[100 100 100 1[100 100 100 4[100 35[{TeXBase1Encoding ReEncodeFont}49 +166.044 /Courier rf /Fq 133[74 3[83 1[55 65 3[83 5[46 +3[74 92 21[120 157 18[55 8[83 5[95 83 55 55 40[{ +TeXBase1Encoding ReEncodeFont}16 166.044 /Times-Bold +rf /Fr 133[65 74 74 111 74 83 46 65 65 1[83 83 83 120 +46 74 1[46 83 83 46 74 83 74 83 83 8[101 1[101 120 92 +83 101 1[101 120 111 138 92 2[55 1[120 101 101 120 111 +101 101 3[112 2[55 83 83 1[83 83 83 1[83 83 1[46 42 55 +42[83 2[{TeXBase1Encoding ReEncodeFont}56 166.044 /Times-Italic +rf /Fs 134[120 3[133 80 93 106 1[133 120 133 199 66 2[66 +2[80 106 133 106 133 120 14[173 1[146 6[93 7[173 13[120 +120 120 49[{TeXBase1Encoding ReEncodeFont}24 239.103 +/Times-Bold rf /Ft 134[83 1[116 1[91 1[83 58 2[91 91 +1[42 2[42 91 91 1[83 91 1[91 17[100 4[108 16[50 58[{ +TeXBase1Encoding ReEncodeFont}17 149.44 /Helvetica-Bold +rf /Fu 134[66 66 100 66 75 42 58 58 75 75 75 75 108 42 +66 1[42 75 75 42 66 75 66 75 75 8[91 124 91 108 83 75 +91 108 91 108 100 124 83 2[50 1[108 91 91 108 100 91 +91 5[50 50 5[75 75 75 75 75 1[37 50 37 4[50 36[75 2[{ +TeXBase1Encoding ReEncodeFont}57 149.44 /Times-Italic +rf /Fv 133[66 75 75 108 75 75 42 58 50 75 75 75 75 116 +42 75 42 42 75 75 50 66 75 66 75 66 3[50 1[50 2[108 141 +108 108 91 83 100 108 83 108 108 133 91 108 58 50 108 +108 83 91 108 100 100 108 5[42 42 75 75 75 75 75 75 75 +75 75 75 42 37 50 37 84 1[50 50 50 116 34[83 83 2[{ +TeXBase1Encoding ReEncodeFont}75 149.44 /Times-Roman +rf /Fw 134[75 75 1[75 83 50 58 66 1[83 75 83 124 42 83 +1[42 83 75 1[66 83 66 83 75 9[149 108 1[100 83 2[91 116 +108 141 100 2[58 1[116 1[100 108 108 1[108 18[37 46[{ +TeXBase1Encoding ReEncodeFont}37 149.44 /Times-Bold rf +/Fx 104[166 83 1[74 74 24[74 83 83 120 83 83 46 65 55 +83 83 83 83 129 46 83 46 46 83 83 55 74 83 74 83 74 3[55 +1[55 2[120 157 120 120 101 92 111 1[92 120 120 148 101 +120 1[55 120 120 92 101 120 111 111 120 153 74 4[46 83 +83 83 83 83 83 83 83 83 83 46 42 55 42 2[55 55 55 5[55 +29[92 92 2[{TeXBase1Encoding ReEncodeFont}77 166.044 +/Times-Roman rf /Fy 87[66 49[88 100 55 78 78 3[100 4[55 +100 2[88 1[88 1[100 11[144 111 6[166 35[66 66 40[{ +TeXBase1Encoding ReEncodeFont}17 199.253 /Times-Italic +rf /Fz 140[78 4[100 1[55 3[100 100 66 88 1[88 1[88 13[111 +133 12[122 22[50 46[{TeXBase1Encoding ReEncodeFont}13 +199.253 /Times-Roman rf /FA 134[100 100 144 100 111 66 +78 88 1[111 100 111 166 55 111 66 55 111 100 66 88 111 +88 111 100 9[199 1[144 133 111 144 1[122 155 1[188 1[155 +1[78 155 155 122 133 144 144 133 144 8[100 100 100 100 +100 100 100 100 2[50 66 3[66 66 1[166 34[111 111 2[{ +TeXBase1Encoding ReEncodeFont}57 199.253 /Times-Bold +rf /FB 138[191 115 1[153 2[172 191 1[96 2[96 191 172 +1[153 191 1[191 172 16[210 2[325 77[{TeXBase1Encoding ReEncodeFont}15 +344.375 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 1200dpi +TeXDict begin +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + end +%%EndSetup +%%Page: 1 1 +TeXDict begin 1 0 bop Black Black Black Black 2103 710 +a FB(P)-7 b(ortable)87 b(Multithr)-6 b(eading)1507 981 +y FA(The)50 b(Signal)f(Stack)h(T)-15 b(rick)51 b(F)-5 +b(or)50 b(User)-7 b(-Space)50 b(Thr)l(ead)g(Cr)l(eation)3133 +1416 y Fz(Ralf)h(S.)f(Engelschall)2296 1663 y Fy(T)-18 +b(ec)m(hnisc)m(he)50 b(Univer)n(sit)3973 1664 y(\250)3957 +1663 y(at)g(M)4344 1664 y(\250)4328 1663 y(unc)m(hen)g(\(TUM\))2217 +1909 y Fx(rse@engelschall.com,)39 b(http://www)-11 b(.engelschall.com)p +Black Black 3622 2470 a Fw(Abstract)p Black Black 415 +2744 a Fv(This)46 b(paper)h(describes)g(a)g(pragmatic)f(b)m(ut)g +(portable)f(f)o(allback)g(approach)i(for)f(creating)g(and)g +(dispatching)f(between)h(the)h(machine)415 2927 y(conte)n(xts)36 +b(of)g(multiple)f(threads)h(of)h(e)n(x)n(ecution)e(on)h(Unix)g(systems) +h(that)f(lack)h(a)g(dedicated)f(user)m(-space)i(conte)n(xt)d(switching) +g(f)o(acility)-10 b(.)415 3109 y(Such)44 b(a)h(f)o(allback)e(approach)h +(for)f(implementing)g(machine)h(conte)n(xts)f(is)h(a)h(vital)e(part)g +(of)h(a)g(user)m(-space)h(multithreading)d(en)-6 b(viron-)415 +3292 y(ment,)46 b(if)e(it)f(has)h(to)g(achie)l(v)n(e)h(maximum)f +(portability)d(across)j(a)h(wide)f(range)g(of)f(Unix)h(\003a)m(v)m +(ors.)67 b(The)44 b(approach)g(is)g(entirely)f(based)415 +3475 y(on)37 b(standard)h(Unix)f(system)h(f)o(acilities)e(and)h(ANSI-C) +h(language)f(features)h(and)g(especially)f(does)h(not)f(require)g(an)n +(y)h(assembly)g(code)415 3657 y(or)54 b(platform)f(speci\002c)i(tricks) +f(at)g(all.)98 b(The)55 b(most)f(interesting)e(issue)j(is)f(the)g +(technique)g(of)g(creating)f(the)i(machine)f(conte)n(xt)g(for)415 +3840 y(threads,)35 b(which)f(this)g(paper)h(e)n(xplains)e(in)h(detail.) +45 b(The)35 b(described)g(approach)f(closely)g(follo)l(ws)g(the)g +(algorithm)f(as)i(implemented)f(by)415 4023 y(the)40 +b(author)e(for)h(the)h(popular)e(user)m(-space)i(multithreading)d +(library)h Fu(GNU)i(P)-12 b(ortable)39 b(Thr)-6 b(eads)40 +b Fv(\()p Fu(GNU)f(Pth)p Fv(,)h([25)o(]\))g(which)f(this)f(w)o(ay)415 +4205 y(quickly)e(g)o(ained)h(the)g(status)g(of)f(one)i(of)e(the)h(most) +g(portable)f(user)m(-space)i(multithreading)d(libraries.)415 +4487 y Ft(K)n(e)n(yw)m(or)m(ds:)43 b Fv(portability)-10 +b(,)29 b(multithreading,)f(Unix,)j(POSIX,)e(SUSv2,)i(ANSI-C,)e(user)m +(-space,)j(conte)n(xt)d(creation,)i(conte)n(xt)d(switch-)415 +4670 y(ing,)37 b(signal)f(handler)-6 b(,)37 b(stack,)h(mak)o(econte)n +(xt,)f(switchconte)n(xt,)e(sig)o(altstack,)i(setjmp,)g(longjmp.)415 +4952 y Ft(Pub)o(lishing:)45 b Fv(Early)34 b(drafts)h(of)f(this)h(paper) +g(were)g(distrib)m(uted)e(with)g(the)i(GNU)g(Pth)g(distrib)m(ution.)42 +b(The)35 b(\002nal)g(release)h(v)n(ersion)e(w)o(as)415 +5135 y(published)i(on)g(the)h(USENIX)h(Annual)e(T)-10 +b(echnical)37 b(Conference,)h(June)f(18-23,)f(2000,)h(San)g(Die)n(go,)g +(California,)f(USA.)0 5895 y Fs(1)239 b(Intr)l(oduction)0 +6293 y FA(1.1)198 b(Multithr)l(eading)0 6634 y Fx(The)51 +b(paradigm)g(of)g(programming)h(with)f(multiple)g(threads)g(of)0 +6833 y(e)n(x)n(ecution)45 b(\(aka)h Fr(multithr)-6 b(eading)p +Fx(\))46 b(is)g(already)g(a)g(v)n(ery)g(old)g(one)0 7032 +y(and)k(dates)f(back)g(to)h(the)g(decades)e(of)i(programming)h(with)f +Fr(co-)0 7232 y(r)-7 b(outines)39 b Fx([2,)h(3].)51 b(P)n(aradoxically) +-11 b(,)39 b(the)h(use)g(of)g(threads)g(on)g(Unix)0 7431 +y(platforms)i(did)g(not)f(become)g(popular)h(until)g(the)f(early)h +(1990s.)0 7776 y FA(Multithr)l(eading)52 b(Adv)n(antages)0 +8057 y Fx(Multithreading)68 b(can)f(pro)n(vide)h(man)n(y)f(bene\002ts)h +(for)g(applica-)0 8256 y(tions)54 b(\(good)g(runtime)g(concurrenc)n(y) +-11 b(,)56 b(parallel)e(programming)0 8455 y(techniques)61 +b(can)g(be)g(implemented)h(more)f(easily)-11 b(,)66 b(the)c(popu-)0 +8654 y(lar)44 b(procedural)h(programming)g(style)f(can)g(be)g(combined) +g(with)0 8854 y(multiple)c(threads)f(of)h(e)n(x)n(ecution,)e +Fr(etc.)p Fx(\))50 b(b)m(ut)39 b(the)h(most)f(interest-)0 +9053 y(ing)52 b(ones)f(are)g(usually)g(performance)h(g)o(ains)f(and)h +(reduced)f(re-)0 9252 y(source)36 b(consumption.)49 b(Because)34 +b(in)j(contrast)f(to)g(multiprocess)0 9451 y(applications,)g +(multithreaded)f(ones)g(usually)g(require)g(less)g(sys-)0 +9651 y(tem)51 b(resources)f(\(mainly)h(memory\))h(and)e(their)i +(internal)f(com-)0 9850 y(munication)72 b(part)g(can)f(le)l(v)n(erage)f +(from)j(the)e(shared)g(address)0 10049 y(space.)0 10395 +y FA(Multithr)l(eading)52 b(and)d(A)-5 b(pplications)0 +10675 y Fx(Ne)l(v)n(ertheless)48 b(there)h(still)h(e)n(xist)f(just)g(a) +h(fe)l(w)f(real)h(applications)0 10874 y(in)70 b(the)h(free)f(softw)n +(are)g(w)n(orld)h(that)g(use)e(multithreading)i(for)0 +11073 y(their)43 b(bene\002t,)f(although)g(their)h(application)f +(domains)g(are)g(pre-)0 11272 y(destined)65 b(for)i(multithreading.)124 +b(F)n(or)66 b(instance,)71 b(the)66 b(popular)p Black +Black 4050 6293 a(Apache)79 b(webserv)n(er)f(as)h(of)h(v)n(ersion)f +(1.3)g(still)h(uses)e(a)i(pre-)4050 6492 y(forking)70 +b(process)e(model)h(for)g(serving)g(HTTP)h(requests,)75 +b(al-)4050 6692 y(though)33 b(tw)n(o)h(e)n(xperiments)e(with)h +(multithreaded)h(Apache)e(v)l(ari-)4050 6891 y(ants)44 +b(in)h(1996)f(\(with)h Fr(r)n(sthr)-6 b(eads)43 b Fx([27]\))j(and)e +(1998)g(\(with)h Fr(NSPR)4050 7090 y Fx([31]\))76 b(already)g(sho)l +(wed)e(great)i(performance)f(boosts.)153 b(The)4050 7289 +y(same)41 b(applies)g(to)g(man)n(y)g(similar)h(applications.)4299 +7587 y(The)j(reason)f(for)i(this)e(restraint)h(mainly)g(is)g(that)g +(for)g(a)g(long)4050 7787 y(time,)38 b(multithreading)g(f)n(acilities)f +(under)h(Unix)f(were)g(rare.)50 b(The)4050 7986 y(situation)d(became)g +(better)g(after)h(some)f(v)n(endors)f(lik)n(e)i Fr(Sun)f +Fx(and)4050 8185 y Fr(DEC)41 b Fx(incorporated)d(threading)f(f)n +(acilities)h(into)f(their)h(Unix)g(\003a-)4050 8384 y(v)m(ors)74 +b(and)f Fr(POSIX)83 b Fx(standardized)73 b(a)h(threading)g +Fr(Application)4050 8584 y(Pr)-7 b(o)n(gr)n(amming)38 +b(Interface)h Fx(\(API\))h(\(aka)f Fr(Pthr)-6 b(eads)39 +b Fx([1]\).)51 b(But)39 b(an)4050 8783 y(API)e(and)f(a)g(fe)l(w)f(v)n +(endor)h(implementations)g(are)g(not)h(enough)f(to)4050 +8982 y(ful\002ll)60 b(the)f(portability)g(requirements)g(of)g(modern)g +(free)g(soft-)4050 9181 y(w)n(are)75 b(packages.)151 +b(Here)75 b(stand-alone)g(and)g(really)g(portable)4050 +9381 y(multithreading)42 b(en)-7 b(vironments)42 b(are)f(needed.)4299 +9678 y(The)102 b(author)g(collected)f(and)g(e)l(v)l(aluated)f(o)n(v)n +(er)h(twenty)4050 9878 y(\(mostly)88 b(user)m(-space\))e(a)m(v)l +(ailable)h(multithreading)h(f)n(acilities)4050 10077 +y(for)33 b(Unix)g(systems)e(\(see)h(T)-13 b(able)32 b(1\),)i(b)m(ut)e +(only)h(a)f(fe)l(w)g(of)h(them)f(are)4050 10276 y(freely)57 +b(a)m(v)l(ailable)e(and)i(sho)l(wed)e(to)i(be)f(really)h(portable.)96 +b(And)4050 10475 y(e)l(v)n(en)41 b(the)h(mostly)g(portable)g(ones)f +(suf)l(fered)h(from)h(the)f(f)n(act)g(that)4050 10675 +y(the)n(y)64 b(partly)h(depend)f(on)g(assembly)f(code)h(or)h(platform)g +(spe-)4050 10874 y(ci\002c)56 b(tricks)g(usually)g(related)f(to)i(the)f +(creation)f(and)h(dispatch-)4050 11073 y(ing)51 b(of)g(the)f(indi)l +(vidual)h(threads.)78 b(This)51 b(means)f(that)h(the)f(num-)4050 +11272 y(ber)45 b(of)g(platforms)g(the)n(y)f(support)h(is)g(limited)g +(and)g(applications)p Black 3858 11872 a(1)p Black eop +end +%%Page: 2 2 +TeXDict begin 2 1 bop Black Black 0 638 a Fx(which)57 +b(are)g(based)f(on)h(these)g(f)n(acilities)g(are)g(only)h(portable)f +(to)0 838 y(those)44 b(platforms.)62 b(This)45 b(situation)g(is)g(not)g +(satisf)n(actory)-11 b(,)45 b(so)g(ap-)0 1037 y(plication)53 +b(authors)h(still)f(a)m(v)m(oid)g(the)g(use)g(of)g(multithreading)i(if) +0 1236 y(the)n(y)j(w)n(ant)g(to)g(\(or)h(ha)m(v)n(e)d(to\))j(achie)l(v) +n(e)e(maximum)h(portability)0 1435 y(for)42 b(their)g(application.)249 +1644 y(A)50 b(pragmatic)h(and)f(mostly)g(portable)h(f)n(allback)f +(technique)0 1844 y(for)45 b(implementing)h(user)m(-space)d(threads)h +(can)h(f)n(acilitate)g(wider)0 2043 y(use)c(of)h(multithreading)g(in)g +(free)f(softw)n(are)h(applications.)0 2370 y FA(Ingr)l(edients)50 +b(of)g(a)g(Thr)l(ead)0 2639 y Fx(A)i(Unix)f(process)g(has)g(man)n(y)g +(ingredients,)j(b)m(ut)d(the)h(most)f(im-)0 2838 y(portant)64 +b(ones)g(are)f(its)h(memory)h(mapping)f(table,)k(the)c(signal)0 +3037 y(dispatching)39 b(table,)g(the)h(signal)f(mask,)g(the)g(set)g(of) +h(\002le)f(descrip-)0 3236 y(tors)61 b(and)f(the)g(machine)g(conte)n +(xt.)107 b(The)61 b(machine)f(conte)n(xt)g(in)0 3436 +y(turn)54 b(consists)e(of)h(at)g(least)f(the)h(CPU)h(re)n(gisters)e +(including)h(the)0 3635 y(program)43 b(counter)e(and)h(the)g(stack)f +(pointer)-9 b(.)53 b(In)42 b(addition,)g(there)0 3834 +y(can)56 b(be)h(light-weight)g(processes)e(\(L)-12 b(WP\))58 +b(or)f(threads,)i(which)0 4033 y(usually)g(share)g(all)h(attrib)m(utes) +g(with)f(the)h(underlying)g(\(hea)m(vy-)0 4233 y(weight\))42 +b(process)e(e)n(xcept)h(for)h(the)f(machine)g(conte)n(xt.)0 +4560 y FA(K)-5 b(er)m(nel-Space)52 b(vs.)61 b(User)-7 +b(-Space)0 4828 y Fx(Those)55 b(L)-12 b(WPs)55 b(or)h(threads,)i(on)d +(a)h(Unix)f(platform)h(classically)0 5028 y(can)69 b(be)g(implemented)g +(either)h(in)f(k)n(ernel-space)g(or)h(in)f(user)m(-)0 +5227 y(space.)153 b(When)75 b(implemented)h(in)g(k)n(ernel-space,)83 +b(one)76 b(usu-)0 5426 y(ally)45 b(calls)f(them)h(L)-12 +b(WPs)45 b(or)g(k)n(ernel)g(threads,)g(otherwise)f(\(user)m(-)0 +5625 y(space\))38 b(threads.)49 b(If)40 b(threads)e(are)g(implemented)h +(by)g(the)f(k)n(ernel,)0 5825 y(the)50 b(thread)f(conte)n(xt)g +(switches)g(are)g(performed)h(by)g(the)g(k)n(ernel)0 +6024 y(without)36 b(notice)g(by)f(the)h(application,)g(similar)g(to)g +(the)f(dispatch-)0 6223 y(ing)68 b(of)g(processes.)128 +b(If)68 b(threads)f(are)h(implemented)g(in)f(user)m(-)0 +6422 y(space,)40 b(the)h(thread)g(conte)n(xt)g(switches)f(are)h +(performed)h(usually)0 6622 y(by)64 b(an)f(application)h(library)g +(without)g(notice)g(by)g(the)f(k)n(ernel.)0 6821 y(Additionally)-11 +b(,)85 b(there)76 b(e)n(xist)f(h)o(ybrid)i(threading)f(approaches,)0 +7020 y(where)58 b(typically)h(a)g(user)m(-space)e(library)j(binds)e +(one)h(or)g(more)0 7219 y(user)m(-space)40 b(threads)h(to)h(one)f(or)h +(more)f(k)n(ernel-space)g(L)-12 b(WPs.)0 7547 y FA(Thr)l(ead)50 +b(Models)0 7815 y Fx(The)57 b(v)n(endor)f(threading)h(f)n(acilities)g +(under)g Fr(Sun)g(Solaris)p Fx(,)j Fr(IBM)0 8014 y(AIX)p +Fx(,)j Fr(DEC)f(T)-9 b(ru64)62 b Fx(\(formerly)i Fr(DIGIT)-8 +b(AL)63 b(UNIX)70 b Fx(or)62 b Fr(OSF/1)p Fx(\))0 8214 +y(and)42 b Fr(SGI)h(IRIX)52 b Fx(use)42 b(a)g Fq(M:N)h +Fx(mapping)g([21,)f(30],)h Fr(i.e)n(.)p Fx(,)e Fq(M)h +Fx(user)m(-)0 8413 y(space)67 b(threads)g(are)h(mapped)g(onto)g +Fq(N)g Fx(k)n(ernel-space)g(L)-12 b(WPs.)0 8612 y(On)42 +b(the)f(other)h(hand,)g Fr(LinuxThr)-6 b(eads)41 b Fx([29])h(under)g +Fr(GNU/Linux)0 8811 y Fx(uses)34 b(a)i Fq(1:1)g Fx(mapping)f(and)h +(pure)f(user)m(-space)f(implementations)0 9011 y(lik)n(e)42 +b Fr(GNU)g(Pth)p Fx(,)g Fr(FSU)g(pthr)-6 b(eads)41 b +Fx(or)h Fr(MIT)h(pthr)-6 b(eads)p Fx(,)40 b Fr(etc.)52 +b Fx(use)41 b(a)0 9210 y Fq(M:1)h Fx(mapping)f([25)q(,)g(22,)g(23].)249 +9419 y(From)82 b(no)l(w)f(on)g(we)f(focus)h(on)g(such)f +Fq(M:1)i Fx(user)e(space)0 9618 y(threading)f(approaches,)87 +b(where)79 b(one)g(or)h(more)f(user)g(space)0 9817 y(threads)34 +b(are)g(implemented)g(inside)g(a)h(single)f(k)n(ernel)g(space)f(pro-)0 +10017 y(cess.)46 b(The)32 b(e)n(x)n(ercise)e(is)h(to)h(implement)g +(this)f(by)h(using)f(standard-)0 10216 y(ized)41 b(Unix)h(system)f(and) +g(ANSI-C)h(language)f(f)n(acilities)g Fr(only)p Fx(.)0 +10744 y FA(1.2)198 b(The)50 b(Exer)l(cise)0 11073 y Fx(As)45 +b(we)h(ha)m(v)n(e)e(mentioned,)i(a)g(thread)g(shares)e(its)i(state)f +(with)h(the)0 11272 y(underlying)57 b(process)f(e)n(xcept)g(for)i(the)f +(machine)f(conte)n(xt.)97 b(So)p Black Black 4050 638 +a(the)34 b(major)h(task)e(for)i(a)f(user)m(-space)e(threading)i(system) +g(is)g(to)g(cre-)4050 838 y(ate)41 b(and)g(dispatch)g(those)g(machine)g +(conte)n(xts.)4299 1037 y(In)35 b(practice,)g(the)f(second)g(major)h +(task)f(it)h(has)f(to)g(do)h(is)f(to)h(en-)4050 1236 +y(sure)42 b(that)h(no)g(thread)f(by)h(accident)f(blocks)g(the)h(whole)f +(process)4050 1436 y(\(and)53 b(thereby)f(all)h(other)g(threads\).)84 +b(Instead)52 b(when)h(an)f(opera-)4050 1635 y(tion)59 +b(w)n(ould)h(block,)j(the)58 b(threading)i(library)f(should)g(suspend) +4050 1834 y(only)40 b(the)g(e)n(x)n(ecution)e(of)i(the)g(current)g +(thread)g(and)f(in)h(the)g(mean-)4050 2033 y(time)h(dispatch)f(the)h +(remaining)g(threads.)51 b(But)41 b(this)f(task)h(is)g(out-)4050 +2233 y(side)61 b(the)g(scope)g(of)h(this)f(paper)g(\(see)g([11])h(for)g +(details)f(about)4050 2432 y(this)47 b(task\).)68 b(W)-13 +b(e)47 b(focus)f(only)i(on)f(the)g(aspect)g(of)g(machine)g(con-)4050 +2631 y(te)n(xt)41 b(handling.)4050 3107 y FA(1.3)198 +b(The)50 b(Curse)g(of)g(P)l(ortability)4050 3418 y Fx(Our)38 +b(goal)f(of)h(real)f(portability)i(for)f(a)f(threading)h(system)f +(causes)4050 3618 y(some)42 b(non-tri)l(vial)i(problems)f(which)f(ha)m +(v)n(e)g(to)h(be)f(solv)n(ed.)54 b(The)4050 3817 y(most)d(ob)n(vious)f +(one)h(is)f(that)h(dealing)g(with)g(machine)f(conte)n(xts)4050 +4016 y(usually)68 b(suf)l(fers)f(from)i(portability)-11 +b(,)75 b(because)67 b(it)h(is)g(a)g(highly)4050 4215 +y(CPU)35 b(dependent)f(task)h(for)g(which)g(not)g(e)l(v)n(ery)f(Unix)h +(\003a)m(v)m(or)f(pro-)4050 4415 y(vides)51 b(a)f(standardized)h(API.)g +(Although)g(such)f(an)h(API)h(w)n(ould)4050 4614 y(be)e(not)g(too)h +(hard)f(for)h(v)n(endors)e(to)h(pro)n(vide,)i(because)d(in)h(prin-)4050 +4813 y(ciple)45 b(it)h(is)f(just)h(a)f(matter)h(of)g(switching)f(a)g +(fe)l(w)g(CPU)h(re)n(gisters)4050 5012 y(\(mainly)c(the)f(program)i +(counter)e(and)g(the)h(stack)e(pointer\).)4050 5312 y +FA(Assembly)49 b(Code)g(Consider)l(ed)i(Harmful)4050 +5561 y Fx(Additionally)-11 b(,)49 b(we)d(disallo)l(w)h(the)g(use)f(of)i +(an)n(y)e(assembly)g(solu-)4050 5760 y(tions)39 b(or)h(platform)g +(speci\002c)e(tricks,)i(because)d(then)j(the)f(thread-)4050 +5959 y(ing)e(system)f(ag)o(ain)h(w)n(ould)g(be)f(only)h(semi-portable,) +h Fr(i.e)n(.)p Fx(,)d(it)j(can)4050 6159 y(be)d(ported)h(to)g +Fq(N)g Fx(platforms)g(b)m(ut)f(on)h(the)g Fq(\(N+1\))p +Fx(th)g(platform)g(one)4050 6358 y(has)56 b(to)h(manually)f(adjust)g +(or)h(e)l(v)n(en)e(e)n(xtend)h(it)h(to)g(w)n(ork)g(there,)4050 +6557 y(too.)4299 6756 y(This)52 b(is)g(usually)g(not)g(acceptable,)h(e) +l(v)n(en)d(if)j(it)f(also)f(mak)n(es)4050 6956 y(solving)43 +b(the)g(problems)g(harder)-9 b(.)56 b(At)43 b(least)g(most)g(of)g(the)g +(kno)l(wn)4050 7155 y(free)54 b(softw)n(are)h(user)m(-space)d +(threading)j(systems)e([22,)h(23,)g(24])4050 7354 y(do)32 +b(not)g(restrict)g(themself)g(to)g(this)g(and)f(therefore)i(are)e(just) +h(semi-)4050 7553 y(portable.)51 b(But)42 b(real)f(portability)h +(should)g(be)f(a)g(major)h(goal.)4050 8114 y Fs(2)239 +b(Pr)l(oblem)60 b(Analysis)4050 8519 y FA(2.1)198 b(The)50 +b(T)-18 b(ask)49 b(in)h(Detail)4050 8830 y Fx(Our)c(task)f(is)h(simple) +f(in)h(principle:)61 b(pro)n(vide)46 b(an)f(API)h(and)g(cor)m(-)4050 +9030 y(responding)h(implementation)h(for)f(creating)g(and)g +(dispatching)4050 9229 y(machine)33 b(conte)n(xts)g(on)h(which)f(user)m +(-space)f(threads)i(can)f(be)g(im-)4050 9428 y(plemented.)4050 +9727 y FA(The)50 b(Pr)l(oposed)f(API)4050 9977 y Fx(In)38 +b(detail)f(we)g(propose)g(the)g(follo)l(wing)h Fr(Application)g(Pr)-7 +b(o)n(gr)n(am-)4050 10176 y(mer)n(s)41 b(Interface)g +Fx(\(API\))h(for)g(the)g(machine)f(conte)n(xt)g(handling:)p +Black 4241 10541 100 100 v Black 4465 10541 a(A)51 b(data)f(structure)h +(of)g(type)g Fp(mctx)p 6531 10541 50 7 v 58 w(t)g Fx(which)f(holds)h +(the)4465 10741 y(machine)41 b(conte)n(xt.)p Black 4241 +11073 100 100 v Black 4465 11073 a(A)190 b(function)h(\223)p +Fq(v)n(oid)g Fp(mctx)p 6496 11073 50 7 v 59 w(create\(mctx)p +7655 11073 V 55 w(t)4465 11301 y(*)4565 11272 y Fr(mctx)p +Fx(,)54 b Fq(v)n(oid)f Fp(\()5430 11301 y(*)5530 11272 +y Fr(sf)p 5651 11272 V 59 w(addr)t Fp(\)\()p Fq(v)n(oid)e(*)p +Fp(\),)k Fq(v)n(oid)7264 11301 y Fp(*)7364 11272 y Fr(sf)p +7485 11272 V 59 w(ar)-6 b(g)p Fx(,)p Black 3858 11872 +a(2)p Black eop end +%%Page: 3 3 +TeXDict begin 3 2 bop Black Black Black 0 479 7727 7 +v 0 5355 7 4877 v 135 1757 a Fw(P)o(ackage)1106 1757 +y + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 1106 1757 a Fw(Genesis)1106 1757 y + currentpoint grestore moveto + 1106 1757 a 1488 +1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 1488 1757 a Fw(Latest)37 b(V)-15 b(ersion)1488 +1757 y + currentpoint grestore moveto + 1488 1757 a 2020 1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 2020 1757 a Fw(Implementation)37 +b(Space)2020 1757 y + currentpoint grestore moveto + 2020 1757 a 2808 1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 2808 1757 +a Fw(Thr)m(ead)h(Mapping)2808 1757 y + currentpoint grestore moveto + 2808 1757 a 3123 +1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 3123 1757 a Fw(Acti)o(v)o(e)e(De)n(v)o(elopment)3123 +1757 y + currentpoint grestore moveto + 3123 1757 a 3406 1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 3406 1757 a Fw(Experimental)h(State)3406 +1757 y + currentpoint grestore moveto + 3406 1757 a 3688 1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 3688 1757 a Fw(Open)h(Sour)m(ce)3688 +1757 y + currentpoint grestore moveto + 3688 1757 a 3970 1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 3970 1757 a Fw(Pthr)m(ead)g(API)3970 +1757 y + currentpoint grestore moveto + 3970 1757 a 4252 1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 4252 1757 a Fw(Pthr)m(ead)h(Shar)m(ed)f +(Memory)4252 1757 y + currentpoint grestore moveto + 4252 1757 a 4535 1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 4535 1757 +a Fw(Nati)o(v)o(e)d(API)4535 1757 y + currentpoint grestore moveto + 4535 1757 a 4817 +1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 4817 1757 a Fw(Nati)o(v)o(e)g(API)j Fo(\025)g +Fw(Pthr)m(ead)g(API)4817 1757 y + currentpoint grestore moveto + 4817 1757 a 5099 1757 +a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 5099 1757 a Fw(Nati)o(v)o(e)d(API)j(is)f(Pthr)m(ead)h(API)5099 +1757 y + currentpoint grestore moveto + 5099 1757 a 5531 1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 5531 1757 a Fw(Pr)m(eempti)o(v)o(e)g +(Scheduling)5531 1757 y + currentpoint grestore moveto + 5531 1757 a 5813 1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 5813 +1757 a Fw(P)m(ortability)5813 1757 y + currentpoint grestore moveto + 5813 1757 a 6719 +1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 6719 1757 a Fw(Assembly)g(Code)6719 1757 y + currentpoint grestore moveto + 6719 +1757 a 7018 1757 a + gsave currentpoint currentpoint translate 45 neg rotate neg exch neg +exch translate + 7018 1757 a Fw(SysCall)e(Wrap.)7018 +1757 y + currentpoint grestore moveto + 7018 1757 a 94 1819 7315 7 v 135 1947 a Fv(gnu-pth)504 +b(1999)82 b(1.3.5)233 b(user)539 b(n:1)123 b(yes)84 b(no)132 +b(yes)83 b(yes)g(no)133 b(yes)83 b(yes)g(no)282 b(no)132 +b(full/mcsc+sjlj)81 b(no)149 b(partly)135 2113 y(cmu-l)o(wp)440 +b(1984)82 b(1.4)345 b(user)539 b(n:1)123 b(yes)84 b(no)132 +b(yes)83 b(no)132 b(-)233 b(yes)83 b(yes)g(partly)f(no)132 +b(semi/\002x)n(ed:8)168 b(yes)100 b(no)135 2279 y(fsu-pthread)289 +b(1992)82 b(3.13)270 b(user)539 b(n:1)123 b(no)133 b(no)f(yes)83 +b(yes)g(no)133 b(no)f(-)232 b(-)382 b(yes)83 b(semi/\002x)n(ed:6)168 +b(yes)100 b(yes)135 2445 y(mit-pthread)272 b(1993)82 +b(1.8.9)233 b(user)539 b(n:1)123 b(no)133 b(no)f(yes)83 +b(yes)g(no)133 b(no)f(-)232 b(-)382 b(yes)83 b(semi/\002x)n(ed:17)93 +b(yes)100 b(yes)135 2611 y(ptl)812 b(1997)82 b(990622)g(user)539 +b(n:1)123 b(no)133 b(no)f(yes)83 b(yes)g(no)133 b(no)f(-)232 +b(-)382 b(yes)83 b(semi/\002x)n(ed:10)93 b(yes)100 b(yes)135 +2777 y(linuxthreads)230 b(1997)82 b(2.1.2)233 b(user+k)o(ernel)82 +b(1:1)123 b(yes)84 b(no)132 b(yes)83 b(yes)g(no)133 b(no)f(-)232 +b(-)382 b(yes)83 b(semi/\002x)n(ed:5)168 b(yes)100 b(yes)135 +2943 y(uthread)522 b(1998)82 b(3.4)345 b(user)539 b(n:1)123 +b(yes)84 b(no)132 b(yes)83 b(yes)g(no)133 b(no)f(-)232 +b(-)382 b(yes)83 b(semi/\002x)n(ed:2)168 b(yes)100 b(yes)135 +3109 y(cthread)531 b(1991)82 b(991115)g(user)539 b(n:1)123 +b(no)133 b(no)f(yes)83 b(no)132 b(-)233 b(yes)83 b(yes)g(no)282 +b(no)132 b(semi/\002x)n(ed:8)168 b(yes)100 b(yes)135 +3275 y(openthreads/qt)89 b(1996)82 b(2.0)345 b(user)539 +b(n:1)123 b(no)133 b(no)f(yes)83 b(no)132 b(-)233 b(yes)83 +b(no)132 b(no)282 b(no)132 b(semi/\002x)n(ed:9)168 b(yes)100 +b(no)135 3441 y(rt++/qt)552 b(1996)82 b(1.0)345 b(user)539 +b(n:1)123 b(no)133 b(no)f(yes)83 b(no)132 b(-)233 b(yes)83 +b(yes)g(no)282 b(no)132 b(semi/\002x)n(ed:9)168 b(yes)100 +b(no)135 3607 y(rsthreads)431 b(1996)82 b(980331)g(user)539 +b(n:1)123 b(no)133 b(yes)83 b(yes)g(no)132 b(-)233 b(yes)83 +b(no)132 b(no)282 b(no)132 b(semi/\002x)n(ed:9)168 b(yes)100 +b(no)135 3773 y(pcthread)456 b(1996)82 b(1.0)345 b(user)539 +b(n:1)123 b(no)133 b(yes)83 b(yes)g(yes)g(no)133 b(no)f(-)232 +b(-)382 b(yes)83 b(semi/\002x)n(ed:1)168 b(yes)100 b(no)135 +3939 y(bbthreads)389 b(1996)82 b(0.3)345 b(k)o(ernel)415 +b(1:1)123 b(no)133 b(yes)83 b(yes)g(no)132 b(-)233 b(yes)83 +b(no)132 b(-)382 b(yes)83 b(semi/\002x)n(ed:1)168 b(yes)100 +b(no)135 4105 y(jkthreads)422 b(1998)82 b(1.2)345 b(k)o(ernel)415 +b(1:1)123 b(no)133 b(yes)83 b(yes)g(no)132 b(-)233 b(yes)83 +b(no)132 b(-)382 b(yes)83 b(semi/\002x)n(ed:1)168 b(yes)100 +b(no)135 4271 y(nthreads)464 b(1997)82 b(970604)g(user)539 +b(n:1)123 b(no)133 b(yes)83 b(yes)g(no)132 b(-)233 b(yes)83 +b(no)132 b(-)382 b(no)132 b(semi/\002x)n(ed:9)168 b(yes)100 +b(partly)135 4437 y(re)n(xthreads)350 b(1993)82 b(930614)g(user)539 +b(n:1)123 b(no)133 b(yes)83 b(yes)g(no)132 b(-)233 b(yes)83 +b(no)132 b(-)382 b(no)132 b(semi/\002x)n(ed:4)168 b(yes)100 +b(no)135 4603 y(coro)705 b(1999)82 b(1.0.3)233 b(user)539 +b(n:1)123 b(no)133 b(yes)83 b(yes)g(no)132 b(-)233 b(yes)83 +b(no)132 b(-)382 b(no)132 b(semi/\002x)n(ed:1)168 b(yes)100 +b(no)135 4769 y(greenthreads)207 b(1995)82 b(1.2)345 +b(user)539 b(n:1)123 b(no)133 b(no)f(no)g(no)g(-)233 +b(yes)83 b(yes)g(-)382 b(yes)83 b(full/mcsc)349 b(no)149 +b(no)135 4935 y(solaris-pthread)81 b(NN)166 b(2.7)345 +b(user+k)o(ernel)82 b(n:m)g(yes)i(no)132 b(no)g(yes)83 +b(yes)h(yes)f(yes)g(no)282 b(yes)83 b(NN)690 b(NN)83 +b(yes)135 5101 y(tru64-pthread)155 b(NN)166 b(5.0)345 +b(user+k)o(ernel)82 b(n:m)g(yes)i(no)132 b(no)g(yes)83 +b(yes)h(no)132 b(no)g(no)282 b(yes)83 b(NN)690 b(NN)83 +b(yes)135 5267 y(aix-pthread)289 b(NN)166 b(4.3)345 b(user+k)o(ernel)82 +b(1:1)123 b(yes)84 b(no)132 b(no)g(yes)83 b(yes)h(no)132 +b(no)g(no)282 b(yes)83 b(NN)690 b(NN)83 b(yes)p 7719 +5355 7 4877 v 0 5362 7727 7 v 0 5537 a Fn(T)-12 b(able)33 +b(1:)133 b Fm(Summary)42 b(of)f(e)m(v)m(aluated)g(multithreading)i +(packages)e(and)g(some)g(of)g(their)g(determined)h(characteristics.)63 +b(Notice)41 b(that)f(mostly)h(all)g(packages)g(contain)589 +5673 y(assembly)34 b(code)g(and)g(are)f(just)g(semi-portable,)i +Fl(i.e)n(.)p Fm(,)f(the)n(y)g(support)h(only)f(a)f(\002x)n(ed)h(set)f +(of)h(platforms)g(and)g(do)g(not)g(automatically)h(adjust)e(for)h(ne)m +(w)f(ones.)p Black 415 6199 a Fq(v)n(oid)764 6228 y Fp(*)864 +6199 y Fr(sk)p 1013 6199 50 7 v 59 w(addr)p Fx(,)47 b +Fq(size)p 1734 6199 V 59 w(t)f Fr(sk)p 2033 6199 V 59 +w(size)p Fp(\))p Fx(\224)f(which)h(creates)f(and)415 +6399 y(initializes)35 b(a)g(machine)g(conte)n(xt)g(structure)g(in)g +Fr(mctx)h Fx(with)415 6598 y(a)51 b(start)g(function)g +Fr(sf)p 1602 6598 V 60 w(addr)p Fx(,)h(a)f(start)f(function)i(ar)m +(gument)415 6797 y Fr(sf)p 536 6797 V 60 w(ar)-6 b(g)p +Fx(,)73 b(and)68 b(a)f(stack)g(starting)h(at)g Fr(sk)p +2687 6797 V 59 w(addr)p Fx(,)74 b(which)67 b(is)415 6996 +y Fr(sk)p 564 6996 V 59 w(size)41 b Fx(bytes)g(in)g(size.)p +Black 191 7480 100 100 v Black 415 7480 a(A)46 b(function)g(\223)p +Fq(v)n(oid)h Fp(mctx)p 2013 7480 50 7 v 58 w(save\(mctx)p +2971 7480 V 56 w(t)3163 7509 y(*)3263 7480 y Fr(mctx)p +Fp(\))p Fx(\224)415 7679 y(which)56 b(sa)m(v)n(es)e(the)i(current)g +(machine)f(conte)n(xt)h(into)g(the)415 7878 y(machine)41 +b(conte)n(xt)g(structure)h Fr(mctx)p Fx(.)p Black 191 +8362 100 100 v Black 415 8362 a(A)157 b(function)h(\223)p +Fq(v)n(oid)g Fp(mctx)p 2347 8362 50 7 v 58 w(restore\(mctx)p +3605 8362 V 55 w(t)415 8590 y(*)515 8561 y Fr(mctx)p +Fp(\))p Fx(\224)81 b(which)h(restores)g(the)g(ne)l(w)f(machine)h(con-) +415 8760 y(te)n(xt)38 b(from)i(the)e(machine)h(conte)n(xt)f(structure)g +Fr(mctx)p Fx(.)50 b(This)415 8960 y(function)64 b(does)f(not)h(return)g +(to)g(the)g(caller)-9 b(.)117 b(Instead)63 b(it)415 9159 +y(does)39 b(return)h(at)f(the)h(location)f(stored)h(in)f +Fr(mctx)h Fx(\(which)f(is)415 9358 y(either)c Fr(sf)p +949 9358 V 60 w(addr)j Fx(from)d(a)g(pre)l(vious)f Fp(mctx)p +2829 9358 V 59 w(create)e Fx(call)415 9557 y(or)42 b(the)f(location)h +(of)g(a)f(pre)l(vious)g Fp(mctx)p 2730 9557 V 58 w(save)f +Fx(call\).)p Black 191 10041 100 100 v Black 415 10041 +a(A)190 b(function)h(\223)p Fq(v)n(oid)g Fp(mctx)p 2446 +10041 50 7 v 59 w(switch\(mctx)p 3605 10041 V 55 w(t)415 +10269 y(*)515 10240 y Fr(mctx)p 839 10240 V 59 w(old)p +Fx(,)40 b Fp(mctx)p 1592 10240 V 59 w(t)1780 10269 y(*)1880 +10240 y Fr(mctx)p 2204 10240 V 59 w(ne)n(w)p Fp(\))p +Fx(\224)f(which)h(switches)415 10439 y(from)123 b(the)f(current)h +(machine)e(conte)n(xt)h(\(sa)m(v)n(ed)f(to)415 10639 +y Fr(mctx)p 739 10639 V 59 w(old)59 b Fx(for)54 b(later)f(use\))g(to)h +(a)f(ne)l(w)g(conte)n(xt)g(\(restored)415 10838 y(from)47 +b Fr(mctx)p 1108 10838 V 59 w(ne)n(w)p Fx(\).)63 b(This)47 +b(function)f(returns)g(only)g(to)g(the)415 11037 y(caller)81 +b(if)g Fp(mctx)p 1457 11037 V 58 w(restore)d Fx(or)j +Fp(mctx)p 2912 11037 V 59 w(switch)d Fx(is)415 11236 +y(ag)o(ain)41 b(used)g(on)h Fr(mctx)p 1693 11236 V 59 +w(old)p Fx(.)p Black Black 4050 6199 a FA(2.2)198 b(T)-18 +b(echnical)51 b(P)l(ossibilities)4050 6513 y Fx(Poking)39 +b(around)g(in)g(the)g(references)f(of)h(the)f(ANSI-C)i(language)4050 +6712 y(reference)77 b(and)f(the)h(Unix)h(standards)e(sho)l(w)g(the)h +(follo)l(wing)4050 6911 y(functions)42 b(on)f(which)g(an)h +(implementation)g(can)f(be)g(based:)p Black 4241 7281 +100 100 v Black 4465 7281 a(There)113 b(is)g(the)f Fp(ucontext)p +Fx(\(3\))f(f)n(acility)i(with)g(the)4465 7480 y(functions)73 +b Fp(getcontext)p Fx(\(3\),)78 b Fp(makecontext)p Fx(\(3\),)4465 +7679 y Fp(swapcontext)p Fx(\(3\))67 b(and)i Fp(setcontext)p +Fx(\(3\))e(which)4465 7879 y(conform)50 b(to)f(the)g +Fr(Single)g(Unix)g(Speci\002cation)p Fx(,)h(V)-18 b(ersion)4465 +8078 y(2)77 b(\()p Fr(SUSv2)g Fx([20)q(],)86 b(aka)76 +b Fr(Unix95/98)p Fx(\).)159 b(Unfortunately)4465 8277 +y(these)32 b(are)h(a)m(v)l(ailable)f(on)h(modern)g(Unix)h(platforms)f +(only)-11 b(.)p Black 4241 8614 V Black 4465 8614 a(There)178 +b(are)f(the)h Fp(jmp)p 6101 8614 50 7 v 59 w(buf)e Fx(based)h +(functions)4465 8813 y Fp(setjmp)p Fx(\(3\))62 b(and)g +Fp(longjmp)p Fx(\(3\))f(which)i(conform)h(to)4465 9012 +y(ISO)83 b(9899:1990)g(\(ISO-C\))h(and)f(the)g Fp(sigjmp)p +7454 9012 V 57 w(buf)4465 9211 y Fx(based)145 b Fp(sigsetjmp)p +Fx(\(3\))e(and)i Fp(siglongjmp)p Fx(\(3\))4465 9411 y(functions)39 +b(which)g(conform)g(to)g(IEEE)h(Std1003.1-1988)4465 9610 +y(\()p Fr(POSIX)7 b Fx(\),)43 b(and)e Fr(Single)g(Unix)g +(Speci\002cation)p Fx(,)g(V)-18 b(ersion)40 b(2)4465 +9809 y(\()p Fr(SUSv2)50 b Fx([20],)i(aka)d Fr(Unix95/98)p +Fx(\).)76 b(The)50 b(\002rst)g(tw)n(o)g(func-)4465 10008 +y(tions)37 b(are)f(a)m(v)l(ailable)g(really)g(on)h(all)g(Unix)g +(platforms,)g(the)4465 10208 y(last)k(tw)n(o)h(are)f(a)m(v)l(ailable)g +(only)h(on)f(some)g(of)h(them.)4465 10475 y(On)j(some)f(platforms)h +Fp(setjmp)p Fx(\(3\))e(and)h Fp(longjmp)p Fx(\(3\))4465 +10675 y(sa)m(v)n(e)91 b(and)h(restore)g(also)g(the)h(signal)f(mask)g +(\(if)h(one)4465 10874 y(does)c(not)h(w)n(ant)g(this)g(semantics,)100 +b(one)90 b(has)f(to)h(call)p 4465 11073 V 4515 11073 +a Fp(setjmp)p Fx(\(3\))74 b(and)p 5708 11073 V 136 w +Fp(longjmp)p Fx(\(3\))g(there\))j(while)f(on)4465 11272 +y(others)106 b(one)h(has)f(to)g(e)n(xplicitly)h(use)e(the)i(superset)p +Black 3858 11872 a(3)p Black eop end +%%Page: 4 4 +TeXDict begin 4 3 bop Black Black 415 638 a Fx(functions)66 +b Fp(sigsetjmp)p Fx(\(3\))d(and)i Fp(siglongjmp)p Fx(\(3\))415 +838 y(for)108 b(this.)250 b(In)107 b(our)h(discussion)f(we)g(can)g +(assume)415 1037 y(that)75 b Fp(setjmp)p Fx(\(3\))f(and)g +Fp(longjmp)p Fx(\(3\))g(sa)m(v)n(e)f(and)i(re-)415 1236 +y(store)69 b(the)g(signal)f(mask,)75 b(because)68 b(if)h(this)g(is)g +(not)g(the)415 1435 y(case)95 b(in)h(practice,)108 b(one)95 +b(easily)h(can)f(replace)g(them)415 1635 y(with)54 b +Fp(sigsetjmp)p Fx(\(3\))d(and)j Fp(siglongjmp)p Fx(\(3\))d(calls)415 +1834 y(\(if)93 b(a)m(v)l(ailable\))f(or)h(\(if)g(not)g(a)m(v)l +(ailable\))f(emulate)g(the)415 2033 y(missing)98 b(functionality)h +(manually)f(with)g(additional)415 2233 y Fp(sigprocmask)p +Fx(\(2\))c(calls)i(\(see)g Fp(pth)p 2877 2233 50 7 v +59 w(mctx.c)f Fx(in)415 2432 y Fr(GNU)41 b(Pth)h Fx([25)q(]\).)p +Black 191 2772 100 100 v Black 415 2772 a(There)77 b(is)g(the)g +(function)h Fp(sigaltstack)p Fx(\(2\))73 b(which)415 +2971 y(conforms)i(to)g(the)f Fr(Single)h(Unix)f(Speci\002cation)p +Fx(,)83 b(V)-18 b(er)m(-)415 3171 y(sion)69 b(2)h(\()p +Fr(SUSv2)g Fx([20],)76 b(aka)69 b Fr(Unix95/98)p Fx(\))h(and)g(its)f +(an-)415 3370 y(cestor)52 b(function)g Fp(sigstack)p +Fx(\(2\))e(from)i Fr(4.2BSD)p Fx(.)g(The)415 3569 y(last)41 +b(one)g(e)n(xists)f(only)i(on)f Fr(BSD)p Fx(-deri)l(v)n(ed)h +(platforms,)f(b)m(ut)415 3768 y(the)f(\002rst)h(function)f(already)g(e) +n(xists)f(on)h(all)h(current)f(Unix)415 3968 y(platforms.)0 +4454 y FA(2.3)198 b(Maximum)50 b(P)l(ortability)g(Solution)0 +4770 y Fx(The)141 b(maximum)h(portable)f(solution)g(ob)n(viously)g(is)g +(to)0 4969 y(use)160 b(the)h(standardized)f Fp(makecontext)p +Fx(\(3\))e(function)0 5168 y(to)176 b(create)f(threads)g(and)g +Fp(switchcontext)p Fx(\(3\))d(or)0 5367 y Fp(getcontext)p +Fx(\(3\)/)p Fp(setcontext)p Fx(\(3\))83 b(to)90 b(dispatch)e(them.)0 +5567 y(And)65 b(actually)g(these)g(are)g(the)h(preferred)f(functions)h +(modern)0 5766 y(user)m(-space)52 b(multithreading)j(systems)e(are)h +(using.)88 b(W)-13 b(e)53 b(could)0 5965 y(easily)78 +b(implement)i(our)f(proposed)g(API)h(as)e(follo)l(wing)i(\(all)0 +6164 y(error)42 b(checks)e(omitted)i(for)g(better)g(readability\):)p +Black Black 0 6490 a Fk(/)90 6516 y(*)306 6490 y Fj(mac)o(hine)c +(context)e(data)g(structure)2308 6516 y Fk(*)2398 6490 +y(/)0 6640 y Fi(typedef)87 b(struct)h Fk(mctx_st)f Fo(f)359 +6789 y Fk(ucontext_t)f(uc;)0 6939 y Fo(g)j Fk(mctx_t;)0 +7238 y(/)90 7264 y(*)306 7238 y Fj(sav)n(e)38 b(mac)o(hine)f(context) +1713 7264 y Fk(*)1803 7238 y(/)0 7387 y Fi(#define)87 +b Fk(mctx_save\(mctx\))e Fo(n)359 7536 y Fk(\()p Fi(void)p +Fk(\)getcontext\(&\(mctx\)->uc)o(\))0 7835 y(/)90 7861 +y(*)306 7835 y Fj(restore)38 b(mac)o(hine)f(context)1873 +7861 y Fk(*)1963 7835 y(/)0 7985 y Fi(#define)87 b Fk +(mctx_restore\(mctx\))d Fo(n)359 8134 y Fk(\()p Fi(void)p +Fk(\)setcontext\(&\(mctx\)->uc)o(\))0 8433 y(/)90 8459 +y(*)306 8433 y Fj(switc)o(h)37 b(mac)o(hine)g(context)1838 +8459 y Fk(*)1928 8433 y(/)0 8583 y Fi(#define)87 b Fk +(mctx_switch\(mctx_old,mctx_new\))80 b Fo(n)359 8732 +y Fk(\()p Fi(void)p Fk(\)swapcontext\(&\(\(mctx_ol)o(d\)-)o(>uc)o(\),)g +Fo(n)1973 8881 y Fk(&\(\(mctx_new\)->uc\)\))0 9180 y(/)90 +9206 y(*)306 9180 y Fj(create)38 b(mac)o(hine)f(context)1823 +9206 y Fk(*)1913 9180 y(/)0 9330 y Fi(void)88 b Fk(mctx_create\()359 +9479 y(mctx_t)986 9505 y(*)1076 9479 y(mctx,)359 9629 +y Fi(void)g Fk(\()897 9655 y(*)987 9629 y(sf_addr\)\()p +Fi(void)2242 9655 y Fk(*)2332 9629 y(\),)g Fi(void)3049 +9655 y Fk(*)3139 9629 y(sf_arg,)359 9778 y Fi(void)807 +9804 y Fk(*)897 9778 y(sk_addr,)f(size_t)g(sk_size\))0 +9927 y Fo(f)359 10226 y Fk(/)449 10252 y(*)665 10226 +y Fj(f)o(etc)o(h)36 b(current)j(context)2039 10252 y +Fk(*)2129 10226 y(/)359 10376 y(getcontext\(&\(mctx->uc\)\);)359 +10675 y(/)449 10701 y(*)665 10675 y Fj(adjust)d(to)h(new)g(context)2055 +10701 y Fk(*)2145 10675 y(/)359 10824 y(mctx->uc.uc_link)981 +b(=)89 b(NULL;)359 10974 y(mctx->uc.uc_stack.ss_sp)351 +b(=)89 b(sk_addr;)359 11123 y(mctx->uc.uc_stack.ss_size)171 +b(=)89 b(sk_size;)359 11272 y(mctx->uc.uc_stack.ss_flags)81 +b(=)89 b(0;)p Black Black 4409 788 a(/)4499 814 y(*)4715 +788 y Fj(mak)l(e)37 b(new)g(context)5905 814 y Fk(*)5995 +788 y(/)4409 937 y(makecontext\(&\(mctx->uc\),)5485 1087 +y(sf_addr,)87 b(1,)i(sf_arg\);)4409 1236 y Fi(return)p +Fk(;)4050 1386 y Fo(g)4050 1762 y Fx(Unfortunately)36 +b(there)f(are)g(still)g(lots)h(of)f(Unix)h(platforms)f(where)4050 +1961 y(this)85 b(approach)h(cannot)f(be)g(used,)96 b(because)84 +b(the)h(standard-)4050 2160 y(ized)80 b Fp(ucontext)p +Fx(\(3\))e(API)j(is)f(not)h(pro)n(vided)f(by)g(the)g(v)n(en-)4050 +2360 y(dor)-9 b(.)162 b(Actually)78 b(the)g(platform)i(test)e(results)g +(for)h Fr(GNU)e(Pth)4050 2559 y Fx(\(see)58 b(T)-13 b(able)59 +b(2)g(belo)l(w\))g(sho)l(wed)f(that)h(only)g(7)g(of)h(21)f(success-) +4050 2758 y(fully)54 b(tested)f(Unix)g(\003a)m(v)m(ors)g(pro)n(vided)h +(the)f(standardized)g(API)4050 2957 y(\()p Fp(makecontext)p +Fx(\(3\),)43 b Fr(etc.)p Fx(\).)62 b(On)46 b(all)f(other)h(platforms,)g +Fr(GNU)4050 3157 y(Pth)64 b Fx(w)n(as)f(forced)h(to)g(use)e(the)i(f)n +(allback)g(approach)f(of)g(imple-)4050 3356 y(menting)53 +b(the)g(machine)g(conte)n(xt)g(as)f(we)h(will)g(describe)g(in)g(the) +4050 3555 y(follo)l(wing.)93 b(Ob)n(viously)54 b(this)i(f)n(allback)f +(approach)g(has)f(to)i(use)4050 3754 y(the)73 b(remaining)h(technical)f +(possibilities)g(\()p Fp(sigsetjmp)p Fx(\(3\),)4050 3954 +y Fr(etc.)p Fx(\).)p 4050 4114 3798 7 v 4050 7921 7 3807 +v 4206 4274 a Fn(Operating)34 b(System)p 5674 4322 7 +158 v 552 w(Ar)n(chitectur)n(e\(s\))p 6901 4322 V 368 +w(mcsc)p 7387 4322 V 205 w(sjlj)4206 4432 y Fm(FreeBSD)f(2.x/3.x)p +5674 4479 V 679 w(Intel)p 6901 4479 V 984 w(no)p 7387 +4479 V 354 w(yes)4206 4590 y(FreeBSD)g(3.x)p 5674 4637 +V 881 w(Intel,)h(Alpha)p 6901 4637 V 593 w(no)p 7387 +4637 V 354 w(yes)4206 4748 y(NetBSD)e(1.3/1.4)p 5674 +4795 V 724 w(Intel,)i(PPC,)f(M68K)p 6901 4795 V 268 w(no)p +7387 4795 V 354 w(yes)4206 4905 y(OpenBSD)g(2.5/2.6)p +5674 4953 V 628 w(Intel,)h(SP)-12 b(ARC)p 6901 4953 V +507 w(no)p 7387 4953 V 354 w(yes)4206 5063 y(BSDI)33 +b(4.0)p 5674 5110 V 1073 w(Intel)p 6901 5110 V 984 w(no)p +7387 5110 V 354 w(yes)4206 5221 y(Linux)i(2.0.x)g(glibc)e(1.x/2.0)p +5674 5268 V 259 w(Intel,)h(SP)-12 b(ARC,)32 b(PPC)p 6901 +5268 V 205 w(no)p 7387 5268 V 354 w(yes)4206 5379 y(Linux)j(2.2.x)g +(glibc)e(2.0/2.1)p 5674 5426 V 259 w(Intel,)h(Alpha,)g(ARM)p +6901 5426 V 223 w(no)p 7387 5426 V 354 w(yes)4206 5536 +y(Sun)g(SunOS)g(4.1.x)p 5674 5584 V 660 w(SP)-12 b(ARC)p +6901 5584 V 817 w(no)p 7387 5584 V 354 w(yes)4206 5694 +y(Sun)34 b(Solaris)f(2.5/2.6/2.7)p 5674 5741 V 363 w(SP)-12 +b(ARC)p 6901 5741 V 817 w(yes)p 7387 5741 V 309 w(yes)4206 +5852 y(SCO)33 b(UnixW)-11 b(are)34 b(2.x/7.x)p 5674 5899 +V 340 w(Intel)p 6901 5899 V 984 w(yes)p 7387 5899 V 309 +w(yes)4206 6010 y(SCO)f(OpenServ)n(er)h(5.0.x)p 5674 +6057 V 353 w(Intel)p 6901 6057 V 984 w(no)p 7387 6057 +V 354 w(yes)4206 6167 y(IBM)f(AIX)g(4.1/4.2/4.3)p 5674 +6215 V 452 w(RS6000,)i(PPC)p 6901 6215 V 495 w(yes)p +7387 6215 V 309 w(yes)4206 6325 y(HP)e(HPUX)g(9.10/10.20)p +5674 6372 V 411 w(HPP)-12 b(A)p 6901 6372 V 899 w(no)p +7387 6372 V 354 w(yes)4206 6483 y(HP)33 b(HPUX)g(11.0)p +5674 6530 V 745 w(HPP)-12 b(A)p 6901 6530 V 899 w(yes)p +7387 6530 V 309 w(yes)4206 6641 y(SGI)33 b(IRIX)g(5.3)p +5674 6688 V 856 w(MIPS)g(32/64)p 6901 6688 V 583 w(no)p +7387 6688 V 354 w(yes)4206 6798 y(SGI)g(IRIX)g(6.2/6.5)p +5674 6846 V 654 w(MIPS)g(32/64)p 6901 6846 V 583 w(yes)p +7387 6846 V 309 w(yes)4206 6956 y(ISC)g(4.0)p 5674 7003 +V 1169 w(Intel)p 6901 7003 V 984 w(no)p 7387 7003 V 354 +w(yes)4206 7114 y(Apple)h(MacOS)f(X)p 5674 7161 V 681 +w(PPC)p 6901 7161 V 990 w(no)p 7387 7161 V 354 w(yes)4206 +7271 y(DEC)g(OSF1/T)-5 b(ru64)35 b(4.0/5.0)p 5674 7319 +V 208 w(Alpha)p 6901 7319 V 903 w(yes)p 7387 7319 V 309 +w(yes)4206 7429 y(SNI)e(ReliantUNIX)p 5674 7477 V 611 +w(MIPS)p 6901 7477 V 917 w(yes)p 7387 7477 V 309 w(yes)4206 +7587 y(Amig)o(aOS)p 5674 7634 V 1044 w(M68K)p 6901 7634 +V 881 w(no)p 7387 7634 V 354 w(yes)p 7841 7921 7 3807 +v 4050 7928 3798 7 v 4050 8102 a Fn(T)-12 b(able)33 b(2:)133 +b Fm(Summary)43 b(of)e(operating)i(system)e(support.)66 +b(The)42 b(le)m(v)n(el)e(and)i(type)4639 8238 y(of)k(support)h(found)h +(on)e(each)g(tested)f(operating)i(system.)78 b Fh(mcsc)p +Fm(:)4639 8374 y(functional)331 b Fh(makecontext)p Fm(\(3\)/)p +Fh(switchcontext)p Fm(\(3\),)4639 8505 y Fh(sjlj)p Fm(:)165 +b(functional)98 b Fh(setjmp)p Fm(\(3\)/)p Fh(longjmp)p +Fm(\(3\))c(or)i Fh(sig-)4639 8635 y(setjmp)p Fm(\(3\)/)p +Fh(siglongjmp)p Fm(\(3\).)51 b(See)37 b(\002le)g Fh(PORTING)e +Fm(in)j Fl(GNU)4639 8766 y(Pth)c Fm([25)q(])f(for)i(more)f(details.) +4050 9199 y FA(2.4)198 b(Remaining)50 b(P)l(ossibilities)4050 +9515 y Fx(Our)g(problem)f(can)g(be)g(di)l(vided)h(into)f(tw)n(o)h +(parts,)h(an)e(easy)f(one)4050 9715 y(and)41 b(a)h(dif)l(\002cult)g +(one.)4050 10022 y FA(The)50 b(Easy)e(P)n(art)4050 10276 +y Fx(That)59 b Fp(setjmp)p Fx(\(3\))f(and)h Fp(longjmp)p +Fx(\(3\))e(can)h(be)h(used)f(to)h(im-)4050 10475 y(plement)43 +b(user)m(-space)e(threads)h(is)g(commonly)h(kno)l(wn)g([24,)f(27,)4050 +10675 y(28].)116 b(Mostly)62 b(all)h(older)g(portable)g(user)m(-space)e +(threading)i(li-)4050 10874 y(braries)53 b(are)f(based)g(on)h(them,)i +(although)e(some)f(problems)h(are)4050 11073 y(kno)l(wn)i(with)h(these) +f(f)n(acilities)g(\(see)g(belo)l(w\).)93 b(So)55 b(it)h(becomes)4050 +11272 y(clear)g(that)h(we)f(also)g(ha)m(v)n(e)f(to)i(use)e(these)h +(functions)h(and)f(base)p Black 3858 11872 a(4)p Black +eop end +%%Page: 5 5 +TeXDict begin 5 4 bop Black Black 0 638 a Fx(our)58 b(machine)g(conte)n +(xt)g(\()p Fp(mctx)p 1910 638 50 7 v 58 w(t)p Fx(\))g(on)g(their)h +Fp(jmp)p 3068 638 V 58 w(buf)e Fx(data)0 838 y(structure.)249 +1038 y(W)-13 b(e)77 b(immediately)h(recognize)f(that)g(this)h(w)n(ay)f +(we)g(ha)m(v)n(e)0 1237 y(at)82 b(least)f(solv)n(ed)g(the)h +(dispatching)g(problem,)92 b(because)81 b(our)0 1437 +y Fp(mctx)p 410 1437 V 58 w(save)p Fx(,)146 b Fp(mctx)p +1456 1437 V 58 w(restore)124 b Fx(and)i Fp(mctx)p 3104 +1437 V 58 w(switch)0 1636 y Fx(functions)67 b(can)g(be)g(easily)g +(implemented)g(with)h Fp(setjmp)p Fx(\(3\))0 1835 y(and)41 +b Fp(longjmp)p Fx(\(3\).)0 2137 y FA(The)50 b(Dif\002cult)h(P)n(art)0 +2389 y Fx(Ne)l(v)n(ertheless,)j(the)f(dif)l(\002cult)i(problem)e(of)h +(ho)l(w)g(to)f(create)g(the)0 2588 y(machine)62 b(conte)n(xt)g +(remains.)114 b(Ev)n(en)62 b(kno)l(wing)g(that)h(our)g(ma-)0 +2787 y(chine)54 b(conte)n(xt)h(is)f Fp(jmp)p 1431 2787 +V 59 w(buf)g Fx(based)g(is)g(no)h(adv)l(antage)f(to)h(us.)0 +2987 y(A)k Fp(jmp)p 489 2987 V 58 w(buf)f Fx(has)h(to)g(be)g(treated)f +(by)h(us)g(as)f(an)h(opaque)f(data)0 3186 y(structure)45 +b(\227)g(for)h(portability)g(reasons.)61 b(The)45 b(only)g(operations)0 +3385 y(we)51 b(can)f(perform)i(on)f(it)g(are)g Fp(setjmp)p +Fx(\(3\))e(and)i Fp(longjmp)p Fx(\(3\))0 3584 y(calls,)89 +b(of)81 b(course.)166 b(Additionally)-11 b(,)91 b(we)80 +b(are)g(forced)g(to)h(use)0 3784 y Fp(sigaltstack)p Fx(\(3\))36 +b(for)j(our)h(stack)e(manipulations,)h(because)0 3983 +y(it)k(is)f(the)h(only)g(portable)f(function)h(which)g(actually)f +(deals)g(with)0 4182 y(stacks.)249 4382 y(So)67 b(it)h(is)e(clear)h +(that)g(our)g(implementation)h(for)f Fp(mctx)p 3602 4382 +V 58 w(-)0 4582 y(create)72 b Fx(has)i(to)h(play)g(a)f(fe)l(w)h(tricks) +f(to)h(use)f(a)g Fp(jmp)p 3402 4582 V 59 w(buf)0 4781 +y Fx(for)92 b(passing)e(e)n(x)n(ecution)g(control)h(to)g(an)g +(arbitrary)h(startup)0 4980 y(routine.)168 b(And)81 b(our)g(approach)f +(has)g(to)g(be)h(careful)f(to)h(en-)0 5179 y(sure)104 +b(that)g(it)g(does)g(not)g(suf)l(fer)g(from)h(une)n(xpected)e(side-)0 +5379 y(ef)l(fects.)263 b(It)112 b(should)h(be)f(also)f(ob)n(vious)h +(that)g(we)g(can-)0 5578 y(not)e(ag)o(ain)f(e)n(xpect)g(to)g(\002nd)h +(an)g(easy)e(solution)i(\(as)f(for)0 5777 y Fp(mctx)p +410 5777 V 58 w(save)p Fx(,)g Fp(mctx)p 1419 5777 V 58 +w(restore)94 b Fx(and)i Fp(mctx)p 3007 5777 V 58 w(switch)p +Fx(\),)0 5976 y(because)59 b Fp(setjmp)p Fx(\(3\))h(and)g +Fp(sigaltstack)p Fx(\(3\))e(cannot)i(be)0 6176 y(tri)l(vially)42 +b(combined)g(to)f(form)i Fp(mctx)p 2205 6176 V 58 w(create)p +Fx(.)0 6742 y Fs(3)239 b(Implementation)0 7116 y Fx(As)48 +b(we)f(ha)m(v)n(e)g(already)h(discussed,)g(our)g(implementation)h(con-) +0 7315 y(tains)62 b(an)f(easy)h(part)g(\()p Fp(mctx)p +1737 7315 V 58 w(save)p Fx(,)k Fp(mctx)p 2703 7315 V +58 w(restore)59 b Fx(and)0 7514 y Fp(mctx)p 410 7514 +V 58 w(switch)p Fx(\))66 b(and)h(a)g(dif)l(\002cult)h(part)g(\()p +Fp(mctx)p 3007 7514 V 58 w(create)p Fx(\).)0 7713 y(Let)47 +b(us)g(start)g(with)g(the)g(easy)f(part,)j(whose)d(implementation)h(is) +0 7913 y(ob)n(vious)56 b(\(all)h(error)g(checks)e(ag)o(ain)h(omitted)h +(for)g(better)g(read-)0 8112 y(ability\):)p Black Black +0 8433 a Fk(/)90 8459 y(*)306 8433 y Fj(mac)o(hine)38 +b(context)e(data)g(structure)2308 8459 y Fk(*)2398 8433 +y(/)0 8583 y Fi(typedef)87 b(struct)h Fk(mctx_st)f Fo(f)359 +8732 y Fk(jmp_buf)g(jb;)0 8881 y Fo(g)i Fk(mctx_t;)0 +9180 y(/)90 9206 y(*)306 9180 y Fj(sav)n(e)38 b(mac)o(hine)f(context) +1713 9206 y Fk(*)1803 9180 y(/)0 9330 y Fi(#define)87 +b Fk(mctx_save\(mctx\))e Fo(n)359 9479 y Fk(\()p Fi(void)p +Fk(\)setjmp\(\(mctx\)->jb\))0 9778 y(/)90 9804 y(*)306 +9778 y Fj(restore)38 b(mac)o(hine)f(context)1873 9804 +y Fk(*)1963 9778 y(/)0 9927 y Fi(#define)87 b Fk(mctx_restore\(mctx\))d +Fo(n)359 10077 y Fk(longjmp\(\(mctx\)->jb,)f(1\))0 10376 +y(/)90 10402 y(*)306 10376 y Fj(switc)o(h)37 b(mac)o(hine)g(context) +1838 10402 y Fk(*)1928 10376 y(/)0 10525 y Fi(#define)87 +b Fk(mctx_switch\(mctx_old,mctx_new\))80 b Fo(n)359 10675 +y Fi(if)89 b Fk(\(setjmp\(\(mctx_old\)->jb\))82 b(==)89 +b(0\))g Fo(n)717 10824 y Fk(longjmp\(\(mctx_new\)->jb,)82 +b(1\))0 11123 y(/)90 11149 y(*)306 11123 y Fj(create)38 +b(mac)o(hine)f(context)1823 11149 y Fk(*)1913 11123 y(/)0 +11272 y Fi(void)88 b Fk(mctx_create\()p Black Black 4409 +638 a(mctx_t)5036 664 y(*)5126 638 y(mctx,)4409 788 y +Fi(void)g Fk(\()4947 814 y(*)5037 788 y(sf_addr\)\()p +Fi(void)6292 814 y Fk(*)6382 788 y(\),)g Fi(void)7099 +814 y Fk(*)7189 788 y(sf_arg,)4409 937 y Fi(void)4857 +963 y Fk(*)4947 937 y(sk_addr,)f(size_t)g(sk_size\))4050 +1087 y Fo(f)4446 1236 y Fj(...initialization)34 b(of)j +Fg(mctx)f Fj(to)h(be)g(\002lled)g(in...)4050 1386 y Fo(g)4050 +1753 y Fx(There)49 b(is)g(one)g(subtle)g(b)m(ut)g(important)h(point)f +(we)g(should)g(men-)4050 1952 y(tion:)93 b(The)62 b(use)f(of)h(the)g(C) +g(pre-processor)f Fp(#define)f Fx(direc-)4050 2151 y(ti)l(v)n(e)73 +b(to)g(implement)h Fp(mctx)p 5762 2151 V 58 w(save)p +Fx(,)79 b Fp(mctx)p 6741 2151 V 59 w(restore)70 b Fx(and)4050 +2351 y Fp(mctx)p 4460 2351 V 58 w(switch)81 b Fx(is)h(intentional.)175 +b(F)n(or)83 b(technical)f(reasons)4050 2550 y(related)72 +b(to)g Fp(setjmp)p Fx(\(3\))f(semantics)g(and)h Fp(return)e +Fx(related)4050 2749 y(stack)i(beha)m(vior)h(\(which)g(we)f(will)h(e)n +(xplain)g(later)g(in)g(detail\))4050 2948 y(we)51 b Fr(cannot)j +Fx(implement)d(these)f(three)h(functions)g(\(at)g(least)g(not)4050 +3148 y Fp(mctx)p 4460 3148 V 58 w(switch)p Fx(\))64 b(as)h(C)h +(functions)f(if)h(we)g(w)n(ant)g(to)g(achie)l(v)n(e)4050 +3347 y(maximum)55 b(portability)g(across)f(all)g(platforms.)91 +b(Instead)54 b(the)n(y)4050 3546 y(ha)m(v)n(e)40 b(to)i(be)f +(implemented)h(as)f(pre-processor)g(macros.)4050 4024 +y FA(3.1)198 b(Algorithm)51 b(Ov)n(er)n(view)4050 4336 +y Fx(The)g(general)g(idea)f(for)i Fp(mctx)p 5881 4336 +V 58 w(create)c Fx(is)j(to)g(con\002gure)g(the)4050 4535 +y(gi)l(v)n(en)31 b(stack)h(as)f(a)h(signal)f(stack)h(via)g +Fp(sigaltstack)p Fx(\(2\),)e(send)4050 4735 y(the)67 +b(current)g(process)f(a)h(signal)g(to)g(transfer)g(e)n(x)n(ecution)f +(con-)4050 4934 y(trol)59 b(onto)f(this)g(stack,)i(sa)m(v)n(e)d(the)g +(machine)h(conte)n(xt)f(there)h(via)4050 5133 y Fp(setjmp)p +Fx(\(3\),)35 b(get)h(rid)g(of)h(the)f(signal)g(handler)g(scope)f(and)g +(boot-)4050 5332 y(strap)41 b(into)h(the)g(startup)f(routine.)4299 +5532 y(The)64 b(real)g(problem)h(in)f(this)g(approach)g(comes)f(from)i +(the)4050 5731 y(signal)60 b(handler)g(scope)f(which)g(implies)h(v)l +(arious)g(restrictions)4050 5931 y(on)44 b(Unix)f(platforms)h(\(the)g +(signal)g(handler)f(scope)g(often)h(is)f(just)4050 6130 +y(a)49 b(\003ag)g(in)h(the)f(process)f(control)i(block)f(\(PCB\))g +(which)g(v)l(arious)4050 6329 y(system)61 b(calls,)k(lik)n(e)d +Fp(sigaltstack)p Fx(\(2\),)g(check)e(before)i(al-)4050 +6528 y(lo)l(wing)52 b(the)f(operation)h(\226)f(b)m(ut)g(because)f(it)i +(is)g(part)f(of)h(the)f(pro-)4050 6728 y(cess)38 b(state)h(the)g(k)n +(ernel)h(manages,)f(the)g(process)g(cannot)g(change)4050 +6927 y(it)h(itself\).)51 b(As)39 b(we)g(will)h(see,)e(we)h(ha)m(v)n(e)f +(to)i(perform)h(a)e(fe)l(w)g(tricks)4050 7126 y(to)44 +b(get)g(rid)h(of)g(it.)59 b(The)44 b(second)g(main)g(problem)g(is:)57 +b(ho)l(w)44 b(do)g(we)4050 7325 y(prepare)54 b(the)f(calling)h(of)g +(the)f(start)h(routine)g(without)g(immedi-)4050 7525 +y(ately)41 b(entering)h(it?)4050 8002 y FA(3.2)198 b(Algorithm)4050 +8315 y Fx(The)42 b(input)g(to)g(the)f Fp(mctx)p 5558 +8315 V 58 w(create)f Fx(function)i(is)f(the)g(machine)4050 +8514 y(conte)n(xt)63 b(structure)i Fr(mctx)f Fx(which)g(should)g(be)g +(initialized,)69 b(the)4050 8713 y(thread)33 b(startup)h(function)g +(address)e Fr(sf)p 6223 8713 V 60 w(addr)p Fx(,)i(the)g(thread)f +(startup)4050 8912 y(function)54 b(ar)m(gument)f Fr(sf)p +5455 8912 V 59 w(ar)-6 b(g)53 b Fx(and)g(a)g(chunk)g(of)g(memory)h +(start-)4050 9112 y(ing)65 b(at)f Fr(sk)p 4660 9112 V +59 w(addr)69 b Fx(and)64 b Fr(sk)p 5545 9112 V 59 w(size)g +Fx(bytes)g(in)h(size,)k(which)64 b(should)4050 9311 y(become)41 +b(the)g(threads)g(stack.)4299 9511 y(The)69 b(follo)l(wing)g(algorithm) +g(for)g Fp(mctx)p 6722 9511 V 58 w(create)d Fx(is)j(di-)4050 +9710 y(rectly)44 b(modeled)g(after)h(the)f(implemented)g(algorithm)h +(one)g(can)4050 9909 y(\002nd)59 b(in)g Fr(GNU)f(Pth)h +Fx([25],)k(which)58 b(in)h(turn)g(w)n(as)f(deri)l(v)n(ed)g(from)4050 +10108 y(techniques)41 b(originally)h(found)g(in)g Fr(r)n(sthr)-6 +b(eads)40 b Fx([27]:)p Black 4258 10475 a(1.)p Black +82 w(Preserv)n(e)49 b(the)h(current)g(signal)g(mask)f(and)h(block)f(an) +h(ar)m(-)4465 10675 y(bitrary)k(w)n(ork)n(er)g(signal)e(\(we)h(use)f +Fp(SIGUSR1)p Fx(,)h(b)m(ut)g(an)n(y)4465 10874 y(signal)47 +b(can)g(be)g(used)g(for)h(this)f(\226)g(e)l(v)n(en)g(an)g(already)g +(used)4465 11073 y(one\).)109 b(This)61 b(w)n(ork)n(er)h(signal)f(is)f +(later)h(temporarily)h(re-)4465 11272 y(quired)42 b(for)g(the)f +(trampoline)h(step.)p Black 3858 11872 a(5)p Black eop +end +%%Page: 6 6 +TeXDict begin 6 5 bop Black Black Black 208 638 a Fx(2.)p +Black 82 w(Preserv)n(e)59 b(a)g(possibly)g(e)n(xisting)g(signal)g +(action)g(for)h(the)415 838 y(w)n(ork)n(er)44 b(signal)f(and)f +(con\002gure)h(a)g(trampoline)h(function)415 1037 y(as)39 +b(the)g(ne)l(w)h(temporary)g(signal)f(action.)50 b(The)40 +b(signal)f(de-)415 1236 y(li)l(v)n(ery)k(is)g(con\002gured)g(to)g +(occur)g(on)g(an)g(alternate)f(signal)415 1435 y(stack)f(\(see)g(ne)n +(xt)g(step\).)p Black 208 1802 a(3.)p Black 82 w(Preserv)n(e)72 +b(a)h(possibly)g(acti)l(v)n(e)f(alternate)h(signal)g(stack)415 +2001 y(and)115 b(con\002gure)f(the)h(memory)g(chunk)f(starting)h(at)415 +2200 y Fr(sk)p 564 2200 50 7 v 59 w(addr)96 b Fx(as)c(the)g(ne)l(w)g +(temporary)h(alternate)f(signal)415 2399 y(stack)41 b(of)h(length)f +Fr(sk)p 1583 2399 V 59 w(size)p Fx(.)p Black 208 2765 +a(4.)p Black 82 w(Sa)m(v)n(e)82 b(parameters)g(for)h(the)g(trampoline)g +(step)f(\()p Fr(mctx)p Fx(,)415 2965 y Fr(sf)p 536 2965 +V 60 w(addr)p Fx(,)52 b Fr(sf)p 1115 2965 V 60 w(ar)-6 +b(g)p Fx(,)52 b Fr(etc.)p Fx(\))80 b(in)51 b(global)g(v)l(ariables,)i +(send)d(the)415 3164 y(current)44 b(process)f(the)g(w)n(ork)n(er)i +(signal,)e(temporarily)i(un-)415 3363 y(block)36 b(it)g(and)g(this)g(w) +n(ay)g(allo)l(w)g(it)g(to)g(be)g(deli)l(v)n(ered)f(on)h(the)415 +3562 y(signal)53 b(stack)f(in)h(order)g(to)g(transfer)g(e)n(x)n +(ecution)f(control)415 3762 y(to)42 b(the)f(trampoline)h(function.)p +Black 208 4128 a(5.)p Black 82 w(After)51 b(the)g(trampoline)h +(function)f(asynchronously)f(en-)415 4327 y(tered,)58 +b(sa)m(v)n(e)53 b(its)i(machine)f(conte)n(xt)g(in)h(the)g +Fr(mctx)g Fx(struc-)415 4526 y(ture)63 b(and)f(immediately)h(return)h +(from)f(it)g(to)g(terminate)415 4725 y(the)42 b(signal)f(handler)g +(scope.)p Black 208 5091 a(6.)p Black 82 w(Restore)59 +b(the)h(preserv)n(ed)f(alternate)g(signal)h(stack,)j(pre-)415 +5291 y(serv)n(ed)39 b(signal)g(action)h(and)f(preserv)n(ed)g(signal)g +(mask)g(for)415 5490 y(w)n(ork)n(er)65 b(signal.)119 +b(This)65 b(w)n(ay)f(an)g(e)n(xisting)g(application)415 +5689 y(con\002guration)42 b(for)g(the)g(w)n(ork)n(er)g(signal)f(is)h +(restored.)p Black 208 6055 a(7.)p Black 82 w(Sa)m(v)n(e)231 +b(the)g(current)h(machine)f(conte)n(xt)g(of)415 6254 +y Fp(mctx)p 825 6254 V 58 w(create)p Fx(.)106 b(This)60 +b(allo)l(ws)g(us)g(to)h(return)g(to)f(this)415 6454 y(point)42 +b(after)g(the)f(ne)n(xt)g(trampoline)h(step.)p Black +208 6820 a(8.)p Black 82 w(Restore)61 b(the)g(pre)l(viously)g(sa)m(v)n +(ed)f(machine)h(conte)n(xt)g(of)415 7019 y(the)33 b(trampoline)g +(function)g(\()p Fr(mctx)p Fx(\))h(to)f(ag)o(ain)g(transfer)f(e)n(x-) +415 7218 y(ecution)67 b(control)g(onto)g(the)g(alternate)f(stack,)72 +b(b)m(ut)67 b(this)415 7417 y(time)42 b(without\(!\))53 +b(signal)41 b(handler)g(scope.)p Black 208 7783 a(9.)p +Black 82 w(After)103 b(reaching)f(the)h(trampoline)g(function)f(\()p +Fr(mctx)p Fx(\))415 7983 y(ag)o(ain,)84 b(immediately)76 +b(bootstrap)f(into)h(a)g(clean)f(stack)415 8182 y(frame)42 +b(by)f(just)h(calling)f(a)h(second)e(function.)p Black +125 8548 a(10.)p Black 82 w(Set)104 b(the)f(ne)l(w)g(signal)g(mask)h +(to)f(be)h(the)f(same)g(as)415 8747 y(the)65 b(original)h(signal)f +(mask)g(which)g(w)n(as)f(acti)l(v)n(e)g(when)415 8946 +y Fp(mctx)p 825 8946 V 58 w(create)59 b Fx(w)n(as)h(called.)108 +b(This)61 b(is)g(required)g(be-)415 9146 y(cause)38 b(in)i(the)g +(\002rst)f(trampoline)h(step)f(we)h(usually)f(had)g(at)415 +9345 y(least)i(the)g(w)n(ork)n(er)i(signal)e(block)n(ed.)p +Black 125 9711 a(11.)p Black 82 w(Load)107 b(the)f(passed)f(startup)h +(information)h(\()p Fr(sf)p 3345 9711 V 60 w(addr)p Fx(,)415 +9910 y Fr(sf)p 536 9910 V 60 w(ar)-6 b(g)p Fx(\))94 b(from)h +Fp(mctx)p 1787 9910 V 59 w(create)d Fx(into)j(local)f(\(stack-)415 +10109 y(based\))57 b(v)l(ariables.)96 b(This)58 b(is)e(important)i +(because)e(their)415 10309 y(v)l(alues)35 b(ha)m(v)n(e)g(to)h(be)g +(preserv)n(ed)f(in)h(machine)g(conte)n(xt)f(de-)415 10508 +y(pendent)h(memory)i(until)f(the)f(created)g(machine)h(conte)n(xt)415 +10707 y(is)k(the)h(\002rst)g(time)f(restored)h(by)f(the)h(application.) +p Black 125 11073 a(12.)p Black 82 w(Sa)m(v)n(e)53 b(the)h(current)g +(machine)f(conte)n(xt)h(for)g(later)g(restor)m(-)415 +11272 y(ing)42 b(by)f(the)h(calling)f(application.)p +Black Black Black 4175 638 a(13.)p Black 82 w(Restore)61 +b(the)g(pre)l(viously)g(sa)m(v)n(ed)f(machine)h(conte)n(xt)g(of)4465 +838 y Fp(mctx)p 4875 838 V 58 w(create)42 b Fx(to)i(transfer)f(e)n(x)n +(ecution)f(control)j(back)4465 1037 y(to)d(it.)p Black +4175 1350 a(14.)p Black 82 w(Return)g(to)f(the)h(calling)f +(application.)4050 1666 y(When)35 b(the)h(calling)g(application)g(no)l +(w)f(ag)o(ain)h(switches)f(into)h(the)4050 1866 y(established)50 +b(machine)i(conte)n(xt)e Fr(mctx)p Fx(,)j(the)f(thread)f(starts)g(run-) +4050 2065 y(ning)58 b(at)g(routine)g Fr(sf)p 5230 2065 +V 59 w(addr)j Fx(with)d(ar)m(gument)g Fr(sf)p 6810 2065 +V 60 w(ar)-6 b(g)p Fx(.)99 b(Figure)58 b(1)4050 2264 +y(illustrates)d(the)f(algorithm)i(\(the)f(numbers)g(refer)g(to)g(the)g +(algo-)4050 2463 y(rithm)42 b(steps)f(listed)g(abo)n(v)n(e\).)4050 +10360 y @beginspecial 0 @llx 0 @lly 224 @urx 461 @ury +2240 @rwi @setspecial +%%BeginDocument: rse-pmt.eps +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: rse-pmt.fig +%%Creator: fig2dev Version 3.2 Patchlevel 5-alpha7 +%%CreationDate: Mon Jun 12 19:51:15 2006 +%%For: rse@en1.engelschall.com (Ralf S. Engelschall) +%%BoundingBox: 0 0 224 461 +%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 461 moveto 0 0 lineto 224 0 lineto 224 461 lineto closepath clip newpath +-21.3 477.0 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit +0 slj 0 slc + 0.06299 0.06299 sc +% +% Fig objects follow +% +% +% here starts figure with depth 100 +% Polyline +0 slj +0 slc +15.000 slw +n 780 705 m 750 705 750 855 30 arcto 4 {pop} repeat + 750 885 900 885 30 arcto 4 {pop} repeat + 930 885 930 735 30 arcto 4 {pop} repeat + 930 705 780 705 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 1035 1185 m 1005 1185 1005 1335 30 arcto 4 {pop} repeat + 1005 1365 1155 1365 30 arcto 4 {pop} repeat + 1185 1365 1185 1215 30 arcto 4 {pop} repeat + 1185 1185 1035 1185 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3075 2760 m 3045 2760 3045 2910 30 arcto 4 {pop} repeat + 3045 2940 3195 2940 30 arcto 4 {pop} repeat + 3225 2940 3225 2790 30 arcto 4 {pop} repeat + 3225 2760 3075 2760 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3105 885 m 3075 885 3075 1035 30 arcto 4 {pop} repeat + 3075 1065 3225 1065 30 arcto 4 {pop} repeat + 3255 1065 3255 915 30 arcto 4 {pop} repeat + 3255 885 3105 885 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 2040 1500 m 2010 1500 2010 1650 30 arcto 4 {pop} repeat + 2010 1680 2160 1680 30 arcto 4 {pop} repeat + 2190 1680 2190 1530 30 arcto 4 {pop} repeat + 2190 1500 2040 1500 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 2040 2100 m 2010 2100 2010 2250 30 arcto 4 {pop} repeat + 2010 2280 2160 2280 30 arcto 4 {pop} repeat + 2190 2280 2190 2130 30 arcto 4 {pop} repeat + 2190 2100 2040 2100 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 1035 705 m 1005 705 1005 855 30 arcto 4 {pop} repeat + 1005 885 1155 885 30 arcto 4 {pop} repeat + 1185 885 1185 735 30 arcto 4 {pop} repeat + 1185 705 1035 705 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 2040 2640 m 2010 2640 2010 2790 30 arcto 4 {pop} repeat + 2010 2820 2160 2820 30 arcto 4 {pop} repeat + 2190 2820 2190 2670 30 arcto 4 {pop} repeat + 2190 2640 2040 2640 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 2040 525 m 2010 525 2010 675 30 arcto 4 {pop} repeat + 2010 705 2160 705 30 arcto 4 {pop} repeat + 2190 705 2190 555 30 arcto 4 {pop} repeat + 2190 525 2040 525 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3075 2505 m 3045 2505 3045 2655 30 arcto 4 {pop} repeat + 3045 2685 3195 2685 30 arcto 4 {pop} repeat + 3225 2685 3225 2535 30 arcto 4 {pop} repeat + 3225 2505 3075 2505 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 1305 1500 m 1275 1500 1275 1650 30 arcto 4 {pop} repeat + 1275 1680 1425 1680 30 arcto 4 {pop} repeat + 1455 1680 1455 1530 30 arcto 4 {pop} repeat + 1455 1500 1305 1500 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 1545 3225 m 1515 3225 1515 3375 30 arcto 4 {pop} repeat + 1515 3405 1665 3405 30 arcto 4 {pop} repeat + 1695 3405 1695 3255 30 arcto 4 {pop} repeat + 1695 3225 1545 3225 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 1350 570 m 1320 570 1320 720 30 arcto 4 {pop} repeat + 1320 750 1470 750 30 arcto 4 {pop} repeat + 1500 750 1500 600 30 arcto 4 {pop} repeat + 1500 570 1350 570 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3345 2505 m 3315 2505 3315 2655 30 arcto 4 {pop} repeat + 3315 2685 3465 2685 30 arcto 4 {pop} repeat + 3495 2685 3495 2535 30 arcto 4 {pop} repeat + 3495 2505 3345 2505 30 arcto 4 {pop} repeat + cp gs 0.00 setgray ef gr gs col0 s gr +% here ends figure; +% +% here starts figure with depth 50 +/Times-Bold ff 158.75 scf sf +3068 2895 m +gs 1 -1 sc (12) col7 sh gr +% Polyline +0 slj +0 slc +7.500 slw +n 630 270 m 1890 270 l 1890 3600 l 630 3600 l + cp gs col0 s gr +% Polyline +n 2340 270 m 3600 270 l 3600 1800 l 2340 1800 l + cp gs col0 s gr +% Polyline +n 2340 2070 m 3600 2070 l 3600 3600 l 2340 3600 l + cp gs col0 s gr +% Polyline + [15 15] 15 sd +n 1980 810 m 2025 720 l 2070 900 l 2115 720 l 2160 900 l + 2205 810 l gs col0 s gr [] 0 sd +% Polyline + [15 15] 15 sd +n 1980 1170 m 2014 1081 l 2059 1261 l 2104 1081 l 2149 1261 l + 2205 1170 l gs col0 s gr [] 0 sd +% Polyline +15.000 slw +gs clippath +1108 660 m 1275 660 l 1275 600 l 1108 600 l 1108 600 l 1228 630 l 1108 660 l cp +eoclip +n 1260 4586 m 1980 4593 l 1980 3690 l 450 3690 l 450 630 l 990 630 l + + 1260 630 l gs col0 s gr gr + +% arrowhead +7.500 slw +n 1108 660 m 1228 630 l 1108 600 l 1108 660 l cp gs 0.00 setgray ef gr col0 s +% Polyline +15.000 slw +gs clippath +1828 840 m 1995 840 l 1995 780 l 1828 780 l 1828 780 l 1948 810 l 1828 840 l cp +eoclip +n 1260 630 m 1260 810 l + 1980 810 l gs col0 s gr gr + +% arrowhead +7.500 slw +n 1828 840 m 1948 810 l 1828 780 l 1828 840 l cp gs 0.00 setgray ef gr col0 s +% Polyline +15.000 slw +gs clippath +2818 840 m 2985 840 l 2985 780 l 2818 780 l 2818 780 l 2938 810 l 2818 840 l cp +eoclip +n 2205 810 m + 2970 810 l gs col0 s gr gr + +% arrowhead +7.500 slw +n 2818 840 m 2938 810 l 2818 780 l 2818 840 l cp gs 0.00 setgray ef gr col0 s +% Polyline +15.000 slw +gs clippath +2940 1018 m 2940 1185 l 3000 1185 l 3000 1018 l 3000 1018 l 2970 1138 l 2940 1018 l cp +eoclip +n 2970 810 m + 2970 1170 l gs col0 s gr gr + +% arrowhead +7.500 slw +n 2940 1018 m 2970 1138 l 3000 1018 l 2940 1018 l cp gs 0.00 setgray ef gr col0 s +% Polyline +15.000 slw +gs clippath +2357 1140 m 2190 1140 l 2190 1200 l 2357 1200 l 2357 1200 l 2237 1170 l 2357 1140 l cp +eoclip +n 2205 1170 m + 2970 1170 l gs col0 s gr gr + +% arrowhead +7.500 slw +n 2357 1140 m 2237 1170 l 2357 1200 l 2357 1140 l cp gs 0.00 setgray ef gr col0 s +% Polyline +15.000 slw +gs clippath +1412 1140 m 1245 1140 l 1245 1200 l 1412 1200 l 1412 1200 l 1292 1170 l 1412 1140 l cp +eoclip +n 1260 1170 m + 1980 1170 l gs col0 s gr gr + +% arrowhead +7.500 slw +n 1412 1140 m 1292 1170 l 1412 1200 l 1412 1140 l cp gs 0.00 setgray ef gr col0 s +% Polyline +15.000 slw +gs clippath +2818 1470 m 2985 1470 l 2985 1410 l 2818 1410 l 2818 1410 l 2938 1440 l 2818 1470 l cp +eoclip +n 1260 1440 m + 2970 1440 l gs col0 s gr gr + +% arrowhead +7.500 slw +n 2818 1470 m 2938 1440 l 2818 1410 l 2818 1470 l cp gs 0.00 setgray ef gr col0 s +% Polyline +15.000 slw +n 1260 1170 m + 1260 1440 l gs col0 s gr +% Polyline +gs clippath +2818 2550 m 2985 2550 l 2985 2490 l 2818 2490 l 2818 2490 l 2938 2520 l 2818 2550 l cp +eoclip +n 2970 1440 m 2970 1890 l 2250 1890 l 2250 2520 l + 2970 2520 l gs col0 s gr gr + +% arrowhead +7.500 slw +n 2818 2550 m 2938 2520 l 2818 2490 l 2818 2550 l cp gs 0.00 setgray ef gr col0 s +% Polyline +15.000 slw +n 2970 2520 m + 2970 2883 l gs col0 s gr +% Polyline +gs clippath +1397 2853 m 1230 2852 l 1229 2912 l 1396 2913 l 1396 2913 l 1277 2883 l 1397 2853 l cp +eoclip +n 2970 2891 m + 1245 2883 l gs col0 s gr gr + +% arrowhead +7.500 slw +n 1397 2853 m 1277 2883 l 1396 2913 l 1397 2853 l cp gs 0.00 setgray ef gr col0 s +% Polyline +15.000 slw +gs clippath +1396 4749 m 1229 4751 l 1230 4811 l 1397 4809 l 1397 4809 l 1277 4781 l 1396 4749 l cp +eoclip +n 1260 2880 m 1260 3150 l 2070 3150 l 2062 4773 l + 1245 4781 l gs col0 s gr gr + +% arrowhead +7.500 slw +n 1396 4749 m 1277 4781 l 1397 4809 l 1396 4749 l cp gs 0.00 setgray ef gr col0 s +% Polyline +15.000 slw +gs clippath +1230 4434 m 1230 4601 l 1290 4601 l 1290 4434 l 1290 4434 l 1260 4554 l 1230 4434 l cp +eoclip +n 450 4050 m 1260 4050 l + 1260 4586 l gs col0 s gr gr + +% arrowhead +7.500 slw +n 1230 4434 m 1260 4554 l 1290 4434 l 1230 4434 l cp gs 0.00 setgray ef gr col0 s +% Polyline +15.000 slw +gs clippath +1226 5068 m 1230 5235 l 1290 5234 l 1286 5067 l 1286 5067 l 1259 5188 l 1226 5068 l cp +eoclip +n 1252 4773 m + 1260 5220 l gs col0 s gr gr + +% arrowhead +7.500 slw +n 1226 5068 m 1259 5188 l 1286 5067 l 1226 5068 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +15.000 slw + [15 45] 45 sd +gs clippath +2818 4260 m 2985 4260 l 2985 4200 l 2818 4200 l 2818 4200 l 2938 4230 l 2818 4260 l cp +eoclip +n 2970 3150 m 2970 3690 l 2250 3690 l 2250 4230 l + 2970 4230 l gs col0 s gr gr + [] 0 sd +% arrowhead +0 slc +7.500 slw +n 2818 4260 m 2938 4230 l 2818 4200 l 2818 4260 l cp gs 0.00 setgray ef gr col0 s +% Polyline +n 630 6300 m 1890 6300 l + 1890 7290 l gs col0 s gr +% Polyline +gs clippath +3660 7408 m 3660 7575 l 3720 7575 l 3720 7408 l 3720 7408 l 3690 7528 l 3660 7408 l cp +3720 6452 m 3720 6285 l 3660 6285 l 3660 6452 l 3660 6452 l 3690 6332 l 3720 6452 l cp +eoclip +n 3690 6300 m + 3690 7560 l gs col0 s gr gr + +% arrowhead +n 3720 6452 m 3690 6332 l 3660 6452 l 3720 6452 l cp gs 0.00 setgray ef gr col0 s +% arrowhead +n 3660 7408 m 3690 7528 l 3720 7408 l 3660 7408 l cp gs 0.00 setgray ef gr col0 s +% Polyline +n 2340 6300 m 3600 6300 l 3600 7560 l 2340 7560 l + cp gs col0 s gr +% Polyline +n 630 3780 m 1890 3780 l 1890 6120 l 630 6120 l + cp gs col0 s gr +% Polyline +n 2340 3780 m 3600 3780 l 3600 6120 l 2340 6120 l + cp gs col0 s gr +% Polyline +1 slc +15.000 slw + [15 45] 45 sd +gs clippath +2818 3180 m 2985 3180 l 2985 3120 l 2818 3120 l 2818 3120 l 2938 3150 l 2818 3180 l cp +eoclip +n 1260 5220 m 2160 5220 l 2160 3150 l + 2970 3150 l gs col0 s gr gr + [] 0 sd +% arrowhead +0 slc +7.500 slw +n 2818 3180 m 2938 3150 l 2818 3120 l 2818 3180 l cp gs 0.00 setgray ef gr col0 s +% Polyline +n 630 6300 m + 630 7380 l gs col0 s gr +% Polyline +1 slc +n 630 6570 m + 900 6300 l gs col0 s gr +% Polyline +n 630 6840 m + 1170 6300 l gs col0 s gr +% Polyline +n 630 7110 m + 1440 6300 l gs col0 s gr +% Polyline +n 630 7380 m + 1710 6300 l gs col0 s gr +% Polyline +n 810 7470 m + 1890 6435 l gs col0 s gr +% Polyline +n 1080 7515 m + 1890 6750 l gs col0 s gr +% Polyline +n 1665 7245 m + 1890 7020 l gs col0 s gr +% Polyline +n 2340 6570 m + 2610 6300 l gs col0 s gr +% Polyline +n 2340 6840 m + 2925 6300 l gs col0 s gr +% Polyline +n 2340 7110 m + 3240 6300 l gs col0 s gr +% Polyline +n 2340 7380 m + 3510 6300 l gs col0 s gr +% Polyline +n 2520 7560 m + 3600 6570 l gs col0 s gr +% Polyline +n 2880 7560 m + 3600 6930 l gs col0 s gr +% Polyline +n 3240 7560 m + 3600 7245 l gs col0 s gr +% Polyline +15.000 slw + [15 45] 45 sd +gs clippath +2940 5158 m 2940 5325 l 3000 5325 l 3000 5158 l 3000 5158 l 2970 5278 l 2940 5158 l cp +eoclip +n 2970 4230 m + 2970 5310 l gs col0 s gr gr + [] 0 sd +% arrowhead +0 slc +7.500 slw +n 2940 5158 m 2970 5278 l 3000 5158 l 2940 5158 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +15.000 slw + [15 45] 45 sd +gs clippath +1412 5280 m 1245 5280 l 1245 5340 l 1412 5340 l 1412 5340 l 1292 5310 l 1412 5280 l cp +eoclip +n 2970 5310 m + 1260 5310 l gs col0 s gr gr + [] 0 sd +% arrowhead +0 slc +7.500 slw +n 1412 5280 m 1292 5310 l 1412 5340 l 1412 5280 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +15.000 slw + [15 45] 45 sd +gs clippath +1412 5640 m 1245 5640 l 1245 5700 l 1412 5700 l 1412 5700 l 1292 5670 l 1412 5640 l cp +eoclip +n 2970 5580 m 2970 5670 l + 1260 5670 l gs col0 s gr gr + [] 0 sd +% arrowhead +0 slc +7.500 slw +n 1412 5640 m 1292 5670 l 1412 5700 l 1412 5640 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +15.000 slw + [15 45] 45 sd +gs clippath +512 5910 m 345 5910 l 345 5970 l 512 5970 l 512 5970 l 392 5940 l 512 5910 l cp +eoclip +n 1260 5670 m 1260 5940 l + 360 5940 l gs col0 s gr gr + [] 0 sd +% arrowhead +0 slc +7.500 slw +n 512 5910 m 392 5940 l 512 5970 l 512 5910 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +15.000 slw + [15 45] 45 sd +gs clippath +2818 5610 m 2985 5610 l 2985 5550 l 2818 5550 l 2818 5550 l 2938 5580 l 2818 5610 l cp +eoclip +n 1260 5355 m 1260 5580 l + 2970 5580 l gs col0 s gr gr + [] 0 sd +% arrowhead +0 slc +7.500 slw +n 2818 5610 m 2938 5580 l 2818 5550 l 2818 5610 l cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj +n 630 7380 m 631 7381 l 634 7383 l 639 7388 l 647 7394 l 657 7402 l + 670 7412 l 686 7423 l 703 7435 l 723 7448 l 744 7460 l + 766 7472 l 791 7483 l 817 7493 l 845 7502 l 877 7509 l + 911 7514 l 949 7517 l 991 7518 l 1035 7515 l 1076 7510 l + 1115 7502 l 1150 7493 l 1181 7483 l 1207 7473 l 1228 7463 l + 1245 7453 l 1259 7443 l 1269 7433 l 1278 7423 l 1286 7414 l + 1294 7404 l 1303 7394 l 1314 7384 l 1327 7373 l 1344 7362 l + 1364 7350 l 1390 7338 l 1419 7326 l 1454 7313 l 1491 7301 l + 1530 7290 l 1576 7279 l 1619 7271 l 1657 7265 l 1690 7262 l + 1720 7261 l 1747 7261 l 1771 7263 l 1793 7266 l 1813 7269 l + 1831 7273 l 1847 7277 l 1861 7280 l 1872 7284 l 1880 7286 l + 1885 7288 l 1889 7289 l + 1890 7290 l gs col0 s gr +/Times-Bold ff 158.75 scf sf +2430 6480 m +gs 1 -1 sc (sk_addr) col0 sh gr +/Times-Bold ff 158.75 scf sf +720 6480 m +gs 1 -1 sc (main stack) col0 sh gr +/Times-Bold ff 158.75 scf sf +720 3960 m +gs 1 -1 sc (main) col0 sh gr +/Times-Bold ff 158.75 scf sf +2430 3960 m +gs 1 -1 sc (sf_addr\(sf_arg\)) col0 sh gr +/Times-Bold ff 158.75 scf sf +2430 2250 m +gs 1 -1 sc (mctx_create) col0 sh gr +/Times-Bold ff 158.75 scf sf +2430 450 m +gs 1 -1 sc (mctx_create) col0 sh gr +/Times-Bold ff 158.75 scf sf +720 450 m +gs 1 -1 sc (mctx_create) col0 sh gr +/Times-Bold ff 158.75 scf sf +3150 2250 m +gs 1 -1 sc (_boot) col0 sh gr +/Times-Bold ff 158.75 scf sf +2790 585 m +gs 1 -1 sc (_trampoline) col0 sh gr +/Times-Bold ff 158.75 scf sf +3870 7110 m +gs 1 -1 sc 90.0 rot (sk_size) col0 sh gr +/Times-Bold ff 158.75 scf sf +1350 5175 m +gs 1 -1 sc (mctx_switch) col0 sh gr +/Times-Bold ff 158.75 scf sf +2385 5445 m +gs 1 -1 sc (mctx_switch) col0 sh gr +/Times-Bold ff 158.75 scf sf +1350 5535 m +gs 1 -1 sc (mctx_switch) col0 sh gr +/Times-Bold ff 158.75 scf sf +2385 5805 m +gs 1 -1 sc (mctx_switch) col0 sh gr +/Times-Bold ff 158.75 scf sf +1305 4725 m +gs 1 -1 sc (mctx_create) col0 sh gr +/Times-Bold ff 158.75 scf sf +810 840 m +gs 1 -1 sc (1) col7 sh gr +/Times-Bold ff 158.75 scf sf +1065 840 m +gs 1 -1 sc (2) col7 sh gr +/Times-Bold ff 158.75 scf sf +1065 1320 m +gs 1 -1 sc (6) col7 sh gr +/Times-Bold ff 158.75 scf sf +1335 1635 m +gs 1 -1 sc (7) col7 sh gr +/Times-Bold ff 158.75 scf sf +2070 1635 m +gs 1 -1 sc (8) col7 sh gr +/Times-Bold ff 158.75 scf sf +2070 660 m +gs 1 -1 sc (4) col7 sh gr +/Times-Bold ff 158.75 scf sf +1380 705 m +gs 1 -1 sc (3) col7 sh gr +/Times-Bold ff 158.75 scf sf +3135 1020 m +gs 1 -1 sc (5) col7 sh gr +/Times-Bold ff 158.75 scf sf +2070 2235 m +gs 1 -1 sc (9) col7 sh gr +/Times-Bold ff 158.75 scf sf +2040 2775 m +gs 1 -1 sc (13) col7 sh gr +/Times-Bold ff 158.75 scf sf +3068 2640 m +gs 1 -1 sc (10) col7 sh gr +/Times-Bold ff 158.75 scf sf +1545 3360 m +gs 1 -1 sc (14) col7 sh gr +/Times-Bold ff 158.75 scf sf +3337 2640 m +gs 1 -1 sc (11) col7 sh gr +% here ends figure; +$F2psEnd +rs +showpage +%%Trailer +%EOF + +%%EndDocument + @endspecial 174 x Fn(Figur)n(e)33 b(1:)134 b Fm(Illustration)28 +b(of)h(the)f(machine)g(conte)n(xt)h(creation)g(procedure.)41 +b(The)4701 10670 y(thick)h(solid)g(lines)g(and)h(numeric)g(marks)f +(correspond)i(to)f(the)f(al-)4701 10806 y(gorithm)35 +b(steps)e(as)g(described)i(in)f(section)f(3.2.)44 b(The)34 +b(thick)g(dotted)4701 10942 y(lines)i(sho)m(w)h(a)g(possible)h(further) +g(processing)g(where)f(a)g(fe)m(w)g(con-)4701 11078 y(te)n(xt)i +(switches)f(are)i(performed)h(to)e(dispatch)h(between)g(the)f(main)4701 +11214 y(thread)34 b(and)g(the)f(ne)m(w)h(created)f(thread.)p +Black 3858 11872 a Fx(6)p Black eop end +%%Page: 7 7 +TeXDict begin 7 6 bop Black Black 0 638 a FA(3.3)198 +b(Sour)l(ce)51 b(Code)0 950 y Fx(The)88 b(corresponding)h(ANSI-C)f +(code,)99 b(which)88 b(implements)0 1149 y Fp(mctx)p +410 1149 50 7 v 58 w(create)p Fx(,)73 b(is)c(a)g(little)g(bit)g(more)g +(complicated.)133 b(But)0 1348 y(with)47 b(the)f(presented)g(algorithm) +h(in)g(mind,)g(it)g(is)f(no)l(w)h(straight-)0 1548 y(forw)n(ard.)p +Black Black 0 1858 a Fi(static)88 b Fk(mctx_t)625 b(mctx_caller;)0 +2007 y Fi(static)88 b Fk(sig_atomic_t)d(mctx_called;)0 +2306 y Fi(static)j Fk(mctx_t)1704 2332 y(*)1794 2306 +y(mctx_creat;)0 2456 y Fi(static)g(void)626 b Fk(\()1704 +2482 y(*)1794 2456 y(mctx_creat_func\)\()p Fi(void)3766 +2482 y Fk(*)3856 2456 y(\);)0 2605 y Fi(static)88 b(void)1704 +2631 y Fk(*)1794 2605 y(mctx_creat_arg;)0 2754 y Fi(static)g +Fk(sigset_t)445 b(mctx_creat_sigs;)0 3053 y Fi(void)88 +b Fk(mctx_create\()359 3203 y(mctx_t)986 3229 y(*)1076 +3203 y(mctx,)359 3352 y Fi(void)g Fk(\()897 3378 y(*)987 +3352 y(sf_addr\)\()p Fi(void)2242 3378 y Fk(*)2332 3352 +y(\),)g Fi(void)3049 3378 y Fk(*)3139 3352 y(sf_arg,)359 +3502 y Fi(void)807 3528 y Fk(*)897 3502 y(sk_addr,)f +Fi(size_t)g Fk(sk_size\))0 3651 y Fo(f)359 3800 y Fi(struct)g +Fk(sigaction)g(sa;)359 3950 y Fi(struct)g Fk(sigaction)g(osa;)359 +4099 y Fi(struct)g Fk(sigaltstack)f(ss;)359 4249 y Fi(struct)h +Fk(sigaltstack)f(oss;)359 4398 y(sigset_t)h(osigs;)359 +4548 y(sigset_t)g(sigs;)359 4847 y(/)449 4873 y(*)665 +4847 y Fj(Step)37 b(1:)1182 4873 y Fk(*)1272 4847 y(/)359 +4996 y(sigemptyset\(&sigs\);)359 5145 y(sigaddset\(&sigs,)84 +b(SIGUSR1\);)359 5295 y(sigprocmask\(SIG_BLOCK,)e(&sigs,)88 +b(&osigs\);)359 5594 y(/)449 5620 y(*)665 5594 y Fj(Step)37 +b(2:)1182 5620 y Fk(*)1272 5594 y(/)359 5743 y(memset\(\()p +Fi(void)1524 5769 y Fk(*)1614 5743 y(\)&sa,)88 b(0,)986 +5893 y Fi(sizeof)p Fk(\()p Fi(struct)e Fk(sigaction\)\);)359 +6042 y(sa.sa_handler)f(=)k(mctx_create_trampoline;)359 +6191 y(sa.sa_flags)d(=)j(SA_ONSTACK;)359 6341 y +(sigemptyset\(&sa.sa_mask\);)359 6490 y(sigaction\(SIGUSR1,)83 +b(&sa,)89 b(&osa\);)359 6789 y(/)449 6815 y(*)665 6789 +y Fj(Step)37 b(3:)1182 6815 y Fk(*)1272 6789 y(/)359 +6939 y(ss.ss_sp)356 b(=)89 b(sk_addr;)359 7088 y(ss.ss_size)176 +b(=)89 b(sk_size;)359 7238 y(ss.ss_flags)d(=)j(0;)359 +7387 y(sigaltstack\(&ss,)84 b(&oss\);)359 7686 y(/)449 +7712 y(*)665 7686 y Fj(Step)37 b(4:)1182 7712 y Fk(*)1272 +7686 y(/)359 7835 y(mctx_creat)534 b(=)90 b(mctx;)359 +7985 y(mctx_creat_func)84 b(=)90 b(sf_addr;)359 8134 +y(mctx_creat_arg)174 b(=)90 b(sf_arg;)359 8284 y(mctx_creat_sigs)84 +b(=)90 b(osigs;)359 8433 y(mctx_called)444 b(=)90 b(FALSE;)359 +8583 y(kill\(getpid\(\),)85 b(SIGUSR1\);)359 8732 y +(sigfillset\(&sigs\);)359 8881 y(sigdelset\(&sigs,)f(SIGUSR1\);)359 +9031 y Fi(while)k Fk(\(!mctx_called\))717 9180 y(sigsuspend\(&sigs\);) +359 9479 y(/)449 9505 y(*)665 9479 y Fj(Step)37 b(6:)1182 +9505 y Fk(*)1272 9479 y(/)359 9629 y(sigaltstack\(NULL,)84 +b(&ss\);)359 9778 y(ss.ss_flags)i(=)j(SS_DISABLE;)359 +9927 y(sigaltstack\(&ss,)84 b(NULL\);)359 10077 y(if)89 +b(\(!\(oss.ss_flags)84 b(&)90 b(SS_DISABLE\)\))717 10226 +y(sigaltstack\(&oss,)84 b(NULL\);)359 10376 y(sigaction\(SIGUSR1,)f +(&osa,)88 b(NULL\);)359 10525 y(sigprocmask\(SIG_SETMASK,)1435 +10675 y(&osigs,)f(NULL\);)359 10974 y(/)449 11000 y(*)665 +10974 y Fj(Step)37 b(7)g(&)h(Step)f(8:)1751 11000 y Fk(*)1841 +10974 y(/)359 11123 y(mctx_switch\(&mctx_caller,)81 b(mctx\);)p +Black Black 4409 638 a(/)4499 664 y(*)4715 638 y Fj(Step)37 +b(14:)5307 664 y Fk(*)5397 638 y(/)4409 788 y Fi(return)p +Fk(;)4050 937 y Fo(g)4050 1236 y Fi(void)88 b Fk +(mctx_create_trampoline\()p Fi(int)81 b Fk(sig\))4050 +1386 y Fo(f)4409 1535 y Fk(/)4499 1561 y(*)4715 1535 +y Fj(Step)37 b(5:)5232 1561 y Fk(*)5322 1535 y(/)4409 +1685 y Fi(if)89 b Fk(\(mctx_save\(mctx_creat\))82 b(==)89 +b(0\))g Fo(f)4767 1834 y Fk(mctx_called)d(=)k(TRUE;)4767 +1983 y Fi(return)p Fk(;)4409 2133 y Fo(g)4409 2432 y +Fk(/)4499 2458 y(*)4715 2432 y Fj(Step)37 b(9:)5232 2458 +y Fk(*)5322 2432 y(/)4409 2581 y(mctx_create_boot\(\);)4050 +2731 y Fo(g)4050 3030 y Fi(void)88 b Fk(mctx_create_boot\()p +Fi(void)p Fk(\))4050 3179 y Fo(f)4409 3328 y Fi(void)g +Fk(\()4947 3354 y(*)5037 3328 y(mctx_start_func\)\()p +Fi(void)7009 3354 y Fk(*)7099 3328 y(\);)4409 3478 y +Fi(void)4857 3504 y Fk(*)4947 3478 y(mctx_start_arg;)4409 +3777 y(/)4499 3803 y(*)4715 3777 y Fj(Step)37 b(10:)5307 +3803 y Fk(*)5397 3777 y(/)4409 3926 y(sigprocmask\(SIG_SETMASK,)5485 +4076 y(&mctx_creat_sigs,)84 b(NULL\);)4409 4374 y(/)4499 +4400 y(*)4715 4374 y Fj(Step)37 b(11:)5307 4400 y Fk(*)5397 +4374 y(/)4409 4524 y(mctx_start_func)84 b(=)90 b(mctx_creat_func;)4409 +4673 y(mctx_start_arg)174 b(=)90 b(mctx_creat_arg;)4409 +4972 y(/)4499 4998 y(*)4715 4972 y Fj(Step)37 b(12)g(&)g(Step)h(13:) +5950 4998 y Fk(*)6040 4972 y(/)4409 5122 y(mctx_switch\(mctx_creat,)82 +b(&mctx_caller\);)4409 5421 y(/)4499 5447 y(*)4715 5421 +y Fj(The)38 b(thread)f(``magically'')e(starts...)6834 +5447 y Fk(*)6924 5421 y(/)4409 5570 y(mctx_start_func\(mctx_start_a)o +(rg\))o(;)4409 5869 y(/)4499 5895 y(*)4678 5869 y(NOTREACHED)5664 +5895 y(*)5754 5869 y(/)4409 6018 y(abort\(\);)4050 6168 +y Fo(g)4050 6721 y FA(3.4)198 b(Run-time)51 b(P)l(enalty)4050 +7060 y Fx(After)64 b(this)g(discussion)f(of)h(the)g(implementation)g +(details,)k(an)4050 7259 y(ob)n(viously)c(occuring)g(question)f(no)l(w) +h(is)g(what)f(the)h(e)n(xpected)4050 7458 y(run-time)j(penalty)f(is.) +125 b(That)67 b(is,)k(what)c(does)e(our)i(presented)4050 +7657 y(machine)88 b(conte)n(xt)h(implementation)g(cost)g(compared)f(to) +h(a)4050 7857 y Fp(ucontext)p Fx(\(3\))70 b(based)h(solution.)143 +b(From)73 b(the)f(already)g(dis-)4050 8056 y(cussed)43 +b(details)g(we)h(can)f(easily)g(guess)g(that)h(our)h(comple)n(x)e(ma-) +4050 8255 y(chine)56 b(conte)n(xt)f(creation)h(procedure)g(\()p +Fp(mctx)p 6784 8255 V 59 w(create)p Fx(\))e(will)4050 +8454 y(be)41 b(certainly)g(noticeably)g(slo)l(wer)f(than)h(a)g +(solution)g(based)f(on)h(a)4050 8654 y Fp(ucontext)p +Fx(\(3\))e(f)n(acility)-11 b(.)4299 8867 y(But)96 b(a)g(wild)h(guess)e +(is)h(not)h(suf)l(\002cing)f(for)h(a)f(reason-)4050 9066 +y(able)c(statement.)201 b(So)92 b(we)g(ha)m(v)n(e)f(written)h(a)f +Fr(Simple)h(Ma-)4050 9266 y(c)n(hine)43 b(Conte)m(xt)g(Benc)n(hmark)j +Fx(\(SMCB)d([32)q(]\))h(which)g(w)n(as)g(used)4050 9465 +y(to)73 b(compare)f(run-time)i(costs)d(of)i(the)g Fp(mctx)p +6842 9465 V 58 w(create)d Fx(and)4050 9664 y Fp(mctx)p +4460 9664 V 58 w(switch)54 b Fx(functions)h(if)h(once)f(implemented)g +(through)4050 9863 y(the)34 b Fr(POSIX)43 b Fp(makecontext)p +Fx(\(3\)/)p Fp(swapcontext)p Fx(\(3\))28 b(func-)4050 +10063 y(tions)112 b(\(as)f(sho)l(wn)h(in)g(section)f(2.3\),)129 +b(and)112 b(once)f(imple-)4050 10262 y(mented)90 b(with)h(our)f(based)g +(f)n(allback)g(implementation)h(\(for)4050 10461 y(con)-7 +b(v)n(enience)84 b(reasons)h(we)g(directly)h(used)f Fp(sigjmp)p +7412 10461 V 58 w(buf)p Fx(,)4050 10660 y Fp(sigsetjmp)p +Fx(\(3\))h(and)k Fp(siglongjmp)p Fx(\(3\))c(in)j(the)g(bench-)4050 +10860 y(mark,)64 b(because)58 b(all)i(tested)f(platforms)h(pro)n(vided) +g(this\).)106 b(The)4050 11059 y(results)41 b(are)g(sho)l(wn)g(T)-13 +b(able)41 b(3)h(belo)l(w)-11 b(.)4299 11272 y(As)106 +b(one)h(can)f(deri)l(v)n(e)g(from)h(these)f(e)l(v)l(aluations,)122 +b(our)p Black 3858 11872 a(7)p Black eop end +%%Page: 8 8 +TeXDict begin 8 7 bop Black Black 0 638 a Fx(signal)114 +b(stack)f(trick)h(to)g(implement)g Fp(mctx)p 2861 638 +50 7 v 58 w(create)e Fx(in)0 838 y(practice)100 b(is)g(approximately)g +(15)g(times)g(slo)l(wer)g(than)g(the)0 1037 y Fp(makecontext)p +Fx(\(3\))51 b(based)j(v)l(ariant.)92 b(This)55 b(cost)f(should)h(not)0 +1236 y(be)k(ne)n(glected.)104 b(On)60 b(the)f(other)h(hand,)j(the)d +Fp(sigsetjmp)p Fx(\(3\)/)0 1435 y Fp(siglongjmp)p Fx(\(3\))36 +b(based)j Fp(mctx)p 2057 1435 V 58 w(switch)e Fx(performs)j(about)0 +1635 y(as)d(good)g(as)f(the)h Fp(swapcontext)p Fx(\(3\))d(based)i(v)l +(ariant)i(\(the)f(rea-)0 1834 y(son)c(wh)o(y)h(on)g(most)g(of)g(the)g +(tested)f(platforms)h(it)g(is)g(e)l(v)n(en)f(slightly)0 +2033 y(f)n(aster)75 b(is)g(not)g(kno)l(wn)g(\226)g(b)m(ut)g(we)f(guess) +g(it)i(is)e(related)h(to)g(a)0 2233 y(greater)55 b(management)g(o)n(v)n +(erhead)f(in)h(the)g Fp(ucontext)p Fx(\(3\))e(f)n(a-)0 +2432 y(cility)-11 b(,)34 b(which)e(is)h(a)f(superset)f(of)i(the)f +(functionality)h(we)f(require\).)0 2631 y(Or)h(in)f(short:)48 +b(our)33 b(presented)e(f)n(allback)i(approach)f(costs)g(notice-)0 +2830 y(able)49 b(e)n(xtra)g(CPU)h(c)n(ycles)e(on)i(thread)f(creation)g +(time,)j(b)m(ut)d(is)h(as)0 3030 y(f)n(ast)34 b(as)f(the)h +(standardized)f(solution)h(under)g(thread)g(dispatching)0 +3229 y(time.)p 0 3456 3798 7 v 0 6335 7 2880 v 156 3597 +a Fn(10000)h Ff(\002)e Fn(mctx)p 952 3597 40 7 v 48 w(cr)n(eate)h(\(in) +f(seconds\):)156 3893 y(Platf)m(orm)p 1654 3941 7 158 +v 1118 w(mcsc)p 2159 3941 V 327 w(sjlj)p 2664 3941 V +206 w(o)o(v)o(erhead)156 4051 y Fm(Sun)h(Solaris)f(2.6)h(\(SP)-12 +b(ARC\))p 1654 4098 V 266 w(0.076)p 2159 4098 V 207 w(1.268)p +2664 4098 V 497 w(16.7)156 4209 y(DEC)33 b(T)-5 b(ru64)35 +b(5.0)f(\(Alpha\))p 1654 4256 V 342 w(0.019)p 2159 4256 +V 207 w(0.235)p 2664 4256 V 497 w(12.4)156 4367 y(SGI)f(IRIX)g(6.5)i +(\(MIPS\))p 1654 4414 V 454 w(0.105)p 2159 4414 V 207 +w(1.523)p 2664 4414 V 497 w(14.5)156 4524 y(SCO)e(UnixW)-11 +b(are)34 b(7.0)h(\(Intel\))p 1654 4572 V 207 w(0.204)p +2159 4572 V 207 w(3.827)p 2664 4572 V 497 w(18.8)156 +4682 y(HP)e(HP/UX)g(11.0)h(\(HPP)-12 b(A\))p 1654 4729 +V 289 w(0.057)p 2159 4729 V 207 w(0.667)p 2664 4729 V +497 w(11.8)2383 4840 y Fn(A)f(v)o(erage:)175 b(14.8)156 +5095 y(10000)35 b Ff(\002)e Fn(mctx)p 952 5095 40 7 v +48 w(switch)g(\(in)g(seconds\):)156 5291 y(Platf)m(orm)p +1654 5339 7 158 v 1118 w(mcsc)p 2159 5339 V 327 w(sjlj)p +2664 5339 V 206 w(o)o(v)o(erhead)156 5449 y Fm(Sun)h(Solaris)f(2.6)h +(\(SP)-12 b(ARC\))p 1654 5497 V 266 w(0.137)p 2159 5497 +V 207 w(0.210)p 2664 5497 V 563 w(1.5)156 5607 y(DEC)33 +b(T)-5 b(ru64)35 b(5.0)f(\(Alpha\))p 1654 5654 V 342 +w(0.034)p 2159 5654 V 207 w(0.022)p 2664 5654 V 563 w(0.6)156 +5765 y(SGI)f(IRIX)g(6.5)i(\(MIPS\))p 1654 5812 V 454 +w(0.235)p 2159 5812 V 207 w(0.190)p 2664 5812 V 563 w(0.8)156 +5922 y(SCO)e(UnixW)-11 b(are)34 b(7.0)h(\(Intel\))p 1654 +5970 V 207 w(0.440)p 2159 5970 V 207 w(0.398)p 2664 5970 +V 563 w(0.9)156 6080 y(HP)e(HP/UX)g(11.0)h(\(HPP)-12 +b(A\))p 1654 6128 V 289 w(0.106)p 2159 6128 V 207 w(0.065)p +2664 6128 V 563 w(0.6)2450 6238 y Fn(A)f(v)o(erage:)174 +b(0.9)p 3791 6335 7 2880 v 0 6342 3798 7 v 0 6516 a(T)-12 +b(able)33 b(3:)133 b Fm(Summary)43 b(of)f Fl(Simple)f(Mac)n(hine)h +(Conte)m(xt)g(Benc)n(hmark)i Fm(\(SMCB,)589 6652 y([32)q(]\).)e(The)33 +b(speed)f(of)h(machine)h(conte)n(xt)f(creation)g(and)g(switching)589 +6788 y(found)51 b(on)f(each)f(tested)g(operating)h(system.)89 +b Fn(mcsc)p Fm(:)71 b(functional)589 6925 y Fh(makecontext)p +Fm(\(3\))23 b(/)j Fh(switchcontext)p Fm(\(3\),)e Fn(sjlj)p +Fm(:)37 b(functional)589 7059 y Fh(sigsetjmp)p Fm(\(3\)/)p +Fh(siglongjmp)p Fm(\(3\).)116 b Fn(o)o(v)o(erhead)p Fm(:)94 +b(the)59 b(o)n(v)n(er)m(-)589 7191 y(head)34 b(of)g(using)g +Fn(sjlj)f Fm(instead)h(of)g Fn(mcsc)p Fm(.)0 7619 y FA(3.5)198 +b(Remaining)50 b(Issues)0 7932 y Fx(The)41 b(presented)g(algorithm)g +(and)g(source)g(code)f(can)h(be)g(directly)0 8131 y(used)59 +b(in)i(practice)e(for)i(implementing)f(a)g(minimal)h(threading)0 +8330 y(system)52 b(or)i(the)f(concept)f(of)h(co-routines.)86 +b(Its)53 b(big)g(adv)l(antage)0 8530 y(is)39 b(that)f(if)i(the)e +(operating)h(system)f(pro)n(vides)g(the)h(required)g(stan-)0 +8729 y(dardized)k(primiti)l(v)n(es,)h(we)f(do)g(not)h(need)f(to)h(kno)l +(w)f(an)n(ything)g(at)0 8928 y(all)56 b(about)f(the)h(machine)f(we)g +(are)h(running)g(on)g(\227)f(e)l(v)n(erything)0 9127 +y(just)50 b(w)n(orks.)78 b(Ne)l(v)n(ertheless,)50 b(there)h(remain)f(a) +g(fe)l(w)g(special)g(is-)0 9327 y(sues)40 b(we)i(still)f(ha)m(v)n(e)f +(to)i(discuss.)0 9627 y FA(The)50 b(W)-13 b(aggly)49 +b(longjmp\(3\))h(after)h(Retur)m(n)0 9877 y Fx(On)e(some)f(platforms,)i +Fp(longjmp)p Fx(\(3\))d(may)i(not)g(be)f(called)h(af-)0 +10076 y(ter)61 b(the)g(function)h(which)e(called)h(the)g +Fp(setjmp)p Fx(\(3\))e(returned.)0 10276 y(When)46 b(this)g(is)g(done,) +h(the)g(stack)e(frame)i(situation)f(is)g(not)h(guar)m(-)0 +10475 y(anteed)54 b(to)h(be)f(in)h(a)f(clean)g(and)h(consistent)e +(state.)90 b(But)55 b(this)f(is)0 10674 y(e)n(xactly)c(the)h(mechanism) +f(we)h(use)f(in)i(order)f(to)g(get)g(rid)h(of)f(the)0 +10873 y(signal)41 b(handler)h(scope)e(in)i(step)f(5.)249 +11073 y(The)35 b(only)g(alternati)l(v)n(e)g(w)n(ould)g(be)g(to)g(lea)m +(v)n(e)e(the)i(signal)g(han-)0 11272 y(dler)56 b(via)f +Fp(longjmp)p Fx(\(3\),)i(b)m(ut)f(then)f(we)h(w)n(ould)g(ha)m(v)n(e)e +(another)p Black Black 4050 638 a(problem,)i(as)d(e)n(xperience)f(sho)l +(wed.)86 b(F)n(or)53 b(instance,)60 b(R)r Fm(O)8 b(B)g(E)g(RT)4054 +838 y Fx(S)g(.)65 b(T)8 b Fm(H)g(A)q(U)t Fx(')-9 b(s)57 +b Fr(Really)g(Simple)g(Thr)-6 b(eads)55 b Fx(\()p Fr(r)n(sthr)-6 +b(eads)p Fx(\))56 b([27)q(])g(w)n(as)4050 1037 y(ported)37 +b(to)g(se)l(v)n(eral)f(platforms)i(and)e(w)n(as)h(used)f(to)i(run)f(an) +g(e)n(xper)m(-)4050 1236 y(imental)47 b(multithreaded)h(v)n(ersion)e +(of)i(the)f(Apache)f(webserv)n(er)-9 b(.)4054 1435 y(T)8 +b Fm(H)g(A)q(U)t Fx(')-9 b(s)35 b(approach)f(w)n(as)g(similar)h(to)g +(ours,)g(b)m(ut)g(dif)l(fered)f(signif-)4050 1635 y(icantly)40 +b(in)g(the)g(w)n(ay)g(the)g(signal)f(handler)h(is)g(left.)51 +b(In)40 b(particular)-7 b(,)4050 1834 y(in)54 b(an)g(attempt)g(to)g(a)m +(v)m(oid)g(the)g(unsafe)f(stack)h(frame,)i(it)f(used)e(a)4050 +2033 y Fp(longjmp)p Fx(\(3\))40 b(call)j(to)f(lea)m(v)n(e)f(the)i +(signal)f(handler)-7 b(,)42 b(rather)h(than)4050 2233 +y(returning)60 b(from)f(it.)103 b(But)59 b(this)g(approach)f(does)h +(not)g(w)n(ork)g(on)4050 2432 y(some)41 b Fr(SysV)13 +b Fx(-deri)l(v)n(ed)41 b(k)n(ernels,)g(as)f(we)i(already)f(mentioned.) +4299 2631 y(The)64 b(problem)h(is)e(that)h(these)g(k)n(ernels)f(do)h +(not)h(\223belie)l(v)n(e\224)4050 2830 y(that)59 b(the)h(code)e(is)h +(out)h(of)f(the)h(signal-handling)f(conte)n(xt,)k(un-)4050 +3030 y(til)i(the)g(signal)g(handler)g(has)f(returned)h(\227)g(and)f +(accordingly)-11 b(,)4050 3229 y(refuse)57 b(to)h(allo)l(w)f +(readjustment)g(of)h(the)f(signal)g(stack)g(until)h(it)4050 +3428 y(has.)121 b(But)66 b(with)f(the)g Fr(r)n(sthr)-6 +b(eads)64 b Fx(approach,)70 b(the)65 b(signal)g(han-)4050 +3627 y(dler)47 b(that)g(created)f(the)h(\002rst)g(thread)g(ne)l(v)n(er) +f(returns,)i(and)e(when)4050 3827 y Fr(r)n(sthr)-6 b(eads)33 +b Fx(w)n(ants)i(to)g(create)f(the)h(second)f(thread,)h(these)f(k)n +(ernels)4050 4026 y(refuse)48 b(to)g(readjust)f(the)h(signal)g(stack,)g +(and)g(we)f(are)h(stuck.)70 b(So)4050 4225 y(with)35 +b(portability)g(in)f(mind,)i(we)e(decided)f(that)i(it)f(is)g(better)h +(to)f(get)4050 4424 y(rid)47 b(of)h(the)f(signal)f(handler)h(scope)g +(with)g(the)g(straight-forw)n(ard)4050 4624 y(\223)p +Fp(return)p Fx(\224)77 b(and)i(instead)g(\002ght)h(the)g(mentioned)f +(\(simpler\))4050 4823 y(problem)42 b(of)g(an)f(unsafe)g(stack)g +(frame.)4299 5022 y(F)n(ortunately)-11 b(,)55 b(in)d(practice)g(this)g +(is)g(not)g(as)f(problematic)i(as)4050 5221 y(it)h(seems,)i(because)c +(e)l(v)l(aluations)h(\(for)i Fr(GNU)f(Pth)p Fx(\))g(on)h(a)e(wide)4050 +5421 y(range)72 b(of)i(current)e(Unix)h(platforms)g(sho)l(wed)f(that)h +(one)g(can)4050 5620 y(reach)43 b(a)g(safe)g(stack)g(frame)h(ag)o(ain)f +(by)h(just)f(calling)h(a)f(function.)4050 5819 y(That)54 +b(is)g(the)g(reason)f(wh)o(y)h(our)h(algorithm)g(enters)e(the)h(second) +4050 6018 y(trampoline)42 b(function)g(in)g(step)f(9.)4050 +6309 y FA(The)50 b(Uncooperati)n(v)n(e)g(longjmp\(3\))4050 +6553 y Fx(Ev)n(en)i(on)g(operating)h(systems)e(which)h(ha)m(v)n(e)f(w)n +(orking)i Fr(POSIX)4050 6752 y Fx(functions,)43 b(our)g(approach)g(may) +g(theoretically)g(still)h(not)f(w)n(ork,)4050 6952 y(because)97 +b Fp(longjmp)p Fx(\(3\))g(does)h(not)h(cooperate.)223 +b(F)n(or)99 b(in-)4050 7151 y(stance,)33 b(on)h(some)f(platforms)g(the) +h(standard)f Fr(libc)g Fp(longjmp)p Fx(\(3\))4050 7350 +y(branches)e(to)h(error)m(-handling)g(code)g(if)g(it)g(detects)f(that)h +(the)f(caller)4050 7549 y(tries)39 b(to)g(jump)g Fr(up)h +Fx(the)e(stack,)h Fr(i.e)n(.)p Fx(,)e(into)i(a)g(stack)f(frame)i(that)f +(has)4050 7749 y(already)i(returned.)4299 7948 y(This)58 +b(is)g(usually)f(implemented)h(by)g(comparing)g(the)g(cur)m(-)4050 +8147 y(rent)d(stack)g(pointer)g(to)h(the)f(one)f(in)i(the)f +Fp(jmp)p 6775 8147 50 7 v 58 w(buf)g Fx(structure.)4050 +8346 y(That)62 b(is)f(wh)o(y)h(it)f(is)h(important)g(for)g(our)g +(algorithm)g(to)f(return)4050 8546 y(from)41 b(the)f(signal)g(handler)g +(and)g(this)g(w)n(ay)h(enter)f(the)g(\(dif)l(ferent\))4050 +8745 y(stack)63 b(of)h(the)f(parent)h(thread.)117 b(In)64 +b(practice,)k(the)c(implemen-)4050 8944 y(tation)54 b(in)f +Fr(GNU)g(Pth)i Fx(sho)l(wed)d(that)i(then)f(one)h(no)f(longer)h(suf-) +4050 9144 y(fers)33 b(from)g(those)f(uncooperati)l(v)n(e)g +Fp(longjmp)p Fx(\(3\))f(implementa-)4050 9343 y(tions,)36 +b(b)m(ut)f(one)h(should)f(k)n(eep)g(this)h(point)g(in)f(mind)h(when)f +(reach-)4050 9542 y(ing)60 b(e)l(v)n(en)f(more)h(uncooperati)l(v)n(e)f +(v)l(ariants)h(on)g(esoteric)f(Unix)4050 9741 y(platforms.)49 +b(If)34 b(it)f(still)h(occurs,)g(one)f(can)f(only)i(try)g(to)f(resume)g +(the)4050 9941 y(operation)52 b(by)g(using)g(a)g(possibly)f(e)n +(xisting)h(platform-speci\002c)4050 10140 y(error)42 +b(handling)g(hook.)4050 10430 y FA(Garbage)49 b(at)h(Bottom)g(of)g +(Stacks)4050 10675 y Fx(There)37 b(is)f(a)g(subtle)h(side-ef)l(fect)f +(of)h(our)g(implementation:)49 b(there)4050 10874 y(remains)35 +b(some)f(g)o(arbage)h(at)g(the)g(bottom)h(of)f(each)f(thread)h(stack.) +4050 11073 y(The)69 b(reason)e(is)h(that)h(if)g(a)f(signal)g(is)g(deli) +l(v)n(ered,)74 b(the)68 b(operat-)4050 11272 y(ing)63 +b(system)f(pushes)g(some)h(state)f(onto)h(the)g(stack,)k(which)c(is)p +Black 3858 11872 a(8)p Black eop end +%%Page: 9 9 +TeXDict begin 9 8 bop Black Black 0 638 a Fx(restored)58 +b(later)-7 b(,)62 b(when)57 b(the)h(signal)g(handler)g(returns.)100 +b(But)58 b(al-)0 838 y(though)64 b(we)f(return)i(from)f(the)g(signal)f +(handler)-7 b(,)69 b(we)64 b(jump)g(in)0 1037 y(ag)o(ain,)56 +b(and)d(this)g(time)h(we)f(enter)g(not)g(directly)h(at)f(the)g(bottom)0 +1236 y(of)35 b(the)g(stack,)g(because)f(of)h(the)g Fp(setjmp)p +Fx(\(3\))e(in)j(the)f(trampoline)0 1435 y(function.)249 +1647 y(Since)64 b(the)g(operating)g(system)g(has)f(to)h(capture)g(all)g +(CPU)0 1846 y(re)n(gisters)44 b(\(including)i(those)e(that)h(are)g +(ordinarily)h(scratch)e(re)n(g-)0 2046 y(isters)d(or)h(caller)m(-sa)m +(v)n(e)e(re)n(gisters\),)g(there)i(can)f(be)g(a)g(f)n(air)i(amount)0 +2245 y(of)g(memory)h(at)f(the)g(bottom)h(of)f(the)g(established)f +(thread)h(stack.)0 2444 y(F)n(or)37 b(some)f(systems)f(this)i(can)f(be) +g(e)l(v)n(en)g(up)h(to)f(1)h(KB)f(of)h(g)o(arbage)0 2643 +y([27].)51 b(But)40 b(e)n(xcept)e(for)i(the)g(additional)g(memory)g +(consumption)0 2843 y(it)i(does)f(not)g(hurt.)249 3054 +y(W)-13 b(e)64 b(just)g(ha)m(v)n(e)f(to)h(k)n(eep)h(in)f(mind)h(this)f +(additional)h(stack)0 3253 y(consumption)57 b(when)f(deciding)h(the)g +(stack)f(size)g(\()p Fr(sk)p 3137 3253 50 7 v 60 w(size)p +Fx(\).)96 b(A)0 3453 y(reasonable)49 b(stack)h(size)f(usually)h(is)g +(between)g(16)g(and)g(32)h(KB.)0 3652 y(Less)62 b(is)g(neither)h +(reasonable)e(nor)i(al)n(w)n(ays)f(allo)l(wed)g(\(current)0 +3851 y(Unix)54 b(platforms)h(usually)e(require)i(a)e(stack)h(to)g(be)g +(at)g(least)f(16)0 4050 y(KB)41 b(in)h(size\).)0 4386 +y FA(Stack)50 b(Ov)n(er\003o)n(ws)0 4660 y Fx(There)98 +b(is)f(a)h(noticeable)f(dif)l(ference)g(between)g(the)g(initial)0 +4859 y Fp(main)p Fx(\(\))59 b(thread)i(and)f(the)g(e)n(xplicitly)g(spa) +n(wned)f(threads:)89 b(the)0 5059 y(initial)63 b(thread)g(runs)g(on)f +(the)h(standard)f(process)g(stack.)114 b(This)0 5258 +y(stack)85 b(automatically)h(can)g(gro)l(w)g(under)g(Unix,)97 +b(while)86 b(the)0 5457 y(stacks)44 b(of)h(the)g(spa)n(wned)f(threads)g +(are)h(\002x)n(ed)g(in)g(size.)60 b(So)46 b(stack)0 5656 +y(o)n(v)n(er\003o)l(ws)54 b(can)h(occur)h(for)g(the)g(spa)n(wned)e +(threads.)93 b(This)55 b(im-)0 5856 y(plies)i(that)g(the)g(parent)g +(has)f(to)h(mak)n(e)g(a)g(reasonable)f(guess)g(of)0 6055 +y(the)45 b(threads)f(stack)g(space)f(requirement)i(already)f(at)h(spa)n +(wning)0 6254 y(time.)249 6466 y(And)i(there)f(is)h(no)f(really)h +(portable)g(solution)g(to)g(this)f(prob-)0 6665 y(lem,)65 +b(because)59 b(e)l(v)n(en)g(if)i(the)f(thread)g(library')-9 +b(s)61 b(scheduler)f(can)0 6864 y(detect)33 b(the)g(stack)g(o)n(v)n +(er\003o)l(w)-11 b(,)34 b(it)f(cannot)h(easily)e(resize)h(the)g(stack.) +0 7063 y(The)70 b(reason)f(is)h(simply)g(that)g(the)f(stack)g +(initialization)i(goes)0 7263 y(hand)55 b(in)h(hand)f(with)h(the)f +(initialization)h(of)f(the)h(start)f(routine,)0 7462 +y(as)49 b(we)h(discussed)e(before.)77 b(And)50 b(this)g(start)f +(routine)i(has)e(to)h(be)0 7661 y(a)d(real)f(C)h(function)g(in)g(order) +g(to)g Fr(call)p Fx(.)67 b(But)47 b(once)f(the)h(thread)f(is)0 +7860 y(running,)54 b(there)d(no)g(longer)g(e)n(xists)f(such)h(an)g +(entry)g(point.)80 b(So,)0 8060 y(e)l(v)n(en)62 b(if)h(the)g(scheduler) +f(w)n(ould)i(be)e(able)h(to)g(gi)l(v)n(e)f(the)h(thread)0 +8259 y(a)g(ne)l(w)f(enlar)m(ged)h(stack,)k(there)c(is)g(no)g(chance)f +(to)h(restart)g(the)0 8458 y(thread)41 b(on)h(this)f(ne)l(w)g(stack.) +249 8670 y(Or)k(more)h(correct,)f(there)g(is)g(no)g Fr(portable)f +Fx(w)n(ay)h(to)h(achie)l(v)n(e)0 8869 y(it.)k(As)35 b(with)i(the)f(pre) +l(vious)g(problems,)h(there)f(is)g(a)h(non-portable)0 +9068 y(solution.)101 b(That)59 b(is)e(wh)o(y)i(our)f(implementation)h +(did)f(not)g(deal)0 9268 y(with)f(this)g(issue.)97 b(Instead)56 +b(in)h(practice)g(one)g(usually)f(lets)h(the)0 9467 y(scheduler)35 +b(just)g(detect)g(the)g(stack)f(o)n(v)n(er\003o)l(w)h(and)g(terminate)g +(the)0 9666 y(thread.)54 b(This)42 b(is)h(done)f(by)g(using)g(a)h(red)f +(zone)g(at)g(the)h(top)f(of)h(the)0 9865 y(stack)k(which)g(is)g(mark)n +(ed)h(with)f(a)g(magic)h(v)l(alue)e(the)i(scheduler)0 +10065 y(checks)40 b(between)h(thread)h(dispatching)f(operations.)249 +10276 y(Resizing)d(solutions)h(are)g(only)h(possible)e(in)i +(semi-portable)0 10475 y(w)n(ays.)79 b(One)50 b(approach)h(is)f(to)h +(place)g(the)f(thread)h(stacks)f(into)h(a)0 10675 y(memory)j(mapped)f +(area)g(\(see)g Fp(mmap)p Fx(\(2\)\))g(of)h(the)f(process)g(ad-)0 +10874 y(dress)61 b(space)h(and)g(let)g(the)g(scheduler)g(catch)f +Fp(SIGSEGV)f Fx(sig-)0 11073 y(nals.)139 b(When)71 b(such)f(a)h(signal) +g(occurs,)77 b(because)70 b(of)h(a)g(stack)0 11272 y(o)n(v)n(er\003o)l +(w)79 b(in)g(this)h(area,)88 b(the)79 b(scheduler)g(e)n(xplicitly)g +(resizes)p Black Black 4050 638 a(the)69 b(memory)h(mapped)f(area.)133 +b(This)70 b(resizing)f(can)f(be)h(done)4050 838 y(either)c(by)g(cop)n +(ying)h(the)f(stack)f(contents)h(into)g(a)g(ne)l(w)g(lar)m(ger)4050 +1037 y(area)57 b(which)h(is)f(then)h(re-mapped)g(to)g(the)f(old)h +(address)f(or)h(via)4050 1236 y(an)65 b(e)l(v)n(en)e(more)i(ele)n(g)o +(ant)f(w)n(ay)-11 b(,)70 b(as)64 b(the)h(v)n(endor)f(threading)h(li-) +4050 1435 y(braries)57 b(of)h Fr(Sun)g(Solaris)p Fx(,)j +Fr(F)-9 b(r)j(eeBSD)57 b Fx(and)h Fr(DEC)f(T)-9 b(ru64)58 +b Fx(do)g(it:)4050 1635 y(the)64 b(thread)g(stacks)f(are)h(allocated)f +(inside)h(memory)g(mapped)4050 1834 y(areas)c(which)g(are)g(already)g +(initially)i(a)e(fe)l(w)g(MB)g(in)h(\(virtual\))4050 +2033 y(size)50 b(and)g(then)g(one)g(just)g(relies)g(on)h(the)f(virtual) +h(memory)g(sys-)4050 2233 y(tem')-9 b(s)61 b(feature)h(that)f(only)h +(the)f(actually)g(consumed)g(memory)4050 2432 y(space)40 +b(is)i(mapped.)4050 2722 y FA(Startup)50 b(Routine)g(T)-18 +b(ermination)4050 2967 y Fx(There)99 b(is)g(a)g(cruel)h +Fp(abort)p Fx(\(3\))e(call)h(at)g(the)g(end)g(of)h(our)4050 +3166 y Fp(mctx)p 4460 3166 V 58 w(create)p 5118 3166 +V 58 w(boot)89 b Fx(function.)200 b(This)91 b(means,)102 +b(if)91 b(the)4050 3365 y(startup)38 b(routine)h(w)n(ould)g(return,)h +(the)e(process)f(is)i(aborted.)50 b(That)4050 3564 y(is)58 +b(ob)n(viously)f(not)i(reasonable,)h(so)e(wh)o(y)g(ha)m(v)n(e)f(we)g +(written)i(it)4050 3764 y(this)41 b(w)n(ay?)4299 3963 +y(If)32 b(the)g(thread)f(returns)h(from)h(the)e(startup)h(routine,)h +(it)f(should)4050 4162 y(be)45 b(cleanly)g(terminated.)62 +b(But)45 b(it)h(cannot)e(terminate)i(itself)f(\(for)4050 +4361 y(instance,)h(because)g(it)g(cannot)h(free)f(its)h(o)l(wn)f(stack) +g(while)g(run-)4050 4561 y(ning)64 b(on)g(it,)70 b Fr(etc.)p +Fx(\).)117 b(So)65 b(the)f(termination)g(handling)g(actually)4050 +4760 y(is)57 b(the)f(task)h(of)g(the)g(thread)g(library)g(scheduler)-9 +b(.)97 b(As)56 b(a)h(conse-)4050 4959 y(quence,)45 b(the)g(thread)g +(spa)n(wning)g(function)g(of)h(a)f(thread)g(library)4050 +5158 y(should)c(be)h(not)f(directly)h Fp(mctx)p 5945 +5158 V 58 w(create)p Fx(.)4299 5358 y(Instead)56 b(the)g(thread)h(spa)n +(wning)e(function)i(should)f(use)g(an)4050 5557 y(additional)38 +b(trampoline)g(function)h(as)e(the)h(higher)m(-le)l(v)n(el)f(startup) +4050 5756 y(routine.)50 b(And)38 b(this)h(trampoline)f(function)h +(performs)g(a)f(conte)n(xt)4050 5955 y(switch)52 b(back)g(into)h(the)g +(thread)f(library)i(scheduler)d(before)i(the)4050 6155 +y(lo)l(wer)m(-le)l(v)n(el)e(startup)g(routine)h(w)n(ould)g(return.)82 +b(The)52 b(scheduler)4050 6354 y(then)g(can)g(safely)g(remo)n(v)n(e)g +(the)g(thread)g(and)h(its)f(machine)g(con-)4050 6553 +y(te)n(xt.)72 b(That)48 b(is)h(wh)o(y)f(the)h Fp(abort)p +Fx(\(3\))e(call)h(is)g(ne)l(v)n(er)g(reached)g(in)4050 +6752 y(practice)56 b(\(more)g(details)g(can)f(be)h(found)g(in)h(the)f +(implementa-)4050 6952 y(tions)44 b(of)h Fp(pth)p 4910 +6952 V 59 w(spawn)d Fx(and)i Fp(pth)p 6095 6952 V 59 +w(exit)f Fx(in)i Fp(pth)p 7071 6952 V 58 w(lib.c)e Fx(of)4050 +7151 y Fr(GNU)e(Pth)h Fx([25)q(]\))4050 7441 y FA(The)50 +b(sigstack\(2\))f(F)-5 b(allback)50 b(Situation)4050 +7686 y Fx(Not)230 b(all)h(platforms)g(pro)n(vide)f(the)g(standardized) +4050 7885 y Fp(sigaltstack)p Fx(\(2\).)266 b(Instead)114 +b(the)n(y)f(at)i(least)e(pro)n(vide)4050 8084 y(the)104 +b Fr(4.2BSD)g Fx(ancestor)g(function)g Fp(sigstack)p +Fx(\(2\).)237 b(But)4050 8284 y(one)122 b(cannot)g(tri)l(vially)h +(replace)e Fp(sigaltstack)p Fx(\(2\))e(by)4050 8483 y +Fp(sigstack)p Fx(\(2\))63 b(in)k(this)e(situation,)72 +b(because)64 b(in)i(contrast)g(to)4050 8682 y Fp(sigaltstack)p +Fx(\(2\),)45 b(the)i(old)g Fp(sigstack)p Fx(\(2\))e(does)i(not)g(au-) +4050 8881 y(tomatically)64 b(handle)g(the)g(machine)f(dependent)g +(direction)i(of)4050 9081 y(stack)41 b(gro)l(wth.)4299 +9280 y(Instead,)90 b(the)81 b(caller)g(has)g(to)g(kno)l(w)h(the)f +(direction)g(and)4050 9479 y(al)n(w)n(ays)103 b(call)h +Fp(sigstack)p Fx(\(2\))d(with)i(the)h(address)e(of)i(the)4050 +9678 y(bottom)j(of)h(the)e(stack.)247 b(So,)123 b(in)107 +b(a)g(real-w)n(orld)g(imple-)4050 9878 y(mentation)80 +b(one)g(\002rst)h(has)e(to)i(determine)f(the)g(direction)h(of)4050 +10077 y(stack)f(gro)l(wth)h(in)f(order)h(to)g(use)f Fp(sigstack)p +Fx(\(2\))e(as)i(a)h(re-)4050 10276 y(placement)102 b(for)g +Fp(sigaltstack)p Fx(\(2\).)230 b(F)n(ortunately)102 b(this)4050 +10475 y(is)108 b(easier)g(than)g(it)h(seems)e(on)i(the)f(\002rst)h +(look)g(\(for)g(de-)4050 10675 y(tails)85 b(see)f(the)h(macros)g +Fp(AC)p 5772 10675 V 59 w(CHECK)p 6331 10675 V 58 w(STACKGROWTH)c +Fx(and)4050 10874 y Fp(AC)p 4260 10874 V 59 w(CHECK)p +4819 10874 V 58 w(STACKSETUP)65 b Fx(in)70 b(\002le)f +Fp(aclocal.m4)c Fx(from)4050 11073 y Fr(GNU)47 b(Pth)h +Fx([25]\).)69 b(Alternati)l(v)n(ely)47 b(if)h(one)f(can)f(af)l(ford)i +(to)g(w)n(aste)4050 11272 y(memory)-11 b(,)38 b(one)f(can)f(use)h(an)g +(ele)n(g)o(ant)f(trick:)50 b(to)37 b(set)g(up)g(a)f(stack)h(of)p +Black 3858 11872 a(9)p Black eop end +%%Page: 10 10 +TeXDict begin 10 9 bop Black Black 0 638 a Fx(size)41 +b Fe(N)18 b Fx(,)43 b(one)f(allocates)f(a)g(chunk)h(of)h(memory)f +(\(starting)h(at)f(ad-)0 838 y(dress)35 b Fe(A)p Fx(\))h(of)g(size)f +Fe(N)f Fd(\002)16 b Fc(2)35 b Fx(and)h(then)f(calls)g +Fp(sigstack)p Fx(\(2\))f(with)0 1037 y(the)41 b(parameters)f +Fr(sk)p 1162 1037 50 7 v 59 w(addr=)p Fe(A)35 b Fc(+)g +Fe(N)59 b Fx(and)41 b Fr(sk)p 2583 1037 V 59 w(size=)p +Fe(N)18 b Fx(,)40 b Fr(i.e)n(.)p Fx(,)f(one)0 1236 y(speci\002es)58 +b(the)h(middle)g(of)g(the)g(memory)h(chunk)f(as)f(the)h(stack)0 +1435 y(base.)0 1726 y FA(The)50 b(Blind)g(Alley)h(of)e(Brain-Dead)h +(Platf)-5 b(orms)0 1970 y Fx(The)34 b(w)n(orld)g(w)n(ould)h(not)e(be)h +(as)f(funn)n(y)h(as)f(it)h(is,)g(if)g(really)g(all)g(Unix)0 +2170 y(platforms)48 b(w)n(ould)g(be)f(f)n(air)i(to)e(us.)69 +b(Instead,)48 b(currently)g(at)g(least)0 2369 y(one)67 +b(platform)h(e)n(xists)e(which)i(plays)e(unf)n(air:)105 +b(unfortunately)-11 b(,)0 2568 y(ancient)62 b(v)n(ersions)g(of)g(the)h +(popular)g Fr(GNU/Linux)p Fx(.)114 b(Although)0 2767 +y(we)35 b(will)g(disco)n(v)n(er)f(that)h(it)g(both)g(pro)n(vides)g +Fp(sigaltstack)p Fx(\(2\))0 2967 y(and)54 b Fp(sigstack)p +Fx(\(2\),)g(our)h(approach)e(w)n(on')m(t)i(w)n(ork)g(on)f +Fr(Linux)0 3166 y Fx(k)n(ernels)37 b(prior)g(to)g(v)n(ersion)f(2.2)g +(and)h Fr(glibc)g Fx(prior)g(to)g(v)n(ersion)f(2.1.)249 +3365 y(Wh)o(y?)87 b(Because)51 b(its)j Fr(libc)f Fx(pro)n(vides)g(only) +g(stubs)g(of)h(these)0 3564 y(functions)j(which)g(al)n(w)n(ays)f +(return)i(just)e Fp(-1)g Fx(with)i Fp(errno)d Fx(set)0 +3764 y(to)i Fp(ENOSYS)p Fx(.)d(So,)60 b(this)d(de\002nitely)g(means)f +(that)g(our)h(nifty)h(al-)0 3963 y(gorithm)85 b(is)f(useless)e(there,) +94 b(because)83 b(its)h(central)g(point)g Fr(is)0 4162 +y Fp(sigaltstack)p Fx(\(2\)/)p Fp(sigstack)p Fx(\(2\).)68 +b(Ne)l(v)n(ertheless)46 b(we)j(do)0 4361 y(not)36 b(need)g(to)h(gi)l(v) +n(e)e(up.)50 b(At)36 b(least)f(not,)j(if)e(we,)h(for)g(a)f(single)f +(brain-)0 4561 y(dead)61 b(platform,)66 b(accept)60 b(to)h(break)g(our) +h(general)e(goal)h(of)h(not)0 4760 y(using)41 b(an)n(y)g(platform)h +(dependent)f(code.)249 4959 y(So,)e(what)f(can)g(we)g(actually)g(do)h +(here?)50 b(All)39 b(we)f(ha)m(v)n(e)f(to)h(do,)0 5158 +y(is)d(to)h(\002ddle)f(around)h(a)f(little)h(bit)g(with)f(the)h +(machine-dependent)0 5358 y Fp(jmp)p 310 5358 V 59 w(buf)46 +b Fx(ingredients)h(\(by)h(poking)g(around)f(in)h Fp(setjmp.h)0 +5557 y Fx(or)33 b(by)h(disassembling)e Fp(longjmp)p Fx(\(3\))f(in)i +(the)g(deb)m(ugger\).)48 b(Usu-)0 5756 y(ally)38 b(one)g(just)g(has)g +(to)g(do)h(a)f Fp(setjmp)p Fx(\(3\))e(to)j(get)f(an)g(initial)h(state)0 +5955 y(in)49 b(the)g Fp(jmp)p 740 5955 V 59 w(buf)e Fx(structure)i(and) +g(then)g(manually)g(adjust)g(tw)n(o)0 6155 y(of)70 b(its)g(\002elds:) +107 b(the)70 b(program)g(counter)g(\(usually)g(a)f(structure)0 +6354 y(member)63 b(with)f(\223)p Fp(pc)p Fx(\224)g(in)g(the)h(name\))f +(and)g(the)h(stack)f(pointer)0 6553 y(\(usually)41 b(a)h(structure)f +(member)h(with)g(\223)p Fp(sp)p Fx(\224)e(in)h(the)h(name\).)249 +6752 y(That)f(is)f(all)g(and)h(can)f(be)g(acceptable)f(for)i(a)f +(real-w)n(orld)h(im-)0 6952 y(plementation)36 b(which)g(really)g(w)n +(ants)g(to)g(co)n(v)n(er)f(mostly)h Fr(all)h Fx(plat-)0 +7151 y(forms)h(\226)f(at)g(least)g(as)g(long)h(as)e(the)i(special)e +(treatment)i(is)f(needed)0 7350 y(just)63 b(for)g(one)f(or)h(tw)n(o)g +(platforms.)115 b(But)63 b(one)f(has)g(to)h(k)n(eep)g(in)0 +7549 y(mind)d(that)f(it)g(at)g(least)g(breaks)f(one)h(of)h(the)f +(initial)h(goals)e(and)0 7749 y(has)41 b(to)h(be)f(treated)g(as)g(a)g +(last)g(chance)g(solution.)0 8039 y FA(Functions)49 b(sigsetjmp\(3\))h +(and)f(siglongjmp\(3\))249 8284 y Fx(One)86 b(certainly)g(w)n(ants)g +(the)g Fr(POSIX)94 b Fx(thread)86 b(semantics)0 8483 +y(where)101 b(a)h(thread)g(has)f(its)h(o)l(wn)f(signal)h(mask.)232 +b(As)101 b(al-)0 8682 y(ready)74 b(mentioned,)82 b(on)75 +b(some)f(platforms)g Fp(setjmp)p Fx(\(3\))f(and)0 8881 +y Fp(longjmp)p Fx(\(3\))c(do)h(not)h(pro)n(vide)f(this)h(and)f(instead) +g(one)h(has)0 9081 y(to)47 b(e)n(xplicitly)h(call)f Fp(sigsetjmp)p +Fx(\(3\))d(and)j Fp(siglongjmp)p Fx(\(3\))0 9280 y(instead.)224 +b(There)99 b(is)g(only)h(one)f(snare:)166 b(on)100 b(some)f(plat-)0 +9479 y(forms)74 b Fp(sigsetjmp)p Fx(\(3\)/)p Fp(siglongjmp)p +Fx(\(3\))68 b(sa)m(v)n(e)k(also)i(in-)0 9678 y(formation)81 +b(about)f(the)g(alternate)f(signals)g(stack.)166 b(So)80 +b(here)0 9878 y(one)92 b(has)f(to)h(mak)n(e)g(sure)g(that)g(although)g +(the)g(thread)g(dis-)0 10077 y(patching)76 b(later)h(uses)e +Fp(sigsetjmp)p Fx(\(3\)/)p Fp(siglongjmp)p Fx(\(3\),)0 +10276 y(the)87 b(thread)g(creation)g(step)f(in)i Fp(mctx)p +2395 10276 V 58 w(create)d Fx(still)i(uses)0 10475 y(plain)93 +b Fp(setjmp)p Fx(\(3\)/)p Fp(longjmp)p Fx(\(3\))c(calls)j(for)h(the)f +(trampo-)0 10675 y(line)g(trick.)204 b(One)92 b(just)g(has)g(to)g(be)g +(careful)g(because)f(the)0 10874 y Fp(jmp)p 310 10874 +V 59 w(buf)38 b Fx(and)i Fp(sigjmp)p 1587 10874 V 57 +w(buf)f Fx(structures)g(cannot)h(be)f(mix)n(ed)0 11073 +y(between)58 b(calls)g(to)g(the)h Fp(sigsetjmp)p Fx(\(3\)/)p +Fp(siglongjmp)p Fx(\(3\))0 11272 y(and)41 b Fp(setjmp)p +Fx(\(3\)/)p Fp(longjmp)p Fx(\(3\).)p Black Black 4050 +638 a FA(Mor)l(e)51 b(Machine)f(Context)g(Ingr)l(edients)4050 +908 y Fx(Finally)-11 b(,)68 b(for)c(a)e(real-w)n(orld)i(threading)f +(implementation)g(one)4050 1107 y(usually)h(w)n(ants)g(to)h(put)f(more) +h(state)e(into)i(the)f(machine)g(con-)4050 1306 y(te)n(xt)87 +b(structure)g Fp(mctx)p 5462 1306 V 58 w(t)p Fx(.)188 +b(F)n(or)87 b(instance)f(to)i(ful\002ll)g(more)4050 1505 +y Fr(POSIX)53 b Fx(threading)45 b(semantics,)f(it)h(is)g(reasonable)f +(to)g(also)h(sa)m(v)n(e)4050 1705 y(and)76 b(restore)g(the)g(global)g +Fp(errno)e Fx(v)l(ariable.)154 b(All)77 b(this)f(can)4050 +1904 y(be)66 b(easily)f(achie)l(v)n(ed)g(by)h(e)n(xtending)f(the)h +Fp(mctx)p 7005 1904 V 58 w(t)g Fx(structure)4050 2103 +y(with)61 b(additional)g(\002elds)g(and)f(by)h(making)g(the)g +Fp(mctx)p 7312 2103 V 58 w(save)p Fx(,)4050 2302 y Fp(mctx)p +4460 2302 V 58 w(restore)77 b Fx(and)h Fp(mctx)p 6013 +2302 V 59 w(switch)e Fx(functions)j(to)g(be)4050 2502 +y(a)n(w)n(are)41 b(of)h(them.)4050 3033 y FA(3.6)198 +b(Related)51 b(W)-15 b(ork)4050 3363 y Fx(Beside)97 b +Fr(GNU)h(Pth)h Fx([25],)112 b(there)99 b(are)f(other)g(multithread-) +4050 3562 y(ing)82 b(libraries)g(which)g(use)f(v)l(ariants)h(of)g(the)g +(presented)f(ap-)4050 3762 y(proach)33 b(for)h(implementing)g(machine)f +(conte)n(xts)g(in)g(user)m(-space.)4050 3961 y(Most)99 +b(notably)g(there)g(are)k(R)r Fm(O)8 b(B)g(E)g(RT)107 +b Fx(S)8 b(.)108 b(T)8 b Fm(H)g(A)q(U)t Fx(')-9 b(s)100 +b Fr(Really)4050 4160 y(Simple)78 b(Thr)-6 b(eads)77 +b Fx(\()p Fr(r)n(sthr)-6 b(eads)p Fx(,)85 b([27]\))79 +b(package)d(which)i(uses)4050 4359 y Fp(sigaltstack)p +Fx(\(2\))42 b(in)j(a)g(v)n(ery)g(similar)h(w)n(ay)f(for)h(thread)f +(cre-)4050 4559 y(ation,)56 b(and)i(K)t Fm(O)s(T)l(A)j +Fx(A)8 b Fm(B)g(E)t Fx(')-9 b(s)54 b Fr(P)-13 b(ortable)53 +b(Thr)-6 b(ead)54 b(Libr)n(ary)e Fx(\()p Fr(PTL)p Fx(,)4050 +4758 y([24]\))34 b(which)f(uses)f(a)g Fp(sigstack)p Fx(\(2\))f +(approach.)48 b(But)32 b(because)4050 4957 y(their)52 +b(approaches)f(handle)h(the)g(signal)f(handler)h(scope)f(dif)l(fer)m(-) +4050 5156 y(ently)-11 b(,)64 b(the)n(y)59 b(are)h(not)g(able)f(to)h +(achie)l(v)n(e)e(the)i(same)f(amount)h(of)4050 5356 y(portability)34 +b(and)f(this)g(w)n(ay)g(do)g(not)h(w)n(ork)f(for)h(instance)e(on)h +(some)4050 5555 y(System-V)-17 b(-deri)l(v)n(ed)42 b(platforms.)4050 +6086 y FA(3.7)198 b(Summary)49 b(&)h(A)-20 b(v)n(ailability)4050 +6416 y Fx(W)-13 b(e)42 b(ha)m(v)n(e)f(presented)h(a)g(pragmatic)g(and)h +(mostly)f(portable)h(f)n(all-)4050 6615 y(back)38 b(approach)f(for)i +(implementing)f(the)g(machine)g(conte)n(xt)f(for)4050 +6815 y(user)m(-space)61 b(threads,)68 b(based)62 b(entirely)i(on)f +(Unix)g(system)f(and)4050 7014 y(ANSI-C)48 b(language)f(f)n(acilities.) +70 b(The)48 b(approach)f(w)n(as)h(success-)4050 7213 +y(fully)55 b(tested)f(in)h(practice)g(on)f(a)h(wide)f(range)h(of)g +(Unix)g(\003a)m(v)m(ors)4050 7412 y(by)36 b Fr(GNU)f(Pth)h +Fx(and)f(should)h(also)f(adapt)g(to)h(the)f(remaining)h(Unix)4050 +7612 y(platforms)c(as)g(long)g(as)g(the)n(y)f(adhere)h(to)g(the)g(rele) +l(v)l(ant)f(standards.)4299 7821 y(The)103 b Fr(GNU)f(Pth)h +Fx(package)f(is)h(distrib)m(uted)f(under)h(the)4050 8020 +y(GNU)64 b(Library)i(General)e(Public)h(License)g(\(LGPL)h(2.1\))e(and) +4050 8219 y(freely)83 b(a)m(v)l(ailable)f(from)i Fr(http://www)-12 +b(.gnu.or)-6 b(g/softwar)g(e/pth/)4050 8419 y Fx(and)41 +b Fr(ftp://ftp.gnu.or)-6 b(g/gnu/pth/)p Fx(.)4050 8949 +y FA(3.8)198 b(Ackno)n(wledgements)4050 9280 y Fx(I)35 +b(w)n(ould)f(lik)n(e)h(to)g(thank)j(R)r Fm(O)8 b(B)g(E)g(RT)43 +b Fx(S)8 b(.)43 b(T)8 b Fm(H)g(A)q(U)t Fx(,)40 b(D)r +Fm(A)-10 b(V)8 b(I)g(D)43 b Fx(B)7 b Fm(U)h(T)g(E)g(N)g +Fx(-)4054 9479 y Fm(H)g(O)g(F)t Fx(,)52 b(M)8 b Fm(A)g(RT)g(I)g(N)56 +b Fx(K)8 b Fm(R)g(A)g(E)g(M)g(E)g(R)t Fx(,)53 b(E)8 b +Fm(R)g(I)g(C)57 b Fx(N)8 b Fm(E)g(W)g(T)e(O)i(N)52 b +Fx(and)f(B)8 b Fm(R)s(U)g(N)g(O)4054 9678 y Fx(H)g Fm(A)g(I)g(B)g(L)g +(E)66 b Fx(for)c(their)f(comments)g(which)f(helped)h(to)g(write)g(the) +4050 9878 y(initial)c(v)n(ersion)f(of)h(this)g(paper)-9 +b(.)96 b(Additionally)-11 b(,)61 b(credit)c(has)f(to)4050 +10077 y(be)42 b(gi)l(v)n(en)g(to)k(C)8 b Fm(H)g(R)g(I)g(S)g(T)e(O)i(P)g +(H)g(E)g(R)51 b Fx(S)8 b Fm(M)g(A)g(L)g(L)48 b Fx(and)42 +b(the)h(USENIX)g(re-)4050 10276 y(vie)l(wers)e(for)h(their)g(in)-7 +b(v)l(aluable)42 b(feedback)f(which)h(allo)l(wed)f(this)4050 +10475 y(paper)58 b(to)h(be)g(e)n(xtended,)i(cleaned)d(up)h(and)f +(\002nally)h(published)4050 10675 y(at)47 b(the)h(USENIX)g(Annual)f(T) +-12 b(echnical)48 b(Conference)e(2000.)69 b(Fi-)4050 +10874 y(nally)-11 b(,)56 b(thanks)e(go)f(to)h(all)g(users)e(of)i +Fr(GNU)g(Pth)g Fx(for)g(their)g(feed-)4050 11073 y(back)39 +b(on)h(the)f(implementation,)h(which)f(helped)h(in)f(\002ne-tuning)4050 +11272 y(the)i(presented)g(approach.)1859 b([)p Fb(rse)p +Fx(])p Black 3817 11872 a(10)p Black eop end +%%Page: 11 11 +TeXDict begin 11 10 bop Black Black 0 638 a Fs(Refer)l(ences)p +Black 141 976 a Fv([1])p Black 82 w Fu(POSIX)38 b(1003.1c)e(Thr)-6 +b(eading)p Fv(,)37 b(IEEE)h(POSIX)f(1003.1c-1995,)398 +1158 y(ISO/IEC)g(9945-1:1996)p Black 141 1397 a([2])p +Black 86 w(M)8 b(.)g(E)g(.)93 b(C)8 b Fa(O)g(N)g(W)-6 +b(A)h(Y)t Fv(:)141 b Fu(Design)86 b(of)g(a)g(separ)n(able)f(tr)n +(ansition-)398 1580 y(dia)o(gr)n(am)35 b(compiler)-17 +b(.)p Fv(,)38 b(Comm.)g(A)-6 b(CM)37 b(6:7,)f(1963,)h(p.396-408)p +Black 141 1819 a([3])p Black 86 w(E)8 b(.)g(W)-6 b(.)45 +b(D)8 b Fa(I)g(J)g(K)g(S)g(T)g(R)g(A)t Fv(:)41 b Fu(Co-oper)n(ating)35 +b(sequential)h(pr)-7 b(ocesses)p Fv(,)39 b(in)398 2001 +y(F)-12 b(.)51 b(Genuys)e(\(Ed.\),)k Fu(Pr)-7 b(o)o(gr)n(amming)48 +b(Langua)o(g)o(es)p Fv(,)j(N)-5 b(A)-17 b(T)m(O)51 b(Ad-)398 +2184 y(v)l(anced)43 b(Study)f(Institute,)g(Academic)h(Press,)i(London,) +e(1965,)398 2367 y(p.42-112.)p Black 141 2605 a([4])p +Black 86 w(B)8 b(.)70 b(N)8 b Fa(I)g(C)g(H)g(O)g(L)g(S)g +Fv(,)73 b(D)8 b(.)70 b(B)7 b Fa(U)h(T)g(T)g(L)g(A)g(R)g +Fv(,)72 b(J)8 b(.)g(P)-9 b(.)70 b(F)n Fa(A)8 b(R)g(R)g(E)g(L)t +Fv(:)93 b Fu(Pthr)-6 b(eads)398 2788 y(Pr)f(o)o(gr)n(amming)43 +b(-)h(A)h(POSIX)f(Standar)-6 b(d)43 b(for)h(Better)h(Multipr)-7 +b(o-)398 2971 y(cessing)p Fv(,)38 b(O'Reilly)-10 b(,)36 +b(1996;)g(ISBN)h(1-56592-115-1)p Black 141 3209 a([5])p +Black 86 w(B)8 b(.)55 b(L)8 b Fa(E)g(W)g(I)g(S)g Fv(,)55 +b(D)8 b(.)55 b(J)8 b(.)55 b(B)8 b Fa(E)g(R)g(G)t Fv(:)63 +b Fu(Thr)-6 b(eads)48 b(Primer)f(-)h(A)f(Guide)g(T)-14 +b(o)398 3392 y(Multithr)-6 b(eaded)33 b(Pr)-7 b(o)o(gr)n(amming)p +Fv(,)33 b(Prentice)g(Hall,)h(1996;)g(ISBN)398 3575 y(0-13-443698-9)p +Black 141 3813 a([6])p Black 86 w(S)8 b(.)40 b(J)8 b(.)39 +b(N)8 b Fa(O)g(R)q(T)e(O)i(N)g Fv(,)37 b(M)8 b(.)39 b(D)8 +b(.)40 b(D)8 b Fa(I)g(P)m(A)g(S)g(Q)f(U)s(A)h(L)g(E)t +Fv(:)39 b Fu(Thr)-6 b(ead)32 b(T)-8 b(ime)31 b(-)h(The)398 +3996 y(Multithr)-6 b(eaded)28 b(Pr)-7 b(o)o(gr)n(amming)26 +b(Guide)p Fv(,)k(Prentice)f(Hall,)h(1997;)398 4179 y(ISBN)37 +b(0-13-190067-6)p Black 141 4417 a([7])p Black 86 w(D)8 +b(.)49 b(R)8 b(.)48 b(B)7 b Fa(U)h(T)g(E)g(N)g(H)g(O)g(F)t +Fv(:)50 b Fu(Pr)-7 b(o)o(gr)n(amming)39 b(with)h(POSIX)h(Thr)-6 +b(eads)p Fv(,)398 4600 y(Addison)36 b(W)-12 b(esle)n(y)i(,)38 +b(1997;)e(ISBN)h(0-201-63392-2)p Black 141 4839 a([8])p +Black 86 w(S)8 b(.)56 b(P)8 b Fa(R)g(A)g(S)g(A)g(D)t +Fv(:)65 b Fu(Multithr)-6 b(eading)46 b(Pr)-7 b(o)o(gr)n(amming)46 +b(T)-14 b(ec)n(hniques)p Fv(,)398 5022 y(McGra)n(w-Hill,)36 +b(1996;)g(ISBN)h(0-079-12250-7)p Black 141 5260 a([9])p +Black 86 w(S)8 b(.)66 b(K)8 b Fa(L)g(E)g(I)g(N)g(M)g(A)g(N)g +Fv(,)68 b(B)8 b(.)65 b(S)8 b Fa(M)g(A)g(L)g(D)g(E)g(R)g(S)g +Fv(,)68 b(D)8 b(.)66 b(S)8 b Fa(H)g(A)g(H)t Fv(:)86 b +Fu(Pr)-7 b(o)o(gr)n(am-)398 5443 y(ming)55 b(with)g(Thr)-6 +b(eads)p Fv(,)61 b(Prentice)55 b(Hall,)61 b(1995;)i(ISBN)56 +b(0-131-)398 5626 y(72389-8)p Black 66 5864 a([10])p +Black 86 w(C)8 b(.)g(J)g(.)82 b(N)8 b Fa(O)g(R)q(T)g(H)g(R)s(U)g(P)t +Fv(:)116 b Fu(Pr)-7 b(o)o(gr)n(amming)73 b(W)-8 b(ith)74 +b(Unix)g(Thr)-6 b(eads)p Fv(,)398 6047 y(John)37 b(W)-6 +b(ile)n(y)36 b(&)i(Sons,)f(1996;)f(ISBN)h(0-471-13751-0)p +Black 66 6286 a([11])p Black 86 w(P)-9 b(.)61 b(B)s Fa(A)8 +b(R)q(T)e(O)i(N)g Fv(-)g(D)s Fa(A)-8 b(V)8 b(I)g(S)g +Fv(,)58 b(D)8 b(.)60 b(M)8 b Fa(C)g Fv(N)s Fa(A)g(M)g(E)g(E)g +Fv(,)61 b(R)8 b(.)60 b(V)-10 b Fa(A)8 b(S)g(W)-6 b(A)8 +b(N)g(I)g Fv(,)61 b(E)8 b(.)402 6468 y(L)g Fa(A)g(Z)g(O)t(W)g(S)g(K)g +(A)t Fv(:)39 b Fu(Adding)28 b(Sc)n(heduler)h(Activations)e(to)i(Mac)n +(h)g(3.0)p Fv(,)398 6651 y(Uni)l(v)n(ersity)51 b(of)i(W)-12 +b(ashington,)55 b(1992;)k(T)-10 b(echnical)53 b(Report)f(92-)398 +6834 y(08-03)p Black 66 7072 a([12])p Black 86 w(D)8 +b(.)37 b(S)8 b Fa(T)g(E)g(I)g(N)g Fv(,)36 b(D)8 b(.)36 +b(S)8 b Fa(H)g(A)g(H)t Fv(:)40 b Fu(Implementing)27 b(Lightwight)f(Thr) +-6 b(eads)p Fv(,)398 7255 y(SunSoft)36 b(Inc.,)i(1992)e(\(published)g +(at)h(USENIX'92\).)p Black 66 7494 a([13])p Black 86 +w(W)-6 b(.)8 b(R)g(.)g(S)g Fa(T)g(E)g(V)g(E)g(N)g(S)t +Fv(:)103 b Fu(Advanced)68 b(Pr)-7 b(o)o(gr)n(amming)66 +b(in)h(the)g(Unix)398 7676 y(En)-6 b(vir)f(onment)p Fv(,)114 +b(Addison-W)-12 b(esle)n(y)i(,)114 b(1992;)128 b(ISBN)99 +b(0-201-)398 7859 y(56317-7)p Black 66 8098 a([14])p +Black 86 w(D)8 b(.)84 b(L)8 b Fa(E)g(W)g(I)g(N)g(E)t +Fv(:)121 b Fu(POSIX)77 b(Pr)-7 b(o)o(gr)n(ammer')h(s)76 +b(Guide:)123 b(Writing)398 8281 y(P)-12 b(ortable)67 +b(Unix)g(Pr)-7 b(o)o(gr)n(ams)p Fv(,)74 b(O'Reilly)65 +b(&)j(Associates,Inc.,)398 8463 y(1994;)36 b(ISBN)h(0-937175-73-0)p +Black 66 8702 a([15])p Black 86 w(B)8 b Fa(RY)-6 b(A)8 +b(N)274 b Fv(O)8 b(')g(S)g Fa(U)g(L)g(L)g(I)g(V)-8 b(A)8 +b(N)t Fv(:)504 b Fu(F)-8 b(r)i(equently)268 b(ask)o(ed)398 +8885 y(questions)369 b(for)h(comp.os.r)-6 b(esear)g(c)n(h)p +Fv(,)456 b(1995;)398 9067 y(http://www)-10 b(.serpentine.com/)p +Fk(\230)p Fv(bos/os-f)o(aq/,)398 9250 y +(ftp://rtfm.mit.edu/pub/usenet/comp.os.research/)p Black +66 9489 a([16])p Black 86 w(S)8 b Fa(U)g(N)50 b Fv(M)8 +b Fa(I)g(C)g(R)s(O)g(S)g(Y)g(S)g(T)g(E)g(M)g(S)g Fv(,)46 +b(I)8 b Fa(N)g(C)t Fv(:)54 b Fu(Thr)-6 b(eads)42 b(F)-8 +b(r)i(equently)43 b(Ask)o(ed)398 9671 y(Questions)p Fv(,)219 +b(1995,)g(http://www.sun.com/w)o(orkshop/-)398 9854 y(threads/f)o +(aq.html)p Black Black Black 4116 638 a([17])p Black +86 w(B)8 b Fa(RY)-6 b(A)8 b(N)156 b Fv(O)8 b(')g(S)g +Fa(U)g(L)g(L)g(I)g(V)-8 b(A)8 b(N)t Fv(:)266 b Fu(F)-8 +b(r)i(equently)150 b(ask)o(ed)g(ques-)4448 821 y(tions)266 +b(for)g(comp.pr)-7 b(o)o(gr)n(amming)n(.thr)h(eads)p +Fv(,)323 b(1997;)4448 1004 y(http://www)-10 b(.serpentine.com/)p +Fk(\230)p Fv(bos/threads-f)o(aq/.)p Black 4116 1253 a([18])p +Black 86 w(B)8 b Fa(I)g(L)167 b Fv(L)8 b Fa(E)g(W)g(I)g(S)t +Fv(:)290 b Fu(F)-8 b(r)i(equently)160 b(ask)o(ed)g(questions)g(for)4448 +1435 y(comp.pr)-7 b(o)o(gr)n(amming)n(.thr)h(eads)p Fv(,)418 +b(1999;)495 b(http://-)4448 1618 y(www)-10 b(.lambdacs.com/ne)l +(wsgroup/F)f(A)j(Q.html)p Black 4116 1867 a([19])p Black +86 w(N)8 b Fa(U)g(M)g(E)g(R)g(I)g(C)116 b Fv(Q)7 b Fa(U)h(E)g(S)g(T)116 +b Fv(I)8 b Fa(N)g(C)t Fv(:)193 b Fu(Multithr)-6 b(eading)109 +b(-)i(De\002ni-)4448 2050 y(tions)118 b(and)h(Guidelines)p +Fv(;)158 b(1998;)h(http://www)-10 b(.numeric-)4448 2233 +y(quest.com/lang/multi-frame.html)p Black 4116 2482 a([20])p +Black 86 w(T)8 b Fa(H)g(E)85 b Fv(O)8 b Fa(P)g(E)g(N)84 +b Fv(G)8 b Fa(R)s(O)g(U)g(P)t Fv(:)125 b Fu(The)79 b(Single)d(Unix)i +(Speci\002cation,)4448 2664 y(V)-17 b(er)o(sion)91 b(2)f(-)h(Thr)-6 +b(eads)p Fv(;)117 b(1997;)f(http://www.opengroup-)4448 +2847 y(.or)m(g/onlinepubs/007908799/xsh/threads.html)p +Black 4116 3096 a([21])p Black 86 w(S)8 b Fa(U)g(N)83 +b Fv(M)8 b Fa(I)g(C)g(R)s(O)g(S)g(Y)g(S)g(T)g(E)g(M)g(S)79 +b Fv(I)8 b Fa(N)g(C)t Fv(:)121 b Fu(SMI)76 b(Thr)-6 b(ead)77 +b(Resour)-6 b(ces)p Fv(;)4448 3279 y(http://www)c(.sun.com/w)o +(orkshop/threads)p Black 4116 3528 a([22])p Black 86 +w(F)8 b Fa(R)g(A)g(N)g(K)59 b Fv(M)8 b Fa(U)g(E)g(L)g(L)g(E)g(R)t +Fv(:)73 b Fu(FSU)53 b(pthr)-6 b(eads)p Fv(;)59 b(1997;)g(http://www-) +4448 3710 y(.cs.fsu.edu/)p Fk(\230)p Fv(mueller/pthreads/)p +Black 4116 3959 a([23])p Black 86 w(C)8 b Fa(H)g(R)g(I)g(S)169 +b Fv(P)8 b Fa(R)s(O)r(V)g(E)g(N)g(Z)g(A)g(N)g(O)t Fv(:)295 +b Fu(MIT)164 b(pthr)-6 b(eads)p Fv(;)227 b(1993;)4448 +4142 y(http://www)-10 b(.mit.edu/people/prov)n(en/pthreads.html)4448 +4325 y(\(old\),)418 b(http://www.humanf)o(actor.com/pthreads/mit-)4448 +4507 y(pthreads.html)36 b(\(updated\))p Black 4116 4756 +a([24])p Black 86 w(K)t Fa(O)s(T)m(A)58 b Fv(A)8 b Fa(B)g(E)t +Fv(:)73 b Fu(P)-12 b(ortable)51 b(Thr)-6 b(eading)51 +b(Libr)n(ary)g Fv(\(PTL\);)h(1999;)4448 4939 y +(http://www.media.osaka-cu.ac.jp/)p Fk(\230)p Fv(k-abe/PTL/)p +Black 4116 5188 a([25])p Black 86 w(R)8 b Fa(A)g(L)g(F)40 +b Fv(S)8 b(.)41 b(E)8 b Fa(N)g(G)g(E)g(L)g(S)g(C)g(H)g(A)g(L)g(L)t +Fv(:)39 b Fu(GNU)33 b(P)-12 b(ortable)33 b(Thr)-6 b(eads)34 +b Fv(\(Pth\);)4448 5371 y(1999;)105 b(http://www.gnu.or)m(g/softw)o +(are/pth/,)88 b(ftp://ftp.gnu-)4448 5553 y(.or)m(g/gnu/pth/)p +Black 4116 5802 a([26])p Black 86 w(M)8 b Fa(I)g(C)g(H)g(A)g(E)g(L)73 +b Fv(T)m(.)j(P)8 b Fa(E)g(T)g(E)g(R)g(S)g(O)g(N)t Fv(:)105 +b Fu(POSIX)68 b(and)g(DCE)h(Thr)-6 b(eads)4448 5985 y(F)-16 +b(or)115 b(Linux)e Fv(\(PCThreads\);)152 b(1995;)e(http://members.aa-) +4448 6168 y(.net/)p Fk(\230)p Fv(mtp/PCthreads.html)p +Black 4116 6417 a([27])p Black 86 w(R)s Fa(O)8 b(B)g(E)g(R)q(T)54 +b Fv(S)8 b(.)58 b(T)8 b Fa(H)g(A)q(U)t Fv(:)71 b Fu(Really)50 +b(Simple)g(Thr)-6 b(eads)50 b Fv(\(rsthreads\);)4448 +6599 y(1996;)36 b(ftp://ftp.ai.mit.edu/pub/rst/)p Black +4116 6849 a([28])p Black 86 w(J)8 b Fa(O)g(H)g(N)189 +b Fv(B)8 b Fa(I)g(R)g(R)g(E)g(L)g(L)t Fv(:)329 b Fu(F)-8 +b(r)i(eeBSD)183 b(uthr)-6 b(eads)p Fv(;)253 b(1998;)4448 +7031 y(ftp://ftp.freebsd.or)m(g/pub/FreeBSD/FreeBSD-)4448 +7214 y(current/src/lib/libc)p 5565 7214 45 7 v 50 w(r/uthread/)p +Black 4116 7463 a([29])p Black 86 w(X)8 b Fa(A)-8 b(V)8 +b(I)g(E)g(R)92 b Fv(L)8 b Fa(E)g(R)s(O)r(Y)t Fv(:)144 +b Fu(The)88 b(LinuxThr)-6 b(eads)87 b(libr)n(ary)p Fv(;)112 +b(1999;)4448 7646 y(http://pauillac.inria.fr/)p Fk(\230)p +Fv(xlero)o(y/linuxth)o(reads/)p Black 4116 7895 a([30])p +Black 86 w(I)8 b(B)g(M)t(:)34 b Fu(AIX)j(V)-17 b(er)o(sion)36 +b(4.3)g(Gener)n(al)g(Pr)-7 b(o)o(gr)n(amming)34 b(Concepts:)4448 +8077 y(Writing)110 b(and)f(Deb)m(ug)o(ging)g(Pr)-7 b(o)o(gr)n(ams;)146 +b(Under)o(standing)4448 8260 y(Thr)-6 b(eads)p Fv(;)81 +b(1998;)d(http://www.rs6000.ibm.com/doc)p 7435 8260 V +50 w(link/-)4448 8443 y(en)p 4598 8443 V 54 w(US/a)p +4951 8443 V 54 w(doc)p 5221 8443 V 53 w(lib/aixpr)m +(ggd/genprogc/understanding-)p 4448 8625 V 4493 8625 +a(threads.htm)p Black 4116 8874 a([31])p Black 82 w Fu(Netscape)218 +b(P)-12 b(ortable)218 b(Runtime)f Fv(\(NSPR\);)g(http://-)4448 +9057 y(www)-10 b(.mozilla.or)m(g/docs/refList/refNSPR/,)493 +b(http://-)4448 9240 y(lxr)-8 b(.mozilla.or)m(g/seamonk)o(e)n +(y/source/nsprpub/)p Black 4116 9489 a([32])p Black 86 +w(R)8 b Fa(A)g(L)g(F)90 b Fv(S)8 b(.)91 b(E)8 b Fa(N)g(G)g(E)g(L)g(S)g +(C)g(H)g(A)g(L)g(L)t Fv(:)134 b Fu(Simple)83 b(Mac)n(hine)g(Conte)m(xt) +4448 9671 y(Benc)n(hmark)s Fv(;)142 b(2000;)g(http://www)-10 +b(.gnu.or)m(g/softw)o(are/pth-)4448 9854 y(/smcb)k(.tar)e(.gz)p +Black 3817 11872 a Fx(11)p Black eop end +%%Trailer + +userdict /end-hook known{end-hook}if +%%EOF Index: ossp-pkg/pth/rse-pmt.tex RCS File: /v/ossp/cvs/ossp-pkg/pth/rse-pmt.tex,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/pth/rse-pmt.tex,v' | diff -u /dev/null - -L'ossp-pkg/pth/rse-pmt.tex' 2>/dev/null --- ossp-pkg/pth/rse-pmt.tex +++ - 2024-05-09 08:33:06.757928468 +0200 @@ -0,0 +1,1389 @@ + +\documentclass[10pt,letterpaper]{article} + +\usepackage{vmargin} +\usepackage{multicol} +\usepackage{times} +\usepackage{epsfig} +\usepackage{float} +\usepackage{color} +\usepackage{calc} +\usepackage{alltt} +\usepackage{verbatim} +\usepackage{moreverb} +\usepackage{fancyheadings} +\usepackage{supertabular} +\usepackage{colortbl} +\usepackage{rotating} + +\floatstyle{boxed} + +\makeatletter + +\let\hangafter\@hangfrom + +\definecolor{dark}{rgb}{0.5,0.5,0.5} +\definecolor{medium}{rgb}{0.7,0.7,0.7} +\definecolor{light}{rgb}{0.95,0.95,0.95} +\newcommand{\grayrow}{\rowcolor[gray]{0.8}} + +\setpapersize{USletter} +\setmarginsrb{1.0in}{1.0in}{1.0in}{0.5in}{0pt}{0pt}{0.5in}{0.5in} + +%\renewcommand{\sfdefault}{phv} +\renewcommand{\section}{\@startsection% + {section}{1}{\z@}% + {-3.5ex \@plus -1ex \@minus -.2ex}% + {2.3ex \@plus.2ex}% + {\normalfont\Large\bfseries}} +\renewcommand{\subsection}{\@startsection% + {subsection}{2}{\z@}% + {-3.25ex\@plus -1ex \@minus -.2ex}% + {1.5ex \@plus .2ex}% + {\normalfont\large\bfseries}} +\renewcommand{\subsubsection}{\@startsection% + {subsubsection}{3}{\z@}% + {-3.25ex\@plus -1ex \@minus -.2ex}% + {1.5ex \@plus .2ex}% + {\normalfont\normalsize}} +\renewcommand{\paragraph}{\@startsection% + {paragraph}{4}{\z@}% + {3.25ex \@plus1ex \@minus.2ex}% + {-1em}% + {\normalfont\normalsize\bfseries}} +\renewcommand{\subparagraph}{\@startsection% + {subparagraph}{5}{\parindent}% + {3.25ex \@plus1ex \@minus .2ex}% + {-1em}% + {\normalfont\normalsize}} + +\renewcommand{\labelitemi}{ \rule{6pt}{6pt} } +\renewcommand{\labelitemii}{ \rule{5pt}{5pt} } +\renewcommand{\labelitemiii}{ \rule{4pt}{4pt} } +\renewcommand{\labelitemiv}{ \rule{3pt}{3pt} } + +\newcommand{\mypar}[1]{\medskip\noindent{\large\bfseries #1}\smallskip} + +\makeatother + +\pagestyle{fancy} +\lhead{} +\chead{} +\rhead{} +\headrulewidth=0pt +\lfoot{} +\cfoot{\thepage} +\rfoot{} + +\begin{document} + +\begin{center} +{\huge\bfseries Portable Multithreading}\\[1mm] +{\large\bfseries The Signal Stack Trick For User-Space Thread Creation}\\[5mm] +{\large Ralf S. Engelschall}\\[1mm] +{\large\textit{Technische Universit\"at M\"unchen (TUM)}}\\[1mm] +rse@engelschall.com, http://www.engelschall.com\\[8mm] +%{\large June 18th, 2000} +\end{center} + +\begin{abstract} +\noindent This paper describes a pragmatic but portable fallback +approach for creating and dispatching between the machine contexts of +multiple threads of execution on Unix systems that lack a dedicated +user-space context switching facility. Such a fallback approach +for implementing machine contexts is a vital part of a user-space +multithreading environment, if it has to achieve maximum portability +across a wide range of Unix flavors. The approach is entirely based +on standard Unix system facilities and ANSI-C language features and +especially does not require any assembly code or platform specific +tricks at all. The most interesting issue is the technique of creating +the machine context for threads, which this paper explains in detail. +The described approach closely follows the algorithm as implemented by +the author for the popular user-space multithreading library \textit{GNU +Portable Threads} (\textit{GNU Pth}, \cite{pth}) which this way quickly +gained the status of one of the most portable user-space multithreading +libraries. + +\medskip +\noindent +\textsf{\bfseries Keywords:} +portability, multithreading, Unix, POSIX, SUSv2, ANSI-C, user-space, context +creation, context switching, signal handler, stack, makecontext, +switchcontext, sigaltstack, setjmp, longjmp. + +\medskip +\noindent +\textsf +{\bfseries Publishing:} +Early drafts of this paper were distributed with the GNU Pth +distribution. The final release version was published on the USENIX +Annual Technical Conference, June 18-23, 2000, San Diego, California, +USA. +\end{abstract} + +\medskip +\columnsep=0.25in +\begin{multicols}{2}[\section{Introduction}] + +\subsection{Multithreading} + +The paradigm of programming with multiple threads of execution (aka +\textit{multithreading}) is already a very old one and dates back to +the decades of programming with \textit{co-routines} \cite{co1,co2}. +Paradoxically, the use of threads on Unix platforms did not become +popular until the early 1990s. + +\mypar{Multithreading Advantages} + +\noindent +Multithreading can provide many benefits for applications (good runtime +concurrency, parallel programming techniques can be implemented more easily, +the popular procedural programming style can be combined with multiple +threads of execution, \textit{etc.}) but the most interesting ones are +usually performance gains and reduced resource consumption. Because +in contrast to multiprocess applications, multithreaded ones usually +require less system resources (mainly memory) and their internal +communication part can leverage from the shared address space. + +\mypar{Multithreading and Applications} + +\noindent +Nevertheless there still exist just a few real applications in the free +software world that use multithreading for their benefit, although +their application domains are predestined for multithreading. For +instance, the popular Apache webserver as of version 1.3 still uses +a pre-forking process model for serving HTTP requests, although +two experiments with multithreaded Apache variants in 1996 (with +\textit{rsthreads} \cite{rsthreads}) and 1998 (with \textit{NSPR} +\cite{nspr}) already showed great performance boosts. The same applies +to many similar applications. + +The reason for this restraint mainly is that for a long time, +multithreading facilities under Unix were rare. The situation +became better after some vendors like \textit{Sun} and \textit{DEC} +incorporated threading facilities into their Unix flavors and +\textit{POSIX} standardized a threading \textit{Application Programming +Interface} (API) (aka \textit{Pthreads} \cite{iso}). But an API and a +few vendor implementations are not enough to fulfill the portability +requirements of modern free software packages. Here stand-alone and +really portable multithreading environments are needed. + +The author collected and evaluated over twenty (mostly user-space) +available multithreading facilities for Unix systems (see Table 1), +but only a few of them are freely available and showed to be really +portable. And even the mostly portable ones suffered from the fact that +they partly depend on assembly code or platform specific tricks usually +related to the creation and dispatching of the individual threads. This +means that the number of platforms they support is limited and +applications which are based on these facilities are only portable to +those platforms. This situation is not satisfactory, so application +authors still avoid the use of multithreading if they want to (or have +to) achieve maximum portability for their application. + +A pragmatic and mostly portable fallback technique for implementing +user-space threads can facilitate wider use of multithreading in free +software applications. + +\newcommand{\he}[1]{\begin{rotate}{45}\textbf{\small #1}\end{rotate}} +\begin{figure*}[t] +\noindent +\fbox +{\small +\setlength{\tabcolsep}{2.5pt} +\begin{tabular}{lllllllllllllllll} +\rule{0pt}{26mm}% +\textbf{Package} & \he{Genesis} & \he{Latest Version} & \he{Implementation Space} & \he{Thread Mapping} & \he{Active Development} & \he{Experimental State} & \he{Open Source} & \he{Pthread API} & \he{Pthread Shared Memory} & \he{Native API} & \he{Native API $\ge$ Pthread API} & \he{Native API is Pthread API} & \he{Preemptive Scheduling} & \he{Portability} & \he{Assembly Code} & \he{SysCall Wrap.} \\ +\hline +gnu-pth & 1999 & 1.3.5 & user & n:1 & yes & no & yes & yes & no & yes & yes & no & no & full/mcsc+sjlj & no & partly \\[-1pt] +cmu-lwp & 1984 & 1.4 & user & n:1 & yes & no & yes & no & - & yes & yes & partly & no & semi/fixed:8 & yes & no \\[-1pt] +fsu-pthread & 1992 & 3.13 & user & n:1 & no & no & yes & yes & no & no & - & - & yes & semi/fixed:6 & yes & yes \\[-1pt] +mit-pthread & 1993 & 1.8.9 & user & n:1 & no & no & yes & yes & no & no & - & - & yes & semi/fixed:17 & yes & yes \\[-1pt] +ptl & 1997 & 990622 & user & n:1 & no & no & yes & yes & no & no & - & - & yes & semi/fixed:10 & yes & yes \\[-1pt] +linuxthreads & 1997 & 2.1.2 & user+kernel & 1:1 & yes & no & yes & yes & no & no & - & - & yes & semi/fixed:5 & yes & yes \\[-1pt] +uthread & 1998 & 3.4 & user & n:1 & yes & no & yes & yes & no & no & - & - & yes & semi/fixed:2 & yes & yes \\[-1pt] +cthread & 1991 & 991115 & user & n:1 & no & no & yes & no & - & yes & yes & no & no & semi/fixed:8 & yes & yes \\[-1pt] +openthreads/qt & 1996 & 2.0 & user & n:1 & no & no & yes & no & - & yes & no & no & no & semi/fixed:9 & yes & no \\[-1pt] +rt++/qt & 1996 & 1.0 & user & n:1 & no & no & yes & no & - & yes & yes & no & no & semi/fixed:9 & yes & no \\[-1pt] +rsthreads & 1996 & 980331 & user & n:1 & no & yes & yes & no & - & yes & no & no & no & semi/fixed:9 & yes & no \\[-1pt] +pcthread & 1996 & 1.0 & user & n:1 & no & yes & yes & yes & no & no & - & - & yes & semi/fixed:1 & yes & no \\[-1pt] +bbthreads & 1996 & 0.3 & kernel & 1:1 & no & yes & yes & no & - & yes & no & - & yes & semi/fixed:1 & yes & no \\[-1pt] +jkthreads & 1998 & 1.2 & kernel & 1:1 & no & yes & yes & no & - & yes & no & - & yes & semi/fixed:1 & yes & no \\[-1pt] +nthreads & 1997 & 970604 & user & n:1 & no & yes & yes & no & - & yes & no & - & no & semi/fixed:9 & yes & partly \\[-1pt] +rexthreads & 1993 & 930614 & user & n:1 & no & yes & yes & no & - & yes & no & - & no & semi/fixed:4 & yes & no \\[-1pt] +coro & 1999 & 1.0.3 & user & n:1 & no & yes & yes & no & - & yes & no & - & no & semi/fixed:1 & yes & no \\[-1pt] +greenthreads & 1995 & 1.2 & user & n:1 & no & no & no & no & - & yes & yes & - & yes & full/mcsc & no & no \\[-1pt] +solaris-pthread & NN & 2.7 & user+kernel & n:m & yes & no & no & yes & yes & yes & yes & no & yes & NN & NN & yes \\[-1pt] +tru64-pthread & NN & 5.0 & user+kernel & n:m & yes & no & no & yes & yes & no & no & no & yes & NN & NN & yes \\[-1pt] +aix-pthread & NN & 4.3 & user+kernel & 1:1 & yes & no & no & yes & yes & no & no & no & yes & NN & NN & yes \\[-1pt] +\end{tabular}\ \ \ \ \ \ \ +}\\[4pt] +\parbox{\linewidth}{\footnotesize\baselineskip=0pt +\hangafter{\textbf{Table 1:}\quad}% +Summary of evaluated multithreading packages and some of their +determined characteristics. Notice that mostly all packages con\-tain +assembly code and are just semi-portable, \textit{i.e.}, they support +only a fixed set of platforms and do not automatically adjust for new +ones. +} +\end{figure*} + +\mypar{Ingredients of a Thread} + +\noindent +A Unix process has many ingredients, but the most important ones are its +memory mapping table, the signal dispatching table, the signal mask, the +set of file descriptors and the machine context. The machine context +in turn consists of at least the CPU registers including the program +counter and the stack pointer. In addition, there can be light-weight +processes (LWP) or threads, which usually share all attributes with the +underlying (heavy-weight) process except for the machine context. + +\mypar{Kernel-Space vs. User-Space} + +\noindent +Those LWPs or threads, on a Unix platform classically can be implemented +either in kernel-space or in user-space. When implemented in +kernel-space, one usually calls them LWPs or kernel threads, otherwise +(user-space) threads. If threads are implemented by the kernel, the +thread context switches are performed by the kernel without notice by +the application, similar to the dispatching of processes. If threads are +implemented in user-space, the thread context switches are performed +usually by an application library without notice by the kernel. +Additionally, there exist hybrid threading approaches, where typically a +user-space library binds one or more user-space threads to one or more +kernel-space LWPs. + +\mypar{Thread Models} + +\noindent +The vendor threading facilities under \textit{Sun Solaris}, +\textit{IBM AIX}, \textit{DEC Tru64} (formerly \textit{DIGITAL +UNIX} or \textit{OSF/1}) and \textit{SGI IRIX} use a \textbf{M:N} +mapping \cite{str,aix}, \textit{i.e.}, \textbf{M} user-space threads +are mapped onto \textbf{N} kernel-space LWPs. On the other hand, +\textit{LinuxThreads} \cite{linuxthreads} under \textit{GNU/Linux} +uses a \textbf{1:1} mapping and pure user-space implementations like +\textit{GNU Pth}, \textit{FSU pthreads} or \textit{MIT pthreads}, +\textit{etc.} use a \textbf{M:1} mapping \cite{pth,fsu,mit}. + +From now on we focus on such \textbf{M:1} user space threading +approaches, where one or more user space threads are implemented +inside a single kernel space process. The exercise is to implement +this by using standardized Unix system and ANSI-C language facilities +\textit{only}. + +\subsection{The Exercise} + +As we have mentioned, a thread shares its state with the underlying +process except for the machine context. So the major task for a +user-space threading system is to create and dispatch those machine +contexts. + +In practice, the second major task it has to do is to ensure that no +thread by accident blocks the whole process (and thereby all other +threads). Instead when an operation would block, the threading library +should suspend only the execution of the current thread and in the +meantime dispatch the remaining threads. But this task is outside the +scope of this paper (see \cite{bmv} for details about this task). We +focus only on the aspect of machine context handling. + +\subsection{The Curse of Portability} + +Our goal of real portability for a threading system causes some +non-trivial problems which have to be solved. The most obvious one is +that dealing with machine contexts usually suffers from portability, +because it is a highly CPU dependent task for which not every Unix +flavor provides a standardized API. Although such an API would be not +too hard for vendors to provide, because in principle it is just a matter +of switching a few CPU registers (mainly the program counter and the +stack pointer). + +\mypar{Assembly Code Considered Harmful} + +\noindent +Additionally, we disallow the use of any assembly solutions or platform +specific tricks, because then the threading system again would be only +semi-portable, \textit{i.e.}, it can be ported to \textbf{N} platforms +but on the \textbf{(N+1)}th platform one has to manually adjust or even +extend it to work there, too. + +This is usually not acceptable, even if it also makes solving the +problems harder. At least most of the known free software user-space +threading systems \cite{fsu,mit,ptl2} do not restrict themself to this +and therefore are just semi-portable. But real portability should be a +major goal. + +\section{Problem Analysis} + +\subsection{The Task in Detail} + +Our task is simple in principle: provide an API and corresponding +implementation for creating and dispatching machine contexts on which +user-space threads can be implemented. + +\mypar{The Proposed API} + +\noindent +In detail we propose the following \textit{Application Programmers +Interface} (API) for the machine context handling: + +\begin{itemize} +\item A data structure of type \texttt{mctx\_t} which holds the machine context. + +\item A function + ``\textbf{void} \texttt{mctx\_crea\-te(}\texttt{mctx\_t} \texttt{*}\textit{mctx}, + \textbf{void} \texttt{(*}\textit{sf\_addr}\texttt{)(}\textbf{void *}\texttt{),} + \textbf{void} \texttt{*}\textit{sf\_arg}, + \textbf{void} \texttt{*}\textit{sk\_addr}, + \textbf{size\_t} \textit{sk\_size}\texttt{)}'' + which creates and initializes a machine context structure in + \textit{mctx} with a start function \textit{sf\_addr}, a start + function argument \textit{sf\_arg}, and a stack starting at + \textit{sk\_addr}, which is \textit{sk\_size} bytes in size. + +\item A function + ``\textbf{void} \texttt{mctx\_save(}\texttt{mctx\_t} + \texttt{*}\textit{mctx}\texttt{)}'' + which saves the current machine context into the machine context + structure \textit{mctx}. + +\item A function + ``\textbf{void} \texttt{mctx\_restore(}\texttt{mctx\_t} + \texttt{*}\textit{mctx}\texttt{)}'' + which restores the new machine context from the machine context + structure \textit{mctx}. This function does not return to + the caller. Instead it does return at the location stored + in \textit{mctx} (which is either \textit{sf\_addr} from a + previous \texttt{mctx\_create} call or the location of a previous + \texttt{mctx\_save} call). + +\item A function + ``\textbf{void} \texttt{mctx\_switch(}\texttt{mctx\_t} \texttt{*}\textit{mctx\-\_old}, + \texttt{mctx\_t} \texttt{*}\textit{mctx\_new}\texttt{)}'' + which switches from the current machine context (saved to + \textit{mctx\_old} for later use) to a new context (restored from + \textit{mctx\_new}). This function returns only to the caller if + \texttt{mctx\_restore} or \texttt{mctx\_switch} is again used on + \textit{mctx\_old}. + +\end{itemize} + +\subsection{Technical Possibilities} + +Poking around in the references of the ANSI-C language reference and the +Unix standards show the following functions on which an implementation +can be based: + +\begin{itemize} +\item There is the \texttt{ucontext}(3) facility with the functions + \texttt{getcontext}(3), \texttt{makecontext}(3), + \texttt{swapcontext}(3) and \texttt{setcontext}(3) which + conform to the \textit{Single Unix Specification}, Version 2 + (\textit{SUSv2} \cite{sus}, aka \textit{Unix95/98}). Unfortunately + these are available on modern Unix platforms only. + +\item There are the \texttt{jmp\_buf} based + functions \texttt{setjmp}(3) and \texttt{long\-jmp}(3) which + conform to ISO 9899:1990 (ISO-C) and the \texttt{sigjmp\_buf} + based \texttt{sigsetjmp}(3) and \texttt{sig\-long\-jmp}(3) + functions which conform to IEEE Std\-1003.1-1988 (\textit{POSIX}), + and \textit{Single Unix Specification}, Version 2 (\textit{SUSv2} + \cite{sus}, aka \textit{Unix95/98}). The first two functions are + available really on all Unix platforms, the last two are available + only on some of them. + + On some platforms \texttt{setjmp}(3) and \texttt{longjmp}(3) + save and restore also the signal mask (if one does not want + this semantics, one has to call \texttt{\_setjmp}(3) and + \texttt{\_longjmp}(3) there) while on others one has to + explicitly use the superset functions \texttt{sigsetjmp}(3) and + \texttt{siglongjmp}(3) for this. In our discussion we can assume + that \texttt{setjmp}(3) and \texttt{longjmp}(3) save and restore + the signal mask, because if this is not the case in practice, + one easily can replace them with \texttt{sigsetjmp}(3) and + \texttt{siglongjmp}(3) calls (if available) or (if not available) + emulate the missing functionality manually with additional + \texttt{sigprocmask}(2) calls (see \texttt{pth\_mctx.c} in + \textit{GNU Pth} \cite{pth}). + +\item There is the function \texttt{sigaltstack}(2) which + conforms to the \textit{Single Unix Specification}, Version 2 + (\textit{SUSv2} \cite{sus}, aka \textit{Unix95/98}) and its + ancestor function \texttt{sigstack}(2) from \textit{4.2BSD}. The + last one exists only on \textit{BSD}-derived platforms, but the + first function already exists on all current Unix platforms. +\end{itemize} + +\subsection{Maximum Portability Solution} + +The maximum portable solution obviously is to use +the standardized \texttt{makecontext}(3) function +to create threads and \texttt{switchcontext}(3) or +\texttt{getcontext}(3)/\texttt{setcontext}(3) to dispatch them. +And actually these are the preferred functions modern user-space +multithreading systems are using. We could easily implement our proposed +API as following (all error checks omitted for better readability): + +{\small +\baselineskip=9pt +\begin{alltt} +/* \textrm{\textit{\bfseries machine context data structure}} */ +\textbf{typedef struct} mctx_st \{ + ucontext_t uc; +\} mctx_t; + +/* \textrm{\textit{\bfseries save machine context}} */ +\textbf{#define} mctx_save(mctx) \(\backslash\) + (\textbf{void})getcontext(&(mctx)->uc) + +/* \textrm{\textit{\bfseries restore machine context}} */ +\textbf{#define} mctx_restore(mctx) \(\backslash\) + (\textbf{void})setcontext(&(mctx)->uc) + +/* \textrm{\textit{\bfseries switch machine context}} */ +\textbf{#define} mctx_switch(mctx_old,mctx_new) \(\backslash\) + (\textbf{void})swapcontext(&((mctx_old)->uc), \(\backslash\) + &((mctx_new)->uc)) + +/* \textrm{\textit{\bfseries create machine context}} */ +\textbf{void} mctx_create( + mctx_t *mctx, + \textbf{void} (*sf_addr)(\textbf{void} *), \textbf{void} *sf_arg, + \textbf{void} *sk_addr, size_t sk_size) +\{ + + /* \textrm{\textit{\bfseries fetch current context}} */ + getcontext(&(mctx->uc)); + + /* \textrm{\textit{\bfseries adjust to new context}} */ + mctx->uc.uc_link = NULL; + mctx->uc.uc_stack.ss_sp = sk_addr; + mctx->uc.uc_stack.ss_size = sk_size; + mctx->uc.uc_stack.ss_flags = 0; + + /* \textrm{\textit{\bfseries make new context}} */ + makecontext(&(mctx->uc), + sf_addr, 1, sf_arg); + \textbf{return}; +\} +\end{alltt}} + +\noindent +Unfortunately there are still lots of Unix platforms where this +approach cannot be used, because the standardized \texttt{ucontext}(3) +API is not provided by the vendor. Actually the platform test results +for \textit{GNU Pth} (see Table 2 below) showed that only 7 of 21 +successfully tested Unix flavors provided the standardized API +(\texttt{makecontext}(3), \textit{etc.}). On all other platforms, +\textit{GNU Pth} was forced to use the fallback approach of implementing +the machine context as we will describe in the following. Obviously +this fallback approach has to use the remaining technical possibilities +(\texttt{sigsetjmp}(3), \textit{etc.}). + +\medskip +\noindent +\fbox +{\parbox{7.8cm} +{\footnotesize +\noindent +\medskip +\begin{tabular}{l|l|l|l} +{\bfseries Operating System} & +{\bfseries Architecture(s)} & +{\bfseries mcsc} & +{\bfseries sjlj} \\ +FreeBSD 2.x/3.x & Intel & no & yes \\ +FreeBSD 3.x & Intel, Alpha & no & yes \\ +NetBSD 1.3/1.4 & Intel, PPC, M68K & no & yes \\ +OpenBSD 2.5/2.6 & Intel, SPARC & no & yes \\ +BSDI 4.0 & Intel & no & yes \\ +Linux 2.0.x glibc 1.x/2.0 & Intel, SPARC, PPC & no & yes \\ +Linux 2.2.x glibc 2.0/2.1 & Intel, Alpha, ARM & no & yes \\ +Sun SunOS 4.1.x & SPARC & no & yes \\ +Sun Solaris 2.5/2.6/2.7 & SPARC & yes & yes \\ +SCO UnixWare 2.x/7.x & Intel & yes & yes \\ +SCO OpenServer 5.0.x & Intel & no & yes \\ +IBM AIX 4.1/4.2/4.3 & RS6000, PPC & yes & yes \\ +HP HPUX 9.10/10.20 & HPPA & no & yes \\ +HP HPUX 11.0 & HPPA & yes & yes \\ +SGI IRIX 5.3 & MIPS 32/64 & no & yes \\ +SGI IRIX 6.2/6.5 & MIPS 32/64 & yes & yes \\ +ISC 4.0 & Intel & no & yes \\ +Apple MacOS X & PPC & no & yes \\ +DEC OSF1/Tru64 4.0/5.0 & Alpha & yes & yes \\ +SNI ReliantUNIX & MIPS & yes & yes \\ +AmigaOS & M68K & no & yes \\ +\end{tabular} + +\medskip +\noindent +{\tiny +\begin{tabular}{ll} +\end{tabular} +} +}}\\[4pt] +\parbox{\linewidth}{\footnotesize\baselineskip=0pt +\hangafter{\textbf{Table 2:}\quad}% +Summary of operating system support. The level and type of support found on +each tested operating system. \texttt{mcsc}: functional +\texttt{makecontext}(3)/\-\texttt{switchcontext}(3), \texttt{sjlj}: functional +\texttt{setjmp}(3)/\texttt{longjmp}(3) or +\texttt{sig\-setjmp}(3)/\-\texttt{siglongjmp}(3). See file \texttt{PORTING} in +\textit{GNU Pth} \cite{pth} for more details. +} + +\subsection{Remaining Possibilities} + +Our problem can be divided into two parts, an easy one and a difficult one. + +\mypar{The Easy Part} + +\noindent +That \texttt{setjmp}(3) and \texttt{longjmp}(3) can be used to implement +user-space threads is commonly known \cite{ptl2,rsthreads,uthread}. +Mostly all older portable user-space threading libraries are based +on them, although some problems are known with these facilities (see +below). So it becomes clear that we also have to use these functions and +base our machine context (\texttt{mctx\_t}) on their \texttt{jmp\_buf} +data structure. + +We immediately recognize that this way we have at least solved +the dispatching problem, because our \texttt{mctx\_save}, +\texttt{mctx\_restore} and \texttt{mctx\_switch} functions can be easily +implemented with \texttt{setjmp}(3) and \texttt{longjmp}(3). + +\mypar{The Difficult Part} + +\noindent +Nevertheless, the difficult problem of how to create the machine context +remains. Even knowing that our machine context is \texttt{jmp\_buf} +based is no advantage to us. A \texttt{jmp\_buf} has to be treated +by us as an opaque data structure --- for portability reasons. The +only operations we can perform on it are \texttt{setjmp}(3) and +\texttt{longjmp}(3) calls, of course. Additionally, we are forced to use +\texttt{sigaltstack}(3) for our stack manipulations, because it is the +only portable function which actually deals with stacks. + +So it is clear that our implementation for \texttt{mctx\_\-create} has +to play a few tricks to use a \texttt{jmp\_buf} for passing execution +control to an arbitrary startup routine. And our approach +has to be careful to ensure that it does not suffer from unexpected +side-effects. It should be also obvious that we cannot again +expect to find an easy solution (as for \texttt{mctx\_save}, +\texttt{mctx\_restore} and \texttt{mctx\_switch}), because +\texttt{setjmp}(3) and \texttt{sigaltstack}(3) cannot be trivially +combined to form \texttt{mctx\_create}. + +\section{Implementation} + +As we have already discussed, our implementation contains an easy part +(\texttt{mctx\_save}, \texttt{mctx\_restore} and \texttt{mctx\_switch}) +and a difficult part (\texttt{mctx\_create}). Let us start with the easy +part, whose implementation is obvious (all error checks again omitted +for better readability): + +{\small +\baselineskip=9pt +\begin{alltt} +/* \textrm{\textit{\bfseries machine context data structure}} */ +\textbf{typedef struct} mctx_st \{ + jmp_buf jb; +\} mctx_t; + +/* \textrm{\textit{\bfseries save machine context}} */ +\textbf{#define} mctx_save(mctx) \(\backslash\) + (\textbf{void})setjmp((mctx)->jb) + +/* \textrm{\textit{\bfseries restore machine context}} */ +\textbf{#define} mctx_restore(mctx) \(\backslash\) + longjmp((mctx)->jb, 1) + +/* \textrm{\textit{\bfseries switch machine context}} */ +\textbf{#define} mctx_switch(mctx_old,mctx_new) \(\backslash\) + \textbf{if} (setjmp((mctx_old)->jb) == 0) \(\backslash\) + longjmp((mctx_new)->jb, 1) + +/* \textrm{\textit{\bfseries create machine context}} */ +\textbf{void} mctx_create( + mctx_t *mctx, + \textbf{void} (*sf_addr)(\textbf{void} *), \textbf{void} *sf_arg, + \textbf{void} *sk_addr, size_t sk_size) +\{ + \textrm{\textit{\bfseries ...initialization of \texttt{mctx} to be filled in...}} +\} +\end{alltt}} + +\noindent +There is one subtle but important point we should mention: The +use of the C pre-processor \texttt{\#define} directive to implement +\texttt{mctx\_save}, \texttt{mctx\_restore} and \texttt{mctx\_switch} +is intentional. For technical reasons related to \texttt{setjmp}(3) +semantics and \texttt{return} related stack behavior (which we will +explain later in detail) we \textit{cannot} implement these three +functions (at least not \texttt{mctx\_switch}) as C functions if we want +to achieve maximum portability across all platforms. Instead they have +to be implemented as pre-processor macros. + +\subsection{Algorithm Overview} + +The general idea for \texttt{mctx\_create} is to configure the given +stack as a signal stack via \texttt{sigaltstack}(2), send the current +process a signal to transfer execution control onto this stack, save +the machine context there via \texttt{setjmp}(3), get rid of the signal +handler scope and bootstrap into the startup routine. + +The real problem in this approach comes from the signal handler scope +which implies various restrictions on Unix platforms (the signal +handler scope often is just a flag in the process control block (PCB) +which various system calls, like \texttt{sigaltstack}(2), check before +allowing the operation -- but because it is part of the process state +the kernel manages, the process cannot change it itself). As we will +see, we have to perform a few tricks to get rid of it. The second main +problem is: how do we prepare the calling of the start routine without +immediately entering it? + +\subsection{Algorithm} + +The input to the \texttt{mctx\_create} function is the machine context +structure \textit{mctx} which should be initialized, the thread startup +function address \textit{sf\_addr}, the thread startup function argument +\textit{sf\_arg} and a chunk of memory starting at \textit{sk\_addr} and +\textit{sk\_size} bytes in size, which should become the threads stack. + +The following algorithm for \texttt{mctx\_create} is directly modeled +after the implemented algorithm one can find in \textit{GNU Pth} +\cite{pth}, which in turn was derived from techniques originally found +in \textit{rsthreads} \cite{rsthreads}: + +\begin{enumerate} + +\item Preserve the current signal mask and block an arbitrary worker + signal (we use \texttt{SIGUSR1}, but any signal can be used for + this -- even an already used one). This worker signal is later + temporarily required for the trampoline step. + +\item Preserve a possibly existing signal action for the worker + signal and configure a trampoline function as the new temporary + signal action. The signal delivery is configured to occur on + an alternate signal stack (see next step). + +\item Preserve a possibly active alternate signal stack and configure + the memory chunk starting at \textit{sk\_addr} as the new + temporary alternate signal stack of length \textit{sk\_size}. + +\item Save parameters for the trampoline step (\textit{mctx}, + \textit{sf\_addr}, \textit{sf\_arg}, \textit{etc.}) in global + variables, send the current process the worker signal, temporarily + unblock it and this way allow it to be delivered on the signal + stack in order to transfer execution control to the trampoline + function. + +\item After the trampoline function asynchronously entered, save its + machine context in the \textit{mctx} structure and immediately + return from it to terminate the signal handler scope. + +\item Restore the preserved alternate signal stack, preserved signal + action and preserved signal mask for worker signal. This way + an existing application configuration for the worker signal is + restored. + +\item Save the current machine context of \texttt{mctx\_create}. This + allows us to return to this point after the next trampoline step. + +\item Restore the previously saved machine context of the trampoline function + (\textit{mctx}) to again transfer execution control onto the alternate + stack, but this time without(!) signal handler scope. + +\item After reaching the trampoline function (\textit{mctx}) again, + immediately bootstrap into a clean stack frame by just calling a + second function. + +\item Set the new signal mask to be the same as the original signal + mask which was active when \texttt{mctx\_create} was called. This + is required because in the first trampoline step we usually had at + least the worker signal blocked. + +\item Load the passed startup information (\textit{sf\_addr}, + \textit{sf\_arg}) from \texttt{mctx\_create} into local + (stack-based) variables. This is important because their values + have to be preserved in machine context dependent memory until + the created machine context is the first time restored by the + application. + +\item Save the current machine context for later restoring by + the calling application. + +\item Restore the previously saved machine context + of \texttt{mctx\_create} to transfer execution control back to it. + +\item Return to the calling application. + +\end{enumerate} + +\noindent +When the calling application now again switches into the established +machine context \textit{mctx}, the thread starts running at routine +\textit{sf\_addr} with argument \textit{sf\_arg}. Figure 1 illustrates +the algorithm (the numbers refer to the algorithm steps listed above). + +\bigskip +\noindent +\psfig{file=rse-pmt.eps}\\[4pt] +\parbox{\linewidth}{\footnotesize\baselineskip=0pt +\hangafter{\textbf{Figure 1:}\quad}% +Illustration of the machine context creation procedure. The thick +solid lines and numeric marks correspond to the algorithm steps as +described in section 3.2. The thick dotted lines show a possible further +processing where a few context switches are performed to dispatch +between the main thread and the new created thread. +} +\smallskip + +\subsection{Source Code} + +The corresponding ANSI-C code, which implements \texttt{mctx\_create}, +is a little bit more complicated. But with the presented algorithm in +mind, it is now straight-forward. + +{\small% +\baselineskip=9pt +\begin{alltt} +\textbf{static} mctx_t mctx_caller; +\textbf{static} sig_atomic_t mctx_called; + +\textbf{static} mctx_t *mctx_creat; +\textbf{static} \textbf{void} (*mctx_creat_func)(\textbf{void} *); +\textbf{static} \textbf{void} *mctx_creat_arg; +\textbf{static} sigset_t mctx_creat_sigs; + +\textbf{void} mctx_create( + mctx_t *mctx, + \textbf{void} (*sf_addr)(\textbf{void} *), \textbf{void} *sf_arg, + \textbf{void} *sk_addr, \textbf{size_t} sk_size) +\{ + \textbf{struct} sigaction sa; + \textbf{struct} sigaction osa; + \textbf{struct} sigaltstack ss; + \textbf{struct} sigaltstack oss; + sigset_t osigs; + sigset_t sigs; + + /* \textrm{\textit{\bfseries Step 1:}} */ + sigemptyset(&sigs); + sigaddset(&sigs, SIGUSR1); + sigprocmask(SIG_BLOCK, &sigs, &osigs); + + /* \textrm{\textit{\bfseries Step 2:}} */ + memset((\textbf{void} *)&sa, 0, + \textbf{sizeof}(\textbf{struct} sigaction)); + sa.sa_handler = mctx_create_trampoline; + sa.sa_flags = SA_ONSTACK; + sigemptyset(&sa.sa_mask); + sigaction(SIGUSR1, &sa, &osa); + + /* \textrm{\textit{\bfseries Step 3:}} */ + ss.ss_sp = sk_addr; + ss.ss_size = sk_size; + ss.ss_flags = 0; + sigaltstack(&ss, &oss); + + /* \textrm{\textit{\bfseries Step 4:}} */ + mctx_creat = mctx; + mctx_creat_func = sf_addr; + mctx_creat_arg = sf_arg; + mctx_creat_sigs = osigs; + mctx_called = FALSE; + kill(getpid(), SIGUSR1); + sigfillset(&sigs); + sigdelset(&sigs, SIGUSR1); + \textbf{while} (!mctx_called) + sigsuspend(&sigs); + + /* \textrm{\textit{\bfseries Step 6:}} */ + sigaltstack(NULL, &ss); + ss.ss_flags = SS_DISABLE; + sigaltstack(&ss, NULL); + if (!(oss.ss_flags & SS_DISABLE)) + sigaltstack(&oss, NULL); + sigaction(SIGUSR1, &osa, NULL); + sigprocmask(SIG_SETMASK, + &osigs, NULL); + + /* \textrm{\textit{\bfseries Step 7 \& Step 8:}} */ + mctx_switch(&mctx_caller, mctx); + + /* \textrm{\textit{\bfseries Step 14:}} */ + \textbf{return}; +\} + +\textbf{void} mctx_create_trampoline(\textbf{int} sig) +\{ + /* \textrm{\textit{\bfseries Step 5:}} */ + \textbf{if} (mctx_save(mctx_creat) == 0) \{ + mctx_called = TRUE; + \textbf{return}; + \} + + /* \textrm{\textit{\bfseries Step 9:}} */ + mctx_create_boot(); +\} + +\textbf{void} mctx_create_boot(\textbf{void}) +\{ + \textbf{void} (*mctx_start_func)(\textbf{void} *); + \textbf{void} *mctx_start_arg; + + /* \textrm{\textit{\bfseries Step 10:}} */ + sigprocmask(SIG_SETMASK, + &mctx_creat_sigs, NULL); + + /* \textrm{\textit{\bfseries Step 11:}} */ + mctx_start_func = mctx_creat_func; + mctx_start_arg = mctx_creat_arg; + + /* \textrm{\textit{\bfseries Step 12 \& Step 13:}} */ + mctx_switch(mctx_creat, &mctx_caller); + + /* \textrm{\textit{\bfseries The thread ``magically'' starts... }} */ + mctx_start_func(mctx_start_arg); + + /* NOTREACHED */ + abort(); +\} +\end{alltt} +} + +\subsection{Run-time Penalty} + +After this discussion of the implementation details, an obviously +occuring question now is what the expected run-time penalty is. That is, +what does our presented machine context implementation cost compared +to a \texttt{ucontext}(3) based solution. From the already discussed +details we can easily guess that our complex machine context creation +procedure (\texttt{mctx\_create}) will be certainly noticeably slower +than a solution based on a \texttt{ucontext}(3) facility. + +But a wild guess is not sufficing for a reasonable statement. So we have +written a \textit{Simple Machine Context Benchmark} (SMCB \cite{smcb}) +which was used to compare run-time costs of the \texttt{mctx\_create} +and \texttt{mctx\_switch} functions if once implemented through +the \textit{POSIX} \texttt{makecontext}(3)/\texttt{swapcontext}(3) +functions (as shown in section 2.3), and once implemented with our +based fallback implementation (for convenience reasons we directly used +\texttt{sigjmp\_buf}, \texttt{sigsetjmp}(3) and \texttt{siglongjmp}(3) +in the benchmark, because all tested platforms provided this). The +results are shown Table 3 below. + +As one can derive from these evaluations, our signal stack trick to +implement \texttt{mctx\_create} in practice is approximately 15 times +slower than the \texttt{makecontext}(3) based variant. This cost +should not be neglected. On the other hand, the \texttt{sigsetjmp}(3)/ +\texttt{siglongjmp}(3) based \texttt{mctx\_switch} performs about as +good as the \texttt{swapcontext}(3) based variant (the reason why +on most of the tested platforms it is even slightly faster is not +known -- but we guess it is related to a greater management overhead +in the \texttt{ucontext}(3) facility, which is a superset of the +functionality we require). Or in short: our presented fallback approach +costs noticeable extra CPU cycles on thread creation time, but is as +fast as the standardized solution under thread dispatching time. + +\bigskip +\noindent +\fbox +{\parbox{7.8cm} +{\footnotesize +\noindent +\medskip +\ \ \ {\bfseries 10000 $\times$ mctx\_create (in seconds):}\\[1mm] +\begin{tabular}{l|r|r|r} +{\bfseries Platform} & +{\bfseries mcsc} & +{\bfseries sjlj} & +{\bfseries overhead} \\ +Sun Solaris 2.6 (SPARC) & 0.076 & 1.268 & 16.7 \\ +DEC Tru64 5.0 (Alpha) & 0.019 & 0.235 & 12.4 \\ +SGI IRIX 6.5 (MIPS) & 0.105 & 1.523 & 14.5 \\ +SCO UnixWare 7.0 (Intel) & 0.204 & 3.827 & 18.8 \\ +HP HP/UX 11.0 (HPPA) & 0.057 & 0.667 & 11.8 \\ +\multicolumn{4}{r}{ + {\bfseries Average: \quad 14.8}} \\ +\end{tabular} + +\medskip +\ \ \ {\bfseries 10000 $\times$ mctx\_switch (in seconds):}\\[1mm] +\begin{tabular}{l|r|r|r} +{\bfseries Platform} & +{\bfseries mcsc} & +{\bfseries sjlj} & +{\bfseries overhead} \\ +Sun Solaris 2.6 (SPARC) & 0.137 & 0.210 & 1.5 \\ +DEC Tru64 5.0 (Alpha) & 0.034 & 0.022 & 0.6 \\ +SGI IRIX 6.5 (MIPS) & 0.235 & 0.190 & 0.8 \\ +SCO UnixWare 7.0 (Intel) & 0.440 & 0.398 & 0.9 \\ +HP HP/UX 11.0 (HPPA) & 0.106 & 0.065 & 0.6 \\ +\multicolumn{4}{r}{ + {\bfseries Average: \quad 0.9}} \\ +\end{tabular} +}}\\[4pt] +\parbox{\linewidth}{\footnotesize\baselineskip=0pt +\hangafter{\textbf{Table 3:}\quad}% +Summary of \textit{Simple Machine Context Benchmark} (SMCB, \cite{smcb}). +The speed of machine context creation and switching found on +each tested operating system. \textbf{mcsc}: functional +\texttt{makecontext}(3) / \texttt{switchcontext}(3), \textbf{sjlj}: functional +\texttt{sigsetjmp}(3)/\texttt{siglongjmp}(3). \textbf{overhead}: the +overhead of using \textbf{sjlj} instead of \textbf{mcsc}. +} + +\subsection{Remaining Issues} + +The presented algorithm and source code can be directly used in +practice for implementing a minimal threading system or the concept +of co-routines. Its big advantage is that if the operating system +provides the required standardized primitives, we do not need to know +anything at all about the machine we are running on --- everything just +works. Nevertheless, there remain a few special issues we still have to +discuss. + +\mypar{The Waggly longjmp(3) after Return} + +\noindent +On some platforms, \texttt{longjmp}(3) may not be called after the +function which called the \texttt{setjmp}(3) returned. When this is +done, the stack frame situation is not guaranteed to be in a clean and +consistent state. But this is exactly the mechanism we use in order to +get rid of the signal handler scope in step 5. + +The only alternative would be to leave the signal handler via +\texttt{longjmp}(3), but then we would have another problem, +as experience showed. For instance, \textsc{Robert S. Thau}'s +\textit{Really Simple Threads} (\textit{rsthreads}) \cite{rsthreads} +was ported to several platforms and was used to run an experimental +multithreaded version of the Apache webserver. \textsc{Thau}'s approach +was similar to ours, but differed significantly in the way the signal +handler is left. In particular, in an attempt to avoid the unsafe stack +frame, it used a \texttt{longjmp}(3) call to leave the signal handler, +rather than returning from it. But this approach does not work on some +\textit{SysV}-derived kernels, as we already mentioned. + +The problem is that these kernels do not ``believe'' that the code +is out of the signal-handling context, until the signal handler has +returned --- and accordingly, refuse to allow readjustment of the +signal stack until it has. But with the \textit{rsthreads} approach, +the signal handler that created the first thread never returns, and +when \textit{rsthreads} wants to create the second thread, these +kernels refuse to readjust the signal stack, and we are stuck. So with +portability in mind, we decided that it is better to get rid of the +signal handler scope with the straight-forward ``\texttt{return}'' and +instead fight the mentioned (simpler) problem of an unsafe stack frame. + +Fortunately, in practice this is not as problematic as it seems, because +evaluations (for \textit{GNU Pth}) on a wide range of current Unix +platforms showed that one can reach a safe stack frame again by just +calling a function. That is the reason why our algorithm enters the +second trampoline function in step 9. + +\mypar{The Uncooperative longjmp(3)} + +\noindent +Even on operating systems which have working \textit{POSIX} +functions, our approach may theoretically still not work, because +\texttt{longjmp}(3) does not cooperate. For instance, on some +platforms the standard \textit{libc} \texttt{longjmp}(3) branches +to error-handling code if it detects that the caller tries to jump +\textit{up} the stack, \textit{i.e.}, into a stack frame that has +already returned. + +This is usually implemented by comparing the current stack pointer +to the one in the \texttt{jmp\_buf} structure. That is why it is +important for our algorithm to return from the signal handler and this +way enter the (different) stack of the parent thread. In practice, +the implementation in \textit{GNU Pth} showed that then one no longer +suffers from those uncooperative \texttt{longjmp}(3) implementations, +but one should keep this point in mind when reaching even more +uncooperative variants on esoteric Unix platforms. If it still occurs, +one can only try to resume the operation by using a possibly existing +platform-specific error handling hook. + +\mypar{Garbage at Bottom of Stacks} + +\noindent +There is a subtle side-effect of our implementation: there remains some +garbage at the bottom of each thread stack. The reason is that if a +signal is delivered, the operating system pushes some state onto the +stack, which is restored later, when the signal handler returns. But +although we return from the signal handler, we jump in again, and this +time we enter not directly at the bottom of the stack, because of the +\texttt{setjmp}(3) in the trampoline function. + +Since the operating system has to capture all CPU registers (including +those that are ordinarily scratch registers or caller-save registers), +there can be a fair amount of memory at the bottom of the established +thread stack. For some systems this can be even up to 1 KB of garbage +\cite{rsthreads}. But except for the additional memory consumption it +does not hurt. + +We just have to keep in mind this additional stack consumption when +deciding the stack size (\textit{sk\_size}). A reasonable stack size +usually is between 16 and 32 KB. Less is neither reasonable nor always +allowed (current Unix platforms usually require a stack to be at least +16 KB in size). + +\mypar{Stack Overflows} + +\noindent +There is a noticeable difference between the initial \texttt{main}() +thread and the explicitly spawned threads: the initial thread runs on +the standard process stack. This stack automatically can grow under +Unix, while the stacks of the spawned threads are fixed in size. So +stack overflows can occur for the spawned threads. This implies that +the parent has to make a reasonable guess of the threads stack space +requirement already at spawning time. + +And there is no really portable solution to this problem, because even +if the thread library's scheduler can detect the stack overflow, it +cannot easily resize the stack. The reason is simply that the stack +initialization goes hand in hand with the initialization of the start +routine, as we discussed before. And this start routine has to be a real +C function in order to \textit{call}. But once the thread is running, +there no longer exists such an entry point. So, even if the scheduler +would be able to give the thread a new enlarged stack, there is no +chance to restart the thread on this new stack. + +Or more correct, there is no \textit{portable} way to achieve it. As +with the previous problems, there is a non-portable solution. That +is why our implementation did not deal with this issue. Instead in +practice one usually lets the scheduler just detect the stack overflow +and terminate the thread. This is done by using a red zone at the top +of the stack which is marked with a magic value the scheduler checks +between thread dispatching operations. + +Resizing solutions are only possible in semi-portable ways. One +approach is to place the thread stacks into a memory mapped area (see +\texttt{mmap}(2)) of the process address space and let the scheduler +catch \texttt{SIGSEGV} signals. When such a signal occurs, because of +a stack overflow in this area, the scheduler explicitly resizes the +memory mapped area. This resizing can be done either by copying the +stack contents into a new larger area which is then re-mapped to the +old address or via an even more elegant way, as the vendor threading +libraries of \textit{Sun Solaris}, \textit{FreeBSD} and \textit{DEC +Tru64} do it: the thread stacks are allocated inside memory mapped areas +which are already initially a few MB in (virtual) size and then one just +relies on the virtual memory system's feature that only the actually +consumed memory space is mapped. + +\mypar{Startup Routine Termination} + +\noindent +There is a cruel \texttt{abort}(3) call at the end of our +\texttt{mctx\_create\_boot} function. This means, if the startup +routine would return, the process is aborted. That is obviously not +reasonable, so why have we written it this way? + +If the thread returns from the startup routine, it should be cleanly +terminated. But it cannot terminate itself (for instance, because +it cannot free its own stack while running on it, \textit{etc.}). So +the termination handling actually is the task of the thread library +scheduler. As a consequence, the thread spawning function of a thread +library should be not directly \texttt{mctx\_create}. + +Instead the thread spawning function should use an additional trampoline +function as the higher-level startup routine. And this trampoline +function performs a context switch back into the thread library +scheduler before the lower-level startup routine would return. +The scheduler then can safely remove the thread and its machine +context. That is why the \texttt{abort}(3) call is never reached +in practice (more details can be found in the implementations of +\texttt{pth\_spawn} and \texttt{pth\_exit} in \texttt{pth\_lib.c} of +\textit{GNU Pth} \cite{pth}) + +\mypar{The sigstack(2) Fallback Situation} + +\noindent +Not all platforms provide the standardized \texttt{sigaltstack}(2). +Instead they at least provide the \textit{4.2BSD} ancestor +function \texttt{sigstack}(2). But one cannot trivially replace +\texttt{sigaltstack}(2) by \texttt{sigstack}(2) in this situation, +because in contrast to \texttt{sigaltstack}(2), the old +\texttt{sigstack}(2) does not automatically handle the machine dependent +direction of stack growth. + +Instead, the caller has to know the direction and always call +\texttt{sigstack}(2) with the address of the bottom of the stack. So, in +a real-world implementation one first has to determine the direction of +stack growth in order to use \texttt{sigstack}(2) as a replacement for +\texttt{sigaltstack}(2). Fortunately this is easier than it seems on the +first look (for details see the macros \texttt{AC\_CHECK\_STACKGROWTH} +and \texttt{AC\_CHECK\_STACKSETUP} in file \texttt{aclocal.m4} from +\textit{GNU Pth} \cite{pth}). Alternatively if one can afford to waste +memory, one can use an elegant trick: to set up a stack of size $N$, +one allocates a chunk of memory (starting at address $A$) of size +$N\times2$ and then calls \texttt{sigstack}(2) with the parameters +\textit{sk\_addr=}$A+N$ and \textit{sk\_size=}$N$, \textit{i.e.}, one +specifies the middle of the memory chunk as the stack base. + +\mypar{The Blind Alley of Brain-Dead Platforms} + +\noindent +The world would not be as funny as it is, if really all Unix platforms +would be fair to us. Instead, currently at least one platform exists +which plays unfair: unfortunately, ancient versions of the popular +\textit{GNU/Linux}. Although we will discover that it both provides +\texttt{sigaltstack}(2) and \texttt{sigstack}(2), our approach won't +work on \textit{Linux} kernels prior to version 2.2 and \textit{glibc} +prior to version 2.1. + +Why? Because its \textit{libc} provides only stubs of these functions +which always return just \texttt{-1} with \texttt{errno} set +to \texttt{ENOSYS}. So, this definitely means that our nifty +algorithm is useless there, because its central point \textit{is} +\texttt{sigaltstack}(2)/\texttt{sigstack}(2). Nevertheless we do not +need to give up. At least not, if we, for a single brain-dead platform, +accept to break our general goal of not using any platform dependent +code. + +So, what can we actually do here? All we have to do, is to fiddle +around a little bit with the machine-dependent \texttt{jmp\_buf} +ingredients (by poking around in \texttt{setjmp.h} or by disassembling +\texttt{longjmp}(3) in the debugger). Usually one just has to do a +\texttt{setjmp}(3) to get an initial state in the \texttt{jmp\_buf} +structure and then manually adjust two of its fields: the program +counter (usually a structure member with ``\texttt{pc}'' in the name) +and the stack pointer (usually a structure member with ``\texttt{sp}'' +in the name). + +That is all and can be acceptable for a real-world implementation which +really wants to cover mostly \textit{all} platforms -- at least as long +as the special treatment is needed just for one or two platforms. But +one has to keep in mind that it at least breaks one of the initial goals +and has to be treated as a last chance solution. + +\mypar{Functions sigsetjmp(3) and siglongjmp(3)} + +One certainly wants the \textit{POSIX} thread semantics where a +thread has its own signal mask. As already mentioned, on some +platforms \texttt{setjmp}(3) and \texttt{longjmp}(3) do not provide +this and instead one has to explicitly call \texttt{sigsetjmp}(3) +and \texttt{siglongjmp}(3) instead. There is only one snare: +on some platforms \texttt{sigsetjmp}(3)/\texttt{siglongjmp}(3) +save also information about the alternate signals stack. So +here one has to make sure that although the thread dispatching +later uses \texttt{sigsetjmp}(3)/\texttt{siglongjmp}(3), the +thread creation step in \texttt{mctx\_create} still uses plain +\texttt{setjmp}(3)/\texttt{longjmp}(3) calls for the trampoline +trick. One just has to be careful because the \texttt{jmp\_buf} +and \texttt{sigjmp\_buf} structures cannot be mixed between +calls to the \texttt{sigsetjmp}(3)/\texttt{siglongjmp}(3) and +\texttt{setjmp}(3)/\texttt{longjmp}(3). + +\mypar{More Machine Context Ingredients} + +\noindent +Finally, for a real-world threading implementation one usually wants to +put more state into the machine context structure \texttt{mctx\_t}. +For instance to fulfill more \textit{POSIX} threading semantics, it is +reasonable to also save and restore the global \texttt{errno} variable. +All this can be easily achieved by extending the \texttt{mctx\_t} +structure with additional fields and by making the \texttt{mctx\_save}, +\texttt{mctx\_restore} and \texttt{mctx\_switch} functions to be aware +of them. + +\subsection{Related Work} + +Beside \textit{GNU Pth} \cite{pth}, there are other multithreading +libraries which use variants of the presented approach for implementing +machine contexts in user-space. Most notably there are \textsc{Robert +S. Thau}'s \textit{Really Simple Threads} (\textit{rsthreads}, +\cite{rsthreads}) package which uses \texttt{sigaltstack}(2) in +a very similar way for thread creation, and \textsc{Kota Abe}'s +\textit{Portable Thread Library} (\textit{PTL}, \cite{ptl2}) which uses +a \texttt{sigstack}(2) approach. But because their approaches handle +the signal handler scope differently, they are not able to achieve the +same amount of portability and this way do not work for instance on some +System-V-derived platforms. + +\subsection{Summary \& Availability} + +We have presented a pragmatic and mostly portable fallback approach +for implementing the machine context for user-space threads, based +entirely on Unix system and ANSI-C language facilities. The approach +was successfully tested in practice on a wide range of Unix flavors by +\textit{GNU Pth} and should also adapt to the remaining Unix platforms +as long as they adhere to the relevant standards. + +The \textit{GNU Pth} package is distributed under the +GNU Library General Public License (LGPL 2.1) and freely +available from \textit{http://www.gnu.org/software/pth/} and +\textit{ftp://ftp.gnu.org/gnu/pth/}. + +\subsection{Acknowledgements} + +I would like to thank \textsc{Robert S. Thau}, \textsc{David Butenhof}, +\textsc{Martin Kraemer}, \textsc{Eric Newton} and \textsc{Bruno Haible} +for their comments which helped to write the initial version of this +paper. Additionally, credit has to be given to \textsc{Christopher +Small} and the USENIX reviewers for their invaluable feedback which +allowed this paper to be extended, cleaned up and finally published +at the USENIX Annual Technical Conference 2000. Finally, thanks +go to all users of \textit{GNU Pth} for their feedback on the +implementation, which helped in fine-tuning the presented approach. +\hfill [\textsf{\small rse}] + +{\small%\baselineskip=10pt +\begin{thebibliography}{XX} + +\bibitem{iso} + \textit{POSIX 1003.1c Threading}, + IEEE POSIX 1003.1c-1995, ISO/IEC 9945-1:1996 + +\bibitem{co1} + \textsc{M.E. Conway}: \textit{Design of a separable transition-diagram + compiler.}, Comm. ACM 6:7, 1963, p.396-408 + +\bibitem{co2} + \textsc{E.W. Dijkstra}: \textit{Co-operating sequential processes}, in + F. Genuys (Ed.), \textit{Programming Languages}, NATO Advanced Study + Institute, Academic Press, London, 1965, p.42-112. + +\bibitem{nbf} + \textsc{B. Nichols, D. Buttlar, J.P. Farrel}: \textit{Pthreads + Programming - A POSIX Standard for Better Multiprocessing}, + O'Reilly, 1996; ISBN 1-56592-115-1 + +\bibitem{lbe} + \textsc{B. Lewis, D. J. Berg}: + \textit{Threads Primer - A Guide To Multithreaded Programming}, + Prentice Hall, 1996; ISBN 0-13-443698-9 + +\bibitem{ndi} + \textsc{S. J. Norton, M. D. Dipasquale}: + \textit{Thread Time - The Multithreaded Programming Guide}, + Prentice Hall, 1997; ISBN 0-13-190067-6 + +\bibitem{drb} + \textsc{D. R. Butenhof}: + \textit{Programming with POSIX Threads}, + Addison Wesley, 1997; + ISBN 0-201-63392-2 + +\bibitem{spr} + \textsc{S. Prasad}: + \textit{Multithreading Programming Techniques}, + McGraw-Hill, 1996; + ISBN 0-079-12250-7 + +\bibitem{kss} + \textsc{S. Kleinman, B. Smalders, D. Shah}: + \textit{Programming with Threads}, + Prentice Hall, 1995; + ISBN 0-131-72389-8 + +\bibitem{cjn} + \textsc{C.J. Northrup}: + \textit{Programming With Unix Threads}, + John Wiley \& Sons, 1996; + ISBN 0-471-13751-0 + +\bibitem{bmv} + \textsc{P. Barton-Davis, D. McNamee, R. Vaswani, E. Lazowska}: + \textit{Adding Scheduler Activations to Mach 3.0}, + University of Washington, 1992; + Technical Report 92-08-03 + +\bibitem{lwp} + \textsc{D. Stein, D. Shah}: \textit{Implementing Lightwight Threads}, + SunSoft Inc., 1992 (published at USENIX'92). + +\bibitem{aup} + \textsc{W.R.Stevens}: \textit{Advanced Programming in + the Unix Environment}, Addison-Wesley, 1992; ISBN 0-201-56317-7 + +\bibitem{posix} + \textsc{D. Lewine}: \textit{POSIX Programmer's Guide: Writing Portable + Unix Programs}, O'Reilly \& Associates,Inc., 1994; ISBN 0-937175-73-0 + +\bibitem{osfaq} + \textsc{Bryan O'Sullivan}: \textit{Frequently asked questions for + comp.os.research}, 1995; http://www.serpentine.com/\verb|~|bos/os-faq/, + ftp://rtfm.mit.edu/pub/usenet/comp.os\-.re\-search/ + +\bibitem{tfaq1} + \textsc{Sun Microsystems, Inc}: \textit{Threads Frequently Asked Questions}, + 1995, http://www\-.sun\-.com/\-workshop/\-threads/\-faq.html + +\bibitem{tfaq2} + \textsc{Bryan O'Sullivan}: \textit{Frequently asked questions for + comp.programming.threads}, 1997; + http://www.serpentine.com/\verb|~|bos/threads-faq/. + +\bibitem{tfaq3} + \textsc{Bil Lewis}: \textit{Frequently asked questions for + comp.programming.threads}, 1999; + http://\-www.lambdacs.com/\-newsgroup/\-FAQ\-.html + +\bibitem{mdg} + \textsc{Numeric Quest Inc}: \textit{Multithreading - Definitions and Guidelines}; + 1998; http://www.numeric-quest.com/lang/multi-frame.html + +\bibitem{sus} + \textsc{The Open Group}: \textit{The Sing\-le Unix Speci\-fi\-cation, Version 2 - Threads}; + 1997; http://www\-.opengroup\-.org/online\-pubs/007908799/xsh/threads.html + +\bibitem{str} + \textsc{Sun Microsystems Inc}: \textit{SMI Thread Resources}; + http://www.sun\-.com/\-workshop/\-threads + +\bibitem{fsu} + \textsc{Frank Mueller}: \textit{FSU pthreads}; 1997; + http://www\-.cs.fsu\-.edu/\-\verb|~|mueller/\-pthreads/ + +\bibitem{mit} + \textsc{Chris Provenzano}: \textit{MIT pthreads}; 1993; + http://www.mit\-.edu/people/\-pro\-ven/\-pthreads.html (old), + http://www\-.human\-factor\-.com/\-pthreads/\-mit-pthreads.html (updated) + +\bibitem{ptl2} + \textsc{Kota Abe}: \textit{Portable Threading Library} (PTL); 1999; + http://www\-.media\-.osaka-cu\-.ac\-.jp/\verb|~|k-abe/PTL/ + +\bibitem{pth} + \textsc{Ralf S. Engelschall}: \textit{GNU Portable Threads} (Pth); 1999; + http://www\-.gnu\-.org/\-software/\-pth/, ftp://ftp\-.gnu\-.org/\-gnu/\-pth/ + +\bibitem{pcthreads} + \textsc{Michael T. Peterson}: \textit{POSIX and DCE Threads For Linux} + (PCThreads); 1995; http://members.aa\-.net/\verb|~|mtp/PCthreads.html + +\bibitem{rsthreads} + \textsc{Robert S. Thau}: \textit{Really Simple Threads} (rsthreads); 1996; + ftp://ftp.ai.mit.edu/pub/rst/ + +\bibitem{uthread} + \textsc{John Birrell}: \textit{FreeBSD uthreads}; 1998; + ftp://ftp.freebsd\-.org/pub/FreeBSD/\-FreeBSD-current/src/lib/libc\_r/uthread/ + +\bibitem{linuxthreads} + \textsc{Xavier Leroy}: \textit{The LinuxThreads library}; 1999; + http://\-pauillac\-.inria\-.fr/\verb|~|xleroy/\-linux\-threads/ + +\bibitem{aix} + \textsc{IBM}: \textit{AIX Version 4.3 General Programming Concepts: + Writing and Debugging Programs; Understanding Threads}; 1998; + http://www\-.rs6000\-.ibm\-.com/\-doc\_link/\-en\_US/\-a\_doc\_lib/\-aixprggd/\-genprogc/\-understanding\-\_threads\-.htm + +\bibitem{nspr} + \textit{Netscape Portable Runtime} (NSPR); + http://\-www.mozilla.org/\-docs/\-refList/refNSPR/, + http://\-lxr.mozilla.org/\-seamonkey/\-source/nsprpub/ + +\bibitem{smcb} + \textsc{Ralf S. Engelschall}: \textit{Simple Machine Context Benchmark}; 2000; + http://\-www.gnu.org\-/software/\-pth\-/smcb.tar.gz + +\end{thebibliography} +} + +\end{multicols} + +\end{document} +