Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Mar 2023 09:04:29 -0600
From:      Warner Losh <imp@bsdimp.com>
To:        Justin Hibbits <jhibbits@freebsd.org>
Cc:        "freebsd-arch@freebsd.org" <freebsd-arch@freebsd.org>
Subject:   Re: Blocks runtime in the kernel
Message-ID:  <CANCZdfrqSc5cuU=Pbo_fGKmbTeeoTYUaYPqZUahRar1XkbJ6=A@mail.gmail.com>
In-Reply-To: <20230316100611.4892008c@gonegalt.net>
References:  <20230316100611.4892008c@gonegalt.net>

next in thread | previous in thread | raw e-mail | index | archive | help
--000000000000b8964a05f705c77a
Content-Type: text/plain; charset="UTF-8"

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

--000000000000b8964a05f705c77a
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div dir=3D"auto"><div><br><br><div class=3D"gmail_quote">=
<div dir=3D"ltr" class=3D"gmail_attr">On Thu, Mar 16, 2023, 8:06 AM Justin =
Hibbits &lt;<a href=3D"mailto:jhibbits@freebsd.org" target=3D"_blank">jhibb=
its@freebsd.org</a>&gt; wrote:<br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Most=
 probably know I&#39;ve been working on the IfAPI conversion of all<br>
network drivers in order to hide the contents of `struct ifnet`.=C2=A0 I&#3=
9;m<br>
pretty much done with the development, and it&#39;s all in review.<br>
However, there&#39;s one bit that I&#39;ve thought is very clunky since I a=
dded<br>
it, the if_foreach() iterator function, which iterates over all<br>
interfaces in the current VNET, and calls a callback to operate on each<br>
interface.=C2=A0 I&#39;ve noticed that oftentimes I end up with a 2 line<br=
>
callback, which just calls if_foreach_addr_type(), so I end up with<br>
just trivial callback functions, which seems like a waste.<br>
<br>
All that backstory to say, would it be beneficial to anyone else to<br>
add a (very basic) blocks runtime to the kernel for doing things like<br>
this?=C2=A0 The rough change to the IfAPI becomes:<br>
<br>
int if_foreach_b(int (^)(if_t));<br>
<br>
__block int foo =3D 0;<br>
<br>
if_foreach_b(^(if_t ifp) {<br>
=C2=A0 if (if_getlinkstate(ifp) =3D=3D LINK_STATE_UP)<br>
=C2=A0 =C2=A0 foo++;<br>
});<br>
<br>
The same could be done for other *_foreach KPIs as well, if this proves<br>
out.=C2=A0 I think I could have something working in the next several days.=
<br>
<br>
The only technical snag I see with this would be other compilers.=C2=A0 I&#=
39;m<br>
not sure if GCC still supports blocks, it did at one point.<br>
<br>
What do you think?<br></blockquote></div></div><div dir=3D"auto"><br></div>=
<div dir=3D"auto"><br></div><div dir=3D"auto"><a href=3D"https://gcc.gnu.or=
g/bugzilla/show_bug.cgi?id=3D78352" target=3D"_blank">https://gcc.gnu.org/b=
ugzilla/show_bug.cgi?id=3D78352</a></div><div dir=3D"auto"><br></div><div d=
ir=3D"auto">Suggests that there were issues upstreaming the apple code. So<=
/div><div>there&#39;s that.=C2=A0 The gcc12 port I have can&#39;t cope with=
 the sample blocks</div><div>code I found on Wikipedia:</div><div>/* blocks=
-test.c */<br>#include &lt;stdio.h&gt;<br>#include &lt;Block.h&gt;<br>/* Ty=
pe of block taking nothing returning an int */<br>typedef int (^IntBlock)()=
;<br><br>IntBlock MakeCounter(int start, int increment) {<br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 __block int i =3D start;<br><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 r=
eturn Block_copy( ^(void) {<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 int ret =3D i;<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 i +=3D increment;<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 return ret;<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 });<br><br>}<b=
r><br>int main(void) {<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 IntBlock mycounter =
=3D MakeCounter(5, 2);<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 printf(&quot;First ca=
ll: %d\n&quot;, mycounter());<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 printf(&quot;S=
econd call: %d\n&quot;, mycounter());<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 printf=
(&quot;Third call: %d\n&quot;, mycounter());<br><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 /* because it was copied, it must also be released */<br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 Block_release(mycounter);<br><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 return 0;<br>}<br></div><div><br></div><div>Our current clang is OK:</d=
iv><div>% clang -fblocks a.c -o a -lBlocksRuntime<br></div><div>%=C2=A0</di=
v><div><br></div><div>But there&#39;s no current users of __block in the ke=
rnel. There&#39;s no kernel-specific Block.h file,</div><div>there&#39;s no=
 references to BlockRuntime anywhere in the kernel tree and the code in</di=
v><div>contrib/llvm-project/compiler-rt/lib/BlocksRuntime is completely use=
rland specific. There<br></div><div>is no kernel support that I could see, =
since we don&#39;t have a libkern/OSAtomic.h. I&#39;m happy</div><div>to be=
 corrected on this though: I&#39;ve never tried to use blocks in the kernel=
 and this is grep</div><div>level confidence.</div><div><br></div><div>Clan=
g also doesn&#39;t enable blocks unless you pass it -fblock, so you&#39;d n=
eed to change a fair</div><div>portion of the kernel build system to enable=
 that.</div><div><br></div><div>So I&#39;m thinking regardless of whether o=
r not the project should do this, you&#39;ll have a fair amount</div><div>o=
f choppy waves ahead of you before you could get to the point of starting t=
he ifnet work.</div><div><br></div><div>Warner</div></div>
</div>

--000000000000b8964a05f705c77a--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CANCZdfrqSc5cuU=Pbo_fGKmbTeeoTYUaYPqZUahRar1XkbJ6=A>