Hi all,
I've been reading the heading comment of include/linux/init.h to learn
when and how __initdata can be used. Some of the help text doesn't seem
to match my observations, and some of it confused me and could probably
be made clearer. However, I don't feel completely comfortable with this
topic yet and would welcome comments.
First, the comment goes:
> /* These macros are used to mark some functions or
> * initialized data (doesn't apply to uninitialized data)
> * as `initialization' functions. The kernel can take this
> * as hint that the function is used only during the initialization
> * phase and free up used memory resources after
My tests (on i386) seem to suggest that "doesn't apply to uninitialized
data" only holds for non-global variables. Tagging uninitialized global
variables __initdata works, and moves the variables from .bss to .data.
Is it correct? Does it work on all archs? If so, the comment above
needs to be fixed.
Second, there is this sentence at the end of the help text:
> * Don't forget to initialize data not at file scope, i.e. within a function,
> * as gcc otherwise puts the data into the bss section and not into the init
> * section.
It took me quite some time to figure out that this part was solely
referring to *static* local variables. Of course, on second thought it
is obvious, as non-static local variables are allocated on the stack at
runtime, and not part of the binary. But I still believe that the text
could be made clearer by explicitely referring to static local
variables.
I'm also slightly puzzled by the whole concept of __initdata static
local variables. They only seem to make sense if the function itself is
tagged __init. If so, isn't it redundant to tag the data __initdata?
Below is a proposed clarification patch.
As a side question, given that an uninitialized global variable being
tagged __initdata will be moved from .bss to .data, will it become a
truly uninitialized variable? Or will it automatically be initialized
to 0 by the compiler as .bss is?
Thanks.
include/linux/init.h | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
--- linux-2.6.15-rc5.orig/include/linux/init.h 2005-10-28 18:24:46.000000000 +0200
+++ linux-2.6.15-rc5/include/linux/init.h 2005-12-04 15:00:24.000000000 +0100
@@ -4,11 +4,10 @@
#include <linux/config.h>
#include <linux/compiler.h>
-/* These macros are used to mark some functions or
- * initialized data (doesn't apply to uninitialized data)
- * as `initialization' functions. The kernel can take this
- * as hint that the function is used only during the initialization
- * phase and free up used memory resources after
+/* These macros are used to mark some functions or data
+ * as `initialization' material. The kernel can take this as hint
+ * that the function/data is used only during the initialization
+ * phase and free up used memory resources afterwards.
*
* Usage:
* For functions:
@@ -25,16 +24,22 @@
*
* extern int initialize_foobar_device(int, int, int) __init;
*
- * For initialized data:
+ * For initialized global and static local variables:
* You should insert __initdata between the variable name and equal
* sign followed by value, e.g.:
*
- * static int init_variable __initdata = 0;
+ * static int init_variable __initdata = 42;
* static char linux_logo[] __initdata = { 0x32, 0x36, ... };
*
- * Don't forget to initialize data not at file scope, i.e. within a function,
- * as gcc otherwise puts the data into the bss section and not into the init
- * section.
+ * For uninitialized global variables:
+ * You should add __initdata after the variable name, e.g.:
+ *
+ * static int init_variable __initdata;
+ *
+ * Tagging an uninitialized global variable "__initdata" will cause
+ * the compiler to move it from .bss to .data.
+ *
+ * Uninitialized static local variables cannot be made "__initdata".
*
* Also note, that this data cannot be "const".
*/
--
Jean Delvare
Am Sonntag 04 Dezember 2005 15:15 schrieb Jean Delvare:
> My tests (on i386) seem to suggest that "doesn't apply to uninitialized
> data" only holds for non-global variables. Tagging uninitialized global
> variables __initdata works, and moves the variables from .bss to .data.
> Is it correct? Does it work on all archs? If so, the comment above
> needs to be fixed.
Yes, your observation is correct. Note that newer gcc versions treat
data that is initialized to zero the same way as uninitialized data (by
putting it into .bss), but that should be independent of the architecture.
> I'm also slightly puzzled by the whole concept of __initdata static
> local variables. They only seem to make sense if the function itself is
> tagged __init. If so, isn't it redundant to tag the data __initdata?
No. If the function is tagged __init, it goes into the init section, but
static variable in it still go to .bss, so you have to flag them separately.
It would be nice if gcc could determine that automatically, but the
current __attribute__((section())) syntax does not allow that.
> As a side question, given that an uninitialized global variable being
> tagged __initdata will be moved from .bss to .data, will it become a
> truly uninitialized variable? Or will it automatically be initialized
> to 0 by the compiler as .bss is?
.bss is special in that it is not initialized by the compiler but by the
ELF loader, or case of the kernel, some very early kernel code.
Moving data from .bss to __initdata causes it to be initialized to
zero by the compiler and it becomes part of the object file.
> + *
> + * Uninitialized static local variables cannot be made "__initdata".
> ? *
As explained above, this sentence is wrong.
> *
> * Also note, that this data cannot be "const".
I think this sentence is wrong as well, can anyone clarify why you should
not be able to have const __initdata?
Arnd <><
On Sun, 4 Dec 2005 15:15:33 +0100,
Jean Delvare <[email protected]> wrote:
>Hi all,
>
>I've been reading the heading comment of include/linux/init.h to learn
>when and how __initdata can be used. Some of the help text doesn't seem
>to match my observations, and some of it confused me and could probably
>be made clearer. However, I don't feel completely comfortable with this
>topic yet and would welcome comments.
>
>First, the comment goes:
>
>> /* These macros are used to mark some functions or
>> * initialized data (doesn't apply to uninitialized data)
>> * as `initialization' functions. The kernel can take this
>> * as hint that the function is used only during the initialization
>> * phase and free up used memory resources after
>
>My tests (on i386) seem to suggest that "doesn't apply to uninitialized
>data" only holds for non-global variables. Tagging uninitialized global
>variables __initdata works, and moves the variables from .bss to .data.
>Is it correct? Does it work on all archs? If so, the comment above
>needs to be fixed.
gcc version dependent. Older versions of gcc put all uninitialized
global variables into .bss, even if there was an attribute like
__initdata that tried to use a different section. So we got into the
habit of '__initdata variables must be explicitly initialized'. Some
platforms are using old versions of gcc where that restriction may
still apply.
On Sun, Dec 04, 2005 at 05:41:43PM +0100, Arnd Bergmann wrote:
> From: Arnd Bergmann <[email protected]>
> To: Jean Delvare <[email protected]>
> Subject: Re: Questions on __initdata
> Date: Sun, 4 Dec 2005 17:41:43 +0100
> Cc: LKML <[email protected]>
> Content-Type: text/plain; charset=iso-8859-1
>
> Am Sonntag 04 Dezember 2005 15:15 schrieb Jean Delvare:
>
> > My tests (on i386) seem to suggest that "doesn't apply to uninitialized
> > data" only holds for non-global variables. Tagging uninitialized global
> > variables __initdata works, and moves the variables from .bss to .data.
> > Is it correct? Does it work on all archs? If so, the comment above
> > needs to be fixed.
>
> Yes, your observation is correct. Note that newer gcc versions treat
> data that is initialized to zero the same way as uninitialized data (by
> putting it into .bss), but that should be independent of the architecture.
>
> > I'm also slightly puzzled by the whole concept of __initdata static
> > local variables. They only seem to make sense if the function itself is
> > tagged __init. If so, isn't it redundant to tag the data __initdata?
>
> No. If the function is tagged __init, it goes into the init section, but
> static variable in it still go to .bss, so you have to flag them separately.
> It would be nice if gcc could determine that automatically, but the
> current __attribute__((section())) syntax does not allow that.
>
> > As a side question, given that an uninitialized global variable being
> > tagged __initdata will be moved from .bss to .data, will it become a
> > truly uninitialized variable? Or will it automatically be initialized
> > to 0 by the compiler as .bss is?
>
> .bss is special in that it is not initialized by the compiler but by the
> ELF loader, or case of the kernel, some very early kernel code.
> Moving data from .bss to __initdata causes it to be initialized to
> zero by the compiler and it becomes part of the object file.
>
> > + *
> > + * Uninitialized static local variables cannot be made "__initdata".
> > ? *
> As explained above, this sentence is wrong.
>
> > *
> > * Also note, that this data cannot be "const".
>
> I think this sentence is wrong as well, can anyone clarify why you should
> not be able to have const __initdata?
gcc hates it:
static const int __initdata somevariable = 42;
will result in something like:
blurb.c: At top level:
blurb.c:3: error: somevariable causes a section type conflict
Ralf
.file "id.c"
.section .inittext,"ax",@progbits
.p2align 4,,15
.globl somefunc
.type somefunc, @function
somefunc:
addl somevariable.1299, %eax
movl %eax, somevariable.1299
ret
.size somefunc, .-somefunc
.section .initdata,"aw",@progbits
.align 4
.type somevariable.1299, @object
.size somevariable.1299, 4
somevariable.1299:
.zero 4
.ident "GCC: (GNU) 4.2.0 20051201 (experimental)"
.section .note.GNU-stack,"",@progbits
On Tue, Dec 06, 2005 at 02:32:12PM +0100, Paweł Sikora wrote:
> Dnia poniedziałek, 5 grudnia 2005 21:37, Ralf Baechle napisał:
>
> > blurb.c: At top level:
> > blurb.c:3: error: somevariable causes a section type conflict
>
> This was a gcc bug. The current gcc mainline works fine.
That was gcc 3.4 which it this time is probably the most common compiler.
It'll be a while until it'll have been phased out - and const __initdata
isn't exactly a must-have construct anyway.
Ralf