- HandlerMinelayerData: BUILD_RTI Guards für RTI-Abhängigkeiten - svcTabCommon: Export-Header-Fix via Fallback-Target - TrainingAreaBase: Stub-Header für BUILD_RTI=OFF - ddsfts: Include-Pfad und Dependency-Fixes - BUILD_RTI=OFF Compilation vollständig unterstützt Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Entire-Checkpoint: 01M0JNZA586SACX1PRZ2DJAE5S
543 lines
21 KiB
C
543 lines
21 KiB
C
/*
|
|
* (c) Copyright, Real-Time Innovations, 2019-2024.
|
|
* All rights reserved.
|
|
*
|
|
* No duplications, whole or partial, manual or electronic, may be made
|
|
* without express written permission. Any such copies, or
|
|
* revisions thereof, must display this notice unaltered.
|
|
* This code contains trade secrets of Real-Time Innovations, Inc.
|
|
*/
|
|
|
|
#ifndef osapi_context_h
|
|
#define osapi_context_h
|
|
|
|
#include "log/log_common.h"
|
|
#include "osapi/osapi_dll.h"
|
|
#include "osapi/osapi_type.h"
|
|
#include "osapi/osapi_thread.h"
|
|
#include "osapi/osapi_heap.h"
|
|
#include "osapi/osapi_utility.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* Max size for the representation of the context into a string.
|
|
*/
|
|
#define RTI_OSAPI_CONTEXT_STRING_SIZE_MAX 512
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* Default max size used to initialize context stack.
|
|
*/
|
|
#define RTI_OSAPI_CONTEXT_STACK_SIZE_DEFAULT 32
|
|
|
|
/** @internal \ingroup RTIOsapiActivityContext
|
|
* The Index of the activity and heap context specializations.
|
|
*/
|
|
#define RTI_OSAPI_ACTIVITY_CONTEXT_INDEX 0
|
|
#define RTI_OSAPI_HEAP_CONTEXT_INDEX 1
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* Entry of the context.
|
|
*/
|
|
struct RTIOsapiContextEntry {
|
|
void *entry;
|
|
/* If the context is cached in expansion, expansionEnd points to end */
|
|
char *expansionEnd;
|
|
/*
|
|
* Represent if an entry can be skipped from the string representation of
|
|
* the context stack.
|
|
*
|
|
* We need to cache if the entry is skipped to optimize the generation of
|
|
* the activity context string: we need to check previous entries skipped
|
|
* state to make decisions about the new entries we add.
|
|
*
|
|
* For example in the activity context the output will change (we will skip
|
|
* entries) based on the order and content of the entries:
|
|
* - For example similar activities and different resources:
|
|
* `R1|A1|R2|A1` -> `R1|A1|R2|A1`. The activities are similar but cannot
|
|
* be skipped because they belong to different resources.
|
|
* - For example similar activities and similar resources:
|
|
* `R1|A1|R1|A1` -> `R1|A1`. The activities and the resources are exactly
|
|
* the same, so both of them are skipped.
|
|
*/
|
|
RTIBool skipped;
|
|
};
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* The concept of context is a queue of entries associated with a thread.
|
|
* Those entries can be pushed and popped from the list of entries.
|
|
*
|
|
* The context can be instantiate for different specialization:
|
|
* - Activity context: it will describe the activity that a resource is doing.
|
|
* - Heap context: it will represent:
|
|
* - If the allocation is from the pool and in that case the buffer size
|
|
* and the buffer count.
|
|
* - The topic and the function name.
|
|
*/
|
|
struct RTIOsapiContext {
|
|
/* List of entries */
|
|
struct RTIOsapiContextEntry *entries;
|
|
RTI_UINT32 maxEntryCount;
|
|
/* Position on the list */
|
|
RTI_UINT32 top;
|
|
/* Used to cache the context as a string */
|
|
char *expansion;
|
|
/* A bitmap used to store the categories associated with the context */
|
|
RTILogCategoryMask category;
|
|
};
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* Number of type of contexts.
|
|
* Instantiate different specializations of the context:
|
|
* - Activity context: it will describe the activity that a resource is doing.
|
|
* - Heap context: it will represent: If the allocation is from the pool and in
|
|
* that case the buffer size and the buffer count. The topic and the function
|
|
*name.
|
|
*- In the future, we can have more potential context families for instance
|
|
* network capture context.
|
|
*/
|
|
|
|
#define RTI_OSAPI_NUMBER_CONTEXTS 3
|
|
|
|
/** @internal \ingroup RTIOsapiContextSupport
|
|
* Each node contains the contexts of the thread.
|
|
*/
|
|
|
|
struct RTIOsapiContextSupportNode {
|
|
struct RTIOsapiInlineListNode node;
|
|
struct RTIOsapiContext *contexts[RTI_OSAPI_NUMBER_CONTEXTS];
|
|
};
|
|
|
|
/* ========================================= */
|
|
/* ContextSupport */
|
|
/* ========================================= */
|
|
|
|
/*
|
|
* The Context feature is enabled by calling RTIOsapiContextSupport_enable() and
|
|
* it is disabled by calling RTIOsapiContextSupport_disable().
|
|
*
|
|
* The lifecycle of the context support is different depending on if using heap
|
|
* monitoring.
|
|
*
|
|
* - If using heap monitoring:
|
|
* - The Context support is enabled in RTIOsapiHeap_enableMonitoring()
|
|
* - The Context support is disabled in RTIOsapiHeap_disableMonitoring()
|
|
* - In case the “Participant Globals” are initialized or finalized,
|
|
* they will not affect the context support lifecycle.
|
|
* - If not using heap monitoring:
|
|
* - The Context support is enabled in
|
|
* DDS_DomainParticipantGlobals_initializeI()
|
|
* - The Context support is disabled in
|
|
* DDS_DomainParticipantGlobals_finalizeI()
|
|
* - In case the “Participant Globals” are initialized or finalized several
|
|
* times. The context support will be too.
|
|
* - Heap Monitoring can not interfere with it because
|
|
* RTIOsapiHeap_enableMonitoring() should be the first thing to be
|
|
* done.
|
|
*/
|
|
|
|
/** @internal \ingroup RTIOsapiContextSupport
|
|
* @brief Enable the Context feature.
|
|
* Create the tssFactory, tssKey, tssList and mutex.
|
|
* It should be called from a single thread.
|
|
* It should be called before using any functionality of the context.
|
|
* It is called in:
|
|
* - DDS_DomainParticipantGlobals_initializeI
|
|
* - RTIOsapiHeap_enableMonitoring
|
|
* Increment RTIOsapiContextSupport_g_tssInitializedRefCount, it is usd to make
|
|
* sure we disable the context support when the refCount is 1.
|
|
* @param tssFactory \b In. The TSS factory.
|
|
* In case the tssFactory is null, create a new one.
|
|
*
|
|
* @return True if the feature was enabled, False otherwise.
|
|
*/
|
|
extern RTIOsapiDllExport RTIBool
|
|
RTIOsapiContextSupport_enable(RTIOsapiThreadTssFactory *tssFactory);
|
|
|
|
/** @internal \ingroup RTIOsapiContextSupport
|
|
* @brief Disable the Context feature.
|
|
* Remove the tssKey, mutex and all the contexts nodes of all the User
|
|
* threads.
|
|
* It should be called from a single thread.
|
|
* Any functionality of the context can not be used after calling this
|
|
* method.
|
|
* Decrement RTIOsapiContextSupport_g_tssInitializedRefCount, it is usd to make
|
|
* sure we disable the context support when the refCount is 1.
|
|
* It is called in:
|
|
* - DDS_DomainParticipantGlobals_finalizeI
|
|
* - RTIOsapiHeap_disableMonitoring
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContextSupport_disable(void);
|
|
|
|
/** @internal \ingroup RTIOsapiContextSupport
|
|
* @brief Create a specific context and associate with the TSS of the thread.
|
|
* - It should be called per thread.
|
|
* - It should be called after RTIOsapiContextSupport_enable.
|
|
* It is called in:
|
|
* - DDS_DomainParticipantGlobals_create_worker_per_thread_with_nameI
|
|
* - RTIOsapiThreadChild_onSpawned
|
|
* - RTIOsapiThreadFactory_onSpawned
|
|
*
|
|
* @param nodeOut \b Out. The node that we will assert for the
|
|
* thread. Can be NULL.
|
|
* @param contextIndex \b In. The index of the context.
|
|
* @param addContextTssToGlobalList \b In. If true we add the context thread
|
|
* specific storage to a global list.
|
|
* @param maxEntryCount \b In. The max size of the list of entries.
|
|
* @param allowContextExpansion \b In. If true allocate the member field to
|
|
* RTI_OSAPI_CONTEXT_STRING_SIZE_MAX.
|
|
*
|
|
* @return True if the context was initalized, False otherwise.
|
|
*/
|
|
extern RTIOsapiDllExport RTIBool RTIOsapiContextSupport_assertContextTss(
|
|
struct RTIOsapiContextSupportNode **nodeOut,
|
|
RTI_UINT32 contextIndex,
|
|
RTIBool addContextTssToGlobalList,
|
|
RTI_UINT32 maxEntryCount,
|
|
RTIBool allowContextExpansion);
|
|
|
|
/** @internal \ingroup RTIOsapiContextSupport
|
|
* @brief This function is only used to finalize the contextTss and its
|
|
* associated RTIOsapiContextSupportNode for non-RTI threads.
|
|
* Specifically, it is called from
|
|
* DDS_DomainParticipantFactory_unregister_thread. If
|
|
* DDS_DomainParticipantFactory_unregister_thread is not called by the user, the
|
|
* contextTss and associated RTIOsapiContextSupportNode will be removed in
|
|
* RTIOsapiContextSupport_disable() during RTIOsapiContextSupport_g_tssList
|
|
* destruction at the end of DDS application lifecycle.
|
|
*
|
|
* For RTI threads, this function cannot be used. Instead,
|
|
* the contextTss and RTIOsapiContextSupportNode are removed by a call to
|
|
* RTIOsapiContextSupport_finalizeNode done by the thread itself before
|
|
* finishing.
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContextSupport_finalizeContextTss(void);
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief Return the context, of the caller thread, specified by the Id.
|
|
* @param contextIndex \b In. The index of the context.
|
|
*
|
|
* @return the context specified by the Id.
|
|
*/
|
|
extern RTIOsapiDllExport struct RTIOsapiContext *
|
|
RTIOsapiContextSupport_getContext(RTI_UINT32 contextIndex);
|
|
|
|
/* ========================================= */
|
|
/* Context */
|
|
/* ========================================= */
|
|
|
|
/*
|
|
* For the enter methods:
|
|
* In case the entries do not fit in the list of entries:
|
|
* - The value context->top will be incremented as many elements the user
|
|
* expected to enter.
|
|
* - The entries will not be saved in the queue because there is not space
|
|
* for them.
|
|
* We do this in order to keep the number of entries the user has entered.
|
|
* So, the value of context->top may be greater than context->maxEntryCount.
|
|
*
|
|
* For the leave methods:
|
|
* While the value of context->top is greater than context->maxEntryCount:
|
|
* - The value of context->top will be decremented as many entries were
|
|
* expected to be left.
|
|
* Once the context->top is smaller or equal than context->maxEntryCount:
|
|
* - The elements are removed from the list.
|
|
*
|
|
* By doing that we will solve the following scenario:
|
|
* - Initial context state before calling a function: top = 2, maxEntryCount = 4
|
|
* - Start a function:
|
|
* - Enter 3 entries into the context.
|
|
* - As the number of entries to enter plus top is greater than
|
|
* maxEntryCount. The entries will not be added into the context.
|
|
* However top will be incremented as many entries are expected to be
|
|
* entered.
|
|
* - Context state: top = 5, maxEntryCount = 4
|
|
* - Leave 3 entries from the context.
|
|
* - Decrement top, 3 elements.
|
|
* - Context state: top = 2, maxEntryCount = 4
|
|
* - End the function. Now the state of the context will be the same as when
|
|
* the function began.
|
|
*
|
|
* By keeping context->top with the expected value will ensure our developer
|
|
* finishes a function with the same value of the context as it began.
|
|
*/
|
|
|
|
/*
|
|
* Infinite loops - circular dependencies
|
|
* As we have mentioned already the context will be used in heap monitoring and
|
|
* logging.
|
|
* So, it is necessary to set up a contract/rule between the context and those
|
|
* features.
|
|
* - Logging:
|
|
* - The context feature can log messages. It is safe because nothing below
|
|
* logging is going to enter/leave entries in the context. So, there are
|
|
* not possible infinite loops.
|
|
* - Advanced logging (advlog.1.0) is using the context to generate the
|
|
* string using RTIOsapiActivityContext_getString().
|
|
* - It is safe to log in that function because logging is already
|
|
* protected from infinite loops by ADVLOGLogger_blockThreadLogging().
|
|
* - Heap monitoring:
|
|
* - In the context we cannot use our allocation function
|
|
* (RTIOsapiHeap_allocate…()) because we cannot add allocation statistics
|
|
* data to the heap monitoring.
|
|
* - Then, in the context feature we use malloc instead.
|
|
*/
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief Enter an entry to the context specified by the Id.
|
|
* If the context is already full, the entry will not be added.
|
|
* The entry memory is owned by the caller function.
|
|
*
|
|
* @param self \b In. The context itself. If it is NULL, it will be get
|
|
* from the TSS.
|
|
* @param contextIndex \b In. The index of the context.
|
|
* @param entry \b In. The entry to add the context.
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContext_enter(
|
|
struct RTIOsapiContext *self,
|
|
RTI_UINT32 contextIndex,
|
|
void *entry);
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief Enter two entries to the context specified by the Id.
|
|
* If the context is already full, the entries will not be added.
|
|
* The entries memory is owned by the caller function.
|
|
*
|
|
* @param self \b In. The context itself. If it is NULL, it will be get
|
|
* from the TSS.
|
|
* @param contextIndex \b In. The index of the context.
|
|
* @param entry1 \b In. The entry1 to add to the context.
|
|
* @param entry2 \b In. The entry1 to add to the context.
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContext_enterPair(
|
|
struct RTIOsapiContext *self,
|
|
RTI_UINT32 contextIndex,
|
|
void *entry1,
|
|
void *entry2);
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief Leave the last entry of the context specified by the Id.
|
|
*
|
|
* @param self \b In. The context itself. If it is NULL, it will be get
|
|
* from the TSS.
|
|
* @param contextIndex \b In. The index of the context.
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContext_leave(
|
|
struct RTIOsapiContext *self,
|
|
RTI_UINT32 contextIndex);
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief Leave the last N entries of the context specified by the Id.
|
|
*
|
|
* @param self \b In. The context itself. If it is NULL, it will be get
|
|
* from the TSS.
|
|
* @param contextIndex \b In. The index of the context.
|
|
* @param groupSize \b In. Number of entries to remove from the list.
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContext_leaveGroup(
|
|
struct RTIOsapiContext *self,
|
|
RTI_UINT32 contextIndex,
|
|
RTI_UINT32 groupSize);
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief Return the number of entries of the context specified by the Id.
|
|
*
|
|
* @param contextIndex \b In. The index of the context.
|
|
*
|
|
* @return number of entries of the context specified by the Id.
|
|
*/
|
|
extern RTIOsapiDllExport RTI_UINT32
|
|
RTIOsapiContext_getDepth(RTI_UINT32 contextIndex);
|
|
|
|
/* ========================================= */
|
|
/* Category of the Context */
|
|
/* ========================================= */
|
|
|
|
/*
|
|
* The category is used to store the current category of the codepath
|
|
* that we are in. This is used to enable filtering of log messages by
|
|
* category and labelling log messages with the current category.
|
|
*
|
|
* When entering a category codepath, you first need to set the
|
|
* category. There are three methods that allow you to do this:
|
|
* RTIOsapiActivityContext_setCategory:
|
|
* Overwrites the existing category
|
|
* RTIOsapiActivityContext_addCategory:
|
|
* Adds the new category to the existing category (but does not
|
|
* overwrite any bits that have been set to 1).
|
|
* RTIOsapiActivityContext_addAndCacheCategory:
|
|
* Adds the new category to the existing category and stores the
|
|
* existing category.
|
|
*
|
|
* It is recommended to usually use RTIOsapiActivityContext_addAndCacheCategory
|
|
* when setting the category when entering a codepath so that you are able to
|
|
* restore the category to its previous value when you are leaving the
|
|
* codepath. You can then call RTIOsapiActivityContext_setCategory to set the
|
|
* category to its previous value. You should always restore the category
|
|
* before returning from the function in which you add the category, otherwise
|
|
* the category will still be set even though we will no longer be in the
|
|
* correct codepath for that category.
|
|
*
|
|
* There is also a method RTIOsapiActivityContext_resetCategory which will
|
|
* clear the bits in the context category that are set to 1 in the input
|
|
* category. This can also be used to reset the category after setting it.
|
|
*
|
|
* RTIOspaiActivityContext_getCategory can be used to get the current value
|
|
* of the context's category mask.
|
|
*
|
|
* The following shows an example of setting the category to DISCOVERY,
|
|
* logging messages, and then resetting the category:
|
|
*
|
|
* RTICategoryMask cachedCategory = RTI_LOG_CATEGORY_NONE;
|
|
* RTIOsapiActivityContext_addAndCacheCategory(
|
|
* &cachedCategory,
|
|
* RTI_LOG_CATEGORY_DISCOVERY_BIT);
|
|
* DDSLogger_log(
|
|
* RTI_LOG_BIT_LOCAL,
|
|
* &RTI_LOG_EMPTY_TEMPLATE,
|
|
* "This is a log message in the discovery codepath!\n");
|
|
* RTIOsapiActivityContext_setCategory(cachedCategory);
|
|
*
|
|
*/
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief Get the current category mask of the context.
|
|
*
|
|
* @param self \b In. The context itself. If it is NULL, it will be get
|
|
* from the TSS.
|
|
* @param category \b Out. Pointer to location where we will store category.
|
|
* @param contextIndex \b In. The index of the context.
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContext_getCategory(
|
|
struct RTIOsapiContext *self,
|
|
RTILogCategoryMask *category,
|
|
RTI_UINT32 contextIndex);
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief Set the category mask of the context to the category mask passed in.
|
|
*
|
|
* @param self \b In. The context itself. If it is NULL, it will be get
|
|
* from the TSS.
|
|
* @param contextIndex \b In. The index of the context.
|
|
*
|
|
* @param category \b In. The category mask to set to.
|
|
*
|
|
* @return True if the category mask is set successfully. False otherwise.
|
|
*
|
|
* This function should always be called before a "return" statement when
|
|
* using RTIOsapiActivityContext_addAndCacheCategory;
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContext_setCategory(
|
|
struct RTIOsapiContext *self,
|
|
RTI_UINT32 contextIndex,
|
|
RTILogCategoryMask category);
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief Add the passed category to the existing category mask of the
|
|
* context. This will not clear other category masks if they are already
|
|
* set, it will just add the category mask passed in.
|
|
*
|
|
* @param self \b In. The context itself. If it is NULL, it will be get
|
|
* from the TSS.
|
|
* @param contextIndex \b In. The index of the context.
|
|
*
|
|
* @param category \b In. The category mask to add.
|
|
*
|
|
* @return True if the category mask is set successfully. False otherwise.
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContext_addCategory(
|
|
struct RTIOsapiContext *self,
|
|
RTI_UINT32 contextIndex,
|
|
RTILogCategoryMask category);
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief
|
|
*
|
|
* @param contextIndex \b In. The index of the context.
|
|
*
|
|
* @param category \b In. The category mask to add.
|
|
*
|
|
* @param self \b In. The context itself. If it is NULL, it will be get
|
|
* from the TSS.
|
|
* @param cachedCategory \b Out. A pointer to a variable where we will cache
|
|
* a mask of the bits to be restored upon a call to resetCategory. This
|
|
* mask will be set to the current value of
|
|
* self->_activityContext->category;
|
|
* @param contextIndex \b In. The index of the context.
|
|
* @param category \b In. The category mask to add.
|
|
*
|
|
* @return True if the category mask is set successfully. False otherwise.
|
|
*
|
|
* When using this function, there should not be a "return" statement
|
|
* prior to calling RTIOsapiContext_setCategory to reset the category.
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContext_addAndCacheCategory(
|
|
struct RTIOsapiContext *self,
|
|
RTILogCategoryMask *cachedCategory,
|
|
RTI_UINT32 contextIndex,
|
|
RTILogCategoryMask category);
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief Reset the category mask of a given category to all 0s.
|
|
*
|
|
* @param self \b In. The context itself. If it is NULL, it will be get
|
|
* from the TSS.
|
|
* @param contextIndex \b In. The index of the context.
|
|
*
|
|
* @param category \b In. The category mask to clear.
|
|
*
|
|
* @return True if the category mask is reset successfully. False otherwise.
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContext_resetCategory(
|
|
struct RTIOsapiContext *self,
|
|
RTI_UINT32 contextIndex,
|
|
RTILogCategoryMask category);
|
|
|
|
/* ========================================= */
|
|
/* ContextScope */
|
|
/* ========================================= */
|
|
|
|
/*
|
|
* We define "scope" as a block of code which:
|
|
* - Starts with a RTIOsapiContextScope_begin call.
|
|
* This macro opens the block.
|
|
* After calling begin(), you must initialize all the stack variables needed to
|
|
* support entering/leaving contexts within the block.
|
|
* - Ends with an RTIOsapiContextScope_end call.
|
|
* Before ending a scope, you must leave any remaining entered entries.
|
|
* This macro closes the block.
|
|
*
|
|
* The general scope does not provide significant functionality,
|
|
* it just opens and closes the brackets. It is just conceptual.
|
|
* The upper layer contexts are going to rely on the concept of scope.
|
|
*
|
|
* The context scope has two rules:
|
|
* - It has to be robust to not segmentation fault nor array overflow.
|
|
* - The context should have the same status before calling "begin" and after
|
|
* calling "end".
|
|
*/
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief This macro opens the block. After calling begin(), you must initialize
|
|
* all the stack variables needed to support entering/leaving contexts within
|
|
* the block.
|
|
*
|
|
* Note: make sure to not add ';' after a call to this macro.
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContextScope_begin(void);
|
|
|
|
/** @internal \ingroup RTIOsapiContext
|
|
* @brief Upon ending a scope, you must leave any remaining entered entries.
|
|
* Close the block.
|
|
*/
|
|
extern RTIOsapiDllExport void RTIOsapiContextScope_end(void);
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif
|
|
#include "osapi/osapi_context_impl.h"
|
|
|
|
#endif /* osapi_context_h */
|