RUN_ONCE(9)

πŸ“¦ version 11.0, in nixpkgs unstable

πŸ’… RUN_ONCE πŸ’…

okay so this is a page from the Kernel Developer's Manual and honestly? it's giving "one and done" energy and i am obsessed. it's RUN_ONCE, INIT_ONCE, and FINI_ONCE β€” the trio that makes sure your function runs exactly once, no cap. periodt. πŸŽ€


✨ SYNOPSIS ✨

first you gotta bring in the header, bestie:

#include <sys/once.h>

then you declare the control thingy:

ONCE_DECL(control);

and then the actual functions, look:

int
RUN_ONCE(once_t *control, int (*init_func)(void));

int
INIT_ONCE(once_t *control, int (*init_func)(void));

void
FINI_ONCE(once_t *control, void (*fini_func)(void));

πŸ¦‹ DESCRIPTION πŸ¦‹

so RUN_ONCE() is literally the kernel's answer to pthread_once(3) β€” same vibe, different function. what it does is it guarantees that, for a given control, init_func() gets executed (successfully, mind you) exactly one single time. iconic behavior honestly.

and what counts as "successful"? it's a successful execution if and only if init_func() returned 0. that's it, that's the rule πŸ‘‘

now the important part: as long as there has not been a successful execution, RUN_ONCE() will just... try again. every time it's called. it's persistent like that. πŸ’ͺ

also heads up β€” RUN_ONCE() can sleep if it's called concurrently. so don't be weird about it in a context where sleeping is illegal, iykyk.

then we have INIT_ONCE(), which is the bestie to FINI_ONCE() β€” they come as a pair, fr fr.

  • INIT_ONCE() will only be run once, same deal as RUN_ONCE().
  • FINI_ONCE() will only be run at the last time, and only if it's called as many times as INIT_ONCE() was called.
  • when FINI_ONCE() does get executed, the next call to INIT_ONCE() will be executed again. so basically INIT_ONCE() and FINI_ONCE() can be nested. cute, right? πŸŽ€

πŸ’– RETURN VALUES πŸ’–

  • on failure, RUN_ONCE() returns whatever init_func() returned. like, it's not gonna sugarcoat it for you.
  • otherwise, it returns 0. slay. ✨

🌸 EXAMPLES 🌸

okay so here's how you actually use RUN_ONCE(). the flex here is that no matter how many times some_func() gets executed, init_func() will be executed exactly once. no more, no less. main character energy.

static int
init_func(void)
{

        /*
         * do some initialization.
         */

        return 0; /* success */
}

int
some_func(void)
{
        static ONCE_DECL(control);

        RUN_ONCE(&control, init_func);

        /*
         * we are sure that init_func has already been completed here.
         */
}

see that little comment at the end? that's the whole point β€” after RUN_ONCE(&control, init_func); you can rest easy knowing init_func is fully done. 🫢


πŸ‘€ SEE ALSO πŸ‘€

go check these out if you want the full lore:


ngl this one's a classic. anyway bestie, that's the whole page β€” go write something that only runs once, and make it iconic πŸ’œ

🌈 and that's a wrap! this page was brought to you by Debian, dated March 19, 2019 β€” mwah, kisses, and may your init functions always return 0 πŸŽ€πŸ’…

πŸ“¦ where this page comes from