[HN Gopher] Toward a better list iterator for the Linux kernel ___________________________________________________________________ Toward a better list iterator for the Linux kernel Author : chmaynard Score : 52 points Date : 2022-03-10 20:23 UTC (2 hours ago) (HTM) web link (lwn.net) (TXT) w3m dump (lwn.net) | dataflow wrote: | > One might argue that all of this is self-inflicted pain caused | by the continued use of C in the kernel. That may be true, but | better alternatives are in somewhat short supply. For example, | since the Rust language, for all of its merits, does not make | life easy for anybody wanting to implement a linked list, a | switch to that language would not automatically solve the problem | | I feel like the elephant in the room is C++. | Hermitian909 wrote: | > I feel like the elephant in the room is C++. | | I don't think it's an elephant given how well trod the topic | is. Linux maintainers want to avoid political fights about | which subset of C++ the kernel uses, this is a struggle in | large companies with top-down structures and would be a | nightmare in something as collective as the kernel. Greg and | Linus don't seem shy about occasionally saying "yes, it'd be | nice if C has [C++ feature], oh well" but still want to | maintain the current set of tradeoffs. | jdlyga wrote: | "Toward a better list iterator for the Linux kernel" is a great | name for a ship in the Halo universe | bitwize wrote: | Or Banks's Culture novels. I bet _Towards a Better List | Iterator for the Linux Kernel_ is great friends with _Smashing | the Stack for Fun and Profit_. | dbrueck wrote: | Or a SpaceX drone ship! | bitwize wrote: | Y'know, these kinds of problems could have been avoided if Linus | had simply... allowed C++ in the kernel. This may not be an "RMS | not allowing GCC to expose the AST" tier instance of the BDFL | obstructing a project's forward progress, but it's clear real | damage has been done. | tptacek wrote: | There were strongly persuasive arguments against C++ when this | was first litigated, and while those arguments have been | blunted by C++'s progress in the ensuing time, at this point, | if you're going to introduce a higher-level language to the | kernel, it might as well be something with pro-forma memory | safety, like Rust. | google234123 wrote: | Can there really be fair arguments when you have a culture of | bullying? | tptacek wrote: | Yes. Also, I didn't use the word "fair". | dbrueck wrote: | The cost/benefit ratio would be way off though. The article | mentions one of the proposals that Linus shot down "because it | did nothing to prevent future problems from being introduced". | | Were they to use C++ in the kernel they'd have to first define | which subset of C++ is allowed (in practice pretty much nobody | uses all of C++ but instead uses some subset of it that they | have more or less learned to use safely, and that subset varies | wildly from person to person), and /then/ they'd have to add | tooling to make sure nobody varies from that subset. :) | stjohnswarts wrote: | Honestly the core kernel programmers are extremely | intelligent and I would trust their "subset" selection better | than 99.999% of the other coders out there. Tamed of course | with some input from graybeards like Stroustrup who I'm sure | would be happy to interject his guidance ;) . I kind of wish | Linus would relent... | codys wrote: | For more advanced intrusive lists in C, I've found that ccan's | tlist2 | (https://github.com/rustyrussell/ccan/blob/master/ccan/tlist2...) | provides a decent model here. | | Compared to the linux kernel's intrusive lists, it also tracks | the offset of the list_node within the structure contained by the | list, which eliminates another class of problems. It does still | have the "using the iterator after the for loop is over" issue | discussed in this article, but it also already tracks the types | as Linus proposed doing in the article to resolve the issue. | loeg wrote: | Seems pretty similar to FreeBSD's queue(3) (sys/queue.h). | | https://www.freebsd.org/cgi/man.cgi?query=queue&apropos=0&se... | | https://github.com/freebsd/freebsd-src/blob/main/sys/sys/que... | wahern wrote: | For some reason the Linux community became enamored of the | `container_of` construct, which eases typecasting across | related structures, and built all their quasi-generic data | structure around it. Whereas the traditional BSD | implementations (substantially unchanged since 4.4BSD) never | needed that bit of black magic; developers simply learned to | avoid playing fast-and-loose with struct types in the first | place. | | In general the BSD implementations are more type-safe (just | plain type-safe, actually), and IMO easier to use and much | simpler to understand. | bee_rider wrote: | This is really part of the intro, but I wonder if someone knows | anyway: | | My very naive first guess at making a generic linked list would | be, of course, a struct with a 'next,' 'prev,' and the void | pointer to the payload (What can I say? At some point my brain | was damaged by OO languages). I guess their method of instead | defining a struct, embedding the linked list into it, and then | using macros would probably interact more nicely with the type | system. | | Are there other benefits, though? I vaguely suspect their system | might tend to prod users toward laying out their memory more | nicely. | dottedmag wrote: | Cache locality and memory consumption. | loeg wrote: | > Are there other benefits, though? | | Yes; you're avoiding an extra pointer indirection between list | navigation and element access, which is usually going to be a | cache miss. Also if you have a pointer to an element of an | intrusive list, you can cheaply navigate to the next element; | this wouldn't work with your external list scheme (you'd need | to maintain a separate list pointer instead). | re wrote: | This is called "internal" vs. "external" storage, or sometimes | an "intrusive linked list". Fewer allocations and better | locality of reference for faster access are some of the biggest | benefits. There's more discussion here: | https://en.wikipedia.org/wiki/Linked_list#Internal_and_exter... | bitcharmer wrote: | Dupe: | | https://news.ycombinator.com/item?id=30629914 | phkahler wrote: | I had a need for doubly linked list and realized you can make the | prev-> pointer point to a pointer_to_object rather than to an | object (a pointer to a pointer). You point the prev pointer at | the prior next-> pointer. In other words, the Nth objects prev | pointer points at the (N-1)th objects next pointer. This was huge | PITA but it allowed me to avoid putting an entire struct in the | base object, just a single pointer initialized to NULL. So: | | BASE_OBJ->linked_obj1->linked_obj2->NULL | | Not showing the back links here, but BASE_OBJ only contains a | pointer to linked_obj1 rather than an instance of its structure. | You can add items to the list via that first pointer. Deletes | work the same as usual too with the oddity of dealing with that | *object. | jjnoakes wrote: | Not sure I follow, can you explain with a code snippet? | kevin_thibedeau wrote: | If you need cheap double linking you should consider an XOR | linked list. | jmholla wrote: | Wouldn't it need to be N-2? N-1's next is N, but prev should | point to N-1. | dahfizz wrote: | > Not showing the back links here, but BASE_OBJ only contains a | pointer to linked_obj1 rather than an instance of its | structure. | | I don't understand what you are after.... | struct Foo { struct Foo* prev; //Just a pointer, not | an actual struct struct Foo* next; //Just a pointer, | not an actual struct }; | | That lets you "avoid putting an entire struct in the base | object" without using a double pointer. It sounds like you did | this: struct Foo { struct Foo** prev; | //double pointer struct Foo* next; }; | | Which works, but is strange... ___________________________________________________________________ (page generated 2022-03-10 23:00 UTC)