Skip to content

Commit f18c79a

Browse files
committed
Merge pull request atomvm#469 from bettio/code-load-module
Dynamic module and AVMPack load/close Goals: - Loading/closing .beam modules from filesystem, flash or binaries, providing same APIs as code module (https://www.erlang.org/doc/man/code.html) - Opening an AVM files/partitions so it can be used at a later time from the usual module loader, by implementing few new NIFs Non Goals: - Providing a mechanism for flashing or handling the whole update flow Other comments: - No regressions detected ( unlikely since they are new additional functions) - All new NIFs are tested - Loading the same module twice will make the VM use the new code (as expected) Future steps (not included here): - Creating a kernel/boot app a making it work These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
2 parents c8bf97f + 1c4733f commit f18c79a

29 files changed

+969
-126
lines changed

.github/workflows/build-and-test-other.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ jobs:
136136
cd build &&
137137
cmake .. ${{ matrix.cmake_opts }} &&
138138
cp ../build_tests/tests/erlang_tests/*.beam tests/erlang_tests/ &&
139+
cp ../build_tests/tests/erlang_tests/code_load/*.beam tests/erlang_tests/code_load/ &&
139140
cp ../build_tests/tests/libs/estdlib/*.avm tests/libs/estdlib/ &&
140141
cp ../build_tests/tests/libs/eavmlib/*.avm tests/libs/eavmlib/ &&
141142
cp ../build_tests/tests/libs/alisp/*.avm tests/libs/alisp/ &&

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4545
- Added support for `erlang:memory(binary)`
4646
- Added support for callbacks on SNTP updates
4747
- Multithreading support (SMP)
48+
- Added support for code:load_abs/1, code:load_binary/3
49+
- Added support for loading / closing AVMPacks at runtime
4850

4951
### Fixed
5052
- Fixed issue with formatting integers with io:format() on STM32 platform

src/libAtomVM/avmpack.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,30 @@ void *avmpack_fold(void *accum, const void *avmpack_binary, avmpack_fold_fun fol
127127

128128
return accum;
129129
}
130+
131+
static void in_memory_avm_pack_destructor(struct AVMPackData *obj, GlobalContext *global);
132+
133+
const struct AVMPackInfo in_memory_avm_pack_info = {
134+
.destructor = in_memory_avm_pack_destructor
135+
};
136+
137+
static void in_memory_avm_pack_destructor(struct AVMPackData *obj, GlobalContext *global)
138+
{
139+
UNUSED(global);
140+
141+
free((void *) obj->data);
142+
free(obj);
143+
}
144+
145+
static void const_avm_pack_destructor(struct AVMPackData *obj, GlobalContext *global);
146+
147+
const struct AVMPackInfo const_avm_pack_info = {
148+
.destructor = const_avm_pack_destructor
149+
};
150+
151+
static void const_avm_pack_destructor(struct AVMPackData *obj, GlobalContext *global)
152+
{
153+
UNUSED(global);
154+
155+
free(obj);
156+
}

src/libAtomVM/avmpack.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,59 @@
3030
extern "C" {
3131
#endif
3232

33+
#include "globalcontext.h"
3334
#include "list.h"
35+
#include <stdbool.h>
36+
#include <stddef.h>
3437
#include <stdint.h>
3538

3639
#define END_OF_FILE 0
3740
#define BEAM_START_FLAG 1
3841
#define BEAM_CODE_FLAG 2
3942

43+
struct AVMPackData;
44+
45+
struct AVMPackInfo
46+
{
47+
void (*destructor)(struct AVMPackData *obj, GlobalContext *global);
48+
};
49+
4050
struct AVMPackData
4151
{
52+
const struct AVMPackInfo *obj_info;
4253
struct ListHead avmpack_head;
54+
bool in_use;
55+
int name_atom_id;
4356
const void *data;
4457
};
4558

59+
static inline void avmpack_data_init(struct AVMPackData *avm_pack_data, const struct AVMPackInfo *info)
60+
{
61+
avm_pack_data->obj_info = info;
62+
avm_pack_data->in_use = false;
63+
avm_pack_data->name_atom_id = 0;
64+
avm_pack_data->data = NULL;
65+
}
66+
67+
static inline void avmpack_data_destroy(struct AVMPackData *avm_pack_data, GlobalContext *global)
68+
{
69+
avm_pack_data->obj_info->destructor(avm_pack_data, global);
70+
}
71+
72+
struct InMemoryAVMPack
73+
{
74+
struct AVMPackData base;
75+
};
76+
77+
extern const struct AVMPackInfo in_memory_avm_pack_info;
78+
79+
struct ConstAVMPack
80+
{
81+
struct AVMPackData base;
82+
};
83+
84+
extern const struct AVMPackInfo const_avm_pack_info;
85+
4686
/**
4787
* @brief callback function for AVMPack section fold.
4888
* @details Instances of this function are supplied to the avmpack_fold function, in order to

src/libAtomVM/defaultatoms.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ static const char *const port_atom = "\x4" "port";
133133

134134
static const char *const info_atom = "\x4" "info";
135135

136+
static const char *const module_atom = "\x06" "module";
137+
136138
void defaultatoms_init(GlobalContext *glb)
137139
{
138140
int ok = 1;
@@ -249,6 +251,8 @@ void defaultatoms_init(GlobalContext *glb)
249251
ok &= globalcontext_insert_atom(glb, port_atom) == PORT_ATOM_INDEX;
250252

251253
ok &= globalcontext_insert_atom(glb, info_atom) == INFO_ATOM_INDEX;
254+
255+
ok &= globalcontext_insert_atom(glb, module_atom) == MODULE_ATOM_INDEX;
252256

253257
if (!ok) {
254258
AVM_ABORT();

src/libAtomVM/defaultatoms.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,9 @@ extern "C" {
142142

143143
#define INFO_ATOM_INDEX 91
144144

145-
#define PLATFORM_ATOMS_BASE_INDEX 92
145+
#define MODULE_ATOM_INDEX 92
146+
147+
#define PLATFORM_ATOMS_BASE_INDEX 93
146148

147149
#define FALSE_ATOM TERM_FROM_ATOM_INDEX(FALSE_ATOM_INDEX)
148150
#define TRUE_ATOM TERM_FROM_ATOM_INDEX(TRUE_ATOM_INDEX)
@@ -259,6 +261,8 @@ extern "C" {
259261

260262
#define INFO_ATOM TERM_FROM_ATOM_INDEX(INFO_ATOM_INDEX)
261263

264+
#define MODULE_ATOM TERM_FROM_ATOM_INDEX(MODULE_ATOM_INDEX)
265+
262266
void defaultatoms_init(GlobalContext *glb);
263267

264268
void platform_defaultatoms_init(GlobalContext *glb);

src/libAtomVM/globalcontext.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "globalcontext.h"
2525

2626
#include "atomshashtable.h"
27+
#include "avmpack.h"
2728
#include "context.h"
2829
#include "defaultatoms.h"
2930
#include "list.h"
@@ -176,7 +177,14 @@ COLD_FUNC void globalcontext_destroy(GlobalContext *glb)
176177
refc_binary_destroy(refc, glb);
177178
}
178179
synclist_destroy(&glb->refc_binaries);
180+
181+
struct ListHead *open_avm_packs = synclist_nolock(&glb->avmpack_data);
182+
MUTABLE_LIST_FOR_EACH (item, tmp, open_avm_packs) {
183+
struct AVMPackData *avmpack_data = GET_LIST_ENTRY(item, struct AVMPackData, avmpack_head);
184+
avmpack_data_destroy(avmpack_data, glb);
185+
}
179186
synclist_destroy(&glb->avmpack_data);
187+
180188
struct ListHead *listeners = synclist_nolock(&glb->listeners);
181189
MUTABLE_LIST_FOR_EACH (item, tmp, listeners) {
182190
sys_listener_destroy(item);

src/libAtomVM/globalcontext.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ struct GlobalContext
9090
int loaded_modules_count;
9191

9292
struct SyncList avmpack_data;
93-
const void **avmpack_platform_data;
9493

9594
struct TimerList timer_list;
9695
#ifndef AVM_NO_SMP

0 commit comments

Comments
 (0)