KasperskyOS Community Edition 1.3

Managing threads (low-level API thread_api.h)

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

Main capabilities of the API:

  • Create, terminate, and lock threads.
  • Resume execution of locked threads.
  • Change the priorities and scheduler classes of threads.
  • Handle exceptions.
  • Detach threads from interrupts.
  • Attach threads to processors (processor cores).

API functions that take the thread ID (TID) as input or return it are obsolete and will be removed in the future. These functions are not described in this section.

Information about API functions is provided in the table below.

The libkos library also provides a high-level API for thread management. This API is defined in the header file sysroot-*-kos/include/kos/thread.h from the KasperskyOS SDK. It is recommended to use this specific API. The low-level API should be used only if the high-level API does not have sufficient capabilities.

Creating threads. Thread scheduler classes

To create a thread, call the KnThreadCreateByHandle() function. You can use the flags parameter of this function for the created thread to define the following scheduler classes:

  • Class for scheduling standard threads.
  • Class for scheduling FIFO real-time threads (First In, First Out).
  • Class for scheduling RR real-time threads Round-Robin).

The priority of a standard thread can take values ranging from 0 to 15. The higher the priority of a standard thread, the larger the time slice allocated to this thread and the more frequently these time slices are allocated. One standard thread with a high priority can occupy multiple consecutive places in the thread queue. Standard threads cannot supersede other standard threads or real-time threads, regardless of their respective priorities. If a real-time thread appears in the queue, the current standard thread immediately transfers control to the real-time thread. If there are no real-time threads in the queue, the current standard thread transfers control to the next standard thread if the current one is terminated, becomes locked, uses up its time slice or gives it up to the next standard thread.

The priority of a real-time thread can take values ranging from 0 to 31. Higher-priority real-time threads supersede lower-priority real-time threads. Real-time threads also supersede standard threads, regardless of their respective priorities. Control is transferred from the current real-time thread to the next real-time thread in the queue in the following cases:

  • The current real-time thread with a FIFO scheduler class is terminated or locked, or a real-time thread with a higher priority appears in the queue.

    Until the real-time thread with a FIFO scheduler class is terminated, locked, or superseded by a real-time thread with a higher priority, it can retain control indefinitely and not transfer control to the next real-time thread.

  • The current real-time thread with an RR scheduler class is terminated, locked or uses up its time slice, or a real-time thread with a higher priority appears in the queue.

    A real-time thread with an RR scheduler class that is not terminated, locked, or superseded by a higher-priority real-time thread transfers control to the next one upon expiry of its time slice if the next one is a real-time thread with the same priority. Otherwise, it transfers control to itself again.

  • The current real-time thread has given up its time slice to the next real-time thread with the same priority in the queue.

    A real-time thread can give up its time slice to the next one in the queue if the next one is a real-time thread with the same priority. Otherwise, it transfers control to itself again.

Execution of lower-priority real-time threads begins only after each of the real-time threads with a higher priority is terminated or locked. Real-time threads with the same priority form a queue based on the FIFO principle.

The thread scheduler class can be changed by calling the KnThreadSetSchedPolicyByHandle() function. This function also changes the size of the time slice allocated to a real-time thread with an RR scheduler class. This value is the only parameter of a real-time thread RR scheduler class that has a default value of 10 ms but can take values ranging from 2 ms to 100 ms. The scheduler class of standard threads and the scheduler class of FIFO real-time threads do not have parameters.

The priority of a thread can be changed by calling the KnThreadSetSchedPolicyByHandle() or KnThreadSetPriorityByHandle() function.

After a thread is attached to an interrupt, the thread becomes a real-time thread with a FIFO scheduler class and a priority higher than 31, irrespective of the specific scheduler class and priority this thread had before it was attached to the interrupt. Managing interrupt processing (irq.h).)

Many API functions cannot be applied for threads that are attached to interrupts. These functions include KnThreadCreateByHandle(), KnThreadSetPriorityByHandle(), KnThreadSuspendCurrent(), KnThreadResumeByHandle(), KnThreadTerminateByHandle(), KnThreadWaitByHandle(), KnSleep(), and KnThreadSetSchedPolicyByHandle().

Creating thread handles

A thread handle is created whenever a thread is created by the KnThreadCreateByHandle() function call. A thread (including the initial thread) can also create its own handle by calling the KnThreadOpenCurrent() function.

A thread handle cannot be transferred to another process via IPC.

Handling exceptions

To register an exception handling function for a thread, call the KnThreadSetExceptionHandler() function. This function deregisters the previous exception handling function and returns its ID. By saving this ID, you can subsequently register the previous exception handling function again.

To get information about the last exception of a thread, call the KnThreadGetLastException() function in the exception handler.

Detaching threads from interrupts

To detach a thread from an interrupt, call the KnThreadDetachIrq() function. (For more details about using the KnThreadDetachIrq() function, see Managing interrupt processing (irq.h).)

After a thread is detached from an interrupt, the thread receives the scheduler class and priority that it had before it was attached to the interrupt.

Attaching threads to processors (processor cores)

To restrict the set of processors (processor cores) that can be used to execute a thread, define an affinity mask for this thread. An affinity mask is a bit mask indicating which specific processors or processor cores must execute the thread.

To create, adjust, and perform other operations with affinity masks, use the API that is defined in the header file sysroot-*-kos/include/rtl/cpuset.h from the KasperskyOS SDK.

To define a thread affinity mask, call the KnThreadSetAffinityByHandle() function.

Terminating threads

When a thread is terminated, it is permanently deleted from the scheduler. A thread is terminated in the following cases:

  • The function executed by the thread is exited.

    The root function (not a nested function) performed by the thread must be exited by the return operator.

  • The KnThreadTerminateByHandle() or KnThreadExit() function is called.

    The KnThreadExit() function terminates the thread even if the function is called from a nested function instead of the root function executed by the thread.

  • The process was terminated or switched to the "frozen" state.

    For details about the "frozen" state, see Managing processes (low-level API task_api.h).

Thread exit codes are defined by the developer of the KasperskyOS-based solution. These codes should be specified in the code parameter of the KnThreadTerminateByHandle() and KnThreadExit() functions, and when calling the return operator in the function executed by the thread. To get the thread exit code, call the KnThreadWaitByHandle() function.

Getting the address of the TCB and defining the base address of a TLS for threads

A thread control block (TCB) is a structure containing thread information that is used by the kernel to manage this specific thread. The type of structure is defined in the header file sysroot-*-kos/include/thread/tcbpage.h from the KasperskyOS SDK. A TCB contains the base address of the thread local storage (TLS). The KnThreadGetTcb() function gets the TCB address. The KnThreadSetTls() function defines the base address of the TLS. These functions are intended for use by the libc library.

Getting thread information

The KnThreadGetInfoByHandle() function gets the base address and stack limit of the thread, and the thread identifier (TID). This function is intended for use by the libc library.

Freeing resources of terminated threads

Resources of a thread include its stack, context, and TCB. To free the resources of a thread after the thread is terminated, you need to close its handle before or after termination of this thread by calling the KnHandleClose() function, which is declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h from the KasperskyOS SDK (an exception to this case is the initial thread of a process whose resources are freed without calling the KnHandleClose() function if the initial thread did not create its own handle by calling the KnThreadOpenCurrent() function). Resources of threads are also freed upon termination of the process that includes these threads.

Information about API functions

thread_api.h functions

Function

Information about the function

KnThreadCreateByHandle()

Purpose

Creates a thread.

Parameters

  • [out,optional] thread – pointer to the thread handle. Specifying RTL_NULL closes the handle automatically after the thread is created.
  • [in] priority – thread priority.
  • [in,optional] stackSize – thread stack limit (in bytes), or 0 to use the default size that was defined when the process was created.
  • [in] startRoutine – parameter that must have the value RTL_NULL.
  • [in] routine – pointer to the function executed by the thread.
  • [in,optional] context – pointer to the parameters passed to the function defined through the routine parameter, or RTL_NULL if parameters do not need to be passed to this function.
  • [in] flags – flags defining the parameters for creating the thread.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the flags parameter, you can specify the following flags:

  • ThreadFlagCreateSuspended – creates a thread in the locked state.
  • ThreadFlagCreateSchedOther – creates a standard thread.
  • ThreadFlagCreateSchedFifo – creates a real-time thread with a FIFO scheduler class.
  • ThreadFlagCreateSchedRR – creates a real-time thread with an RR scheduler class.

A standard thread is created by default.

Handles of threads cannot be transferred between processes via IPC.

KnThreadOpenCurrent()

Purpose

Creates the handle of the calling thread.

Parameters

  • [out] thread – pointer to the thread handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadGetPriorityByHandle()

Purpose

Gets the priority of a thread.

Parameters

  • [in] thread – thread handle.
  • [out] priority – pointer to the thread priority.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadSetPriorityByHandle()

Purpose

Defines the priority of a thread.

Parameters

  • [in] thread – thread handle.
  • [in] priority – thread priority.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadSuspendCurrent()

Purpose

Locks the calling thread.

Parameters

N/A

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadResumeByHandle()

Purpose

Resumes execution of a locked thread.

Parameters

  • [in] thread – thread handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadTerminateByHandle()

Purpose

Terminates a thread.

Parameters

  • [in] thread – thread handle.
  • [in] code – thread exit code.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadExit()

Purpose

Terminates the calling thread.

Parameters

  • [in] code – thread exit code.

Returned values

Error code.

KnThreadGetInfoByHandle()

Purpose

Gets information about a thread.

Parameters

  • [in] thread – thread handle.
  • [out] info – pointer to the structure containing the base address of the thread stack and its size (in bytes), and the thread identifier (TID).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadWaitByHandle()

Purpose

Locks the calling thread until the defined thread is terminated.

Parameters

  • [in] thread – thread handle.
  • [in] msDelay – timeout (in milliseconds) for the termination of a thread, or INFINITE_TIMEOUT to define an unlimited timeout.
  • [out] exitCode – pointer to the thread exit code.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnSleep()

Purpose

Locks the calling thread for the specified duration.

Parameters

  • [in] mdelay – thread lockout duration (in milliseconds).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadGetTcb()

Purpose

Gets the address of the thread control block (TCB) for the calling thread.

Parameters

N/A

Returned values

Pointer to the TCB. The data type for TCB storage is defined in the header file sysroot-*-kos/include/thread/tcbpage.h from the KasperskyOS SDK.

KnThreadSetTls()

Purpose

Defines the base address of the thread local storage (TLS) for the calling thread.

Parameters

  • [in] tls – pointer to the TLS.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadDetachIrq()

Purpose

Detaches the calling thread from the interrupt handled in its context.

Parameters

N/A

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadSetExceptionHandler()

Purpose

Registers the exception handling function for the calling thread.

Parameters

  • [in,optional] handler – ID of the exception handling function, or RTL_NULL to deregister the previously registered exception handling function without registering a new one. The parameter type is defined in the header file sysroot-*-kos/include/thread/tcbpage.h from the KasperskyOS SDK.

Returned values

ID of the previously registered exception handling function if one exists, otherwise RTL_NULL. The type of returned value is defined in the header file sysroot-*-kos/include/thread/tcbpage.h from the KasperskyOS SDK.

KnThreadGetLastException()

Purpose

Gets information about the last exception of the calling thread.

Parameters

  • [out] exception – pointer to the structure containing information about the exception. The type of structure is defined in the header file sysroot-*-kos/include/thread/tcbpage.h from the KasperskyOS SDK.

Returned values

N/A

KnThreadGetAffinityByHandle()

Purpose

Gets a thread affinity mask.

Parameters

  • [in] thread – thread handle.
  • [out] mask – pointer to the structure containing the thread affinity mask. The type of structure is defined in the header file sysroot-*-kos/include/rtl/cpuset.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadSetAffinityByHandle()

Purpose

Defines a thread affinity mask.

Parameters

  • [in] thread – thread handle.
  • [in] mask – pointer to the structure containing the thread affinity mask. The type of structure is defined in the header file sysroot-*-kos/include/rtl/cpuset.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadGetSchedPolicyByHandle()

Purpose

Gets information about the thread scheduler class.

Parameters

  • [in] thread – thread handle.
  • [out] policy – pointer to the thread scheduler class. The data type for storing the thread scheduler class is defined in the header file sysroot-*-kos/include/thread/tidtype.h from the KasperskyOS SDK.
  • [out,optional] param – pointer to the parameters of the thread scheduler class, or RTL_NULL.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the param parameter, you can specify RTL_NULL if you do not need to get the thread scheduler class parameters.

In the param parameter, you must specify RTL_NULL if the thread scheduler class does not have any parameters.

KnThreadSetSchedPolicyByHandle()

Purpose

Defines the scheduler class and priority of the thread.

Parameters

  • [in] thread – thread handle.
  • [in] policy – thread scheduler class. The parameter type is defined in the header file sysroot-*-kos/include/thread/tidtype.h from the KasperskyOS SDK.
  • [in] prio – thread priority.
  • [in,optional] param – pointer to the parameters of the thread scheduler class, or RTL_NULL.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the param parameter, you can specify RTL_NULL if you need to define the thread scheduler class parameters that are applied by default.

In the param parameter, you must specify RTL_NULL if the thread scheduler class does not have any parameters.