We added the code to trace all the contins linked to a particular
Lockvoker, into SerializedAsyncContinuation. This basically
ensures that we'll almost never deal with a deadlock. So cool.
We previously passed a sh_ptr to the caller's contin as arguments
to the std::bind() callable. In order for us to be able to trace
deadlocks, we need to be able to access them explicitly.
So here's that change.
We added a timestamp to each Lockvoker so that we can detect when
a lockvoker has been in a qutex for "too long", where "too long"
is defined arbitrarily as 500ms.
Next we're going to change the way we create callbacks to enable
us to more explicitly access the sh_ptr<AsyncContin> via
the callback object.
We now detect that a deadlock is likely when
CONFIG_DEBUG_QUTEX_DEADLOCK_TIMEOUT_MS has elapsed. This is the
preliminary work required to do a backtrace through the call
stack and figure out if a deadlock has really occured.
To do this, we'd have to go through the async call chain and
search for a previous caller which acquired the same qutex as
the one that first failed during this Lockvoker LockSet acquisition
attempt.
CONT_SET_EXC: Set exception on the continuation, to be rethrown
by the caller.
CONT_SET_EXC_AND_RET: Convenience which returns immediately
after setting the exception.
Implements: LockSet, SerializedAsynchronousContinuation,
LockerAndInvoker, LockerAndInvokerBase, Qutex.
Very big leap in functionality here. See qutexes.md for
an explanation of what we've done.
Async: Use new [Non]PostedAsyncCont and callOriginalCb
This new hierarchy of classes gives us a central mechanism for
managing both reply-posting and lockSpec unlocking.
* callOriginalCb: Now uses a modern C++ variadic template design
enabling it to handle both direct calling and std::bind()
re-binding of an arbitrary number of arguments from the caller.
This enables us to mostly eliminate the repeated, bespoke
definitions of callOriginalCb littered throughout the codebase.
We've also propagated these changes throughout the codebase in
this patch.
This class allows us to list a series of spinlocks that are all
acquired and released together. It has simple, primitive detection
for deadlocks and will throw if it detects one.
This makes the initialization sequence much cleaner and conceptually
well encapsulated.
We also now dynamically allocate the Mind objects. They're allocated
dynamically by Mrntt inside of initializeReq. This means that we no
longer have to worry about jolting and cleaning up the running threads
of global mind object even when we never explicitly called
Mind.initializeReq.
Along with other conceptual improvements to our abstractions, this
patch also gets us to a real "end of program initialization" point
for the first time.
This class enables us to consistently represent continuations
that are intended to be posted on a particular target handling
thread. It hols a sh_ptr to the caller so that the target thread
can re-enqueue the response on the caller after processing the
REQ/IND op.
This class encapsulates all the logic and operations required to
correctly bridge an async operation into a sync function.
In particular, it also makes it less easy to forget to check if the
io_service exited because it was stop()ped.
This language is used broadly to specify how to attach (and thus
also how to detach) devices to/from Salmanoff. The next bit of work
we'll do is split off the DSL parsing from the management of the
list of parsed binary attached spec objects.
We'll be creating a PipeDeviceAttachmentParser, and later on when
we support URDF, we'll create a URDFDeviceAttachmentParser.
This patch adds some nicely weighty code for connecting to X displays
and managing those connections. Attaching devices will automatically
connect to their required X display. Removing all devices dependent
on a given X display connection will also disconnect from that
Xdisplay.
We decided to get rid of the C FFI for libs. It was becoming too intricate
and complicated. It was becoming a technical burden and expanding into
too much extra code. It's unfortunate, but we'll have to give up on getting
out-of-tree hot-loadable libraries the easy way.
It's possible to still do it with cross compilation or by keeping track
of the libstdc++ version that the running harikoff binary was compiled
against. Then we can ensure that our loadable lib code is linked against
that same libstdc++ code and this should ensure ABI stability.