Skip to content

Commit

Permalink
DeadlineManager: perform better under load
Browse files Browse the repository at this point in the history
Make sure queue_lock is not held indefinitely by the DeadlineManager's thread.
Subsequent notifications should be at least kResolution apart.

PiperOrigin-RevId: 705499170
Change-Id: Id0ec8cf8d32d1a74168ccc53afc87a2e62bce166
  • Loading branch information
happyCoder92 authored and copybara-github committed Dec 12, 2024
1 parent cd03f6e commit afe4c62
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 16 deletions.
51 changes: 36 additions & 15 deletions sandboxed_api/sandbox2/util/deadline_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@

#include <sys/syscall.h>

#include <algorithm>
#include <csignal>
#include <memory>
#include <vector>

#include "absl/base/call_once.h"
#include "absl/flags/flag.h"
Expand Down Expand Up @@ -137,27 +139,46 @@ void DeadlineManager::Run() {
return (!queue_.empty() && next_deadline != (*queue_.begin())->deadline) ||
cancelled_;
};
absl::MutexLock lock(&queue_mutex_);
while (!cancelled_) {
next_deadline = absl::InfiniteFuture();
if (!queue_.empty()) {
next_deadline = (*queue_.begin())->deadline;
}
if (queue_mutex_.AwaitWithDeadline(
absl::Condition(&next_deadline_changed_or_cancelled),
next_deadline)) {
continue;
for (;;) {
std::vector<DeadlineRegistration::Data*> to_be_notified;
{
absl::MutexLock lock(&queue_mutex_);
if (cancelled_) {
break;
}
next_deadline = absl::InfiniteFuture();
if (!queue_.empty()) {
next_deadline = (*queue_.begin())->deadline;
}
if (queue_mutex_.AwaitWithDeadline(
absl::Condition(&next_deadline_changed_or_cancelled),
next_deadline)) {
continue;
}
absl::Time current = std::max(absl::Now(), next_deadline);
while (!queue_.empty() && (*queue_.begin())->deadline <= current) {
to_be_notified.push_back(*queue_.begin());
queue_.erase(queue_.begin());
}
}
absl::Time next_notification_time = RoundUpTo(absl::Now(), kResolution);
while (!queue_.empty() && (*queue_.begin())->deadline <= next_deadline) {
DeadlineRegistration::Data* entry = *queue_.begin();
queue_.erase(queue_.begin());
std::vector<DeadlineRegistration::Data*> to_reinsert;
absl::Time next_notification_time =
RoundUpTo(absl::Now() + kResolution, kResolution);
for (DeadlineRegistration::Data* entry : to_be_notified) {
absl::MutexLock lock(&entry->mutex);
entry->expired = true;
if (entry->in_blocking_fn) {
util::Syscall(__NR_tgkill, getpid(), entry->tid, signal_nr_);
entry->deadline = next_notification_time;
queue_.insert(entry);
to_reinsert.push_back(entry);
}
}
{
absl::MutexLock lock(&queue_mutex_);
for (DeadlineRegistration::Data* entry : to_reinsert) {
if (entry->deadline != absl::InfiniteFuture()) {
queue_.insert(entry);
}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion sandboxed_api/sandbox2/util/deadline_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ class DeadlineRegistration {

struct Data {
absl::Mutex mutex;
// Changed only under both DeadlineManager::queue_mutex_ and Data::mutex.
// Adjusted under both DeadlineManager::queue_mutex_ and Data::mutex.
// DeadlineManager thread reads it holding just queue_mutex_ and writes
// holding just Data::mutex.
absl::Time deadline = absl::InfiniteFuture();
pid_t ABSL_GUARDED_BY(mutex) tid = -1;
bool ABSL_GUARDED_BY(mutex) in_blocking_fn = false;
Expand Down

0 comments on commit afe4c62

Please sign in to comment.