Skip to content

Commit

Permalink
pmreorder: share markers from an application through env variable
Browse files Browse the repository at this point in the history
Fixes: pmem#5419
  • Loading branch information
igchor authored and nofuturre committed Aug 12, 2022
1 parent 2752f6a commit 2674edf
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 30 deletions.
29 changes: 25 additions & 4 deletions doc/pmreorder/pmreorder.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ header: "pmreorder version 1.5"
---

[comment]: <> (SPDX-License-Identifier: BSD-3-Clause)
[comment]: <> (Copyright 2018-2021, Intel Corporation)
[comment]: <> (Copyright 2018-2022, Intel Corporation)

[comment]: <> (pmreorder.1 -- man page for pmreorder)

Expand Down Expand Up @@ -43,9 +43,25 @@ a persistent memory checking tool.

Pmreorder performs the store reordering between persistent
memory barriers - a sequence of flush-fence operations.
It uses a consistency checking routine provided in the
command line options to check whether files are in a
consistent state.
It uses a consistency checking routine provided
in the command line options to check whether files are in a consistent state.
To help with this task, pmreorder sets an environmental variable
PMREORDER_MARKERS. Said variable contains a subset of markers
passed from the application, which is visible at the current state
of pmreordering. Individual markers are separated by vertical bar (‘|’).

Example of how PMREORDER_MARKERS variable can be parsed in c++ using regex
based environment variable tokener:

'''
auto env = std::getenv("ENV_PASS");
std::string senv(env ? env : "");
std::regex rgx("(\\w+)(\\||$)");
for( std::sregex_iterator it(senv.begin(),
senv.end(), rgx), it_end; it != it_end; ++it){
std::cout << (*it)[1].str() << std::endl;
}
'''

Considering that logging, replaying and reordering of operations
are very time consuming, it is recommended to use as few stores as
Expand Down Expand Up @@ -381,6 +397,11 @@ To enable API macros logging set environment variable:

+ **PMREORDER_EMIT_LOG**=1

User defined markers passed from an application
are stored in the variable:

+ **PMREORDER_MARKERS**

# EXAMPLE #

```
Expand Down
17 changes: 14 additions & 3 deletions src/tools/pmreorder/opscontext.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright 2018-2021, Intel Corporation
# Copyright 2018-2022, Intel Corporation

from operationfactory import OperationFactory
from binaryoutputhandler import BinaryOutputHandler
Expand Down Expand Up @@ -56,19 +56,30 @@ def extract_operations(self):
:return: list of subclasses of :class:`memoryoperations.BaseOperation`
"""
enumerated_ops = list(enumerate(self._operations))
markers = list(
filter(
lambda e: e[1].endswith(".BEGIN") or e[1].endswith(".END"),
enumerated_ops,
)
)
operation_ids = list(enumerated_ops)

stop_index = start_index = 0

for i, elem in enumerate(self._operations):
for i, elem in enumerated_ops:
if "START" in elem:
start_index = i
elif "STOP" in elem:
stop_index = i

return list(
operations = list(
map(
OperationFactory.create_operation,
self._operations[start_index + 1: stop_index],
repeat(self.markers),
repeat(self.stack_engines),
)
)

return (operations, operation_ids, markers)
3 changes: 2 additions & 1 deletion src/tools/pmreorder/pmreorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ def main():

# init and run the state machine
a = statemachine.StateMachine(statemachine.InitState(context))
if a.run_all(context.extract_operations()) is False:
operations, operation_ids, markers = context.extract_operations()
if a.run_all(operations, operation_ids, markers) is False:
sys.exit(1)


Expand Down
40 changes: 18 additions & 22 deletions src/tools/pmreorder/statemachine.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright 2018-2021, Intel Corporation
# Copyright 2018-2022, Intel Corporation

import memoryoperations as memops
import reorderengines
from reorderexceptions import InconsistentFileException
from reorderexceptions import NotSupportedOperationException
import os


class State:
Expand Down Expand Up @@ -158,7 +159,6 @@ def run(self, in_op):
def substitute_reorder(self, order_ops):
"""
Changes the reordering engine based on the log marker class.
:param order_ops: The reordering marker class.
:type order_ops: subclass of :class:`memoryoperations.ReorderBase`
:return: None
Expand Down Expand Up @@ -232,9 +232,8 @@ def reg_file(self, file_op):
:type file_op: memoryoperations.Register_file
:return: None
"""
self._context.file_handler.add_file(
file_op.name, file_op.address, file_op.size
)
self._context.file_handler.add_file(file_op.name,
file_op.address, file_op.size)

def move_inner_state(self, in_op):
"""
Expand All @@ -249,10 +248,8 @@ def move_inner_state(self, in_op):
"""
if isinstance(in_op, memops.Store) and self._inner_state == "init":
self._inner_state = "dirty"
elif (
isinstance(in_op, memops.FlushBase)
and self._inner_state == "dirty"
):
elif isinstance(in_op, memops.FlushBase) and \
self._inner_state == "dirty":
self._inner_state = "flush"
elif isinstance(in_op, memops.Fence) and self._inner_state == "flush":
self._inner_state = "fence"
Expand Down Expand Up @@ -308,23 +305,18 @@ def run(self, in_op):
flushed_stores = list(filter(lambda x: x.flushed, self._ops_list))

# not-flushed stores should be passed to next state
State.trans_stores = list(
filter(lambda x: x.flushed is False, self._ops_list)
)
State.trans_stores = list(filter(lambda x: x.flushed is False,
self._ops_list))

if self._context.test_on_barrier:
self._context.logger.debug(
"Current reorder engine: {}".format(
self._context.reorder_engine
)
)
self._context.logger.debug("Current reorder engine: {}"
.format(self._context.reorder_engine))
for i, seq in enumerate(
self._context.reorder_engine.generate_sequence(flushed_stores)
):
self._context.logger.debug(
"NEXT Sequence (no. {0}) with length: {1}".format(
i, len(seq)
)
"NEXT Sequence (no. {0}) with length: \
{1}".format(i, len(seq))
)
for j, op in enumerate(seq):
self._context.logger.debug(
Expand Down Expand Up @@ -371,7 +363,7 @@ def __init__(self, init_state):
"""
self._curr_state = init_state

def run_all(self, operations):
def run_all(self, operations, operation_ids, markers):
"""
Starts the state machine.
Expand All @@ -381,8 +373,12 @@ def run_all(self, operations):
:return: None
"""
all_consistent = True
for ops in operations:
for ops, ops_id in zip(operations, operation_ids):
self._curr_state._context.logger.info(ops)
markers_to_pass = (m[1] for m in markers if m[0] < ops_id[0])
markers_to_pass = "|".join(markers_to_pass)
self._curr_state._context.logger.info(markers_to_pass)
os.environ["PMREORDER_MARKERS"] = markers_to_pass
self._curr_state = self._curr_state.next(ops)
check = self._curr_state.run(ops)
if check is False:
Expand Down

0 comments on commit 2674edf

Please sign in to comment.