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 <<a href=3D"mailto:jhibbits@freebsd.org" target=3D"_blank">jhibb= its@freebsd.org</a>> 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've been working on the IfAPI conversion of all<br> network drivers in order to hide the contents of `struct ifnet`.=C2=A0 I= 9;m<br> pretty much done with the development, and it's all in review.<br> However, there's one bit that I'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'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's that.=C2=A0 The gcc12 port I have can't cope with= the sample blocks</div><div>code I found on Wikipedia:</div><div>/* blocks= -test.c */<br>#include <stdio.h><br>#include <Block.h><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("First ca= ll: %d\n", mycounter());<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 printf("S= econd call: %d\n", mycounter());<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 printf= ("Third call: %d\n", 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's no current users of __block in the ke= rnel. There's no kernel-specific Block.h file,</div><div>there'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't have a libkern/OSAtomic.h. I'm happy</div><div>to be= corrected on this though: I'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't enable blocks unless you pass it -fblock, so you'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'm thinking regardless of whether o= r not the project should do this, you'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>