Skip to content

Commit f30b1f3

Browse files
committed
Process aliases
Signed-off-by: Mateusz Front <[email protected]>
1 parent 02d955b commit f30b1f3

File tree

12 files changed

+358
-7
lines changed

12 files changed

+358
-7
lines changed

libs/estdlib/src/erlang.erl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
make_ref/0,
100100
send/2,
101101
monitor/2,
102+
monitor/3,
102103
demonitor/1,
103104
demonitor/2,
104105
exit/1,
@@ -133,7 +134,9 @@
133134
dist_ctrl_put_data/2,
134135
unique_integer/0,
135136
unique_integer/1,
136-
raise/3
137+
raise/3,
138+
alias/0,
139+
unalias/1
137140
]).
138141

139142
-export_type([
@@ -1167,6 +1170,9 @@ send(_Target, _Message) ->
11671170
monitor(_Type, _PidOrPort) ->
11681171
erlang:nif_error(undefined).
11691172

1173+
monitor(_Type, _PidOrPort, _Options) ->
1174+
erlang:nif_error(undefined).
1175+
11701176
%%-----------------------------------------------------------------------------
11711177
%% @param Monitor reference of monitor to remove
11721178
%% @returns `true'
@@ -1578,3 +1584,9 @@ nif_error(_Reason) ->
15781584
no_return().
15791585
raise(_Class, _Reason, _Stacktrace) ->
15801586
erlang:nif_error(undefined).
1587+
1588+
alias() ->
1589+
erlang:nif_error(undefined).
1590+
1591+
unalias(_Alias) ->
1592+
erlang:nif_error(undefined).

src/libAtomVM/context.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ void context_destroy(Context *ctx)
260260
case CONTEXT_MONITOR_MONITORED_LOCAL:
261261
case CONTEXT_MONITOR_MONITORING_LOCAL:
262262
case CONTEXT_MONITOR_MONITORING_LOCAL_REGISTEREDNAME:
263+
case CONTEXT_MONITOR_ALIAS:
263264
UNREACHABLE();
264265
}
265266
}
@@ -799,6 +800,9 @@ static struct Monitor *context_monitors_handle_terminate(Context *ctx)
799800
free(monitor);
800801
break;
801802
}
803+
case CONTEXT_MONITOR_ALIAS: {
804+
free(monitor);
805+
}
802806
}
803807
}
804808
return result;
@@ -869,6 +873,19 @@ struct Monitor *monitor_registeredname_monitor_new(int32_t monitor_process_id, t
869873
return &monitor->monitor;
870874
}
871875

876+
struct Monitor *monitor_alias_new(uint64_t ref_ticks, enum ContextMonitorAliasType alias_type)
877+
{
878+
struct MonitorAlias *monitor = malloc(sizeof(struct MonitorAlias));
879+
if (IS_NULL_PTR(monitor)) {
880+
return NULL;
881+
}
882+
monitor->monitor.monitor_type = CONTEXT_MONITOR_ALIAS;
883+
monitor->ref_ticks = ref_ticks;
884+
monitor->alias_type = alias_type;
885+
886+
return &monitor->monitor;
887+
}
888+
872889
struct Monitor *monitor_resource_monitor_new(void *resource, uint64_t ref_ticks)
873890
{
874891
struct ResourceContextMonitor *monitor = malloc(sizeof(struct ResourceContextMonitor));
@@ -920,6 +937,16 @@ bool context_add_monitor(Context *ctx, struct Monitor *new_monitor)
920937
}
921938
break;
922939
}
940+
case CONTEXT_MONITOR_ALIAS: {
941+
struct MonitorAlias *new_alias_monitor = CONTAINER_OF(new_monitor, struct MonitorAlias, monitor);
942+
struct MonitorAlias *existing_alias_monitor = CONTAINER_OF(existing, struct MonitorAlias, monitor);
943+
944+
if (UNLIKELY(existing_alias_monitor->alias_type == new_alias_monitor->alias_type && existing_alias_monitor->ref_ticks == new_alias_monitor->ref_ticks)) {
945+
free(new_monitor);
946+
return false;
947+
}
948+
break;
949+
}
923950
case CONTEXT_MONITOR_RESOURCE: {
924951
struct ResourceContextMonitor *new_resource_monitor = CONTAINER_OF(new_monitor, struct ResourceContextMonitor, monitor);
925952
struct ResourceContextMonitor *existing_resource_monitor = CONTAINER_OF(existing, struct ResourceContextMonitor, monitor);
@@ -1053,6 +1080,8 @@ void context_unlink_ack(Context *ctx, term link_pid, uint64_t unlink_id)
10531080

10541081
void context_demonitor(Context *ctx, uint64_t ref_ticks)
10551082
{
1083+
context_unalias(ctx, ref_ticks, true);
1084+
10561085
struct ListHead *item;
10571086
LIST_FOR_EACH (item, &ctx->monitors_head) {
10581087
struct Monitor *monitor = GET_LIST_ENTRY(item, struct Monitor, monitor_list_head);
@@ -1086,11 +1115,46 @@ void context_demonitor(Context *ctx, uint64_t ref_ticks)
10861115
}
10871116
case CONTEXT_MONITOR_LINK_LOCAL:
10881117
case CONTEXT_MONITOR_LINK_REMOTE:
1118+
case CONTEXT_MONITOR_ALIAS:
10891119
break;
10901120
}
10911121
}
10921122
}
10931123

1124+
struct MonitorAlias *context_find_alias(Context *ctx, uint64_t ref_ticks)
1125+
{
1126+
struct ListHead *item;
1127+
LIST_FOR_EACH (item, &ctx->monitors_head) {
1128+
struct Monitor *monitor = GET_LIST_ENTRY(item, struct Monitor, monitor_list_head);
1129+
if (monitor->monitor_type == CONTEXT_MONITOR_ALIAS) {
1130+
struct MonitorAlias *alias_monitor = CONTAINER_OF(monitor, struct MonitorAlias, monitor);
1131+
if (alias_monitor->ref_ticks == ref_ticks) {
1132+
return alias_monitor;
1133+
}
1134+
}
1135+
}
1136+
1137+
return NULL;
1138+
}
1139+
1140+
bool context_unalias(Context *ctx, uint64_t ref_ticks, bool from_demonitor)
1141+
{
1142+
struct MonitorAlias *alias_monitor = context_find_alias(ctx, ref_ticks);
1143+
if (IS_NULL_PTR(alias_monitor)) {
1144+
return false;
1145+
}
1146+
1147+
if (alias_monitor->alias_type == CONTEXT_MONITOR_ALIAS_DEMONITOR
1148+
|| (alias_monitor->alias_type == CONTEXT_MONITOR_ALIAS_EXPLICIT_UNALIAS && !from_demonitor)) {
1149+
struct Monitor *monitor = &alias_monitor->monitor;
1150+
list_remove(&monitor->monitor_list_head);
1151+
free(monitor);
1152+
return true;
1153+
} else {
1154+
return false;
1155+
}
1156+
}
1157+
10941158
term context_get_monitor_pid(Context *ctx, uint64_t ref_ticks, bool *is_monitoring)
10951159
{
10961160
struct ListHead *item;
@@ -1117,6 +1181,7 @@ term context_get_monitor_pid(Context *ctx, uint64_t ref_ticks, bool *is_monitori
11171181
case CONTEXT_MONITOR_LINK_LOCAL:
11181182
case CONTEXT_MONITOR_LINK_REMOTE:
11191183
case CONTEXT_MONITOR_RESOURCE:
1184+
case CONTEXT_MONITOR_ALIAS:
11201185
break;
11211186
}
11221187
}
@@ -1246,6 +1311,12 @@ COLD_FUNC void context_dump(Context *ctx)
12461311
fprintf(stderr, "\n");
12471312
break;
12481313
}
1314+
case CONTEXT_MONITOR_ALIAS: {
1315+
struct MonitorLocalMonitor *monitored_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
1316+
fprintf(stderr, "has alias ref=%lu", (long unsigned) monitored_monitor->ref_ticks);
1317+
fprintf(stderr, "\n");
1318+
break;
1319+
}
12491320
case CONTEXT_MONITOR_MONITORED_LOCAL: {
12501321
struct MonitorLocalMonitor *monitored_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
12511322
fprintf(stderr, "monitored by ");

src/libAtomVM/context.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,13 @@ enum ContextMonitorType
172172
CONTEXT_MONITOR_RESOURCE,
173173
CONTEXT_MONITOR_LINK_REMOTE,
174174
CONTEXT_MONITOR_MONITORING_LOCAL_REGISTEREDNAME,
175+
CONTEXT_MONITOR_ALIAS,
176+
};
177+
178+
enum ContextMonitorAliasType
179+
{
180+
CONTEXT_MONITOR_ALIAS_EXPLICIT_UNALIAS,
181+
CONTEXT_MONITOR_ALIAS_DEMONITOR,
175182
};
176183

177184
#define UNLINK_ID_LINK_ACTIVE 0x0
@@ -207,6 +214,13 @@ struct MonitorLocalRegisteredNameMonitor
207214
term monitor_name;
208215
};
209216

217+
struct MonitorAlias
218+
{
219+
struct Monitor monitor;
220+
uint64_t ref_ticks;
221+
enum ContextMonitorAliasType alias_type;
222+
};
223+
210224
// The other half is called ResourceMonitor and is a linked list of resources
211225
struct ResourceContextMonitor
212226
{
@@ -512,6 +526,8 @@ struct Monitor *monitor_link_new(term link_pid);
512526
*/
513527
struct Monitor *monitor_new(term monitor_pid, uint64_t ref_ticks, bool is_monitoring);
514528

529+
struct Monitor *monitor_alias_new(uint64_t ref_ticks, enum ContextMonitorAliasType alias_type);
530+
515531
/**
516532
* @brief Create a monitor on a process by registered name.
517533
*
@@ -577,6 +593,9 @@ void context_unlink_ack(Context *ctx, term link_pid, uint64_t unlink_id);
577593
*/
578594
void context_demonitor(Context *ctx, uint64_t ref_ticks);
579595

596+
struct MonitorAlias *context_find_alias(Context *ctx, uint64_t ref_ticks);
597+
bool context_unalias(Context *ctx, uint64_t ref_ticks, bool from_demonitor);
598+
580599
/**
581600
* @brief Get target of a monitor.
582601
*

src/libAtomVM/defaultatoms.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,9 @@ X(LOAD_ATOM, "\x4", "load")
209209
X(JIT_X86_64_ATOM, "\xA", "jit_x86_64")
210210
X(JIT_AARCH64_ATOM, "\xB", "jit_aarch64")
211211
X(JIT_ARMV6M_ATOM, "\xA", "jit_armv6m")
212+
213+
X(ALIAS_ATOM, "\x5", "alias")
214+
X(DEMONITOR_ATOM, "\x9", "demonitor")
215+
X(EXPLICIT_UNALIAS_ATOM, "\x10", "explicit_unalias")
216+
X(REPLY_DEMONITOR_ATOM, "\xF", "reply_demonitor")
217+
X(TAG_ATOM, "\x3", "tag")

src/libAtomVM/ets_hashtable.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,9 @@ static uint32_t hash_term_incr(term t, int32_t h, GlobalContext *global)
368368
return hash_local_port(t, h, global);
369369
} else if (term_is_external_port(t)) {
370370
return hash_external_port(t, h, global);
371+
} else if (term_is_pid_reference(t)) {
372+
fprintf(stderr, "error: hash pid reference\n");
373+
AVM_ABORT();
371374
} else if (term_is_local_reference(t)) {
372375
return hash_local_reference(t, h, global);
373376
} else if (term_is_external_reference(t)) {

src/libAtomVM/externalterm.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,10 @@ static int serialize_term(uint8_t *buf, term t, GlobalContext *glb)
483483
WRITE_32_UNALIGNED(buf + k + 8, term_get_external_node_creation(t));
484484
}
485485
return k + 12;
486+
} else if (term_is_pid_reference(t)) {
487+
// FIXME: implement pid reference serialization
488+
fprintf(stderr, "Error: serialize pid reference");
489+
AVM_ABORT();
486490
} else if (term_is_local_reference(t)) {
487491
if (!IS_NULL_PTR(buf)) {
488492
buf[0] = NEWER_REFERENCE_EXT;

0 commit comments

Comments
 (0)