On Thu, Apr 6, 2023 at 1:03 PM Arnd Bergmann <arnd@xxxxxxxx> wrote: > > As far as I can tell, almost no users of > {cmp,}xchg{,_local,_relaxed,acquire,release} that actually use > 8-bit and 16-bit objects, and they are not even implemented on > some architectures. Yeah, I think we only have a driver or two that wants to do a 8/16-bit cmpxchg, and many architectures don't support it at all natively (ie it has to be implemented as a load-mask-store). But iirc we *did* have a couple of uses, so.. > There is already a special case for the 64-bit xchg()/cmpxchg() > variants that can get called on 32-bit architectures, so what > I'd prefer is having each architecture implement only explicit > fixed length cmpxchg8(), cmpxchg16(), cmpgxchg32() and optionally > cmpxchg64() interfaces as normal inline functions that work on > the respective integer types. Hmm. Maybe. Except the reason we have those size-dependent macros is that it is *really* really convenient - to the point of being very important - when different architectures (or different kernel configurations) end up causing the same logical thing to have different sizes. The whole "switch (sizeof(x))" model with complex macros is very ugly and I'd much rather strive to implement something that is much more geared to actual compiler issues where the compiler really explicitly does select the right thign (rather than have the preprocessor expand it to multiple things and then depending on the optimizer to do the "selection"). But at the same time, aside from the macro ugliness, it really ends up being *hugely* powerful as a concept, and avoiding a lot of conditionals in the use cases. Now, cmpxchg *may* be uncommon enough that the use cases are limited enough that the "generic size" model wouldn't be worth it there, but I was really thinking about the more generic cases. Things like "get_user()" and "put_user()" would be *entirely* useless without the automatic sizing. How do I know? because we originally didn't have "get_user()". We had "get_fs_byte()" and "get_fs_word()" etc. The "fs" part was due to the original x86 implementation, so ignore the naming, but the issue with "just use fixed types" really DOES NOT WORK when different architectures have different types. So switching over to "get_user()" that just automatically did the right thing based on size instead of the size-specific ones really was a huge deal. There's no way we could ever go back. And while 'cmpxchg()' is the problem case here, I really think it would be lovely if we had some nice *unified* way of handling these "use size of access to determine variant" thing. Something like _Generic, just based on size. I guess __builtin_choose_expr() might be the right way to go there. That's very much a "compiler statically picks one over the other" interface. I despise the syntax, which is why it's not very commonly used, but it might be what we should use. Of course, another reason - other than syntax - for our "switch (sizeof())" model is simply history. The kernel "get_user()" interfaces go back to 1995 and Linux-1.3.0, and actually predates __builtin_choose_expt() support in gcc by several years. Gcc only started doing that in 2001 (gcc-3.4.5) So we do have a few uses of __builtin_choose_expr() in the kernel, but our really old interfaces simply didn't even have it available. Linus