blob: e9c76b98636d33f250737f7c7fa06f3a233e041d [file] [log] [blame]
#ifndef AOS_REALTIME_H_
#define AOS_REALTIME_H_
#include <sched.h>
#include <ostream>
#include <string_view>
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/strings/str_format.h"
// Stringifies the cpu_set_t for LOG().
template <typename Sink>
void AbslStringify(Sink &sink, const cpu_set_t &cpuset) {
sink.Append("{CPUs ");
bool first_found = false;
for (int i = 0; i < CPU_SETSIZE; ++i) {
if (CPU_ISSET(i, &cpuset)) {
if (first_found) {
sink.Append(", ");
}
absl::Format(&sink, "%d", i);
first_found = true;
}
}
sink.Append("}");
}
namespace aos {
// Locks everything into memory and sets the limits. This plus InitNRT are
// everything you need to do before SetCurrentThreadRealtimePriority will make
// your thread RT. Called as part of ShmEventLoop::Run()
void InitRT();
// Sets up this process to write core dump files.
// This is called by Init*, but it's here for other files that want this
// behavior without calling Init*.
void WriteCoreDumps();
void LockAllMemory();
void ExpandStackSize();
// Sets the name of the current thread.
// This will displayed by `top -H`, dump_rtprio, and show up in logs.
// name can have a maximum of 16 characters.
void SetCurrentThreadName(const std::string_view name);
// Creates a cpu_set_t from a list of CPUs.
inline cpu_set_t MakeCpusetFromCpus(std::initializer_list<int> cpus) {
cpu_set_t result;
CPU_ZERO(&result);
for (int cpu : cpus) {
CPU_SET(cpu, &result);
}
return result;
}
// Returns the affinity representing all the CPUs.
inline cpu_set_t DefaultAffinity() {
cpu_set_t result;
for (int i = 0; i < CPU_SETSIZE; ++i) {
CPU_SET(i, &result);
}
return result;
}
// Returns the current thread's CPU affinity.
cpu_set_t GetCurrentThreadAffinity();
// Sets the current thread's scheduling affinity.
void SetCurrentThreadAffinity(const cpu_set_t &cpuset);
// Everything below here needs AOS to be initialized before it will work
// properly.
// Sets the current thread's realtime priority.
void SetCurrentThreadRealtimePriority(int priority);
// Unsets all threads realtime priority in preparation for exploding.
void FatalUnsetRealtimePriority();
// Sets the current thread back down to non-realtime priority.
void UnsetCurrentThreadRealtimePriority();
// Registers our hooks which crash on RT malloc.
void RegisterMallocHook();
// CHECKs that we are (or are not) running on the RT scheduler. Useful for
// enforcing that operations which are or are not bounded shouldn't be run. This
// works both in simulation and when running against the real target.
void CheckRealtime();
void CheckNotRealtime();
// Marks that we are or are not running on the realtime scheduler. Returns the
// previous state.
//
// Note: this shouldn't be used directly. The event loop primitives should be
// used instead.
bool MarkRealtime(bool realtime);
// Class which restores the current RT state when destructed.
class ScopedRealtimeRestorer {
public:
ScopedRealtimeRestorer();
~ScopedRealtimeRestorer() { MarkRealtime(prior_); }
private:
const bool prior_;
};
// Class which marks us as on the RT scheduler until it goes out of scope.
// Note: this shouldn't be needed for most applications.
class ScopedRealtime {
public:
ScopedRealtime() : prior_(MarkRealtime(true)) {}
~ScopedRealtime() {
CHECK(MarkRealtime(prior_)) << ": Priority was modified";
}
private:
const bool prior_;
};
// Class which marks us as not on the RT scheduler until it goes out of scope.
// Note: this shouldn't be needed for most applications.
class ScopedNotRealtime {
public:
ScopedNotRealtime() : prior_(MarkRealtime(false)) {}
~ScopedNotRealtime() {
CHECK(!MarkRealtime(prior_)) << ": Priority was modified";
}
private:
const bool prior_;
};
} // namespace aos
#endif // AOS_REALTIME_H_