Re: [RFC] An idea for general kernel post-processing automation in FreeBSD
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