1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license.
3
4#include <cstdint>
5#include <deque>
6#include <thread>
7#include "gtest/gtest.h"
8
9#include "core/light_epoch.h"
10#include "core/malloc_fixed_page_size.h"
11#include "device/null_disk.h"
12
13struct alignas(32) Item {
14 uint8_t buffer[32];
15};
16
17using namespace FASTER::core;
18
19typedef MallocFixedPageSize<Item, FASTER::device::NullDisk> alloc_t;
20
21TEST(MallocFixedPageSize, AllocFree) {
22 LightEpoch epoch;
23 alloc_t allocator{};
24 allocator.Initialize(256, epoch);
25 for(size_t idx = 0; idx < 1000000; ++idx) {
26 FixedPageAddress address = allocator.Allocate();
27 Item* item = &allocator.Get(address);
28 ASSERT_EQ(0, reinterpret_cast<size_t>(item) % alignof(Item));
29 allocator.FreeAtEpoch(address, 0);
30 }
31 ASSERT_EQ(1, allocator.free_list().size());
32}
33
34TEST(MallocFixedPageSize, Alloc) {
35 LightEpoch epoch;
36 alloc_t allocator{};
37 allocator.Initialize(128, epoch);
38 for(size_t idx = 0; idx < 3200000; ++idx) {
39 FixedPageAddress address = allocator.Allocate();
40 Item* item = &allocator.Get(address);
41 ASSERT_EQ(0, reinterpret_cast<size_t>(item) % alignof(Item));
42 }
43 ASSERT_EQ(0, allocator.free_list().size());
44}
45
46
47static void MultiThread_Worker(alloc_t* allocator) {
48 constexpr size_t kAllocCount = 1600000;
49 FixedPageAddress* addresses = new FixedPageAddress[kAllocCount];
50
51 for(size_t idx = 0; idx < kAllocCount; ++idx) {
52 addresses[idx] = allocator->Allocate();
53 Item* item = &allocator->Get(addresses[idx]);
54 ASSERT_EQ(0, reinterpret_cast<size_t>(item) % alignof(Item));
55 }
56 for(size_t idx = 0; idx < kAllocCount; ++idx) {
57 allocator->FreeAtEpoch(addresses[idx], idx);
58 }
59 ASSERT_EQ(kAllocCount, allocator->free_list().size());
60
61 delete[] addresses;
62}
63
64TEST(MallocFixedPageSize, Concurrent) {
65 constexpr size_t kNumThreads = 2;
66 LightEpoch epoch;
67 alloc_t allocator{};
68 allocator.Initialize(64, epoch);
69 std::deque<std::thread> threads{};
70 for(size_t idx = 0; idx < kNumThreads; ++idx) {
71 threads.emplace_back(MultiThread_Worker, &allocator);
72 }
73 for(auto& thread : threads) {
74 thread.join();
75 }
76}
77
78int main(int argc, char** argv) {
79 ::testing::InitGoogleTest(&argc, argv);
80 return RUN_ALL_TESTS();
81}