1 dnl AC_CHECK_UCONTEXT: Check whether ucontext are working
3 dnl Most of the code is stolen from the GNU pth autoconf macros by
4 dnl Ralf S. Engelschall.
5 dnl # ``"Reuse an expert's code" is the right
6 dnl # advice for most people. But it's a useless
7 dnl # advice for the experts writing the code
8 dnl # in the first place.'
9 dnl # -- Dan J. Bernstein
11 dnl OK, you're definitely the expert on this point... :)
14 dnl ## Display Configuration Headers
17 dnl ## AC_MSG_PART(<text>)
20 m4_define(AC_MSG_PART,[dnl
21 if test ".$enable_subdir" != .yes; then
23 AC_MSG_RESULT(${TB}$1:${TN})
28 dnl ## Display a message under --verbose
31 dnl ## AC_MSG_VERBOSE(<text>)
34 m4_define(AC_MSG_VERBOSE,[dnl
35 if test ".$verbose" = .yes; then
41 dnl ## Do not display message for a command
44 dnl ## AC_MSG_SILENT(...)
47 m4_define(AC_FD_TMP, 9)
48 m4_define(AC_MSG_SILENT,[dnl
49 exec AC_FD_TMP>&AC_FD_MSG AC_FD_MSG>/dev/null
51 exec AC_FD_MSG>&AC_FD_TMP AC_FD_TMP>&-
55 dnl ## Check for direction of stack growth
58 dnl ## AC_CHECK_STACKGROWTH(<define>)
60 dnl ## #undef <define>
62 dnl ## #include "config.h"
63 dnl ## #if <define> < 0
64 dnl ## ...stack grow down...
66 dnl ## ...stack grow up...
70 AC_DEFUN([AC_CHECK_STACKGROWTH],[dnl
71 AC_MSG_CHECKING(for direction of stack growth)
72 AC_CACHE_VAL(ac_cv_check_stackgrowth, [
75 changequote(<<, >>)dnl
79 static int iterate = 10;
80 static int growsdown(int *x)
90 int main(int argc, char *argv[])
94 if ((f = fopen("conftestval", "w")) == NULL)
96 fprintf(f, "%s\n", growsdown(&x) ? "down" : "up");;
103 ac_cv_check_stackgrowth=`cat conftestval`,
104 ac_cv_check_stackgrowth=down,
105 ac_cv_check_stackgrowth=down
108 AC_MSG_RESULT([$ac_cv_check_stackgrowth])
109 if test ".$ac_cv_check_stackgrowth" = ".down"; then
114 AC_DEFINE_UNQUOTED($1, $val, [define for stack growth])
118 dnl ## Check whether SVR4/SUSv2 makecontext(2), swapcontext(2) and
119 dnl ## friends can be used for user-space context switching
122 dnl ## AC_CHECK_MCSC(<success-action>, <failure-action>)
125 AC_DEFUN([AC_CHECK_MCSC], [
126 AC_MSG_CHECKING(for usable SVR4/SUSv2 makecontext(2)/swapcontext(2))
127 AC_CACHE_VAL(ac_cv_check_mcsc, [
132 #include <ucontext.h>
139 if (swapcontext(&uc_child, &uc_main) != 0)
143 int main(int argc, char *argv[])
148 /* the default is that it fails */
149 if ((fp = fopen("conftestval", "w")) == NULL)
154 /* configure a child user-space context */
155 if ((stack = malloc(64*1024)) == NULL)
157 if (getcontext(&uc_child) != 0)
159 uc_child.uc_link = NULL;
160 uc_child.uc_stack.ss_sp = (char *)stack+(32*1024);
161 uc_child.uc_stack.ss_size = 32*1024;
162 uc_child.uc_stack.ss_flags = 0;
163 makecontext(&uc_child, child, 0);
165 /* switch into the user context */
166 if (swapcontext(&uc_main, &uc_child) != 0)
169 /* Fine, child came home */
170 if ((fp = fopen("conftestval", "w")) == NULL)
172 fprintf(fp, "yes\n");
175 /* die successfully */
179 ac_cv_check_mcsc=`cat conftestval`,
184 AC_MSG_RESULT([$ac_cv_check_mcsc])
185 if test ".$ac_cv_check_mcsc" = .yes; then
186 ifelse([$1], , :, [$1])
188 ifelse([$2], , :, [$2])
193 dnl ## Check how stacks have to be setup for the functions
194 dnl ## sigstack(2), sigaltstack(2) and makecontext(2).
197 dnl ## AC_CHECK_STACKSETUP(sigstack|sigaltstack|makecontext, <macro-addr>, <macro-size>)
199 dnl ## #undef HAVE_{SIGSTACK|SIGALTSTACK|MAKECONTEXT}
200 dnl ## #undef HAVE_STACK_T
202 dnl ## @<macro-addr>@
203 dnl ## @<macro-size>@
205 dnl ## #include "header.h"
206 dnl ## xxx.sp_ss = <macro-addr>(skaddr, sksize);
207 dnl ## xxx.sp_size = <macro-size>(skaddr, sksize);
210 AC_DEFUN([AC_CHECK_STACKSETUP],[dnl
211 dnl # check for consistent usage
212 ifelse($1,[sigstack],,[
213 ifelse($1,[sigaltstack],,[
214 ifelse($1,[makecontext],,[
215 errprint(__file__:__line__: [AC_CHECK_STACKSETUP: only sigstack, sigaltstack and makecontext supported
217 dnl # we require the C compiler and the standard headers
218 AC_REQUIRE([AC_HEADER_STDC])dnl
219 dnl # we at least require the function to check
221 dnl # sigaltstack on some platforms uses stack_t instead of struct sigaltstack
222 ifelse($1, sigaltstack, [
223 AC_ONCE(stacksetup_stack_t, [
224 AC_CHECK_TYPEDEF(stack_t, signal.h)
227 dnl # display processing header
228 AC_MSG_CHECKING(for stack setup via $1)
229 dnl # but cache the whole results
230 AC_CACHE_VAL(ac_cv_stacksetup_$1,[
231 if test ".$ac_cv_func_$1" = .no; then
232 dnl # no need to check anything when function is already missing
233 ac_cv_stacksetup_$1="N.A.:/*N.A.*/,/*N.A.*/"
235 dnl # setup compile environment
237 CFLAGS="$CFLAGS -DTEST_$1"
239 dnl # compile and run the test program
244 #if defined(TEST_sigstack) || defined(TEST_sigaltstack)
245 #include <sys/types.h>
249 #if defined(TEST_makecontext)
250 #include <ucontext.h>
259 static volatile char *handler_addr = (char *)0xDEAD;
260 #if defined(TEST_sigstack) || defined(TEST_sigaltstack)
261 static volatile int handler_done = 0;
262 void handler(int sig)
267 for (i = 0; i < 1024; i++)
269 handler_addr = (char *)&dummy;
274 #if defined(TEST_makecontext)
275 static ucontext_t uc_handler;
276 static ucontext_t uc_main;
282 for (i = 0; i < 1024; i++)
284 handler_addr = (char *)&dummy;
285 swapcontext(&uc_handler, &uc_main);
289 int main(int argc, char *argv[])
298 skbuf = (char *)malloc(sksize*2+2*sizeof(union alltypes));
301 for (i = 0; i < sksize*2+2*sizeof(union alltypes); i++)
303 skaddr = skbuf+sizeof(union alltypes);
304 #if defined(TEST_sigstack) || defined(TEST_sigaltstack)
307 #if defined(TEST_sigstack)
309 #elif defined(TEST_sigaltstack) && defined(HAVE_STACK_T)
312 struct sigaltstack ss;
314 #if defined(TEST_sigstack)
315 ss.ss_sp = (void *)(skaddr + sksize);
317 if (sigstack(&ss, NULL) < 0)
319 #elif defined(TEST_sigaltstack)
320 ss.ss_sp = (void *)(skaddr + sksize);
323 if (sigaltstack(&ss, NULL) < 0)
326 memset((void *)&sa, 0, sizeof(struct sigaction));
327 sa.sa_handler = handler;
328 sa.sa_flags = SA_ONSTACK;
329 sigemptyset(&sa.sa_mask);
330 sigaction(SIGUSR1, &sa, NULL);
331 kill(getpid(), SIGUSR1);
332 while (!handler_done)
336 #if defined(TEST_makecontext)
338 if (getcontext(&uc_handler) != 0)
340 uc_handler.uc_link = NULL;
341 uc_handler.uc_stack.ss_sp = (void *)(skaddr + sksize);
342 uc_handler.uc_stack.ss_size = sksize;
343 uc_handler.uc_stack.ss_flags = 0;
344 makecontext(&uc_handler, handler, 0);
345 swapcontext(&uc_main, &uc_handler);
348 if (handler_addr == (char *)0xDEAD)
350 if (handler_addr < skaddr+sksize) {
351 /* stack was placed into lower area */
352 if (*(skaddr+sksize) != 'A')
353 sprintf(result, "(skaddr)+(sksize)-%d,(sksize)-%d",
354 sizeof(union alltypes), sizeof(union alltypes));
356 strcpy(result, "(skaddr)+(sksize),(sksize)");
359 /* stack was placed into higher area */
360 if (*(skaddr+sksize*2) != 'A')
361 sprintf(result, "(skaddr),(sksize)-%d", sizeof(union alltypes));
363 strcpy(result, "(skaddr),(sksize)");
365 if ((f = fopen("conftestval", "w")) == NULL)
367 fprintf(f, "%s\n", result);
372 dnl # test successully passed
373 ac_cv_stacksetup_$1=`cat conftestval`
374 ac_cv_stacksetup_$1="ok:$ac_cv_stacksetup_$1"
377 ac_cv_stacksetup_$1='guessed:(skaddr),(sksize)'
379 dnl # cross-platform => failed
380 ac_cv_stacksetup_$1='guessed:(skaddr),(sksize)'
382 dnl # restore original compile environment
386 dnl # extract result ingredients of single cached result value
387 type=`echo $ac_cv_stacksetup_$1 | sed -e 's;:.*$;;'`
388 addr=`echo $ac_cv_stacksetup_$1 | sed -e 's;^.*:;;' -e 's;,.*$;;'`
389 size=`echo $ac_cv_stacksetup_$1 | sed -e 's;^.*:;;' -e 's;^.*,;;'`
390 dnl # export result ingredients
391 $2="#define $2(skaddr,sksize) ($addr)"
392 $3="#define $3(skaddr,sksize) ($size)"
395 dnl # display result indicator
396 AC_MSG_RESULT([$type])
397 dnl # display results in detail
398 AC_MSG_VERBOSE([$]$2)
399 AC_MSG_VERBOSE([$]$3)