diff options
author | Rickard Green <[email protected]> | 2016-08-29 17:52:10 +0200 |
---|---|---|
committer | Rickard Green <[email protected]> | 2016-08-29 17:52:10 +0200 |
commit | 928d74ffa09bd56652d9390b02fa51ef51d71d51 (patch) | |
tree | bfb9cd9e76d4ef766dbcd999adf16c700350b399 /erts/emulator/beam/beam_emu.c | |
parent | 69d442f8afc67aef33c70d68d7eaab2bdad1400f (diff) | |
parent | 9d0638216d35ca0f21c1eea20f8daa3992ac4f71 (diff) | |
download | otp-928d74ffa09bd56652d9390b02fa51ef51d71d51.tar.gz otp-928d74ffa09bd56652d9390b02fa51ef51d71d51.tar.bz2 otp-928d74ffa09bd56652d9390b02fa51ef51d71d51.zip |
Merge branch 'rickard/fun-purge-bug/OTP-13809' and 'rickard/new-purge-strategy/OTP-13833' into maint
* rickard/fun-purge-bug/OTP-13809:
Fix purge of code
Reclaim literal area after purge has completed
Separate literal area from code
Conflicts:
erts/doc/src/erlang.xml
erts/emulator/beam/beam_bif_load.c
erts/emulator/beam/erl_init.c
erts/preloaded/ebin/init.beam
Diffstat (limited to 'erts/emulator/beam/beam_emu.c')
-rw-r--r-- | erts/emulator/beam/beam_emu.c | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 8f90a999c4..ac8dd85b46 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -6526,34 +6526,49 @@ call_fun(Process* p, /* Current process. */ * representation (the module has never been loaded), * or the module defining the fun has been unloaded. */ + module = fe->module; - if ((modp = erts_get_module(module, code_ix)) != NULL - && modp->curr.code_hdr != NULL) { + + ERTS_SMP_READ_MEMORY_BARRIER; + if (fe->pend_purge_address) { /* - * There is a module loaded, but obviously the fun is not - * defined in it. We must not call the error_handler - * (or we will get into an infinite loop). + * The system is currently trying to purge the + * module containing this fun. Suspend the process + * and let it try again when the purge operation is + * done (may succeed or not). */ - goto badfun; + ep = erts_suspend_process_on_pending_purge_lambda(p); + ASSERT(ep); } + else { + if ((modp = erts_get_module(module, code_ix)) != NULL + && modp->curr.code_hdr != NULL) { + /* + * There is a module loaded, but obviously the fun is not + * defined in it. We must not call the error_handler + * (or we will get into an infinite loop). + */ + goto badfun; + } - /* - * No current code for this module. Call the error_handler module - * to attempt loading the module. - */ + /* + * No current code for this module. Call the error_handler module + * to attempt loading the module. + */ - ep = erts_find_function(erts_proc_get_error_handler(p), - am_undefined_lambda, 3, code_ix); - if (ep == NULL) { /* No error handler */ - p->current = NULL; - p->freason = EXC_UNDEF; - return NULL; + ep = erts_find_function(erts_proc_get_error_handler(p), + am_undefined_lambda, 3, code_ix); + if (ep == NULL) { /* No error handler */ + p->current = NULL; + p->freason = EXC_UNDEF; + return NULL; + } } reg[0] = module; reg[1] = fun; reg[2] = args; reg[3] = NIL; - return ep->addressv[erts_active_code_ix()]; + return ep->addressv[code_ix]; } } } else if (is_export_header(hdr)) { |