1#include <stdio.h>
2#include <stdlib.h>
3#include <ucontext.h>
4#include "tests/sys_mman.h"
5
6#include "valgrind.h"
7
8#define STACK_SIZE (10 * 4096)
9
10// This test is checking the libc context calls (setcontext, etc.) and
11// checks that Valgrind notices their stack changes properly.
12
13typedef  struct ucontext  mycontext;
14
15mycontext ctx1, ctx2, oldc;
16int count;
17
18void hello(mycontext *newc)
19{
20    printf("hello, world: %d\n", count);
21    if (count++ == 2)
22        newc = &oldc;
23    setcontext(newc);
24}
25
26int init_context(mycontext *uc)
27{
28    void *stack;
29    int ret;
30
31    if (getcontext(uc) == -1) {
32        //perror("getcontext");
33        printf("getcontext() doesn't seem to work\n");
34        exit(1);
35    }
36
37    stack = (void *)mmap(0, STACK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC,
38                                        MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
39
40    if (stack == (void*)-1) {
41        perror("mmap");
42        exit(1);
43    }
44
45    ret = VALGRIND_STACK_REGISTER(stack, stack + STACK_SIZE);
46
47    uc->uc_link = NULL;
48    uc->uc_stack.ss_sp = stack;
49    uc->uc_stack.ss_size = STACK_SIZE;
50    uc->uc_stack.ss_flags = 0;
51
52    return ret;
53}
54
55int main(int argc, char **argv)
56{
57    int c1 = init_context(&ctx1);
58    int c2 = init_context(&ctx2);
59
60    makecontext(&ctx1, (void (*)()) hello, 1, &ctx2);
61    makecontext(&ctx2, (void (*)()) hello, 1, &ctx1);
62
63    swapcontext(&oldc, &ctx1);
64
65    VALGRIND_STACK_DEREGISTER(c1);
66    //free(ctx1.uc_stack.ss_sp);
67    VALGRIND_STACK_DEREGISTER(c2);
68    //free(ctx2.uc_stack.ss_sp);
69
70    return 0;
71}
72