-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Revisit, assess and extend ETISS Fault Injection #100
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good to merge, just some comments
src/ETISS.cpp
Outdated
if (!faults.empty()) | ||
{ | ||
std::list<std::string> ffs = etiss::split(faults, ';'); | ||
for (auto ff : ffs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default pattern for this should be "const auto&". If you need mutablity, drop const and if you need a copy, drop the reference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed (copied from old code base). Fixed with 3087cae
src/ETISS.cpp
Outdated
} | ||
|
||
etiss::log(etiss::VERBOSE, std::string("Add InstructionAccurateCallback Plugin to ") + cpu_core->getName() + std::string(". Required for etiss::fault::Injector.")); | ||
cpu_core->addPlugin(std::shared_ptr<etiss::Plugin>(new etiss::plugin::InstructionAccurateCallback())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avoid explicit "new" by using "make_shared"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed (copied from example/bare_etiss_processor/main.cpp:L129). Fixed with 5149bc1 - also addresses example/bare_etiss_processor/main.cpp
|
||
std::shared_ptr<VirtualStruct> MemoryManipulationSystem::getStruct(void) | ||
{ | ||
if(!vsystem_) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file and others do not follow our coding style. please use the provided .clang-format configuration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was not aware of clang format style. Used the following before committing changes:
clang-format --style=file --verbose src/fault/Fault.cpp src/fault/Action.cpp include/etiss/fault/Action.h \
include/etiss/fault/Fault.h include/etiss/fault/Trigger.h src/fault/Trigger.cpp src/fault/Stressor.cpp \
include/etiss/fault/Injector.h src/VirtualStruct.cpp include/etiss/VirtualStruct.h src/fault/InjectorAddress.cpp \
include/etiss/fault/InjectorAddress.h include/etiss/fault/Stressor.h src/fault/Injector.cpp -i
split_cmd.push_back(cmd); | ||
if (split_cmd.size() > 1) | ||
{ | ||
std::stringstream ss; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::stoll would make this less verbose and more robust
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would prefer boost::lexical_cast over std::sto*, but either over std::stringstream. Fixed with 459ac53
src/VirtualStruct.cpp
Outdated
find = fieldPrettyNames_.find(field); | ||
if (find == fieldPrettyNames_.end()) | ||
{ | ||
f = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is already set
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hello copy paste my old friend... Fixed with c8f9478
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure if that fix is correct. the line you removed was searching a different list. what i meant is that f is already initialized to null at the start of the function, so this assignment is redundant and the conditional block can be dropped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are right. reversed and fixed with c86cb7f
src/fault/Action.cpp
Outdated
{ | ||
return type_; | ||
} | ||
|
||
const InjectorAddress &Action::getInjectorAddress() const | ||
{ | ||
if(unlikely(!(type_ == Type::BITFLIP || type_ == Type::MASK || type_ == Type::COMMAND))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unless they are measurably important for performance, i'd perfer to avoid the un/likely clutter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed. From old code base, but the getters are not performance critical. Fixed with b6da677
src/fault/Trigger.cpp
Outdated
Trigger::Trigger(const Trigger &sub, uint64_t count) | ||
: type_(META_COUNTER), sub_(new Trigger(sub)), param1_(count), param2_(0) | ||
: type_(Type::META_COUNTER) | ||
, sub_(new Trigger(sub)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be unique_ptr + make_unique
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/fault/Trigger.cpp
Outdated
: type_(Type::META_COUNTER) | ||
, sub_(new Trigger(sub)) | ||
, param1_(count) | ||
, param2_(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there are many uninitialized fields in these constructors. maybe just default initialize them in the class definition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed with 909d74e
include/etiss/fault/Action.h
Outdated
|
||
private: // Attributes | ||
type_t type_; ///< type of the Attribute | ||
std::unique_ptr<InjectorAddress> inj_{ nullptr }; ///< Address of Injector |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for unique_ptr and string the initialization is redundant
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
include/etiss/fault/Misc.h
Outdated
//////////////////////////////////////////////////////////////////////////////////////////////// | ||
/// \brief Action type class | ||
template <typename enum_t> | ||
class SmartType : public etiss::ToString |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems nice, but as implemented a bit weak: you still have to manually set up the table causing code duplication and potential for errors. the error handling is inconsistent between from/toString - one returns bool, the other throws. a lot of code could be constant evaluated. outdated docstrings
i think it makes sense to just use an existing solution for this problem. for example i found this: https://github.com/aantron/better-enums
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I understand these concerns. I had this laying around for when I needed string->enum and enum->string encoding as we need here for all the from and to xml stuff going on in ETISS-FI.
The better-enums
seems perfect, but would need a third party integration of it in ETISS, which I would like to avoid in this PR. I'd even suggest to add a /third_party/
directory to ETISS root to easier integrate such things - either through git submodules or CMake fetch. Otherwise we end up with missing copyright/licenses and pasted source code like we already have here:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed with 5e795d7
include/etiss/fault/Fault.h
Outdated
Fault(int nullid); | ||
Fault(const Fault &cpy); | ||
Fault &operator=(const Fault &cpy); | ||
#if CXX0X_UP_SUPPORTED |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these can be removed, because we now support c++14
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
include/etiss/fault/Injector.h
Outdated
volatile bool has_pending_triggers; | ||
std::list<std::pair<Trigger, int32_t>> pending_triggers; ///> Triggers which were just added | ||
std::list<std::pair<Trigger, int32_t>> unknown_triggers; ///> Triggers to look at in callbacks | ||
volatile bool has_pending_triggers{false}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are these volatile? if thread-safety is intended, this will not work. an atomic would be required
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not know either. I removed them for now fba85d5
src/VirtualStruct.cpp
Outdated
find = fieldPrettyNames_.find(field); | ||
if (find == fieldPrettyNames_.end()) | ||
{ | ||
f = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure if that fix is correct. the line you removed was searching a different list. what i meant is that f is already initialized to null at the start of the function, so this assignment is redundant and the conditional block can be dropped.
switch (type_) | ||
{ | ||
case Type::BITFLIP: | ||
inj_ = std::make_unique<InjectorAddress>(cpy.getInjectorAddress()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is not clear to me why you made inj_ pointers. could they not just be value types so that this copy becomes a trivial "=default"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately not so easily.
For example in Stressor::firedTrigger:
for (std::vector<etiss::fault::Action>::iterator iter = find->second.actions.begin();
iter != find->second.actions.end(); ++iter)
{
...
default: // on field actions
{
if (iter->getInjectorAddress().getInjector())
The inj_
member of Action
is used to decide whether the Action
may run through this Injector or is legal in the first place. The check is whether the member was set. Without major changes to most of the old fault injection stuff, I can not re-use most of it. All this FI code is way older than this open source repository. I do not even know who wrote it initially.
The idea behind this PR was to make the FI usable again, seems to take a lot more work to make the code up to date than the functionality.
The Action
and Trigger
classes both are built similar in that their instances have uninitialized members depending on their respective type_
. Obviously, this could be done much better through different design patterns, but such major changes were not initially the idea behind this PR. If you think such a refactoring process is a must, I can start with it.
src/fault/Fault.cpp
Outdated
|
||
Fault::Fault(int nullid) : id_(nullid) {} | ||
|
||
Fault::Fault(const Fault &cpy) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these copy/move constr/assign are equivalent to the default
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Was not aware of the main CMakeLists.txt already forcing c++14
eff549b
src/fault/Injector.cpp
Outdated
#if CXX0X_UP_SUPPORTED | ||
std::lock_guard<std::mutex> lock(sync); | ||
#endif | ||
for (const auto &rm : remove_triggers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could use erase-remove idiom
auto shouldRemove = [&](auto elem){
return std::find(b.begin(), b.end(), elem) != b.end();
};
a.erase(std::remove_if(a.begin(), a.end(), shouldRemove), a.end());
otherwise the typical pattern uses a while loop and iter=a.erase(iter);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the justifications, but please don't feel obligated to address all of my comments. as i said, this would have been fine to merge on the first iteration. just noted some stuff that caught my eye |
… of VirtualStruct require it being mounted with an instance of CPUCore::getStruct(). Move 'faults.xml' configuration resolve from etiss::initialize to initialize_virtual (requires mounted VirtualStruct). Add 'faults.xml' configuration as command line parameter. Make VirtualStruct::Field::flags_ member a non-const to allow runtime configuration of access type.
…d), but are discarded.
…ger[lock mutex]->Stresser::addFault[lock mutex]
…initialize_virtualstruct call. Add WIP: Fault Injection How-To to examples/bare_etiss_processor/README.md and example `fault.xml` file for better reference.
… action for CPUCore's VirtualStruct
… fault injection flag of a field will be set if a fault for the field is configured through Stressor. Add "MASK" fault as Action. A Mask fault has a mask operation <op> (and, or, xor, nand, nor) and a mask value <value> (64-bit) acting on a <field>: "<field> = <field> <op> <value>"
…om xml). Add event type to <action> types which allows to inject ETISS simulation events (all ETISS::RETURNCODES), e.g., to flush translation cache. Minor fixes in mask type <action>
…instructionAccurateCallback() to trigger on next trigger check. Update Trigger typing code.
…ication of mounted structs. Minor typo fixes.
…actions from fault injection. Extends SimpleMemSystem.
…nique_ptr, add missing copy constructors.
…xplicitly added through a fault's INJECTION action or through the <initial> node in given XML, add EJECTION action that deactivates all triggers of the referenced fault, disable automatic removal of a trigger once it was fired to allow permanent faults - remove triggers (therefore the fault) through EJECTION action of a referenced fault, extend faults.xml example and readme section w.r.t. new features.
b57f159
to
1d6f2d7
Compare
rebase from master
…ple instances insert callback within same codeblock
This PR revisits the existing fault injection functionality in ETISS and extends it.