Multi-step thread-safe initialization and finalization (init_fini.h)

The API is defined in the header file sysroot-*-kos/include/kos/init_fini.h from the KasperskyOS SDK.

The API lets you define a sequence of initialization/finalization steps that will be performed in their forward order during initialization and in reverse order during finalization, for example, when a program starts and terminates. This sequence of steps is an array of structures that, along with other fields, contain fields for the IDs of callback functions for initialization and finalization. In other words, a step is a structure that contains the ID of the callback function for initialization and/or the ID of the callback function for finalization. Initialization occurs via calls of the initialization callback functions when the steps are enumerated in ascending order of their indexes in the array. Finalization occurs via calls of the finalization callback functions when the steps are enumerated in descending order of their indexes in the array. If an error occurs at step i when calling the initialization callback function, initialization does not continue. Instead, finalization is performed starting with step i-1 to undo the part of initialization that was successfully completed prior to the error. If an error occurs when calling the finalization callback function, finalization does not continue.

The startup of initialization and finalization has a thread-safe implementation.

Information about API macros is provided in the table below.

Creating a sequence of initialization/finalization steps

To create a sequence of initialization/finalization steps, use the KOS_STEPS_COUNT_DECL_BEGIN(), KOS_APPEND_STEP_EX()/KOS_APPEND_STEP(), and KOS_STEPS_DECL_END macros.

Example:

/* Create a sequence of initialization/finalization steps named Client.

* This name must be unique within a single translation unit.

KOS_STEPS_COUNT_DECL_BEGIN(Client)

KOS_APPEND_STEP_EX("Transport", RTL_NULL, TransportInit, RTL_NULL, RTL_NULL, 0)

KOS_APPEND_STEP("Client objects", ClientObjInit, ClientObjFini)

KOS_APPEND_STEP("Group subscription objects", GroupSubscrObjInit, GroupSubscrObjFini)

KOS_APPEND_STEP("Group publication objects", GroupPubObjInit, GroupPubObjFini)

KOS_APPEND_STEP("Initialization flag", InitializationFlagSet, InitializationFlagReset)

KOS_STEPS_DECL_END

In the source code file, the construct for creating the sequence of initialization/finalization steps must be placed into a global scope area (outside of the definitions of functions) where there is access to the initialization and finalization callback functions and access to the data that will be passed to these callback functions via the _init_ctx_ and _fini_ctx_ parameters of the KOS_APPEND_STEP_EX() macro.

The KOS_STEPS_COUNT_DECL_BEGIN() and KOS_STEPS_DECL_END macros declare the beginning and end of the sequence of initialization/finalization steps, respectively.

The KOS_APPEND_STEP_EX() and KOS_APPEND_STEP() macros declare the initialization/finalization step. You can use these macros to add a step to the sequence in which initialization and symmetric finalization will be performed. For this step, specify the ID of the initialization callback function in the _init_cb_ parameter and specify the ID of the symmetric finalization callback function in the _fini_cb_ parameter. For example, you can also add a step to the sequence in which only finalization will be performed. For this step, set the _init_cb_ parameter to RTL_NULL, and set the _fini_cb_ parameter to the ID of a finalization callback function that is symmetric in relation to the several initialization callback functions defined by the subsequent declarations of steps.

The KOS_APPEND_STEP_EX() macro is an extended version of the KOS_APPEND_STEP() macro that lets you define not only the initialization and finalization callback functions (the _init_cb_ and _fini_cb_ parameters) but also the data that will be passed to these callback functions (the _init_ctx_ and _fini_ctx_ parameters). The KOS_APPEND_STEP_EX() macro also lets you indicate whether you need to log errors of the initialization callback function at a declared step (the _err_verbosity_ parameter). When using the KOS_APPEND_STEP() macro, errors of the initialization callback function at the declared step are always logged.

You can use the _step_name_ parameter of the KOS_APPEND_STEP_EX() and KOS_APPEND_STEP() macros to define the name of the initialization/finalization step so that the error logging data contains the name of this step. If you don't do this, the declared step in the error logging data can be identified only by its number. The numbering of steps begins with zero and matches the order in which the steps are declared. In the example, the step named Transport has the number 0, the step named Client objects has the number 1, and the step named Group subscription objects has the number 2.

The initialization and finalization callback functions for the KOS_APPEND_STEP_EX() and KOS_APPEND_STEP() macros have different signatures. The signature of the initialization callback function for the KOS_APPEND_STEP_EX() macro corresponds to the KosInitItInitCallback type. This callback function uses its own context parameter to receive arbitrary data defined via the _init_ctx_ parameter of the KOS_APPEND_STEP_EX() macro. If successful, the function returns rcOk, otherwise it returns an error code. The signature of the finalization callback function for the KOS_APPEND_STEP_EX() macro corresponds to the KosInitItFiniCallback type. This callback function uses its own context parameter to receive arbitrary data defined via the _fini_ctx_ parameter of the KOS_APPEND_STEP_EX() macro, and uses its stepType parameter to receive the finalization type (KosInitItStepFini refers to normal finalization, while KosInitItStepRollBack refers to finalization resulting from an error of the initialization callback function or canceled initialization). If successful, the function returns rcOk, otherwise it returns an error code. The signature of the initialization and finalization callback functions for the KOS_APPEND_STEP() macro corresponds to the KosInitItStepCallback type. These callback functions do not have any parameters. If successful, the functions return rcOk, otherwise they return an error code.

Canceling initialization

You can use the KOS_SET_INIT_CANCEL_CALLBACK() macro to define an initialization cancellation callback function for a sequence of initialization/finalization steps. The signature of this callback function corresponds to the KosInitItCancelCallback type. The initialization cancellation callback function is called at each step during initialization and receives the number of the specific step via the stepIndx parameter. If the initialization cancellation callback function returns rtl_true at step i, the initialization callback function corresponding to step i is not called. Instead, finalization is performed starting with step i-1. If the initialization cancellation callback function returns rtl_false at step i, the initialization callback function corresponding to step i is called and then proceeds to step i+1 if the initialization callback function is successfully completed.

You can use the initialization cancellation callback function to control the fulfillment of certain conditions during initialization. For example, you can monitor the time it takes to complete steps and cancel initialization if a specific duration is exceeded. You can also use this callback function to perform certain preparatory operations before calling the initialization callback function at a specific step.

The KOS_SET_INIT_CANCEL_CALLBACK() macro has a value consisting of the ID of the preceding initialization cancellation callback function. By saving this value, you will have the capability to subsequently use the preceding initialization cancellation callback function.

In the source code file, the definitions of functions that use the KOS_SET_INIT_CANCEL_CALLBACK() macro must be positioned after the construct for creating the sequence of initialization/finalization steps.

Logging errors

If the initialization or finalization callback function at a step ends with an error, a message about this error is put into diagnostic output by default. (When using the KOS_APPEND_STEP_EX() macro, you can cancel error logging of the initialization callback function at a declared step.) This message contains the name of the sequence of initialization/finalization steps, the name or number of the step (depending on whether the name was defined when declaring the step), the type of procedure (init refers to initialization, fini refers to normal finalization, and rollback refers to finalization resulting from an error of the initialization callback function or canceled initialization), and information about the error.

Instead of the default method, you can use your own error logging method. To do so, use the KOS_SET_LOGGER_CALLBACK() macro to define your own error logging callback function for a sequence of initialization/finalization steps. This callback function is called if the initialization or finalization callback function at a step ends with an error. (When using the KOS_APPEND_STEP_EX() macro, you can cancel error logging of the initialization callback function at a declared step.) The signature of the error logging callback function corresponds to the KosInitItErrorLoggerCallback type. The error logging callback function receives the name of the initialization/finalization sequence (the subsystemName parameter), the step number (the failedStep parameter), step name (if it was defined via the stepName parameter when declaring the step), error code (the rc parameter) and the type of procedure (the stepType parameter, which receives the following values: KosInitItStepInit refers to initialization, KosInitItStepFini refers to normal finalization, and KosInitItStepRollBack refers to finalization resulting from an error of the initialization callback function or canceled initialization). It does not return any values. For example, an implementation of this callback function may write error information to the buffer instead of putting it into diagnostic output.

The KOS_SET_LOGGER_CALLBACK() macro has a value consisting of the ID of the preceding error logging callback function. By saving this value, you will have the capability to subsequently use the preceding error logging callback function.

In the source code file, the definitions of functions that use the KOS_SET_LOGGER_CALLBACK() macro must be positioned after the construct for creating the sequence of initialization/finalization steps.

Starting initialization and finalization

To start initialization according to a defined sequence of initialization/finalization steps, use the KOS_RUN_INIT_STEPS() macro. If the initialization callback functions at all steps are completed successfully, the macro returns the value rcOk. If an initialization callback function at one of the steps ended with an error, the macro returns the code of this error. If initialization is canceled, the macro returns the value rcAbort.

To start finalization according to a defined sequence of initialization/finalization steps, use the KOS_RUN_FINI_STEPS() macro. If the finalization callback functions at all steps are completed successfully, the macro returns the value rcOk. If a finalization callback function at one of the steps ended with an error, the macro returns the code of this error.

Example of starting initialization and finalization:

int main(void)

{

int ret = -1;

INFO(UARTSR, "UART server start");

if (KOS_RUN_INIT_STEPS(UART) == rcOk)

{

KosEventWait(&shutdownEvent, rtl_false);

KOS_RUN_FINI_STEPS(UART);

ret = 0;

}

INFO(UARTSR, "UART server stop");

return ret;

}

Although initialization based on a single sequence of initialization/finalization steps can be started in multiple parallel threads, essentially initialization will be performed only once. This is also true for finalization. However, you must ensure that the number of successful startups of initialization (when the KOS_RUN_INIT_STEPS() macro has the rcOk value) is equal to the number of successful startups of finalization (when the KOS_RUN_FINI_STEPS() macro has the value rcOk). This is necessary because the first successful startup of initialization actually performs the initialization and increments the initialization startup counter, while subsequent successful startups of initialization only increment this counter. However, a successful startup of finalization decrements the initialization startup counter and does not actually perform finalization until this counter takes the value that it had before the first successful startup of initialization.

In the source code, the definitions of functions that use the KOS_RUN_INIT_STEPS() and KOS_RUN_FINI_STEPS() macros must be positioned after the construct for creating the sequence of initialization/finalization steps.

Information about API macros

init_fini.h macros

Macro

Macro details

KOS_STEPS_COUNT_DECL_BEGIN()

Purpose

Declares the start of the sequence of initialization/finalization steps.

Parameters

  • [in] _name_ – name of the sequence of initialization/finalization steps. It must be unique within a single translation unit.

Macro values

N/A

KOS_APPEND_STEP_EX()

Purpose

Declares the step in the sequence of initialization/finalization steps.

Parameters

  • [in,optional] _step_name_ – pointer to the string containing the name of the initialization/finalization step to make sure that the error logging data contains the name of this step, or RTL_NULL if this is not required.
  • [in,optional] _init_ctx_ – pointer to the data that will be passed to the initialization callback function that was defined via the _init_cb_ parameter. You can specify RTL_NULL if data does not need to be passed. The initialization callback function will receive the passed data through its own context parameter.
  • [in,optional] _init_cb_ – ID of the initialization callback function (the KosInitItInitCallback type) or RTL_NULL if initialization is not performed at the step.
  • [in,optional] _fini_ctx_ – pointer to the data that will be passed to the finalization callback function that was defined via the _fini_cb_ parameter. You can specify RTL_NULL if data does not need to be passed. The finalization callback function will receive the passed data through its own context parameter.
  • [in,optional] _fini_cb_ – ID of the finalization callback function (the KosInitItFiniCallback type) or RTL_NULL if finalization is not performed at the step.
  • [in] _err_verbosity_ – value that indicates whether error logging of the initialization callback function must be performed (0 – do not perform error logging, 1 – perform error logging).

Macro values

N/A

KOS_STEPS_DECL_END

Purpose

Declares the end of the sequence of initialization/finalization steps.

Parameters

N/A

Macro values

N/A

KOS_APPEND_STEP()

Purpose

Declares the step in the sequence of initialization/finalization steps.

Parameters

  • [in,optional] _step_name_ – pointer to the string containing the name of the initialization/finalization step to make sure that the error logging data contains the name of this step, or RTL_NULL if this is not required.
  • [in,optional] _init_cb_ – ID of the initialization callback function (the KosInitItStepCallback type) or RTL_NULL if initialization is not performed at the step.
  • [in,optional] _fini_cb_ – ID of the finalization callback function (the KosInitItStepCallback type) or RTL_NULL if finalization is not performed at the step.

Macro values

N/A

KOS_SET_INIT_CANCEL_CALLBACK()

Purpose

Defines the initialization cancellation callback function.

Parameters

  • [in] _name_ – name of the sequence of initialization/finalization steps.
  • [in] _cancelCb – ID of the initialization cancellation callback function (the KosInitItCancelCallback type).

Macro values

ID of the preceding initialization cancellation callback function if one exists, otherwise RTL_NULL.

KOS_SET_LOGGER_CALLBACK()

Purpose

Defines the error logging callback function.

Parameters

  • [in] _name_ – name of the sequence of initialization/finalization steps.
  • [in] logger – ID of the error logging callback function (the KosInitItErrorLoggerCallback type).

Macro values

ID of the preceding error logging callback function if one exists, otherwise RTL_NULL.

KOS_RUN_INIT_STEPS()

Purpose

Starts initialization according to a defined sequence of initialization/finalization steps.

Parameters

  • [in] _name_ – name of the sequence of initialization/finalization steps.

Macro values

It has a value of rcOk if successful, otherwise it has an error code value.

KOS_RUN_FINI_STEPS()

Purpose

Starts finalization according to a defined sequence of initialization/finalization steps.

Parameters

  • [in] _name_ – name of the sequence of initialization/finalization steps.

Macro values

It has a value of rcOk if successful, otherwise it has an error code value.

Page top