… | |
… | |
8 | |
8 | |
9 | $DEFINE = ""; |
9 | $DEFINE = ""; |
10 | |
10 | |
11 | $DEFINE .= " -DHAVE_MMAP" if $Config{d_mmap} eq "define" && $Config{d_munmap} eq "define"; |
11 | $DEFINE .= " -DHAVE_MMAP" if $Config{d_mmap} eq "define" && $Config{d_munmap} eq "define"; |
12 | |
12 | |
13 | if ($^O =~ /win32/i) { |
13 | if ($^O =~ /win32/i or $^O =~ /cygwin/) { |
14 | $DEFINE = " -DCORO_LOOSE"; |
14 | $DEFINE = " -DCORO_LOOSE"; |
15 | } elsif ($^O =~ /irix/) { |
15 | } elsif ($^O =~ /irix/) { |
16 | $iface = "i"; |
16 | $iface = "i"; |
17 | } elsif ($^O =~ /linux/) { |
17 | } elsif ($^O =~ /linux/) { |
|
|
18 | # default to setjmp/longjmp on non-x86... |
|
|
19 | $iface = $Config{archname} =~ /^i[3456]86-/ ? "l" : "s"; |
|
|
20 | } elsif ($^O =~ /(free|net|open)bsd/) { |
|
|
21 | # FreeBSD 4.x has ucontext.h but no makecontext et al (see BUGS section of |
|
|
22 | # man context). Assume the same problem for all other BSDs. |
18 | $iface = "l"; |
23 | $iface = "s"; |
19 | } elsif ($^O =~ /solaris/) { |
24 | } elsif ($^O =~ /solaris/) { |
|
|
25 | $iface = "s"; |
|
|
26 | } elsif ($^O =~ /darwin/) { |
20 | $iface = "s"; |
27 | $iface = "s"; |
21 | } elsif (-e "/usr/include/ucontext.h") { |
28 | } elsif (-e "/usr/include/ucontext.h") { |
22 | $iface = "u"; |
29 | $iface = "u"; |
23 | } else { |
30 | } else { |
24 | $iface = "s"; |
31 | $iface = "s"; |
25 | } |
32 | } |
26 | |
33 | |
27 | print <<EOF; |
34 | print <<EOF; |
28 | |
35 | |
29 | Version 0.12 introduced experimental C context sharing. This makes it |
36 | Version 0.12 introduced C context sharing. This makes it possible to share |
30 | possible to share the C stack and context between many coroutines, |
37 | the C stack and context between many coroutines, resulting in memory |
31 | resulting in memory savings and slight speed gains, at the cost of |
38 | savings and slight speed gains, at the cost of potential (but mostly |
32 | potential segfaults (especially with exception handling). On my Linux/x86 |
39 | theoretical) segfaults. On my Linux/x86 machine this decreased the size |
33 | machine this decreased the size of a new coroutine from 9k to 5k, the |
40 | of a new coroutine from 9k to 5k, but the savings are much more apparent |
34 | savings are much more apparent on machines without mmap or good memory |
41 | on machines without mmap or good memory management. This algorithm relies |
35 | management. This algorithm relies on the non-fact that the same machine |
42 | on the non-fact that the same machine stack pointer indicates the same |
36 | stack pointer indicates the same function call nesting level, which |
43 | function call nesting level, which usually works good enough but might |
37 | usually works good enough but might fail... |
44 | fail... |
38 | |
45 | |
39 | The default (disabled) is safe, as it only increases memory consumption. |
46 | The default (enabled) has been in-use on productions servers for some time |
|
|
47 | now, without any problem reports so far. |
40 | |
48 | |
41 | EOF |
49 | EOF |
42 | |
50 | |
43 | print "Do you want to enable experimental context sharing (y/n) [n]? "; |
51 | print "Do you want to enable C context sharing (y/n) [y]? "; |
44 | |
52 | |
45 | if (<> =~ /^\s*y/i) { |
53 | if (<> !~ /^\s*n/i) { |
46 | print "\nExperimental context sharing enabled.\n\n"; |
54 | print "\nExperimental context sharing enabled.\n\n"; |
47 | $DEFINE .= " -DCORO_LAZY_STACK"; |
55 | $DEFINE .= " -DCORO_LAZY_STACK"; |
48 | } |
56 | } |
49 | |
57 | |
50 | if ($iface) { |
58 | if ($iface) { |
51 | print <<EOF; |
59 | print <<EOF; |
52 | |
60 | |
53 | Coro has the option of using two different ways to implement coroutines |
61 | Coro can use various ways to implement coroutines at the C level: |
54 | at the C level: |
|
|
55 | |
62 | |
56 | u The unix ucontext functions are newer and not implemented in older |
63 | u The unix ucontext functions are newer and not implemented in older |
57 | unices (or broken libc's like glibc-2.2.2 and below). They allow very |
64 | unices (or broken libc's like glibc-2.2.2 and below). They allow very |
58 | fast coroutine creation and fast switching, and, most importantly, are |
65 | fast coroutine creation and fast switching, and, most importantly, are |
59 | very stable. |
66 | very stable. |
… | |
… | |
65 | faster than with the ucontext functions). Unfortunately, glibc-2.1 and |
72 | faster than with the ucontext functions). Unfortunately, glibc-2.1 and |
66 | below don't even feature a working sigaltstack. |
73 | below don't even feature a working sigaltstack. |
67 | |
74 | |
68 | l Older GNU/Linux systems (glibc-2.1 and below) need this hack. Since it is |
75 | l Older GNU/Linux systems (glibc-2.1 and below) need this hack. Since it is |
69 | very linux-specific it is also quite fast for newer versions; when it |
76 | very linux-specific it is also quite fast for newer versions; when it |
70 | works, that is... |
77 | works, that is (currently x86 only)... |
71 | |
78 | |
72 | i IRIX. For some reason, SGI really does not like to follow the unix |
79 | i IRIX. For some reason, SGI really does not like to follow the unix |
73 | standard (does that surprise you?), so this techniquee should be fast |
80 | standard (does that surprise you?), so this workaround might be needed |
74 | and safe (althogh s and u should also work now). |
81 | (it's fast), although s and u should also work now. |
75 | |
82 | |
76 | EOF |
83 | EOF |
77 | |
84 | |
78 | retry: |
85 | retry: |
79 | print "Use which implementation,\n", |
86 | print "Use which implementation,\n", |
… | |
… | |
83 | $iface = lc $1 if $r =~ /(\S)/; |
90 | $iface = lc $1 if $r =~ /(\S)/; |
84 | |
91 | |
85 | if ($iface eq "u") { |
92 | if ($iface eq "u") { |
86 | $DEFINE .= " -DCORO_UCONTEXT"; |
93 | $DEFINE .= " -DCORO_UCONTEXT"; |
87 | print "\nUsing ucontext implementation\n\n"; |
94 | print "\nUsing ucontext implementation\n\n"; |
|
|
95 | conftest("TEST_makecontext"); |
88 | } elsif ($iface eq "s") { |
96 | } elsif ($iface eq "s") { |
89 | $DEFINE .= " -DCORO_SJLJ"; |
97 | $DEFINE .= " -DCORO_SJLJ"; |
90 | print "\nUsing setjmp/longjmp/sigaltstack implementation\n\n"; |
98 | print "\nUsing setjmp/longjmp/sigaltstack implementation\n\n"; |
|
|
99 | conftest("TEST_sigaltstack"); |
91 | } elsif ($iface eq "l") { |
100 | } elsif ($iface eq "l") { |
92 | $DEFINE .= " -DCORO_LINUX"; |
101 | $DEFINE .= " -DCORO_LINUX"; |
93 | print "\nUsing linux-specific implementation\n\n"; |
102 | print "\nUsing linux-specific implementation\n\n"; |
94 | } elsif ($iface eq "i") { |
103 | } elsif ($iface eq "i") { |
95 | $DEFINE .= " -DCORO_IRIX"; |
104 | $DEFINE .= " -DCORO_IRIX"; |
… | |
… | |
97 | } else { |
106 | } else { |
98 | print "\nUnknown implementation \"$iface\"\n"; |
107 | print "\nUnknown implementation \"$iface\"\n"; |
99 | goto retry; |
108 | goto retry; |
100 | } |
109 | } |
101 | } else { |
110 | } else { |
102 | print "\nUsing microsoft coroutine implementation\n\n"; |
111 | print "\nUsing microsoft compatible coroutines\n\n"; |
103 | } |
112 | } |
104 | |
113 | |
105 | WriteMakefile( |
114 | WriteMakefile( |
106 | NAME => "Coro::State", |
115 | NAME => "Coro::State", |
107 | VERSION_FROM => "State.pm", |
116 | VERSION_FROM => "State.pm", |
108 | DEFINE => $DEFINE, |
117 | DEFINE => $DEFINE, |
109 | DIR => [], |
118 | DIR => [], |
110 | PM => { |
|
|
111 | 'State.pm' => '$(INST_LIBDIR)/State.pm', |
|
|
112 | |
|
|
113 | 'MakeMaker.pm' => '$(INST_LIBDIR)/MakeMaker.pm', |
|
|
114 | 'CoroAPI.h' => '$(INST_LIBDIR)/CoroAPI.h', |
|
|
115 | |
|
|
116 | 'Cont.pm' => '$(INST_LIBDIR)/Cont.pm', |
|
|
117 | |
|
|
118 | 'Specific.pm' => '$(INST_LIBDIR)/Specific.pm', |
|
|
119 | |
|
|
120 | 'Signal.pm' => '$(INST_LIBDIR)/Signal.pm', |
|
|
121 | 'Channel.pm' => '$(INST_LIBDIR)/Channel.pm', |
|
|
122 | 'Semaphore.pm' => '$(INST_LIBDIR)/Semaphore.pm', |
|
|
123 | 'SemaphoreSet.pm' => '$(INST_LIBDIR)/SemaphoreSet.pm', |
|
|
124 | 'RWLock.pm' => '$(INST_LIBDIR)/RWLock.pm', |
|
|
125 | }, |
|
|
126 | ); |
119 | ); |
127 | |
120 | |
|
|
121 | sub conftest { |
|
|
122 | my $type = shift; |
|
|
123 | |
|
|
124 | print "\nTrying to detect stack growth direction (for $type)\n"; |
|
|
125 | print "You might see some warnings, this should not concern you.\n\n"; |
|
|
126 | system "$Config{cc} $Config{ccflags} -D$type libcoro/conftest.c"; |
|
|
127 | |
|
|
128 | my $res = qx<./a.out>; |
|
|
129 | $res =~ s/\s+$//; |
|
|
130 | my ($sp, $ss) = split /,/, $res; |
|
|
131 | |
|
|
132 | print "\n\n*****************************************************************************\n"; |
|
|
133 | print "If the testsuite fails PLEASE provide the following information\n"; |
|
|
134 | print "to Marc Lehmann <pcg\@goof.com>: operating system name, version,\n"; |
|
|
135 | print "architecture name and this string '$sp|$ss'. Thanks a lot!\n";#d# |
|
|
136 | print "*****************************************************************************\n\n"; |
|
|
137 | |
|
|
138 | unlink "a.out"; |
|
|
139 | unlink "conftestval"; |
|
|
140 | } |
128 | |
141 | |
129 | |
142 | |