Multics Technical Bulletin MTB-732-02 Changes to the Hardcore To: Distribution From: Douglas Howe Date: 13 May 1986 Subject: Changes Required to Hardcore by C 1. Abstract This MTB describes the changes to hardcore required by C to install heap variables. Revision 1 Changes made in this revision correct the initialization of the stack header and are marked with change bars. Revision 2 The changes made reflect the comments made on MCR 7395 | and MCR 7396. The changes also include the description of | list_heap_variables. | _________________________________________________________________ Multics project internal documentation; not to be reproduced or distributed outside the Multics project. MTB-732-02 Multics Technical Bulletin Changes to the Hardcore Comments should be sent to the authors: via Multics mail to: DGHowe.Multics via posted mail to: Douglas G. Howe Advanced Computing Technology Centre Foothills Professional Building 1620 29th St., N.W. Calgary Alberta Canada T2N-4L7 via telephone to: (403)-284-6400 (403)-284-6432 (Howe) via forum on System-M to: >udd>m>DGHowe>mtgs_dir>c>c_imp (c) Multics Technical Bulletin MTB-732-02 Changes to the Hardcore TABLE OF CONTENTS Section Page Subject ======= ==== ======= 1 i Abstract 2 1 Preface 3 2 Introduction 3.1 3 . . References For This Document 4 4 Background 5 5 The Heap 5.1 5 . . Stacking Heaps 5.2 6 . . Heap Variable Name List 5.3 6 . . Mallocs Use of The Heap 6 7 star_heap Links 6.1 7 . . Allocation of Heap Links 7 7 Routines to be Changed 7.1 8 . . Changes to link_snap 7.2 8 . . set_ext_variable_$star_heap 7.3 8 . . heap_manager_ 8 8 Multiple Execution Level Heap References 9 9 New Commands 10 9 Initialization of heap Links 11 9 Dependencies 12 9 Documentation Changes 13 10 Include File Changes 14 11 Appendix A 15 12 Appendix B 16 14 Appendix C 17 16 Appendix D 18 19 Appendix E Multics Technical Bulletin MTB-732-02 Changes to the Hardcore 2. Preface This MTB along with MTBs 691, 647, 733 and 738 are intended to give a full explanation of how C will execute under Multics. MTB-732-02 Multics Technical Bulletin Changes to the Hardcore 3. Introduction There are various possible methods of implementing C external variables. External variables currently are implemented via *system links which are allocated or freed on a per-login process basis. C external variables could have been implemented using the existing structure of *system links in the following ways: 1) use *system links directly. 2) use *system links stacking the variable references by stepping through all active segments saving and resetting the references. 3) use *system links and a renaming convention where all external names would have a level associated with them. For example x would refer to the external variable x for level 0 and x01 would refer to the variable at level 1. The previous methods have some disadvantages that a full implementation of a C environment would not allow. These are: 1) for 2 and 3 above the implementation would take a lot longer to execute than the current environment. 2) 1 above would not allow for multiple unique execution levels. 3) 2 above alters the users definition of their environment by renaming the variables. 4) 2 and 3 above involve stepping through all active segments on exit or entrance to an execution unit to stack the variable references. For these reasons a new environment area was developed similar to the user_free_area. The difference being that this area will be in the control of the user. This area is called a heap and references to it are performed by *heap links. This MTB describes the proposed implementation for *heap links as defined for C. Multics Technical Bulletin MTB-732-02 Changes to the Hardcore 3.1. References For This Document 1) MTB-647 created by Greg Baryza. 2) The C Programming Language Kernighan, Brian W. & Ritchie, Dennis M. Prentice-Hall (1978) Englewood Cliffs, New Jersey 3) Multics Programmers Reference Manual (10.2 AG91-03A) (hereafter referred to as MPRM) 4) MTB 688 titled The Multics C Implementation Specification by Doug Howe. 5) MTB 691 titled Multics C Execution Environment Specification by Doug Howe. MTB-732-02 Multics Technical Bulletin Changes to the Hardcore 4. Background Under normal circumstances external variables in C are allocated on a heap. This heap is allocated and freed on a per-execution basis, allowing multiple main-execution levels to have a clean environment. On Multics, external allocations are usually performed in the user_free_area which is allocated and freed per ring on a per-login-process basis. On Multics the heap will be allocated per ring. This difference can lead to large difficulties in transferring existing C software to Multics. For this reason a new method of allocation was proposed for C and is implemented in the form of *heap external links. Multics Technical Bulletin MTB-732-02 Changes to the Hardcore 5. The Heap A new area similar to the user_free_area will be developed This area will be under direct control of the user and will be referred to as the `heap'. The heap will be an area obtained via define_area_. The heap will be used for an execution units external variable allocations and for C's storage allocation. Each heap will contain a heap header pointed to by a new field in the stack header named heap_header_ptr (see Appendix B). The heap header is defined as follows and is included in system_link_names.incl.pl1 (see Appendix A): 1 heap_header based, 2 version char(8), | 2 heap_name_list_ptr pointer, 2 previous_heap_header pointer, 2 area_ptr pointer, 2 current_execution_level fixed bin (17); where: heap_name_list_ptr: points to the variable_table_header of the current heap variables at the current execution level. previous_heap_header_ptr: points to the previous execution levels heap header. area_ptr: points to the heap area. This area is defined to be extensible. current_execution_level: represents the current level of execution by a fixed number starting at zero. 5.1. Stacking Heaps A method of stacking the heap is required due to the possibility of entering multiple main execution levels from a C program. The heap will be allocated and stacked by the environment control mechanism (main_ in C) every time a new execution unit is entered or by the user directly. It will remain the users responsibility to include the environment control mechanism with their bound execution unit. For a description of the environment mechanism see MTB 691. MTB-732-02 Multics Technical Bulletin Changes to the Hardcore The ability to stack the heap will be added in the form of entry points in a module named heap_manager_. The pushing of a heap will be a simple allocation of a new heap at the current execution level. A new heap header will be created and then the previous levels heap header will be chained in a list of heap headers. The popping of the heap will involve the freeing of all heap segments that have been allocated for the current level and resetting the heap to the previous levels heap segments. For a more detailed description of the entry points in heap_manager_ see Appendix D. In order for the new heap levels references to be effective, the execution environment will also have to be stacked. To perform this the LOT and ISOT entries for this module will have to be saved / reset. (see MTB 691) 5.2. Heap Variable Name List In order to keep track of the external variable references at each level, a name list will be generated for each heap level. The name list will be composed of a variable_table_header (defined in system_link_names.incl.pl1 see Appendix A.) pointing to a series of variable_nodes from a hash table contained in the variable_table_header. The variable_table_header will also contain some metering information as it currently does for set_ext_variable_. NOTE: All heap structure allocations will take place in the heap area. This includes the heap header, variable nodes and variable node header. 5.3. Mallocs Use of The Heap C's allocation routines will allocate and free their storage on the current execution levels heap. The variables will not exist on the heaps name list but will be allocated or freed directly in the heap by the use of the standard Multics allocation routines (allocate and free). Multics Technical Bulletin MTB-732-02 Changes to the Hardcore 6. star_heap Links To reference external variables allocated within the heap a new type of link is required. This new link type will be called a `*heap' link. `*heap' links are defined as a link with a type of 5 and a class of 6. This puts them into the same family as `*system' links. `*heap' links will act the same as `*system' links in terms of initialization and references. The only languages at this point that will support heap links will be C and ALM. 6.1. Allocation of Heap Links The allocation of `*heap' link targets will take place in the current heap. The allocation of the space required for each heap variable will be done via the standard Multics allocation packages. When a variable is allocated an entry is made on the heap name list stating the variables name, size and initialization information. 7. Routines to be Changed In order to implement `*heap' links the following system routines will be altered: 1) link_snap : link_snap has to understand `*heap' links in the same manner that it currently understands `*system' links. 2) set_ext_variable_$star_heap : is a new entry point in set_ext_variable controlling the allocation and resolution of references to `*heap' links. 3) heap_manager_ : a new group of entry points to control the heap and return information concerning heap levels. 4) link_man$get_initial_linkage : will have to be altered to initialize the new field being added to the stack_header structure. (see Appendix B) 5) bootload_1 : will have to be altered to initialize the new field being added to the stack header for the ring zero stack header. (see Appendix B). 6) interpret_link_ : will have to understand heap links. 7) linkage_error_ : will have to understand heap links. MTB-732-02 Multics Technical Bulletin Changes to the Hardcore 7.1. Changes to link_snap The changes to link_snap involve checking for `*heap' links similar to how `*system' links are checked for now. When a `*heap' link is found a call to the entry point set_ext_variable_$star_heap will perform the desired function. 7.2. set_ext_variable_$star_heap star_heap will control the allocation and references to heap variables via `*heap' links. The biggest difference between star_heap and the other entry points in set_ext_variable_ is where the allocation of the external variable takes place. In set_ext_variable_ external variables are allocated in the user_free_area pointed to by user_free_ptr in the users stack header. `*heap' links are allocated in the defined heap pointed to by area_ptr in the heap header. star_heap is called from link_snap or user programs to allocate or find a heap variable on the current execution levels heap. If the variable is not found it is allocated, initialized and added to the name list at the current level of execution. If it is found the address to the target variable node is returned. If the heap does not exist a level zero heap is created. This heap will then exist for the life of the login process. Normal, stacked heaps will begin at level one. 7.3. heap_manager_ A series of entry points will be available in heap_manager_ to handle various heap operations. For a complete description see Appendix D. 8. Multiple Execution Level Heap References With the stacking of the heap and the use of the environment control mechanism (main_), references across execution levels to heap variables of the same name will be resolved to the specific execution levels name list and thus to separate copies of the heap variable. Multics Technical Bulletin MTB-732-02 Changes to the Hardcore 9. New Commands A new command will be added to Multics to allow the user to find out information concerning `*heap' links as follows: 1) list_heap_variables would be equivalent to list_ext_variables for the current heap level. For a complete description see | Appendix E. | 10. Initialization of_heap Links `*heap' links are initialized in the same manner that is currently done for `*system' links. `*heap' links will be initialized on first reference within an execution unit. 11. Dependencies The above mentioned design is dependent on the following: 1) If the entry is recursive the execution environment has been stacked. The environment for the module being entered must be fresh / clean On exit from the module the environment will have to be reset to the previous value (see MTB 691). 2) Binding or Link Editing (via the Linkage Editor) of the executable object is required to join all initialization information together for heap links. This is required only if the initialization information is separated across segments or if the sequence in which the variable is referenced can not be guarantied to initialize it correctly. 3) Access to the heap header information is required by main_ and C so that it can make use of the heap. 12. Documentation Changes The following lists all the changes required to Multics documentation. 1) heap_manager_.info and AG93 Manual changes see Appendix D. 2) set_ext_variable_.info and AG93 Manual changes will be included with MTB 738. 3) Change AG91 to describe the changes to the stack header as follows: MTB-732-02 Multics Technical Bulletin Changes to the Hardcore add the declaration of the new stack header in section H-3 and add the following to H-4. heap_header_ptr points to the heap header for the current execution level for the current ring. 4) The changes to the Commands Manual and lhv.info can be found | in Appendix E. | 13. Include File Changes The following lists the required changes to system include files. 1) system_link_names.incl.pl1 Appendix A. 2) stack_header.incl.pl1 Appendix B. 3) stack_header.incl.alm Appendix C. Multics Technical Bulletin MTB-732-02 Changes to the Hardcore 14. Appendix A /* BEGIN INCLUDE FILE ... system_link_names.incl.pl1 */ /* created by M. Weaver 7/28/76 */ /* Modified: 82-11-19 by T. Oke to add LIST_TEMPLATE_INIT. */ /* Modified 02/11/83 by M. Weaver to add have_vla_variables flag */ dcl 1 variable_table_header aligned based, 2 hash_table (0:63) ptr unaligned, 2 total_search_time fixed bin (71), 2 total_allocation_time fixed bin (71), 2 number_of_searches fixed bin, 2 number_of_variables fixed bin (35), 2 flags unaligned, 3 have_vla_variables bit (1) unaligned, 3 pad bit (11) unaligned, 2 cur_num_of_variables fixed bin (24) unal, 2 number_of_steps fixed bin, 2 total_allocated_size fixed bin (35); dcl 1 variable_node aligned based, 2 forward_thread ptr unaligned, 2 vbl_size fixed bin (24) unsigned unaligned, 2 init_type fixed bin (11) unaligned, 2 time_allocated fixed bin (71), 2 vbl_ptr ptr, 2 init_ptr ptr, 2 name_size fixed bin(21) aligned, 2 name char (nchars refer (variable_node.name_size)); dcl 1 heap_header based, | 2 version char(8), | 2 heap_name_list_ptr pointer, | 2 previous_heap_ptr pointer, | 2 area_ptr pointer, | 2 execution_level fixed bin (17); | dcl heap_header_version_1 char(8) static options (constant) | init ("Heap_v01"); | /* END INCLUDE FILE ... system_link_names.incl.pl1 */ MTB-732-02 Multics Technical Bulletin Changes to the Hardcore 15. Appendix B /* BEGIN INCLUDE FILE ... stack_header.incl.pl1 .. 3/72 Bill Silver*/ /* modified 7/76 by M. Weaver for *system links and more system use of areas */ /* modified 3/77 by M. Weaver to add rnt_ptr */ /* Modified April 1983 by C. Hornig for tasking. (the trace stuff is temporary - MBW) */ /* format: style2 */ /* NOTE -------------------------------------------------- the following structures are also declared in stack_header.incl.alm and should be kept equivalent to these ------------------------------------------------------- */ dcl sb ptr; dcl 1 stack_header based (sb) aligned, 2 pad1 (4) fixed bin, 2 old_lot_ptr ptr, 2 combined_stat_ptr ptr, 2 clr_ptr ptr, 2 max_lot_size fixed bin (17) unal, 2 main_proc_invoked fixed bin (11) unal, 2 have_static_vlas bit (1) unal, 2 pad4 bit (2) unal, 2 run_unit_depth fixed bin (2) unal, 2 cur_lot_size fixed bin (17) unal, 2 pad2 bit (18) unal, 2 system_free_ptr ptr, 2 user_free_ptr ptr, 2 null_ptr ptr, 2 stack_begin_ptr ptr, 2 stack_end_ptr ptr, 2 lot_ptr ptr, 2 signal_ptr ptr, 2 bar_mode_sp ptr, 2 pl1_operators_ptr ptr, 2 call_op_ptr ptr, 2 push_op_ptr ptr, 2 return_op_ptr ptr, 2 return_no_pop_op_ptr ptr, 2 entry_op_ptr ptr, 2 trans_op_tv_ptr ptr, 2 isot_ptr ptr, 2 sct_ptr ptr, Multics Technical Bulletin MTB-732-02 Changes to the Hardcore 2 unwinder_ptr ptr, 2 sys_link_info_ptr ptr, 2 rnt_ptr ptr, 2 ect_ptr ptr, 2 assign_linkage_ptr ptr, 2 task_data_ptr ptr, 2 trace, 3 frames, 4 count fixed bin, 4 top_ptr ptr unal, 3 in_trace bit (36) aligned, 2 mbz bit (36) aligned, | 2 heap_header_ptr ptr; | /* The following offset refers to a table within the pl1 operator table. */ dcl tv_offset fixed bin init (361) internal static; /* (551) octal */ /* The following constants are offsets within this transfer vector table. */ dcl ( call_offset fixed bin init (271), push_offset fixed bin init (272), return_offset fixed bin init (273), return_no_pop_offset fixed bin init (274), entry_offset fixed bin init (275) ) internal static; /* The following declaration is an overlay of the whole stack header. Procedures which move the whole stack header should use this overlay. */ dcl stack_header_overlay (size (stack_header)) fixed bin based (sb); /* END INCLUDE FILE ... stack_header.incl.pl1 */ MTB-732-02 Multics Technical Bulletin Changes to the Hardcore 16. Appendix C " BEGIN INCLUDE FILE ... stack_header.incl.alm 3/72 Bill Silver " " modified 7/76 by M. Weaver for *system links and more system " use of areas " modified 3/77 by M. Weaver to add rnt_ptr " modified 7/77 by S. Webber to add run_unit_depth and " assign_linkage_ptr " modified 6/83 by J. Ives to add trace_frames and in_trace. " NOTE -------------------------------------------------- " the following declarations describe the stack header structure which is " declared in stack_header.incl.pl1 and should be kept equivalent " -------------------------------------------------------- equ stack_header.old_lot_ptr,4 equ stack_header.combined_stat_ptr,6 equ stack_header.clr_ptr,8 equ stack_header.max_lot_size,10 equ stack_header.main_proc_invoked,10 equ stack_header.run_unit_depth,10 equ stack_header.cur_lot_size,11 equ stack_header.system_free_ptr,12 equ stack_header.user_free_ptr,14 equ stack_header.parent_ptr,16 equ stack_header.stack_begin_ptr,18 equ stack_header.stack_end_ptr,20 equ stack_header.lot_ptr,22 equ stack_header.signal_ptr,24 equ stack_header.bar_mode_sp,26 equ stack_header.pl1_operators_ptr,28 equ stack_header.call_op_ptr,30 equ stack_header.push_op_ptr,32 equ stack_header.return_op_ptr,34 equ stack_header.ret_no_pop_op_ptr,36 equ stack_header.entry_op_ptr,38 equ stack_header.trans_op_tv_ptr,40 equ stack_header.isot_ptr,42 equ stack_header.sct_ptr,44 equ stack_header.unwinder_ptr,46 Multics Technical Bulletin MTB-732-02 Changes to the Hardcore equ stack_header.sys_link_info_ptr,48 equ stack_header.rnt_ptr,50 equ stack_header.ect_ptr,52 equ stack_header.assign_linkage_ptr,54 equ stack_header.task_data_ptr,56 equ stack_header.trace_frames,58 equ stack_header.in_trace,60 equ stack_header.heap_header_ptr,62 | equ stack_header_end,64 equ trace_frames.count,0 equ trace_frames.top_ptr,1 " The following constant is an offset within the pl1 operators " table. It references a transfer vector table. bool tv_offset,551 " The following constants are offsets within this transfer vector " table. equ call_offset,tv_offset+271 equ push_offset,tv_offset+272 equ return_offset,tv_offset+273 equ return_no_pop_offset,tv_offset+274 equ entry_offset,tv_offset+275 " END INCLUDE FILE stack_header.incl.alm MTB-732-02 Multics Technical Bulletin Changes to the Hardcore 17. Appendix D 03/17/86 heap_manager_ Entry points in heap_manager_: (List is generated by the help command) :Entry: push_heap_level: 03/17/86: heap_manager_$push_heap_level Function: This entry point creates a new heap level, allocates the heap header and chains the previous heap to the current heap. If the stack_header_ptr is null an error of error_table_$null_info_ptr is returned. Syntax: declare heap_manager_$push_heap_level entry (pointer, fixed bin(17), fixed bin(35)); call heap_manager_$push_heap_level (stack_header_ptr, exe_level, code); Arguments: stack_header_ptr is a pointer to the stack header. This can be obtained via the PL/1 builtin stackbaseptr(). (Input) exe_level is the new execution level after the new heap is created. (Output) code is a standard status code. (Output) :Entry: pop_heap_level: 03/17/86: heap_manager_$pop_heap_level Function: This entry point resets the heap to the previous level freeing the old heap and any variables allocated therein. Syntax: declare heap_manager_$pop_heap_level entry (pointer, fixed bin(35)); call heap_manager_$pop_heap_level (stack_header_ptr, code); Multics Technical Bulletin MTB-732-02 Changes to the Hardcore Arguments: stack_header_ptr is a pointer to the stack header. This can be obtained via the PL/1 builtin stackbaseptr(). (Input) code is a standard status code. (Output) :Entry: get_heap_header: 03/17/86: heap_manager_$get_heap_header Function: This entry point returns a pointer to the heap header for the specified execution level. If the execution level does not exist an error of error_table_$no_heap_defined is returned. Syntax: declare heap_manager_$get_heap_header entry (pointer, fixed bin(17), pointer, fixed bin(35)); call heap_manager_$get_heap_header (stack_header_ptr, exe_level, heap_header_ptr, code); Arguments: exe_level is the execution level of the heap required. If a -1 is passed then the current execution level is used. (Input) stack_header_ptr is a pointer to the stack header. This can be obtained via the PL/1 builtin stackbaseptr(). (Input) heap_header_ptr is a pointer to the heap header for the passed execution level. (Output). code is a standard status code. (Output) :Entry: get_heap_level: 03/17/86: heap_manager_$get_heap_level Function: This entry point returns the current execution level from the current heap header. If the heap does not exist an execution level of -1 is returned. Syntax: declare heap_manager_$get_heap_level entry (pointer) returns (fixed bin(17)); exe_level = heap_manager_$get_heap_level (stack_header_ptr); MTB-732-02 Multics Technical Bulletin Changes to the Hardcore Arguments: stack_header_ptr is a pointer to the stack header. This can be obtained via the PL/1 builtin stackbaseptr(). (Input) :Entry: get_heap_area: 03/17/86: heap_manager_$get_heap_area Function: This entry point returns a pointer to the heap area for the specified level. The area is max_segsize - 50 words. If the heap level specified does not exist an error of error_table_$no_heap_defined is returned. Syntax: declare heap_manager_$get_heap_area entry (pointer, fixed bin(17), pointer, fixed bin(35)); call heap_manager_$get_heap_area (stack_header_ptr, exe_level, heap_area_ptr, code); Arguments: exe_level is the execution level of the heap area required. If a -1 is passed then the current execution level is used. (Input) stack_header_ptr is a pointer to the stack header. This can be obtained via the PL/1 builtin stackbaseptr(). (Input) heap_area_ptr is pointer to the heap area for the passed level. (Output) code is a standard status code. (Output) Multics Technical Bulletin MTB-732-02 Changes to the Hardcore 18. Appendix E 05/12/86 list_heap_variables, lhv | | Syntax: lhv names {-control_args} | | | Function: Prints information concerning heap variables. Only | variables at the current execution level are printed. The | default information is the location and size of each specified | variable. | | Arguments: | names | are names of external variables, separated by spaces. | | | Control arguments: | -all, -a | prints information for all heap variables at the current | execution level. | -long, -lg | prints how and when the variables were allocated. | -no_header, -nhe | suppresses the printing of the header. | -to level | specifes what execution level to stop printing variables at. | If not present the current execution level is assumed. | -from level | specifies what execution level to start printing variables at. | If not present execution level 0 is assumed. | | Note: The -from and -to arguments are meant to be used together to| specify a range of execution levels to be printed. If neither are | present the current execution level is assumed. |