// RUN: %clangxx_msan -O0 %s -o %t && %run %t #include #include #include #include #include #include namespace { const int kStackSize = 1 << 20; char fiber_stack[kStackSize] = {}; ucontext_t main_ctx; ucontext_t fiber_ctx; void fiber() { printf("%s: entering fiber\n", __FUNCTION__); // This fiber was switched into from main. Verify the details of main's stack // have been populated by MSAN. const void *previous_stack_bottom = nullptr; size_t previous_stack_size = 0; __msan_finish_switch_fiber(&previous_stack_bottom, &previous_stack_size); assert(previous_stack_bottom != nullptr); assert(previous_stack_size != 0); printf("%s: implicitly swapcontext to main\n", __FUNCTION__); __msan_start_switch_fiber(previous_stack_bottom, previous_stack_size); } } // namespace // Set up a fiber, switch to it, and switch back, invoking __msan_*_switch_fiber // functions along the way. At each step, validate the correct stack addresses and // sizes are returned from those functions. int main(int argc, char **argv) { if (getcontext(&fiber_ctx) == -1) { perror("getcontext"); _exit(1); } fiber_ctx.uc_stack.ss_sp = fiber_stack; fiber_ctx.uc_stack.ss_size = sizeof(fiber_stack); fiber_ctx.uc_link = &main_ctx; makecontext(&fiber_ctx, fiber, 0); // Tell MSAN a fiber switch is about to occur, then perform the switch printf("%s: swapcontext to fiber\n", __FUNCTION__); __msan_start_switch_fiber(fiber_stack, kStackSize); if (swapcontext(&main_ctx, &fiber_ctx) == -1) { perror("swapcontext"); _exit(1); } // The fiber switched to above now switched back here. Tell MSAN that switch // is complete and verify the fiber details return by MSAN are correct. const void *previous_stack_bottom = nullptr; size_t previous_stack_size = 0; __msan_finish_switch_fiber(&previous_stack_bottom, &previous_stack_size); assert(previous_stack_bottom == fiber_stack); assert(previous_stack_size == kStackSize); printf("%s: exiting\n", __FUNCTION__); return 0; }