This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Is init_priority file scope or global scope?


On 12/12/2010 06:54, H.J. Lu wrote:

[ off-list, but it's not personal, so let's Cc the list back in, someone might
find this explanation of the mechanism useful in the archives. ]

> Can you check the assembly output? Since
> 
> ----
>     Note that the particular values of PRIORITY do not matter; only
>     their relative ordering.
> ---
> 
> on Linux, the numeric string in section name isn't the same as
> PRIORITY in source file. That means on Linux, the order
> of .ctors sections in 2 files isn't the relative ordering of PRIORITY
> of those 2 files.

  Well, at least on PE-COFF, the numeric string is (65536-priority).  It is
zero padded to five digits, so that the linker's alphabetical sort effectively
becomes a numeric sort, and the reason for the inverting the numeric order of
priorities is because .ctors gets read backwards at startup.

  I did actually check the assembly somewhere between writing "IIRC" and
finishing my email as it happens.  For a testcase based on your example:

class Some_Class {
  int x;
public:
  Some_Class();
  ~Some_Class();
};

Some_Class  A  __attribute__ ((init_priority (2000)));
Some_Class  B  __attribute__ ((init_priority (543)));

... what we get is a static_initialization_and_destruction function that takes
the init priority level as an argument and constructs or destroys (per a
second argument) everything at that level only:

	.file	"clas.c"
	.globl	_A
	.bss
	.align 4
_A:
	.space 4
	.globl	_B
	.align 4
_B:
	.space 4
	.text
	.def	__Z41__static_initialization_and_destruction_0ii;	.scl	3;	.type	32;	.endef
__Z41__static_initialization_and_destruction_0ii:
LFB0:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$24, %esp
	cmpl	$1, 8(%ebp)
	jne	L2
	cmpl	$2000, 12(%ebp)
        ^^^^^^^^^^^^^^^^^^^^^^^
	jne	L3
        ^^^^^^^^^^
	movl	$_A, (%esp)
	call	__ZN10Some_ClassC1Ev
L3:
	cmpl	$543, 12(%ebp)
        ^^^^^^^^^^^^^^^^^^^^^^
	jne	L2
        ^^^^^^^^^^
	movl	$_B, (%esp)
	call	__ZN10Some_ClassC1Ev
L2:
	cmpl	$0, 8(%ebp)
	jne	L1
	cmpl	$543, 12(%ebp)
        ^^^^^^^^^^^^^^^^^^^^^^
	jne	L5
        ^^^^^^^^^^
	movl	$_B, (%esp)
	call	__ZN10Some_ClassD1Ev
L5:
	cmpl	$2000, 12(%ebp)
        ^^^^^^^^^^^^^^^^^^^^^^^
	jne	L1
        ^^^^^^^^^^
	movl	$_A, (%esp)
	call	__ZN10Some_ClassD1Ev
L1:
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
LFE0:


  Then we have __GLOBAL__[I/D] functions for each priority level, which load
the appropriate priority and construct/destruct argument and call that:

	.def	__GLOBAL__I.00543_A;	.scl	3;	.type	32;	.endef
__GLOBAL__I.00543_A:
LFB1:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	$543, 4(%esp)
        ^^^^^^^^^^^^^^^^^^^^^
	movl	$1, (%esp)
        ^^^^^^^^^^^^^^^^^^
	call	__Z41__static_initialization_and_destruction_0ii
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
LFE1:

	.def	__GLOBAL__D.00543_A;	.scl	3;	.type	32;	.endef
__GLOBAL__D.00543_A:
LFB2:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	$543, 4(%esp)
        ^^^^^^^^^^^^^^^^^^^^^
	movl	$0, (%esp)
        ^^^^^^^^^^^^^^^^^^
	call	__Z41__static_initialization_and_destruction_0ii
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
LFE2:

	.def	__GLOBAL__I.02000_A;	.scl	3;	.type	32;	.endef
__GLOBAL__I.02000_A:
LFB3:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	$2000, 4(%esp)
        ^^^^^^^^^^^^^^^^^^^^^^
	movl	$1, (%esp)
        ^^^^^^^^^^^^^^^^^^
	call	__Z41__static_initialization_and_destruction_0ii
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
LFE3:

	.def	__GLOBAL__D.02000_A;	.scl	3;	.type	32;	.endef
__GLOBAL__D.02000_A:
LFB4:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	$2000, 4(%esp)
        ^^^^^^^^^^^^^^^^^^^^^^
	movl	$0, (%esp)
        ^^^^^^^^^^^^^^^^^^
	call	__Z41__static_initialization_and_destruction_0ii
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
LFE4:

... and it is these routines that are inserted in reverse-priority order into
the .ctors and .dtors tables (don't forget that the .ctors table is run
backward, the .dtors is run forward):

	.section	.ctors.64992,"w"
	.align 4
	.long	__GLOBAL__I.00543_A
	.text

	.section	.dtors.64992,"w"
	.align 4
	.long	__GLOBAL__D.00543_A
	.text

	.section	.ctors.63535,"w"
	.align 4
	.long	__GLOBAL__I.02000_A
	.text

	.section	.dtors.63535,"w"
	.align 4
	.long	__GLOBAL__D.02000_A


  So that ought to be entirely global ordering at final-link time.  I don't
know if ELF does it differently.

    cheers,
      DaveK


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]