Skip to content

Commit 34989f6

Browse files
committed
Add support for writing thread-aware device models
1 parent 8cd3138 commit 34989f6

File tree

10 files changed

+535
-17
lines changed

10 files changed

+535
-17
lines changed

RELEASENOTES-1.4.docu

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,4 +529,9 @@
529529
<build-id _6="next" _7="next"><add-note> Fixed a bug where executed callbacks
530530
posted via immediate after statements would not trigger the device state
531531
change notifier.</add-note></build-id>
532+
<build-id _6="next" _7="next"><add-note> Added the `thread_aware` device
533+
template to provide support for writing thread-aware device models.
534+
For more information, see the Device templates subsection of the
535+
Libraries and Built-ins section of the DML 1.4 Reference
536+
Manual.</add-note></build-id>
532537
</rn>

include/simics/dmllib.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <simics/base/conf-object.h>
1717
#include <simics/base/version.h>
1818
#include <simics/util/swabber.h>
19+
#include <simics/base/object-locks.h>
1920
#include <simics/model-iface/bank-instrumentation.h>
2021
#include <simics/simulator/conf-object.h>
2122
#include <simics/util/alloc.h>
@@ -633,6 +634,22 @@ FOR_ENDIAN_VARIANTS(DEFINE_PRECHANGE);
633634
#undef FOR_ALL_BITSIZES
634635
#undef FOR_ENDIAN_VARIANTS
635636

637+
638+
#define DML_THREAD_AWARE_IFACE_CALL(target_obj, call_expr) (({ \
639+
domain_lock_t *__lock; \
640+
SIM_ACQUIRE_TARGET(target_obj, &__lock); \
641+
__auto_type __iface_ret = call_expr; \
642+
SIM_RELEASE_TARGET(target_obj, &__lock); \
643+
__iface_ret; \
644+
}))
645+
646+
#define DML_THREAD_AWARE_IFACE_CALL_VOID(target_obj, call_expr) (({ \
647+
domain_lock_t *__lock; \
648+
SIM_ACQUIRE_TARGET(target_obj, &__lock); \
649+
call_expr; \
650+
SIM_RELEASE_TARGET(target_obj, &__lock); \
651+
}))
652+
636653
UNUSED static attr_value_t
637654
_serialize_identity(const _id_info_t *id_info_array, const _identity_t id) {
638655
if (unlikely(id.id) == 0) {
@@ -1293,15 +1310,23 @@ _DML_execute_immediate_afters_now(conf_object_t *dev,
12931310
UNUSED static void
12941311
_DML_execute_immediate_afters(conf_object_t *dev, lang_void *aux) {
12951312
_dml_immediate_after_state_t *state = (_dml_immediate_after_state_t *)aux;
1296-
ASSERT(state->posted);
1313+
// Only acquire the device if it hasn't been deleted to avoid a
1314+
// use-after-free. There's no possibility of a data race on state->deleted
1315+
// (nor any other part of the state if state->deleted is true) as the
1316+
// device can only be deleted in global context.
12971317
if (unlikely(state->deleted)) {
1318+
ASSERT(state->posted);
12981319
ASSERT(QEMPTY(state->queue));
12991320
// No need to call QFREE, already done
13001321
MM_FREE(state);
13011322
return;
13021323
}
1324+
domain_lock_t *lock;
1325+
SIM_ACQUIRE_OBJECT(dev, &lock);
1326+
ASSERT(state->posted);
13031327
if (unlikely(QEMPTY(state->queue))) {
13041328
state->posted = false;
1329+
SIM_RELEASE_OBJECT(dev, &lock);
13051330
return;
13061331
}
13071332
_dml_immediate_after_queue_elem_t elem = QREMOVE(state->queue);
@@ -1314,6 +1339,7 @@ _DML_execute_immediate_afters(conf_object_t *dev, lang_void *aux) {
13141339
}
13151340
elem.callback(dev, elem.data.indices, elem.data.args);
13161341
_free_simple_event_data(elem.data);
1342+
SIM_RELEASE_OBJECT(dev, &lock);
13171343
}
13181344

13191345
UNUSED static void

0 commit comments

Comments
 (0)