Age | Commit message (Collapse) | Author |
|
|
|
|
|
If the main lock is not taken then any process running
on a dirty scheduler may cause all kinds of problems.
|
|
The guard BIF `length/1` would calculate the length of the list in one
go without yielding, even if the list was were long. To make it even
worse, the call to `length/1` would only cost a single reduction.
This commit reimplements `length/1` so that it eats a number of
reductions proportional to the length of the list, and yields if the
available reductions run out.
|
|
"(void)result" will silence warning about unused variable
and compiler will optimize away such unused variables.
|
|
and let compiler determine string lengths.
These were actually wrong in erl_db.c:
count_trap\0
replace_tra
select_tra
|
|
* sverker/ets-delete_all_objects-trap/OTP-15078:
erts: Rename untrapping db_free_*empty*_table
erts: Make ets:delete_all_objects yield on fixed table
erts: Optimize ets delete all in fixed table
erts: Refactor ets select iteration code
erts: Cleanup ets code
erts: Optimize ets hash object deallocactions
erts: Refactor pseudo deleted ets objects
erts: Make atomic ets:delete_all_objects yield
erts: Fix reduction bump for ets:delete/1
|
|
|
|
This complements the `map_get/2` guard BIF introduced in #1784.
Rationale.
`map_get/2` allows accessing map fields in guards, but it might be
problematic in more complex guard expressions, for example:
foo(X) when map_get(a, X) =:= 1 or is_list(X) -> ...
The `is_list/1` part of the guard could never succeed since the
`map_get/2` guard would fail the whole guard expression. In this
situation, this could be solved by using `;` instead of `or` to separate
the guards, but it is not possible in every case.
To solve this situation, this PR proposes a `is_map_key/2` guard that
allows to check if a map has key inside a guard before trying to access
that key. When combined with `is_map/1` this allows to construct a
purely boolean guard expression testing a value of a key in a map.
Implementation.
Given the use case motivating the introduction of this function, the PR
contains compiler optimisations that produce optimial code for the
following guard expression:
foo(X) when is_map(X) and is_map_key(a, X) and map_get(a, X) =:= 1 -> ok;
foo(_) -> error.
Given all three tests share the failure label, the `is_map_key/2` and
`is_map/2` tests are optimised away.
As with `map_get/2` the `is_map_key/2` BIF is allowed in match specs.
|
|
Rationale
Today all compound data types except for maps can be deconstructed in guards.
For tuples we have `element/2` and for lists `hd/1` and `tl/1`. Maps are
completely opaque to guards. This means matching on maps can't be
abstracted into macros, which is often done with repetitive guards. It
also means that maps have to be always selected whole from ETS tables,
even when only one field would be enough, which creates a potential
efficiency issue.
This PR introduces an `erlang:map_get/2` guard-safe function that allows
extracting a map field in guard. An alternative to this function would be
to introduce the syntax for extracting a value from a map that was planned
in the original EEP: `Map#{Key}`.
Even outside of guards, since this function is a guard-BIF it is more
efficient than using `maps:get/2` (since it does not need to set up the
stack), and more convenient from pattern matching on the map (compare:
`#{key := Value} = Map, Value` to `map_get(key, Map)`).
Performance considerations
A common concern against adding this function is the notion that "guards
have to be fast" and ideally execute in constant time. While there are
some counterexamples (`length/1`), what is more important is the fact
that adding those functions does not change in any way the time
complexity of pattern matching - it's already possible to match on map
fields today directly in patterns - adding this ability to guards will
niether slow down or speed up the execution, it will only make certain
programs more convenient to write.
This first version is very naive and does not perform any optimizations.
|
|
OTP-14899
|
|
Implementation of true asynchronous signaling between processes
|
|
Communication between Erlang processes has conceptually always been
performed through asynchronous signaling. The runtime system
implementation has however previously preformed most operation
synchronously. In a system with only one true thread of execution, this
is not problematic (often the opposite). In a system with multiple threads
of execution (as current runtime system implementation with SMP support)
it becomes problematic. This since it often involves locking of structures
when updating them which in turn cause resource contention. Utilizing
true asynchronous communication often avoids these resource contention
issues.
The case that triggered this change was contention on the link lock due
to frequent updates of the monitor trees during communication with a
frequently used server. The signal order delivery guarantees of the
language makes it hard to change the implementation of only some signals
to use true asynchronous signaling. Therefore the implementations
of (almost) all signals have been changed.
Currently the following signals have been implemented as true
asynchronous signals:
- Message signals
- Exit signals
- Monitor signals
- Demonitor signals
- Monitor triggered signals (DOWN, CHANGE, etc)
- Link signals
- Unlink signals
- Group leader signals
All of the above already defined as asynchronous signals in the
language. The implementation of messages signals was quite
asynchronous to begin with, but had quite strict delivery constraints
due to the ordering guarantees of signals between a pair of processes.
The previously used message queue partitioned into two halves has been
replaced by a more general signal queue partitioned into three parts
that service all kinds of signals. More details regarding the signal
queue can be found in comments in the erl_proc_sig_queue.h file.
The monitor and link implementations have also been completely replaced
in order to fit the new asynchronous signaling implementation as good
as possible. More details regarding the new monitor and link
implementations can be found in the erl_monitor_link.h file.
|
|
to call a common static function dmc_stack_grow()
and reduce the code bloat.
and did a combined DMC_PUSH2
|
|
|
|
|
|
This refactor was done using the unifdef tool like this:
for file in $(find erts/ -name *.[ch]); do unifdef -t -f defile -o $file $file; done
where defile contained:
#define ERTS_SMP 1
#define USE_THREADS 1
#define DDLL_SMP 1
#define ERTS_HAVE_SMP_EMU 1
#define SMP 1
#define ERL_BITS_REENTRANT 1
#define ERTS_USE_ASYNC_READY_Q 1
#define FDBLOCK 1
#undef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
#define ERTS_POLL_ASYNC_INTERRUPT_SUPPORT 0
#define ERTS_POLL_USE_WAKEUP_PIPE 1
#define ERTS_POLL_USE_UPDATE_REQUESTS_QUEUE 1
#undef ERTS_HAVE_PLAIN_EMU
#undef ERTS_SIGNAL_STATE
|
|
* lukas/erts/trace_recv_esdp_bug/OTP-14411:
erts: the esdp is not always available in matchspec
|
|
erts: Remove old unused functions
|
|
The functions have been found using: https://github.com/caolanm/callcatcher
|
|
* sverker/ets-select-replace-const:
stdlib: Add examples for ets:select_replace docs
erts: Fix ets:select_replace with {const, NewTuple}
|
|
Enable ets:select_replace to do a generic single object
compare-and-swap operation of any ets-tuple using
a matchspec like this:
[{Old, [], [{const, New}]}]
The only exception when this does not work is if the key
contains maps or atoms looking like variables (like '$1').
|
|
This happens for instance when a receive_trace is run in the
sys_msg_dispatcher thread when the trace_delivered trace message
is traced.
|
|
|
|
|
|
for temporary matchspec results.
ToDo: Would be even nicer if PAM could allocate and build
the ETS objects without extra copy_struct needed.
|
|
Looks like this line has truly been dead code
as ets has (so far) always been using ERTS_PAM_COPY_RESULT
and matchPushExpr is not generated for tracing.
|
|
|
|
Preemptively fail operation with badarg if the replacement object
might have a different key.
|
|
|
|
A magic destructor can return 0 and thereby take control
and prolong the lifetime of a magic binary.
|
|
|
|
Magic references are *intentionally* indistinguishable from ordinary
references for the Erlang software. Magic references do not change
the language, and are intended as a pure runtime internal optimization.
An ordinary reference is typically used as a key in some table. A
magic reference has a direct pointer to a reference counted magic
binary. This makes it possible to implement various things without
having to do lookups in a table, but instead access the data directly.
Besides very fast lookups this can also improve scalability by
removing a potentially contended table. A couple of examples of
planned future usage of magic references are ETS table identifiers,
and BIF timer identifiers.
Besides future optimizations using magic references it should also
be possible to replace the exposed magic binary cludge with magic
references. That is, magic binaries that are exposed as empty
binaries to the Erlang software.
|
|
* maint:
Atomic reference count of binaries also in non-SMP
Conflicts:
erts/emulator/beam/erl_fun.c
|
|
NIF resources was not handled in a thread-safe manner in the runtime
system without SMP support.
As a consequence of this fix, the following driver functions are now
thread-safe also in the runtime system without SMP support:
- driver_free_binary()
- driver_realloc_binary()
- driver_binary_get_refc()
- driver_binary_inc_refc()
- driver_binary_dec_refc()
|
|
|
|
This commit adds two new structs to be used to represent
erlang code in erts.
ErtsCodeInfo is used to describe the i_func_info header
that is part of all Export entries and the prelude of
each function. This replaces all the BeamInstr * that
were previously used to point to these locations.
After this change the code should never use BeamInstr *
with offsets to figure out different parts of the
func_info header.
ErtsCodeMFA is a struct that is used to descripe a
MFA in code. It is used within ErtsCodeInfo and also
in Process->current.
All function that previously took Eterm * or BeamInstr *
to identify a MFA now use the ErtsCodeMFA or ErtsCodeInfo
where appropriate.
The code has been tested to work when adding a new field to the
ErtsCodeInfo struct, but some updates are needed in ops.tab to
make it work.
|
|
Make it so that it is only possible to remove a tracer via
returning remove from an erl_tracer. This limition is put in
place in order to avoid a lot of lock checking and taking
in various places, especially in regards to trace events
happening on dirty schedulers.
|
|
- Termination of a process...
- Modify trace flags of process...
- Process info on process...
- Register/unregister of name on process...
- Set group leader on process...
... while it is executing a dirty NIF.
|
|
'on_load' is a call trace.
|
|
also simplified the interface to to run PAM from trace
|
|
All 'EXIT' and monitor messages are sent from 'system'
Timeouts are "sent" from 'clock_service'
|
|
and non-call-trace.
This is the easy way out to avoid difficult locking
scenarios when accessing tracing flags on another process.
|
|
|
|
for enable_trace and disable_trace operations.
Instead seize needed locks while updating trace flags.
|
|
Add the possibility to use modules as trace data receivers. The functions
in the module have to be nifs as otherwise complex trace probes will be
very hard to handle (complex means trace probes for ports for example).
This commit changes the way that the ptab->tracer field works from always
being an immediate, to now be NIL if no tracer is present or else be
the tuple {TracerModule, TracerState} where TracerModule is an atom that
is later used to lookup the appropriate tracer callbacks to call and
TracerState is just passed to the tracer callback. The default process and
port tracers have been rewritten to use the new API.
This commit also changes the order which trace messages are delivered to the
potential tracer process. Any enif_send done in a tracer module may be delayed
indefinitely because of lock order issues. If a message is delayed any other
trace message send from that process is also delayed so that order is preserved
for each traced entity. This means that for some trace events (i.e. send/receive)
the events may come in an unintuitive order (receive before send) to the
trace receiver. Timestamps are taken when the trace message is generated so
trace messages from differented processes may arrive with the timestamp
out of order.
Both the erlang:trace and seq_trace:set_system_tracer accept the new tracer
module tracers and also the backwards compatible arguments.
OTP-10267
|
|
|
|
|
|
This is mostly a pure refactoring.
Except for the buggy cases when calling erlang:halt() with a positive
integer in the range -(INT_MIN+2) to -INT_MIN that got confused with
ERTS_ABORT_EXIT, ERTS_DUMP_EXIT and ERTS_INTR_EXIT.
Outcome OLD erl_exit(n, ) NEW erts_exit(n, )
------- ------------------- -------------------------------------------
exit(Status) n = -Status <= 0 n = Status >= 0
crashdump+abort n > 0, ignore n n = ERTS_ERROR_EXIT < 0
The outcome of the old ERTS_ABORT_EXIT, ERTS_INTR_EXIT and
ERTS_DUMP_EXIT are the same as before (even though their values have
changed).
|
|
|