Skip to content

Commit e11cc94

Browse files
committed
Encode the DOWN ref shape in the monitor type
Storing a RefData (ref ticks plus owner pid) in every local monitor grew each MonitorLocalMonitor, MonitorLocalRegisteredNameMonitor and MonitorAlias by 8 bytes (uint64_t alignment), paid by every plain monitor/2, that is by every gen_server:call, on the embedded targets. The pid was redundant everywhere: on the monitored side it duplicates monitor_obj, the monitoring process, which is exactly the alias owner; on the monitoring, registered name and alias entries it was never read. Keep a plain uint64_t ref_ticks in the monitor structs, their baseline layout, and carry the only new bit of information, that the 'DOWN' reference must be rebuilt alias shaped, as a monitor type: CONTEXT_MONITOR_MONITORED_LOCAL_ALIAS. The 'DOWN' path derives the process reference pid from monitor_obj. monitor_new now takes the monitor type directly, replacing the is_monitoring bool as well. RefData stays as the NIF local value type used to build result references (term_from_ref_data) in monitor/3, spawn_opt and alias/1. Behavior is unchanged and pinned by the existing tests: test_monitor_down_alias asserts the 'DOWN' carries the very alias reference, and process_info(monitored_by) keeps listing alias shaped monitors. Signed-off-by: Davide Bettio <davide@uninstall.it>
1 parent 236fa99 commit e11cc94

3 files changed

Lines changed: 74 additions & 56 deletions

File tree

src/libAtomVM/context.c

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ void context_destroy(Context *ctx)
279279
}
280280
case CONTEXT_MONITOR_LINK_LOCAL:
281281
case CONTEXT_MONITOR_MONITORED_LOCAL:
282+
case CONTEXT_MONITOR_MONITORED_LOCAL_ALIAS:
282283
case CONTEXT_MONITOR_MONITORING_LOCAL:
283284
case CONTEXT_MONITOR_MONITORING_LOCAL_REGISTEREDNAME:
284285
case CONTEXT_MONITOR_ALIAS:
@@ -445,7 +446,7 @@ void context_process_monitor_down_signal(Context *ctx, struct TermSignal *signal
445446
struct Monitor *monitor = GET_LIST_ENTRY(item, struct Monitor, monitor_list_head);
446447
if (monitor->monitor_type == CONTEXT_MONITOR_MONITORING_LOCAL) {
447448
struct MonitorLocalMonitor *monitoring_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
448-
if (monitoring_monitor->monitor_obj == monitor_obj && monitoring_monitor->ref_data.ref_ticks == ref_ticks) {
449+
if (monitoring_monitor->monitor_obj == monitor_obj && monitoring_monitor->ref_ticks == ref_ticks) {
449450
// Remove link
450451
list_remove(&monitor->monitor_list_head);
451452
free(monitoring_monitor);
@@ -464,7 +465,7 @@ void context_process_monitor_down_signal(Context *ctx, struct TermSignal *signal
464465
} else if (monitor->monitor_type == CONTEXT_MONITOR_MONITORING_LOCAL_REGISTEREDNAME) {
465466
int32_t monitor_process_id = term_to_local_process_id(monitor_obj);
466467
struct MonitorLocalRegisteredNameMonitor *monitoring_monitor = CONTAINER_OF(monitor, struct MonitorLocalRegisteredNameMonitor, monitor);
467-
if (monitoring_monitor->monitor_process_id == monitor_process_id && monitoring_monitor->ref_data.ref_ticks == ref_ticks) {
468+
if (monitoring_monitor->monitor_process_id == monitor_process_id && monitoring_monitor->ref_ticks == ref_ticks) {
468469
// Remove link
469470
list_remove(&monitor->monitor_list_head);
470471

@@ -619,7 +620,8 @@ bool context_get_process_info(Context *ctx, term *out, size_t *term_size, term a
619620
ret_size = TUPLE_SIZE(2);
620621
LIST_FOR_EACH (item, &ctx->monitors_head) {
621622
struct Monitor *monitor = GET_LIST_ENTRY(item, struct Monitor, monitor_list_head);
622-
if (monitor->monitor_type == CONTEXT_MONITOR_MONITORED_LOCAL) {
623+
if (monitor->monitor_type == CONTEXT_MONITOR_MONITORED_LOCAL
624+
|| monitor->monitor_type == CONTEXT_MONITOR_MONITORED_LOCAL_ALIAS) {
623625
ret_size += CONS_SIZE;
624626
} else if (monitor->monitor_type == CONTEXT_MONITOR_RESOURCE) {
625627
ret_size += CONS_SIZE + TERM_BOXED_REFERENCE_RESOURCE_SIZE;
@@ -728,7 +730,8 @@ bool context_get_process_info(Context *ctx, term *out, size_t *term_size, term a
728730
struct ListHead *item;
729731
LIST_FOR_EACH (item, &ctx->monitors_head) {
730732
struct Monitor *monitor = GET_LIST_ENTRY(item, struct Monitor, monitor_list_head);
731-
if (monitor->monitor_type == CONTEXT_MONITOR_MONITORED_LOCAL) {
733+
if (monitor->monitor_type == CONTEXT_MONITOR_MONITORED_LOCAL
734+
|| monitor->monitor_type == CONTEXT_MONITOR_MONITORED_LOCAL_ALIAS) {
732735
struct MonitorLocalMonitor *monitored_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
733736
list = term_list_prepend(monitored_monitor->monitor_obj, list, heap);
734737
} else if (monitor->monitor_type == CONTEXT_MONITOR_RESOURCE) {
@@ -786,7 +789,7 @@ static struct Monitor *context_monitors_handle_terminate(Context *ctx)
786789
Context *target = globalcontext_get_process_nolock(glb, local_process_id);
787790
if (LIKELY(target != NULL)) {
788791
// target can be null if we didn't process a MonitorDownSignal
789-
mailbox_send_ref_signal(target, DemonitorSignal, monitoring_monitor->ref_data.ref_ticks);
792+
mailbox_send_ref_signal(target, DemonitorSignal, monitoring_monitor->ref_ticks);
790793
}
791794
free(monitoring_monitor);
792795
break;
@@ -798,7 +801,7 @@ static struct Monitor *context_monitors_handle_terminate(Context *ctx)
798801
Context *target = globalcontext_get_process_nolock(glb, local_process_id);
799802
if (LIKELY(target != NULL)) {
800803
// target can be null if we didn't process a MonitorDownSignal
801-
mailbox_send_ref_signal(target, DemonitorSignal, monitoring_monitor->ref_data.ref_ticks);
804+
mailbox_send_ref_signal(target, DemonitorSignal, monitoring_monitor->ref_ticks);
802805
}
803806
free(monitoring_monitor);
804807
break;
@@ -840,13 +843,14 @@ static struct Monitor *context_monitors_handle_terminate(Context *ctx)
840843
}
841844
break;
842845
}
843-
case CONTEXT_MONITOR_MONITORED_LOCAL: {
846+
case CONTEXT_MONITOR_MONITORED_LOCAL:
847+
case CONTEXT_MONITOR_MONITORED_LOCAL_ALIAS: {
844848
struct MonitorLocalMonitor *monitored_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
845849
int32_t local_process_id = term_to_local_process_id(monitored_monitor->monitor_obj);
846850
Context *target = globalcontext_get_process_nolock(glb, local_process_id);
847851
// Target cannot be NULL as we processed Demonitor signals
848852
assert(target != NULL);
849-
bool is_monitored_alias = monitored_monitor->ref_data.process_id != INVALID_PROCESS_ID;
853+
bool is_monitored_alias = monitor->monitor_type == CONTEXT_MONITOR_MONITORED_LOCAL_ALIAS;
850854
int ref_size = is_monitored_alias ? TERM_BOXED_REFERENCE_PROCESS_SIZE : TERM_BOXED_REFERENCE_SHORT_SIZE;
851855
int required_terms = ref_size + TUPLE_SIZE(5);
852856
if (UNLIKELY(memory_ensure_free(ctx, required_terms) != MEMORY_GC_OK)) {
@@ -856,7 +860,12 @@ static struct Monitor *context_monitors_handle_terminate(Context *ctx)
856860
AVM_ABORT();
857861
}
858862
// Prepare the message on ctx's heap, which is freed afterwards.
859-
term ref = term_from_ref_data(&monitored_monitor->ref_data, &ctx->heap);
863+
term ref;
864+
if (is_monitored_alias) {
865+
ref = term_make_process_reference(local_process_id, monitored_monitor->ref_ticks, &ctx->heap);
866+
} else {
867+
ref = term_from_ref_ticks(monitored_monitor->ref_ticks, &ctx->heap);
868+
}
860869

861870
term port_or_process = term_pid_or_port_from_context(ctx);
862871
term port_or_process_atom
@@ -920,24 +929,23 @@ struct Monitor *monitor_link_new(term link_pid)
920929
}
921930
}
922931

923-
struct Monitor *monitor_new(term monitor_pid, const RefData *ref_data, bool is_monitoring)
932+
struct Monitor *monitor_new(term monitor_pid, uint64_t ref_ticks, enum ContextMonitorType monitor_type)
924933
{
934+
assert(monitor_type == CONTEXT_MONITOR_MONITORING_LOCAL
935+
|| monitor_type == CONTEXT_MONITOR_MONITORED_LOCAL
936+
|| monitor_type == CONTEXT_MONITOR_MONITORED_LOCAL_ALIAS);
925937
struct MonitorLocalMonitor *monitor = malloc(sizeof(struct MonitorLocalMonitor));
926938
if (IS_NULL_PTR(monitor)) {
927939
return NULL;
928940
}
929-
if (is_monitoring) {
930-
monitor->monitor.monitor_type = CONTEXT_MONITOR_MONITORING_LOCAL;
931-
} else {
932-
monitor->monitor.monitor_type = CONTEXT_MONITOR_MONITORED_LOCAL;
933-
}
941+
monitor->monitor.monitor_type = monitor_type;
934942
monitor->monitor_obj = monitor_pid;
935-
monitor->ref_data = *ref_data;
943+
monitor->ref_ticks = ref_ticks;
936944

937945
return &monitor->monitor;
938946
}
939947

940-
struct Monitor *monitor_registeredname_monitor_new(int32_t monitor_process_id, term monitor_name, const RefData *ref_data)
948+
struct Monitor *monitor_registeredname_monitor_new(int32_t monitor_process_id, term monitor_name, uint64_t ref_ticks)
941949
{
942950
struct MonitorLocalRegisteredNameMonitor *monitor = malloc(sizeof(struct MonitorLocalRegisteredNameMonitor));
943951
if (IS_NULL_PTR(monitor)) {
@@ -946,19 +954,19 @@ struct Monitor *monitor_registeredname_monitor_new(int32_t monitor_process_id, t
946954
monitor->monitor.monitor_type = CONTEXT_MONITOR_MONITORING_LOCAL_REGISTEREDNAME;
947955
monitor->monitor_process_id = monitor_process_id;
948956
monitor->monitor_name = monitor_name;
949-
monitor->ref_data = *ref_data;
957+
monitor->ref_ticks = ref_ticks;
950958

951959
return &monitor->monitor;
952960
}
953961

954-
struct Monitor *monitor_alias_new(const RefData *ref_data, context_monitor_alias_type_t alias_type)
962+
struct Monitor *monitor_alias_new(uint64_t ref_ticks, context_monitor_alias_type_t alias_type)
955963
{
956964
struct MonitorAlias *monitor = malloc(sizeof(struct MonitorAlias));
957965
if (IS_NULL_PTR(monitor)) {
958966
return NULL;
959967
}
960968
monitor->monitor.monitor_type = CONTEXT_MONITOR_ALIAS;
961-
monitor->ref_data = *ref_data;
969+
monitor->ref_ticks = ref_ticks;
962970
monitor->alias_type = alias_type;
963971

964972
return &monitor->monitor;
@@ -993,6 +1001,7 @@ void monitor_destroy(struct Monitor *monitor)
9931001
break;
9941002
case CONTEXT_MONITOR_MONITORING_LOCAL:
9951003
case CONTEXT_MONITOR_MONITORED_LOCAL:
1004+
case CONTEXT_MONITOR_MONITORED_LOCAL_ALIAS:
9961005
free(CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor));
9971006
break;
9981007
case CONTEXT_MONITOR_MONITORING_LOCAL_REGISTEREDNAME:
@@ -1024,10 +1033,11 @@ bool context_add_monitor(Context *ctx, struct Monitor *new_monitor)
10241033
break;
10251034
}
10261035
case CONTEXT_MONITOR_MONITORING_LOCAL:
1027-
case CONTEXT_MONITOR_MONITORED_LOCAL: {
1036+
case CONTEXT_MONITOR_MONITORED_LOCAL:
1037+
case CONTEXT_MONITOR_MONITORED_LOCAL_ALIAS: {
10281038
struct MonitorLocalMonitor *new_local_monitor = CONTAINER_OF(new_monitor, struct MonitorLocalMonitor, monitor);
10291039
struct MonitorLocalMonitor *existing_local_monitor = CONTAINER_OF(existing, struct MonitorLocalMonitor, monitor);
1030-
if (UNLIKELY(existing_local_monitor->monitor_obj == new_local_monitor->monitor_obj && existing_local_monitor->ref_data.ref_ticks == new_local_monitor->ref_data.ref_ticks)) {
1040+
if (UNLIKELY(existing_local_monitor->monitor_obj == new_local_monitor->monitor_obj && existing_local_monitor->ref_ticks == new_local_monitor->ref_ticks)) {
10311041
free(new_local_monitor);
10321042
return false;
10331043
}
@@ -1038,7 +1048,7 @@ bool context_add_monitor(Context *ctx, struct Monitor *new_monitor)
10381048
struct MonitorLocalRegisteredNameMonitor *existing_local_registeredname_monitor = CONTAINER_OF(existing, struct MonitorLocalRegisteredNameMonitor, monitor);
10391049
if (UNLIKELY(existing_local_registeredname_monitor->monitor_process_id == new_local_registeredname_monitor->monitor_process_id
10401050
&& existing_local_registeredname_monitor->monitor_name == new_local_registeredname_monitor->monitor_name
1041-
&& existing_local_registeredname_monitor->ref_data.ref_ticks == new_local_registeredname_monitor->ref_data.ref_ticks)) {
1051+
&& existing_local_registeredname_monitor->ref_ticks == new_local_registeredname_monitor->ref_ticks)) {
10421052
free(new_local_registeredname_monitor);
10431053
return false;
10441054
}
@@ -1048,7 +1058,7 @@ bool context_add_monitor(Context *ctx, struct Monitor *new_monitor)
10481058
struct MonitorAlias *new_alias_monitor = CONTAINER_OF(new_monitor, struct MonitorAlias, monitor);
10491059
struct MonitorAlias *existing_alias_monitor = CONTAINER_OF(existing, struct MonitorAlias, monitor);
10501060

1051-
if (UNLIKELY(existing_alias_monitor->alias_type == new_alias_monitor->alias_type && existing_alias_monitor->ref_data.ref_ticks == new_alias_monitor->ref_data.ref_ticks)) {
1061+
if (UNLIKELY(existing_alias_monitor->alias_type == new_alias_monitor->alias_type && existing_alias_monitor->ref_ticks == new_alias_monitor->ref_ticks)) {
10521062
free(new_alias_monitor);
10531063
return false;
10541064
}
@@ -1202,9 +1212,10 @@ void context_demonitor(Context *ctx, uint64_t ref_ticks)
12021212
struct Monitor *monitor = GET_LIST_ENTRY(item, struct Monitor, monitor_list_head);
12031213
switch (monitor->monitor_type) {
12041214
case CONTEXT_MONITOR_MONITORING_LOCAL:
1205-
case CONTEXT_MONITOR_MONITORED_LOCAL: {
1215+
case CONTEXT_MONITOR_MONITORED_LOCAL:
1216+
case CONTEXT_MONITOR_MONITORED_LOCAL_ALIAS: {
12061217
struct MonitorLocalMonitor *local_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
1207-
if (local_monitor->ref_data.ref_ticks == ref_ticks) {
1218+
if (local_monitor->ref_ticks == ref_ticks) {
12081219
list_remove(&monitor->monitor_list_head);
12091220
free(local_monitor);
12101221
return;
@@ -1213,7 +1224,7 @@ void context_demonitor(Context *ctx, uint64_t ref_ticks)
12131224
}
12141225
case CONTEXT_MONITOR_MONITORING_LOCAL_REGISTEREDNAME: {
12151226
struct MonitorLocalRegisteredNameMonitor *local_registeredname_monitor = CONTAINER_OF(monitor, struct MonitorLocalRegisteredNameMonitor, monitor);
1216-
if (local_registeredname_monitor->ref_data.ref_ticks == ref_ticks) {
1227+
if (local_registeredname_monitor->ref_ticks == ref_ticks) {
12171228
list_remove(&monitor->monitor_list_head);
12181229
free(local_registeredname_monitor);
12191230
return;
@@ -1249,7 +1260,7 @@ struct MonitorAlias *context_find_alias(Context *ctx, uint64_t ref_ticks)
12491260
struct Monitor *monitor = GET_LIST_ENTRY(item, struct Monitor, monitor_list_head);
12501261
if (monitor->monitor_type == CONTEXT_MONITOR_ALIAS) {
12511262
struct MonitorAlias *alias_monitor = CONTAINER_OF(monitor, struct MonitorAlias, monitor);
1252-
if (alias_monitor->ref_data.ref_ticks == ref_ticks) {
1263+
if (alias_monitor->ref_ticks == ref_ticks) {
12531264
return alias_monitor;
12541265
}
12551266
}
@@ -1280,17 +1291,18 @@ term context_get_monitor_pid(Context *ctx, uint64_t ref_ticks, bool *is_monitori
12801291
struct Monitor *monitor = GET_LIST_ENTRY(item, struct Monitor, monitor_list_head);
12811292
switch (monitor->monitor_type) {
12821293
case CONTEXT_MONITOR_MONITORING_LOCAL:
1283-
case CONTEXT_MONITOR_MONITORED_LOCAL: {
1294+
case CONTEXT_MONITOR_MONITORED_LOCAL:
1295+
case CONTEXT_MONITOR_MONITORED_LOCAL_ALIAS: {
12841296
struct MonitorLocalMonitor *local_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
1285-
if (local_monitor->ref_data.ref_ticks == ref_ticks) {
1297+
if (local_monitor->ref_ticks == ref_ticks) {
12861298
*is_monitoring = monitor->monitor_type == CONTEXT_MONITOR_MONITORING_LOCAL;
12871299
return local_monitor->monitor_obj;
12881300
}
12891301
break;
12901302
}
12911303
case CONTEXT_MONITOR_MONITORING_LOCAL_REGISTEREDNAME: {
12921304
struct MonitorLocalRegisteredNameMonitor *local_registeredname_monitor = CONTAINER_OF(monitor, struct MonitorLocalRegisteredNameMonitor, monitor);
1293-
if (local_registeredname_monitor->ref_data.ref_ticks == ref_ticks) {
1305+
if (local_registeredname_monitor->ref_ticks == ref_ticks) {
12941306
*is_monitoring = true;
12951307
return term_from_local_process_id(local_registeredname_monitor->monitor_process_id);
12961308
}
@@ -1426,21 +1438,22 @@ COLD_FUNC void context_dump(Context *ctx)
14261438
struct MonitorLocalMonitor *monitoring_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
14271439
fprintf(stderr, "monitor to ");
14281440
term_display(stderr, monitoring_monitor->monitor_obj, ctx);
1429-
fprintf(stderr, " ref=%lu", (long unsigned) monitoring_monitor->ref_data.ref_ticks);
1441+
fprintf(stderr, " ref=%lu", (long unsigned) monitoring_monitor->ref_ticks);
14301442
fprintf(stderr, "\n");
14311443
break;
14321444
}
14331445
case CONTEXT_MONITOR_ALIAS: {
14341446
struct MonitorAlias *monitor_alias = CONTAINER_OF(monitor, struct MonitorAlias, monitor);
1435-
fprintf(stderr, "has alias ref=%lu", (long unsigned) monitor_alias->ref_data.ref_ticks);
1447+
fprintf(stderr, "has alias ref=%lu", (long unsigned) monitor_alias->ref_ticks);
14361448
fprintf(stderr, "\n");
14371449
break;
14381450
}
1439-
case CONTEXT_MONITOR_MONITORED_LOCAL: {
1451+
case CONTEXT_MONITOR_MONITORED_LOCAL:
1452+
case CONTEXT_MONITOR_MONITORED_LOCAL_ALIAS: {
14401453
struct MonitorLocalMonitor *monitored_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
14411454
fprintf(stderr, "monitored by ");
14421455
term_display(stderr, monitored_monitor->monitor_obj, ctx);
1443-
fprintf(stderr, " ref=%lu", (long unsigned) monitored_monitor->ref_data.ref_ticks);
1456+
fprintf(stderr, " ref=%lu", (long unsigned) monitored_monitor->ref_ticks);
14441457
fprintf(stderr, "\n");
14451458
break;
14461459
}
@@ -1450,7 +1463,7 @@ COLD_FUNC void context_dump(Context *ctx)
14501463
term_display(stderr, local_registeredname_monitor->monitor_name, ctx);
14511464
fprintf(stderr, " (");
14521465
term_display(stderr, term_from_local_process_id(local_registeredname_monitor->monitor_process_id), ctx);
1453-
fprintf(stderr, ") ref=%lu", (long unsigned) local_registeredname_monitor->ref_data.ref_ticks);
1466+
fprintf(stderr, ") ref=%lu", (long unsigned) local_registeredname_monitor->ref_ticks);
14541467
fprintf(stderr, "\n");
14551468
break;
14561469
}

0 commit comments

Comments
 (0)