Files
cpu-check/silkscreen.cc
Kevin Boyd 83eed0a886 Sync with upstream repo.
Changes include:
* CPU check has been broken up into a number of small libraries
* BoringSSL option has been removed
* Better abseil integration
2020-11-09 13:03:39 -08:00

92 lines
2.9 KiB
C++

// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "silkscreen.h"
#include <unistd.h>
#include <random>
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "utils.h"
namespace cpu_check {
static const size_t kPageSize = sysconf(_SC_PAGESIZE);
Silkscreen::Silkscreen(const std::vector<int> &tid_list)
: buffer_address_(static_cast<char *>(aligned_alloc(
kPageSize, kPageSize * ((kSize + kPageSize - 1) / kPageSize)))) {
std::knuth_b rng;
std::uniform_int_distribution<size_t> dist(0, tid_list.size() - 1);
for (size_t k = 0; k < kSize; k++) {
size_t w = dist(rng);
const int o = tid_list[w];
slot_count_[o]++;
owner_.push_back(o);
}
}
absl::Status Silkscreen::WriteMySlots(int tid, uint64_t round) {
uint64_t j = 0;
for (size_t k = 0; k < kSize; k++) {
if (owner(k) == tid) {
*data(k) = static_cast<char>(round);
j++;
}
}
if (j != slot_count_[tid]) {
std::string err = absl::StrCat(Json("written", j), ", ",
Json("expected", slot_count_[tid]));
return absl::Status(absl::StatusCode::kInternal, err);
}
return absl::OkStatus();
}
// When Silkscreen fails, it often fails, on several bad machines,
// in a surprising way: all slots owned by reading tid are
// are corrupt, in a way that suggests the previous round's
// writes never happened. Weird, and deserves some study, but
// meanwhile the log spew is suppressed by reporting only the last
// error and the error count.
absl::Status Silkscreen::CheckMySlots(int tid, uint64_t round) const {
const char expected = static_cast<char>(round);
uint64_t slots_read = 0;
uint64_t error_count = 0;
std::string last_error;
for (size_t k = 0; k < Silkscreen::kSize; k++) {
if (owner(k) != tid) continue;
slots_read++;
const char v = *data(k);
if (v == expected) continue;
error_count++;
last_error = absl::StrCat(Json("position", k), ", ", Json("is", v), ", ",
Json("expected", expected));
}
if (slot_count(tid) != slots_read) {
last_error = absl::StrCat(Json("read", slots_read), ", ",
Json("expected", slot_count(tid)));
error_count++;
}
if (error_count > 0) {
return absl::Status(
absl::StatusCode::kInternal,
absl::StrCat(last_error, ", ", Json("errors", error_count)));
} else {
return absl::OkStatus();
}
}
} // namespace cpu_check