Re: Blocks runtime in the kernel

From: Warner Losh <imp_at_bsdimp.com>
Date: Thu, 16 Mar 2023 15:04:29 UTC
On Thu, Mar 16, 2023, 8:06 AM Justin Hibbits <jhibbits@freebsd.org> wrote:

> Most probably know I've been working on the IfAPI conversion of all
> network drivers in order to hide the contents of `struct ifnet`.  I'm
> pretty much done with the development, and it's all in review.
> However, there's one bit that I've thought is very clunky since I added
> it, the if_foreach() iterator function, which iterates over all
> interfaces in the current VNET, and calls a callback to operate on each
> interface.  I've noticed that oftentimes I end up with a 2 line
> callback, which just calls if_foreach_addr_type(), so I end up with
> just trivial callback functions, which seems like a waste.
>
> All that backstory to say, would it be beneficial to anyone else to
> add a (very basic) blocks runtime to the kernel for doing things like
> this?  The rough change to the IfAPI becomes:
>
> int if_foreach_b(int (^)(if_t));
>
> __block int foo = 0;
>
> if_foreach_b(^(if_t ifp) {
>   if (if_getlinkstate(ifp) == LINK_STATE_UP)
>     foo++;
> });
>
> The same could be done for other *_foreach KPIs as well, if this proves
> out.  I think I could have something working in the next several days.
>
> The only technical snag I see with this would be other compilers.  I'm
> not sure if GCC still supports blocks, it did at one point.
>
> What do you think?
>


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78352

Suggests that there were issues upstreaming the apple code. So
there's that.  The gcc12 port I have can't cope with the sample blocks
code I found on Wikipedia:
/* blocks-test.c */
#include <stdio.h>
#include <Block.h>
/* Type of block taking nothing returning an int */
typedef int (^IntBlock)();

IntBlock MakeCounter(int start, int increment) {
        __block int i = start;

        return Block_copy( ^(void) {
                int ret = i;
                i += increment;
                return ret;
        });

}

int main(void) {
        IntBlock mycounter = MakeCounter(5, 2);
        printf("First call: %d\n", mycounter());
        printf("Second call: %d\n", mycounter());
        printf("Third call: %d\n", mycounter());

        /* because it was copied, it must also be released */
        Block_release(mycounter);

        return 0;
}

Our current clang is OK:
% clang -fblocks a.c -o a -lBlocksRuntime
%

But there's no current users of __block in the kernel. There's no
kernel-specific Block.h file,
there's no references to BlockRuntime anywhere in the kernel tree and the
code in
contrib/llvm-project/compiler-rt/lib/BlocksRuntime is completely userland
specific. There
is no kernel support that I could see, since we don't have a
libkern/OSAtomic.h. I'm happy
to be corrected on this though: I've never tried to use blocks in the
kernel and this is grep
level confidence.

Clang also doesn't enable blocks unless you pass it -fblock, so you'd need
to change a fair
portion of the kernel build system to enable that.

So I'm thinking regardless of whether or not the project should do this,
you'll have a fair amount
of choppy waves ahead of you before you could get to the point of starting
the ifnet work.

Warner