/*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
FOLLY_TLS sem_t* DeterministicSchedule::tls_sem;
FOLLY_TLS DeterministicSchedule* DeterministicSchedule::tls_sched;
FOLLY_TLS unsigned DeterministicSchedule::tls_threadId;
+thread_local AuxAct DeterministicSchedule::tls_aux_act;
+AuxChk DeterministicSchedule::aux_chk;
// access is protected by futexLock
static std::unordered_map<detail::Futex<DeterministicAtomic>*,
DeterministicSchedule::DeterministicSchedule(
const std::function<int(int)>& scheduler)
- : scheduler_(scheduler), nextThreadId_(1) {
+ : scheduler_(scheduler), nextThreadId_(1), step_(0) {
assert(tls_sem == nullptr);
assert(tls_sched == nullptr);
+ assert(tls_aux_act == nullptr);
tls_sem = new sem_t;
sem_init(tls_sem, 0, 1);
if (!sched) {
return;
}
+ sem_post(sched->sems_[sched->scheduler_(sched->sems_.size())]);
+}
+void DeterministicSchedule::afterSharedAccess(bool success) {
+ auto sched = tls_sched;
+ if (!sched) {
+ return;
+ }
+ sched->callAux(success);
sem_post(sched->sems_[sched->scheduler_(sched->sems_.size())]);
}
return 0;
}
+void DeterministicSchedule::setAuxAct(AuxAct& aux) {
+ tls_aux_act = aux;
+}
+
+void DeterministicSchedule::setAuxChk(AuxChk& aux) {
+ aux_chk = aux;
+}
+
+void DeterministicSchedule::clearAuxChk() {
+ aux_chk = nullptr;
+}
+
sem_t* DeterministicSchedule::beforeThreadCreate() {
sem_t* s = new sem_t;
sem_init(s, 0, 0);
delete tls_sem;
tls_sem = nullptr;
tls_sched = nullptr;
+ tls_aux_act = nullptr;
}
void DeterministicSchedule::join(std::thread& child) {
child.join();
}
+void DeterministicSchedule::callAux(bool success) {
+ ++step_;
+ if (tls_aux_act) {
+ tls_aux_act(success);
+ tls_aux_act = nullptr;
+ }
+ if (aux_chk) {
+ aux_chk(step_);
+ }
+}
+
void DeterministicSchedule::post(sem_t* sem) {
beforeSharedAccess();
sem_post(sem);
<< ", .., " << std::hex << waitMask
<< ") beginning..");
futexLock.lock();
- if (data == expected) {
+ if (this->data == expected) {
auto& queue = futexQueues[this];
queue.emplace_back(waitMask, &awoken);
auto ours = queue.end();