OSSP CVS Repository

ossp - Check-in [5419]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 5419
Date: 2006-Jun-12 20:02:51 (local)
2006-Jun-12 18:02:51 (UTC)
User:rse
Branch:
Comment: 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.
Tickets:
Inspections:
Files:
ossp-pkg/pth/.cvsignore      1.21 -> 1.22     4 inserted, 0 deleted
ossp-pkg/pth/ChangeLog      1.645 -> 1.646     8 inserted, 0 deleted
ossp-pkg/pth/Makefile.in      1.156 -> 1.157     20 inserted, 0 deleted
ossp-pkg/pth/rse-pmt.fig      added-> 1.1
ossp-pkg/pth/rse-pmt.pdf      added-> 1.1
ossp-pkg/pth/rse-pmt.ps      added-> 1.9
ossp-pkg/pth/rse-pmt.tex      added-> 1.1

ossp-pkg/pth/.cvsignore 1.21 -> 1.22

--- .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


ossp-pkg/pth/ChangeLog 1.645 -> 1.646

--- 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


ossp-pkg/pth/Makefile.in 1.156 -> 1.157

--- 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


ossp-pkg/pth/rse-pmt.fig -> 1.1

*** /dev/null    Sat Apr 27 15:11:00 2024
--- -    Sat Apr 27 15:11:53 2024
***************
*** 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


ossp-pkg/pth/rse-pmt.pdf -> 1.1

Binary files /dev/null and - differ


ossp-pkg/pth/rse-pmt.ps -> 1.9

*** /dev/null    Sat Apr 27 15:11:00 2024
--- -    Sat Apr 27 15:11:53 2024
***************
*** 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


ossp-pkg/pth/rse-pmt.tex -> 1.1

*** /dev/null    Sat Apr 27 15:11:00 2024
--- -    Sat Apr 27 15:11:53 2024
***************
*** 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}
+ 

CVSTrac 2.0.1