blob: 66543fa2a8959cf2d2dff7916ca54fbcefef2159 (
plain) (
tree)
|
|
/*
* %CopyrightBegin%
*
* Copyright Ericsson AB 2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* %CopyrightEnd%
*/
/* Description:
* This is the interface that facilitate changing the beam code
* (load,upgrade,delete) while allowing executing Erlang processes to
* access the code without any locks or other expensive memory barriers.
*
* The basic idea is to maintain several "logical copies" of the code. These
* copies are identified by a global 'code index', an integer of 0, 1 or 2.
* The code index is used as argument to code access structures like
* export, module, beam_catches, beam_ranges.
*
* The current 'active' code index is used to access the current running
* code. The 'staging' code index is used by the process that performs
* a code change operation. When a code change operation completes
* succesfully, the staging code index becomes the new active code index.
*
* The third code index is not explicitly used. It can be thought of as
* the "previous active" or the "next staging" index. It is needed to make
* sure that we do not reuse a code index for staging until we are sure
* that no executing BIFs are still referring it.
* We could get by with only two (0 and 1), but that would require that we
* must wait for all schedulers to re-schedule before each code change
* operation can start staging.
*
* Note that the 'code index' is very loosely coupled to the concept of
* 'current' and 'old' module versions. You can almost say that they are
* orthogonal to each other. Code index is an emulator global concept while
* 'current' and 'old' is specific for each module.
*/
#ifndef __CODE_IX_H__
#define __CODE_IX_H__
#ifndef __SYS_H__
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include "sys.h"
#endif
struct process;
#define ERTS_NUM_CODE_IX 3
typedef unsigned ErtsCodeIndex;
/* Called once at emulator initialization.
*/
void erts_code_ix_init(void);
/* Return active code index.
* Is guaranteed to be valid until the calling BIF returns.
* To get a consistent view of the code, only one call to erts_active_code_ix()
* should be made and the returned ix reused within the same BIF call.
*/
ERTS_GLB_INLINE
ErtsCodeIndex erts_active_code_ix(void);
/* Return staging code ix.
* Only used by a process performing code loading/upgrading/deleting/purging.
* code_ix must be locked.
*/
ERTS_GLB_INLINE
ErtsCodeIndex erts_staging_code_ix(void);
/* Try lock code_ix that is needed for (exlusive) access of the staging area.
* Main process lock (only) must be held.
* Caller is suspended and *must* yield if 0 is returned.
*/
int erts_try_lock_code_ix(struct process*);
/* Unlock code_ix
*/
void erts_unlock_code_ix(void);
/* Make the "staging area" a complete copy of the active code.
* code_ix must be locked.
* Must be followed by a call to either "commit" or "abort" before code_ix lock
* is released.
*/
void erts_start_staging_code_ix(void);
/* Commit the staging area and update the active code index.
* code_ix must be locked and erts_start_staging_code_ix() called.
* ToDo: Updating active code index should be done according to Rickard's recipe.
* This function might need to be split into two.
*/
void erts_commit_staging_code_ix(void);
/* Abort the staging.
* code_ix must be locked and erts_start_staging_code_ix() called.
*/
void erts_abort_staging_code_ix(void);
#ifdef ERTS_ENABLE_LOCK_CHECK
int erts_is_code_ix_locked(void);
#endif
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
extern erts_smp_atomic32_t the_active_code_index;
extern erts_smp_atomic32_t the_staging_code_index;
ERTS_GLB_INLINE ErtsCodeIndex erts_active_code_ix(void)
{
return erts_smp_atomic32_read_nob(&the_active_code_index);
}
ERTS_GLB_INLINE ErtsCodeIndex erts_staging_code_ix(void)
{
return erts_smp_atomic32_read_nob(&the_staging_code_index);
}
#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
#endif /* !__CODE_IX_H__ */
|