1 // Copyright 2019 The Marl Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "osfiber.h"
16 
17 #include "marl_test.h"
18 
19 namespace {
20 
21 auto constexpr fiberStackSize = 8 * 1024;
22 
23 }  // anonymous namespace
24 
TEST_F(WithoutBoundScheduler,OSFiber)25 TEST_F(WithoutBoundScheduler, OSFiber) {
26   std::string str;
27   auto main = marl::OSFiber::createFiberFromCurrentThread(allocator);
28   marl::Allocator::unique_ptr<marl::OSFiber> fiberA, fiberB, fiberC;
29   fiberC = marl::OSFiber::createFiber(allocator, fiberStackSize, [&] {
30     str += "C";
31     fiberC->switchTo(fiberB.get());
32   });
33   fiberB = marl::OSFiber::createFiber(allocator, fiberStackSize, [&] {
34     str += "B";
35     fiberB->switchTo(fiberA.get());
36   });
37   fiberA = marl::OSFiber::createFiber(allocator, fiberStackSize, [&] {
38     str += "A";
39     fiberA->switchTo(main.get());
40   });
41 
42   main->switchTo(fiberC.get());
43 
44   ASSERT_EQ(str, "CBA");
45 }
46 
TEST_F(WithoutBoundScheduler,StackAlignment)47 TEST_F(WithoutBoundScheduler, StackAlignment) {
48   uintptr_t address = 0;
49 
50   struct alignas(16) AlignTo16Bytes {
51     uint64_t a, b;
52   };
53 
54   auto main = marl::OSFiber::createFiberFromCurrentThread(allocator);
55   marl::Allocator::unique_ptr<marl::OSFiber> fiber;
56   fiber = marl::OSFiber::createFiber(allocator, fiberStackSize, [&] {
57     AlignTo16Bytes stack_var;
58 
59     address = reinterpret_cast<uintptr_t>(&stack_var);
60 
61     fiber->switchTo(main.get());
62   });
63 
64   main->switchTo(fiber.get());
65 
66   ASSERT_TRUE((address & 15) == 0)
67       << "Stack variable had unaligned address: 0x" << std::hex << address;
68 }
69