// Copyright 2021 The Emscripten Authors. All rights reserved. // Emscripten is available under two separate licenses, the MIT license and the // University of Illinois/NCSA Open Source License. Both these licenses can be // found in the LICENSE file. // This file defines fuzzer workloads which primarily fuzz multi-threaded // operations. #include "workload.h" namespace wasmfs { bool ReadWrite::isSame(std::vector& target) { std::set seen; for (auto it = target.begin(); it != target.end() - 1; it++) { seen.insert(*it); if (seen.size() > 1) { printf("Read the following incorrect data: %s\n", target.data()); return false; } } return true; } void ReadWrite::writer() { while (!go) { std::this_thread::yield(); } while (!stop) { if (VERBOSE) { std::cout << std::this_thread::get_id() << " is running.\n"; } auto current = rand.upTo(work.size()); int bytesWritten = pwrite(fd, work[current].c_str(), work[current].size(), 0); assert(bytesWritten == work[current].size()); } } void ReadWrite::reader() { while (!go) { std::this_thread::yield(); } if (VERBOSE) { std::cout << std::this_thread::get_id() << " is running.\n"; } int size = work.begin()->size(); // Add room for null terminator. std::vector buf(size + 1, 0); while (!stop) { std::fill(buf.begin(), buf.end(), 0); int bytesRead = pread(fd, buf.data(), size, 0); if (VERBOSE) { printf("Read the following data: %s\n", buf.data()); printf("Bytes read: %i", bytesRead); printf("Expected: %lu", work.begin()->size()); } assert(bytesRead == work.begin()->size()); assert(isSame(buf)); } } void ReadWrite::execute() { // This function should produce a string that consists of 1 character type. work.resize(1 + rand.upTo(MAX_WORK)); for (int i = 0; i < work.size(); i++) { work[i] = rand.getSingleSymbolString(FILE_SIZE); } // Generate a test file to read and write to. fd = open("test", O_CREAT | O_RDWR, 0777); assert(fd != -1); // Populate the file with initial data. assert(pwrite(fd, work.begin()->c_str(), work.begin()->size(), 0) != -1); // Create writer threads. std::vector writers; std::vector readers; for (int i = 0; i < NUM_WRITERS; i++) { std::thread th(&ReadWrite::writer, this); writers.emplace_back(std::move(th)); } for (int i = 0; i < NUM_READERS; i++) { std::thread th(&ReadWrite::reader, this); readers.emplace_back(std::move(th)); } // This atomic bool ensures that all threads have an equal chance of // starting first. go.store(true); std::this_thread::sleep_for(std::chrono::seconds(DURATION)); // Stop file operations after pre-defined duration. stop.store(true); for (auto& th : writers) { th.join(); } for (auto& th : readers) { th.join(); } // Clean up files. unlink("test"); close(fd); } } // namespace wasmfs