aboutsummaryrefslogblamecommitdiffstats
path: root/erts/emulator/beam/code_ix.h
blob: 66543fa2a8959cf2d2dff7916ca54fbcefef2159 (plain) (tree)
1
2
3
4


                   
                                                   













                                                                         





























                                                                                 


                     





                       

               



                               
 

                                          
                             


                                                           

                                                                               
   
               
                                        




                                                                             
               
                                         
 


                                                                             
   
                                           
 
                 
   
                               
 




                                                                               
                                      





                                                                                 
                                       



                                                                  
                                      
 
                             


                                 

















                                                               
                           
 
/*
 * %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__ */