Skip to content

Add support for writing thread-aware device models #269

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

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions RELEASENOTES-1.4.docu
Original file line number Diff line number Diff line change
Expand Up @@ -529,4 +529,9 @@
<build-id _6="next" _7="next"><add-note> Fixed a bug where executed callbacks
posted via immediate after statements would not trigger the device state
change notifier.</add-note></build-id>
<build-id _6="next" _7="next"><add-note> Added the `thread_aware` device
template to provide support for writing thread-aware device models.
For more information, see the Device templates subsection of the
Libraries and Built-ins section of the DML 1.4 Reference
Manual.</add-note></build-id>
</rn>
28 changes: 27 additions & 1 deletion include/simics/dmllib.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <simics/base/conf-object.h>
#include <simics/base/version.h>
#include <simics/util/swabber.h>
#include <simics/base/object-locks.h>
#include <simics/model-iface/bank-instrumentation.h>
#include <simics/simulator/conf-object.h>
#include <simics/util/alloc.h>
Expand Down Expand Up @@ -633,6 +634,22 @@ FOR_ENDIAN_VARIANTS(DEFINE_PRECHANGE);
#undef FOR_ALL_BITSIZES
#undef FOR_ENDIAN_VARIANTS


#define DML_THREAD_AWARE_IFACE_CALL(target_obj, call_expr) (({ \
domain_lock_t *__lock; \
SIM_ACQUIRE_TARGET(target_obj, &__lock); \
__auto_type __iface_ret = call_expr; \
SIM_RELEASE_TARGET(target_obj, &__lock); \
__iface_ret; \
}))

#define DML_THREAD_AWARE_IFACE_CALL_VOID(target_obj, call_expr) (({ \
domain_lock_t *__lock; \
SIM_ACQUIRE_TARGET(target_obj, &__lock); \
call_expr; \
SIM_RELEASE_TARGET(target_obj, &__lock); \
}))

UNUSED static attr_value_t
_serialize_identity(const _id_info_t *id_info_array, const _identity_t id) {
if (unlikely(id.id) == 0) {
Expand Down Expand Up @@ -1293,15 +1310,23 @@ _DML_execute_immediate_afters_now(conf_object_t *dev,
UNUSED static void
_DML_execute_immediate_afters(conf_object_t *dev, lang_void *aux) {
_dml_immediate_after_state_t *state = (_dml_immediate_after_state_t *)aux;
ASSERT(state->posted);
// Only acquire the device if it hasn't been deleted to avoid a
// use-after-free. There's no possibility of a data race on state->deleted
// (nor any other part of the state if state->deleted is true) as the
// device can only be deleted in global context.
if (unlikely(state->deleted)) {
ASSERT(state->posted);
ASSERT(QEMPTY(state->queue));
// No need to call QFREE, already done
MM_FREE(state);
return;
}
domain_lock_t *lock;
SIM_ACQUIRE_OBJECT(dev, &lock);
ASSERT(state->posted);
if (unlikely(QEMPTY(state->queue))) {
state->posted = false;
SIM_RELEASE_OBJECT(dev, &lock);
return;
}
_dml_immediate_after_queue_elem_t elem = QREMOVE(state->queue);
Expand All @@ -1314,6 +1339,7 @@ _DML_execute_immediate_afters(conf_object_t *dev, lang_void *aux) {
}
elem.callback(dev, elem.data.indices, elem.data.args);
_free_simple_event_data(elem.data);
SIM_RELEASE_OBJECT(dev, &lock);
}

UNUSED static void
Expand Down
Loading