Re: [RFC] An idea for general kernel post-processing automation in FreeBSD

From: Hans Petter Selasky <hps_at_selasky.org>
Date: Thu, 25 May 2023 15:28:41 UTC
On 5/25/23 16:03, John Baldwin wrote:
>> To be more precise:
>>
>> The static mutex can only be accessed from within the routine itself,
>> when it is part of a block scope. That is expected.
>>
>> However the static sysinit, which is also inside the block scope of the
>> function, is accessed from _outside_ the function.
>> This might be viewed as a violation of the block scope limitation.
>>
>> Therefore the DEFINE_MUTEX() should be outside the block scope, due to
>> how it is implemented in the LinuxKPI currently.
> 
> I don't think you are correct here.  A sysinit is much like a constructor,
> and it's perfectly valid to pass a pointer to an object that can not be
> accessed by name outside of a scope to some other bit of code outside of
> that scope (e.g. a constructor).  It's not even just the SYSINIT.  You are
> passing a pointer to this function-static variable to routines like
> sx_xlock, etc. as well which is also outside of scope, but that's perfectly
> fine.  The scoping rules are about when the compiler can resolve the
> variable by name, not restricting which bits of code are able to access
> the variable by reference/pointer.

Hi John,

> 
> However, I also think that this sub-thread has passed its point of 
> usefulness
> and should end.

Yes, I know. I'm going far too deep into the details, but maybe others 
reading this find it useful. Like competence sharing. Who knows.

FreeBSD sysinits are custom constructors and destructors, primarily by 
using the section attribute for the sysinit structures.

FreeBSD does not use the compiler supported constructor feature. I 
noticed the constructor attribute in clang can take a priority, and just 
want to point out it ends up by suffixing the priority as a decimal 
integer, to the section name:

   5 .init_array.0       00000008 0000000000000000
   6 .rela.init_array.0  00000018 0000000000000000
   7 .init_array.11      00000008 0000000000000000
   8 .rela.init_array.11 00000018 0000000000000000

 From this:

#define _c(x) __attribute__((__constructor__(x)))

static void _c(11)
test0()
{
         printf("test0()\n");
}

static void _c(0)
test1()
{
         printf("test1()\n");
}


Trying a 17-bit priority _c(1 << 16):

# gcc12 -Wall -c test.c
test.c:10:1: error: constructor priorities must be integers from 0 to 
65535 inclusive
    10 | {
       | ^

And clang just masks the value, so (1 << 16) becomes 0, without any kind 
of warning.

# clang15 -Wall -c test.c


This leaves us where we are currently. FreeBSD uses a custom constructor 
mechanism for startup, and the bloat associated with it, because of 
missing compiler and linker support, but we are close to a solution. 
Maybe just propose two arguments for __constructor__ and then we have 
all we need!


--HPS