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

From: Mark Millard <marklmi_at_yahoo.com>
Date: Thu, 25 May 2023 00:00:55 UTC
On May 24, 2023, at 09:52, Mark Millard <marklmi@yahoo.com> wrote:

> On May 22, 2023, at 13:16, Mark Millard <marklmi@yahoo.com> wrote:
> 
>> On May 22, 2023, at 03:00, Hans Petter Selasky <hps@selasky.org> wrote:
>> 
>>> On 5/22/23 01:07, Mark Millard wrote:
>>>> In the C language standard, the original had a status of "no linkage"
>>>> and "static storage duration". ("a block scope identifier
>>>> for an object declared without the storage-class specifier
>>>> extern" leads to the "no linkage" status.)
>>>> The change still has "static storage duration" but now has "internal
>>>> linkage" status instead. I'm being cautious about the distinction.
>>>> (I'm looking at ISO/IEC 9899:2011 (E).)
>>>> I've had trouble identifying the match of your wordings to the
>>>> language standard, leaving me unsure of the interpretation to
>>>> give your wording.
>>>> I've yet to figure out why internal linkage could end up
>>>> being required, given how the language specifies things.
>>> 
>>> Hi,
>>> 
>>> If you find something, let me know. I'll let the issue rest for some days.
>> 
>> Okay. File the below for later.
>> 
>> (Some detailed whitespace below might not survive.)
>> 
>> 
>> I still find no reason in the C11 standard to change
>> the code in question from:
>> 
>> Block Scope, No       Linkage, Static Storage Duration
>> 
>> into:
>> 
>> File  Scope, Internal Linkage, Static Storage Duration
>> 
>> I'll ponder the standard's text some more but I doubt
>> that I'll find something that I've missed so far.
>> 
>> 
>> I propose using 2 source files that I show below as
>> the basis for terminology. I set them up based on
>> text from the C11 standard. If you can explain why
>> Internal Linkage would be required in terms of some
>> similar example and terminology, it would help be
>> sure I'm not missing something that you are
>> referencing.
>> 
>> (Part of the text was just me trying to make sure that
>> I'd appropriately covered the allowed combinations of
>> official language concepts that are involved.)
>> 
>> 
>> # more NameScope_Linkage_StorageDuration_combinations.c
>> // For -std=c99 or c11 or c17 or c2x (showing c99):
>> 
>> // cc -std=c99 -pedantic -Wall -Wextra -c FileScope_ExternalLinkage_initialization.c
>> // cc -std=c99 -pedantic -Wall -Wextra NameScope_Linkage_StorageDuration_combinations.c FileScope_ExternalLinkage_initialization.o
>> // ./a.out
>> 
>> // gcc13 -std=c99 -pedantic -Wall -Wextra -c FileScope_ExternalLinkage_initialization.c
>> // gcc13 -std=c99 -pedantic -Wall -Wextra NameScope_Linkage_StorageDuration_combinations.c FileScope_ExternalLinkage_initialization.o
>> // ./a.out
>> 
>> 
>> // Indentification of contexts and the subset covered here:
>> 
>> // Just objects (not macros, functions, tags, typedefs names, lables, etc.):
>> //              (Note: function prototype scope is not relevant here)
>> //
>> // Scopes (visibility):   Block, File
>> // Linkages:              None (No), External, Internal
>> // Storage durations:     Automatic, Static (, Thread, Allocated)
>> // Name space:            Ordinary Identifiers (Note: no alternatives)
>> 
>> // Note: I do not cover any thread-storage-duration related contexts here.
>> // Note: I do not cover any allocated-storage-duration contexts here.
>> 
>> // Note: I do not cover the special non-lvalue expression contexts here
>> //       that involve the combination:
>> //       temporary-lifetime and automatic-storage-duration
>> 
>> // For reference:
>> // Static Storage Duration: "Its lifetime is the entire execution of the
>> //                           program and its storage value is initialized
>> //                           only once, prior to program startup."
>> //
>> // It need not be tied to file scope or to external/internal linkage.
>> 
>> // Covered here:
>> // Block Scope, No       Linkage, Automatic Storage Duration
>> // Block Scope, No       Linkage, Static    Storage Duration
>> // Block Scope, External Linkage, Static    Storage Duration
>> // File  Scope, Internal Linkage, Static    Storage Duration
>> // File  Scope, External Linkage, Static    Storage Duration
>> 
>> // Note: Only external linkage objects have a definition vs.
>> //       declaration distinction.
>> 
>> // I count 4 distinct non-stack types of whole-program-lifetime
>> // object contexts in that list: The static-storage-duration ones.
>> // But:
>> //
>> // Block Scope, External Linkage, Static    Storage Duration
>> //
>> // can only be used to declare access to an external-linkage
>> // defined elsewhere (defined outside any block scope).
>> 
>> // Note: There is no such thing as the combination:
>> //       Block Scope, Internal Linkage, Static Storage Duration
>> 
>> // Note: "Each declaration of an identifier with no linkage
>> //        denotes a unique entity." This prevents various
>> //        forms of multiple declarations for the same
>> //        namespace and scope combination.
>> 
>> #include <stdio.h>
>> 
>> // Note: Only automatic storage duration is in a call stack.
>> int Using_BlockScope_NoLinkage_AutomaticStorageDuration(void)
>> {
>>   int BlockScope_NoLinkage_AutomaticStorageDuration = 1;
>>   return ++BlockScope_NoLinkage_AutomaticStorageDuration;
>> }
>> 
>> // Note: No direct notation for file scope access exists but
>> //       the storage duration spans when the function is not
>> //       in use.
>> int Using_BlockScope_NoLinkage_StaticStorageDuration(void)
>> {
>>   static int BlockScope_NoLinkage_StaticStorageDuration = 1;
>>   return ++BlockScope_NoLinkage_StaticStorageDuration;
>> }
>> 
>> int Using_BlockScope_ExternalLinkage_StaticStorageDuration(void)
>> {
>>   // Note: Defined/initialized in FileScope_ExternalLinkage_initialization.c
>>   //       Such an external definition is not allowed in block scope.
>>   extern int ExternalLinkage_StaticStorageDuration; // a declaration
>>   return ++ExternalLinkage_StaticStorageDuration;
>> }
>> 
>> // Note: To have internal linkage requires a file scope declaration.
>> static int FileScope_InternalLinkage_StaticStorageDuration = 1;
>> // Note: after such an internal linkage definition, the following
>> //       is allowed (not required) but does not change the status.
>> //       "extern" does not always mean external-storage-duration.
>> extern int FileScope_InternalLinkage_StaticStorageDuration;
>> int Using_FileScope_InternalLinkage_StaticStorageDuration(void)
>> {
>>   // Note: after such an internal linkage definition, the following
>>   //       is allowed (not required) but does not change the status.
>>   //       "extern" does not always mean external-storage-duration.
>>   extern int FileScope_InternalLinkage_StaticStorageDuration;
>> 
>>   return ++FileScope_InternalLinkage_StaticStorageDuration;
>> }
>> 
>> // Note: Defined/initialized in FileScope_ExternalLinkage_initialization.c
>> extern int FileScope_ExternalLinkage_StaticStorageDuration; // a declaration
>> // Note: Without "extern", a definition would be allowed above, instead
>> //       of having one in FileScope_ExternalLinkage_initialization.c .
>> int Using_FileScope_ExternalLinkage_StaticStorageDuration(void)
>> {
>>   return ++FileScope_ExternalLinkage_StaticStorageDuration;
>> }
>> 
>> int main(void)
>> {
>>   (void) Using_BlockScope_NoLinkage_AutomaticStorageDuration();
>>   printf("Using_BlockScope_NoLinkage_AutomaticStorageDuration()   : %d (expect 2)\n"
>>         , Using_BlockScope_NoLinkage_AutomaticStorageDuration());
>> 
>>   (void) Using_BlockScope_NoLinkage_StaticStorageDuration();
>>   printf("Using_BlockScope_NoLinkage_StaticStorageDuration()      : %d (expect 3)\n"
>>         , Using_BlockScope_NoLinkage_StaticStorageDuration());
>> 
>>   (void) Using_BlockScope_ExternalLinkage_StaticStorageDuration();
>>   printf("Using_BlockScope_ExternalLinkage_StaticStorageDuration(): %d (expect 3)\n"
>>         , Using_BlockScope_ExternalLinkage_StaticStorageDuration());
>> 
>>   (void) Using_FileScope_InternalLinkage_StaticStorageDuration();
>>   printf("Using_FileScope_InternalLinkage_StaticStorageDuration() : %d (expect 3)\n"
>>         , Using_FileScope_InternalLinkage_StaticStorageDuration());
>>   printf("Accessing FileScope_InternalLinkage_StaticStorageDuration : %d (expect 3 again)\n"
>>         , FileScope_InternalLinkage_StaticStorageDuration);
>> }
>> 
>> 
>> # more FileScope_ExternalLinkage_initialization.c
>> // For -std=c99 or c11 or c17 or c2x (showing c99):
>> 
>> // cc -std=c99 -pedantic -Wall -Wextra -c NameScope_Linkage_StorageDuration_combinations.c
>> 
>> // gcc13 -std=c99 -pedantic -Wall -Wextra -c NameScope_Linkage_StorageDuration_combinations.c
>> 
>> // Defined at file scope here.
>> // Used separately at block scope elsewhere.
>> // The definition can not be in block scope.
>> int ExternalLinkage_StaticStorageDuration = 1; // a definition
>> 
>> // Defined at file scope here.
>> // Used separately at file scope elsewhere.
>> int FileScope_ExternalLinkage_StaticStorageDuration = 1; // a definition
>> 
> 
> It has been a few days. So I'll add the following.
> 
> Stepping outside the language definition, in
> case you are curious about an example of how:
> 
> Block Scope, No       Linkage, Static    Storage Duration
> 
> can be handled by a toolchain, in a FreeBSD
> main aarch64 context I get:
> 
> # nm a.out | grep Linkage
> 0000000000410c7c d BlockScope_NoLinkage_StaticStorageDuration.0
> 0000000000410c80 D ExternalLinkage_StaticStorageDuration
> 0000000000410c84 D FileScope_ExternalLinkage_StaticStorageDuration
> 0000000000410c78 d FileScope_InternalLinkage_StaticStorageDuration
> 00000000004005e4 T Using_BlockScope_ExternalLinkage_StaticStorageDuration
> 0000000000400594 T Using_BlockScope_NoLinkage_AutomaticStorageDuration
> 00000000004005b8 T Using_BlockScope_NoLinkage_StaticStorageDuration
> 000000000040063c T Using_FileScope_ExternalLinkage_StaticStorageDuration
> 0000000000400610 T Using_FileScope_InternalLinkage_StaticStorageDuration
> 
> "BlockScope_NoLinkage_StaticStorageDuration.0" is not a valid
> C identifier but has a structure allowing making each such:
> 
> Block Scope, No       Linkage, Static    Storage Duration
> 
> unique when the identifier part is not: replacing the 0 in .0
> with other numerals, incrementing values, say. The "d" status
> avoids it being external.
> 
> Overall, then there is nothing else having a possible linkage:
> "linkage none" in the C11 standard's terms.

I took a look at a . . ./sys/modules/mlx4/mlx4_main.o via nm
and it showed a different convention for creating uniqueness
for the type of context involved:

static ssize_t set_port_type(struct device *dev,
 			    struct device_attribute *attr,
 			    const char *buf, size_t count)
{
. . .
	static DEFINE_MUTEX(set_port_type_mutex);
. . .

ended up with the static routine's name prefixed,
with a "." separator:

0000000000006da0 t set_port_type
0000000000000018 d set_port_type.__set_sysinit_set_sym_set_port_type_mutex_sx_sysinit_sys_init
0000000000000008 d set_port_type.__set_sysuninit_set_sym_set_port_type_mutex_sx_sysuninit_sys_uninit
0000000000000020 b set_port_type.set_port_type_mutex
00000000000004a8 d set_port_type.set_port_type_mutex_args
00000000000004c0 d set_port_type.set_port_type_mutex_sx_sysinit_sys_init
00000000000004d8 d set_port_type.set_port_type_mutex_sx_sysuninit_sys_uninit

This was based on:

# uname -apKU # long output line manually split for readability
FreeBSD CA72_16Gp_ZFS 14.0-CURRENT FreeBSD 14.0-CURRENT #94
main-n262658-b347c2284603-dirty: Fri Apr 28 19:57:23 PDT 2023
root@CA72_16Gp_ZFS:/usr/obj/BUILDs/main-CA72-nodbg-clang/usr/main-src/arm64.aarch64/sys/GENERIC-NODBG-CA72
arm64 aarch64 1400088 1400088

and so the context predates any changes.

===
Mark Millard
marklmi at yahoo.com