Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/system/lib/wasmfs/fuzzer/workload.cpp
6175 views
1
// Copyright 2021 The Emscripten Authors. All rights reserved.
2
// Emscripten is available under two separate licenses, the MIT license and the
3
// University of Illinois/NCSA Open Source License. Both these licenses can be
4
// found in the LICENSE file.
5
6
// This file defines fuzzer workloads which primarily fuzz multi-threaded
7
// operations.
8
9
#include "workload.h"
10
11
namespace wasmfs {
12
13
bool ReadWrite::isSame(std::vector<char>& target) {
14
std::set<char> seen;
15
16
for (auto it = target.begin(); it != target.end() - 1; it++) {
17
seen.insert(*it);
18
if (seen.size() > 1) {
19
printf("Read the following incorrect data: %s\n", target.data());
20
return false;
21
}
22
}
23
return true;
24
}
25
26
void ReadWrite::writer() {
27
while (!go) {
28
std::this_thread::yield();
29
}
30
31
while (!stop) {
32
if (VERBOSE) {
33
std::cout << std::this_thread::get_id() << " is running.\n";
34
}
35
auto current = rand.upTo(work.size());
36
37
int bytesWritten =
38
pwrite(fd, work[current].c_str(), work[current].size(), 0);
39
40
assert(bytesWritten == work[current].size());
41
}
42
}
43
44
void ReadWrite::reader() {
45
while (!go) {
46
std::this_thread::yield();
47
}
48
if (VERBOSE) {
49
std::cout << std::this_thread::get_id() << " is running.\n";
50
}
51
52
int size = work.begin()->size();
53
// Add room for null terminator.
54
std::vector<char> buf(size + 1, 0);
55
56
while (!stop) {
57
std::fill(buf.begin(), buf.end(), 0);
58
59
int bytesRead = pread(fd, buf.data(), size, 0);
60
if (VERBOSE) {
61
printf("Read the following data: %s\n", buf.data());
62
printf("Bytes read: %i", bytesRead);
63
printf("Expected: %lu", work.begin()->size());
64
}
65
assert(bytesRead == work.begin()->size());
66
67
assert(isSame(buf));
68
}
69
}
70
71
void ReadWrite::execute() {
72
// This function should produce a string that consists of 1 character type.
73
work.resize(1 + rand.upTo(MAX_WORK));
74
75
for (int i = 0; i < work.size(); i++) {
76
work[i] = rand.getSingleSymbolString(FILE_SIZE);
77
}
78
// Generate a test file to read and write to.
79
fd = open("test", O_CREAT | O_RDWR, 0777);
80
assert(fd != -1);
81
82
// Populate the file with initial data.
83
assert(pwrite(fd, work.begin()->c_str(), work.begin()->size(), 0) != -1);
84
85
// Create writer threads.
86
std::vector<std::thread> writers;
87
std::vector<std::thread> readers;
88
89
for (int i = 0; i < NUM_WRITERS; i++) {
90
std::thread th(&ReadWrite::writer, this);
91
writers.emplace_back(std::move(th));
92
}
93
94
for (int i = 0; i < NUM_READERS; i++) {
95
std::thread th(&ReadWrite::reader, this);
96
readers.emplace_back(std::move(th));
97
}
98
99
// This atomic bool ensures that all threads have an equal chance of
100
// starting first.
101
go.store(true);
102
103
std::this_thread::sleep_for(std::chrono::seconds(DURATION));
104
105
// Stop file operations after pre-defined duration.
106
stop.store(true);
107
108
for (auto& th : writers) {
109
th.join();
110
}
111
112
for (auto& th : readers) {
113
th.join();
114
}
115
116
// Clean up files.
117
unlink("test");
118
close(fd);
119
}
120
} // namespace wasmfs
121
122