Messages in this thread | | | From | Nick Desaulniers <> | Date | Tue, 5 May 2020 11:27:53 -0700 | Subject | Re: [PATCH v4 14/18] static_call: Add static_cond_call() |
| |
On Tue, May 5, 2020 at 11:13 AM Nick Desaulniers <ndesaulniers@google.com> wrote: > > On Tue, May 5, 2020 at 2:36 AM Peter Zijlstra <peterz@infradead.org> wrote: > > > > > > HJ, Nick, > > > > Any chance any of you can see a way to make your respective compilers > > not emit utter junk for this? > > > > On Mon, May 04, 2020 at 10:14:45PM +0200, Peter Zijlstra wrote: > > > > > https://godbolt.org/z/SDRG2q > > Woah, a godbolt link! Now we're speaking the same language. What were > you expecting? Us to remove the conditional check that a volatile read > wasn't NULL? (Not using READ_ONCE, produces the direct tail call I > suspect you're looking for, but am unsure if that's what you meant, > and understand that's not a solution). I am simultaneously impressed > and disgusted by this btw, cool stuff. > > i.e. > void *func = &name.func; \ > rather than > void *func = READ_ONCE(name.func); \
Changing void *func = READ_ONCE(name.func); \ to void *func = &READ_ONCE(name.func); \ produces the tail call. Not sure if that's relevant/what you were looking for/even correct (haven't thought to hard about the implications of that change; juggling other stuff ATM)
> (I'm surprised that `&name.func;` and `name.func;` also produce > different results). > > > > > > > --- > > > #include <stddef.h> > > > > > > > > > #define READ_ONCE(var) (*((volatile typeof(var) *)&(var))) > > > #define WRITE_ONCE(var, val) (*((volatile typeof(var) *)&(var)) = (val)) > > > > > > struct static_call_key { > > > void *func; > > > }; > > > > > > #define DECLARE_STATIC_CALL(name, func) \ > > > extern struct static_call_key name; \ > > > extern typeof(func) __SCT__##name; > > > > > > #define DEFINE_STATIC_COND_CALL(name, _func) \ > > > DECLARE_STATIC_CALL(name, _func) \ > > > struct static_call_key name = { \ > > > .func = NULL, \ > > > } > > > > > > static void __static_call_nop(void) > > > { > > > } > > > > > > #define __static_cond_call(name) \ > > > ({ \ > > > void *func = READ_ONCE(name.func); \ > > > if (!func) \ > > > func = &__static_call_nop; \ > > > (typeof(__SCT__##name)*)func; \ > > > }) > > > > > > #define static_cond_call(name) (void)__static_cond_call(name) > > > > > > static void inline static_call_update(struct static_call_key *call, void *func) > > > { > > > WRITE_ONCE(call->func, func); > > > } > > > > > > volatile int _x; > > > > > > void bar(int x) > > > { > > > _x = x; > > > } > > > > > > DEFINE_STATIC_COND_CALL(foo, bar); > > > > > > void ponies(int x) > > > { > > > static_cond_call(foo)(x); > > > } > > > > -- > Thanks, > ~Nick Desaulniers
-- Thanks, ~Nick Desaulniers
| |