CALL_ONCE(3) Library Functions Manual CALL_ONCE(3)

call_oncedynamic package initialization

#include <threads.h>

void call_once(once_flag *flag, void (*init_routine)(void));
once_flag flag = ONCE_FLAG_INIT;

[CX] The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1-2024 defers to the ISO C standard.

The call_once () function shall use the pointed to by flag to ensure that init_routine is called exactly once, the first time the call_once () function is called with that value of flag. Completion of an effective call to the call_once () function shall synchronize with all subsequent calls to the call_once () function with the same value of flag.

[CX] The call_once () function is not a cancellation point. However, if init_routine is a cancellation point and is canceled, the effect on flag shall be as if call_once () was never called.

If the call to init_routine is terminated by a call to longjmp(3) or siglongjmp(3), the behavior is undefined.

The behavior of call_once () is undefined if flag has automatic storage duration or is not initialized by ONCE_FLAG_INIT.

The call_once () function shall not be affected if the calling thread executes a signal handler during the call.

The call_once () function shall not return a value.

No errors are defined.

None.

If init_routine recursively calls call_once () with the same flag, the recursive call will not call the specified init_routine, and thus the specified init_routine will not complete, and thus the recursive call to call_once () will not return. Use of longjmp(3) or siglongjmp(3) within an init_routine to jump to a point outside of init_routine prevents init_routine from returning.

For dynamic library initialization in a multi-threaded process, if an initialization flag is used the flag needs to be protected against modification by multiple threads simultaneously calling into the library. This can be done by using a statically-initialized mutex. However, the better solution is to use call_once () or pthread_once(3) which are designed for exactly this purpose, for example:

#include <threads.h>
static once_flag random_is_initialized = ONCE_FLAG_INIT;
extern void initialize_random(void);

int random_function()
{
    call_once(&random_is_initialized, initialize_random);
    ...
    /* Operations performed after initialization. */
}

The call_once () function is not affected by signal handlers for the reasons stated in XRAT B.2.3 Error Numbers.

None.

pthread_once(3)

XBD V1_chap04(7), <threads.h>

First released in Issue 8. Included for alignment with the ISO/IEC 9899:2018 standard.

June 14, 2024 posix.fail