Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Implement Multi-Threading's Mutex Callback APIs #167

Merged
merged 4 commits into from
Nov 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 31 additions & 8 deletions include/libXbSymbolDatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,29 +170,29 @@ unsigned int XbSymbolDatabase_LibraryVersion();

/// <summary>
/// Total symbols return give ability to support for progress bar from third-party software. Not all symbols will be detected in every titles.
/// <param name="library_filter">See defined prefix of XbSymbolLib_ above to choose one or more library you wish to obtain total symbols.</param>
/// </summary>
/// <param name="library_filter">See defined prefix of XbSymbolLib_ above to choose one or more library you wish to obtain total symbols.</param>
/// <returns>Return total symbols in current database system.</returns>
unsigned XbSymbolDatabase_GetTotalSymbols(uint32_t library_filter);

/// <summary>
/// Register one or more library to be scan instead of whole database for optimize performance.
/// <param name="library_filter">See defined prefix of XbSymbolLib_ above to choose one or more library you wish to scan.</param>
/// </summary>
/// <param name="library_filter">See defined prefix of XbSymbolLib_ above to choose one or more library you wish to scan.</param>
/// <returns>Return true if success, or else will return false for invalid parameter.</returns>
bool XbSymbolContext_RegisterLibrary(XbSymbolContextHandle pHandle, uint32_t library_filter);

/// <summary>
/// To register any detected symbol name with address and build version back to third-party program.
/// NOTE: Be aware of library name will be varity since some libraries are detecting in other sections as well.
/// Callback function type for output message to software when have information to be output.
/// </summary>
/// <param name="library_str">Name of the library in string.</param>
/// <param name="message_flag">Output enum level flag.</param>
/// <param name="message_str">Output log message.</param>
typedef void (*xb_output_message_t)(xb_output_message message_flag, const char* message_str);

/// <summary>
/// For output a message to a program when have information to be output.
/// Register output message callback function to receive output message.
/// </summary>
/// <param name="message_func">Set output message to a function.</param>
/// <param name="message_func">Set output message to a callback function.</param>
void XbSymbolDatabase_SetOutputMessage(xb_output_message_t message_func);

/// <summary>
Expand Down Expand Up @@ -264,6 +264,28 @@ void XbSymbolContext_SetContinuousSigScan(XbSymbolContextHandle pHandle, bool en
/// <param name="enable">Input boolean to use first symbol address only or not.</param>
void XbSymbolContext_SetFirstDetectAddressOnly(XbSymbolContextHandle pHandle, bool enable);

/// <summary>
/// To register mutex lock callback functions.
/// </summary>
/// <param name="opaque_ptr">Retrieve opaque pointer if set from XbSymbolContext_SetMutex registration.</param>
/// <returns>True: Successful lock. False: Failure to lock.</returns>
typedef bool (*xb_mutex_lock_t)(XbSymbolContextHandle pHandle, void* opaque_ptr);

/// <summary>
/// To register mutex unlock callback functions.
/// </summary>
/// <param name="opaque_ptr">Retrieve opaque pointer if set from XbSymbolContext_SetMutex registration.</param>
typedef void (*xb_mutex_unlock_t)(XbSymbolContextHandle pHandle, void* opaque_ptr);

/// <summary>
/// To register mutex (un)lock callback functions for multi-thread safe purpose.
/// </summary>
/// <param name="opaque_ptr">Set pointer to be used to retrieve during (un)lock callback events.</param>
/// <param name="mutex_lock">Set mutex lock to a callback function.</param>
/// <param name="mutex_unlock">Set mutex unlock to a callback function.</param>
/// <returns>Return true if success, or else will return false for invalid parameter.</returns>
bool XbSymbolContext_SetMutex(XbSymbolContextHandle pHandle, void* opaque_ptr, xb_mutex_lock_t mutex_lock, xb_mutex_unlock_t mutex_unlock);

/// <summary>
/// Step 1: Generate library array for LibraryHeader input.
/// First call with <paramref name="library_out"/> as null pointer will return total count. Then second call will insert information to <paramref name="library_out"/>.filters field.
Expand Down Expand Up @@ -308,7 +330,8 @@ bool XbSymbolDatabase_CreateXbSymbolContext(XbSymbolContextHandle* ppHandle, xb_
void XbSymbolContext_ScanManual(XbSymbolContextHandle pHandle);

/// <summary>
/// Step 6a: (multi-thread safe, C11 standard) Process individual library input by third-party.
/// Step 6a: (multi-thread safe, optional) Process individual library input by third-party.
/// NOTE: If planned to use multi-thread purpose, please register mutex (un)lock callbacks to XbSymbolContext_SetMutex.
/// </summary>
/// <param name="pHandle">Input XbSymbolContextHandle handler.</param>
/// <param name="pLibrary">Input pointer of a library to start a scan process.</param>
Expand Down
5 changes: 3 additions & 2 deletions projects/cli/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@ cmake_minimum_required(VERSION 3.10.2)

project(XbSymbolDatabaseCLI LANGUAGES C)

find_package(Threads)

add_executable(${PROJECT_NAME} ${XBSDB_ROOT_DIR}/src/cli/main.c)

target_compile_definitions(${PROJECT_NAME} PRIVATE _CRT_SECURE_NO_WARNINGS)

target_link_libraries(${PROJECT_NAME} libXbSymbolDatabase)

#[[thread is not implemented in cli.
find_package(Threads)
if(Threads_FOUND)
target_link_libraries(${PROJECT_NAME} Threads::Threads)
endif()
#]]

set_target_properties(${PROJECT_NAME} PROPERTIES
C_STANDARD 11
Expand Down
2 changes: 2 additions & 0 deletions src/lib/internal_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,8 @@ static bool internal_SetLibraryTypeStart(iXbSymbolContext* pContext, eLibraryTyp

bool ret = false;

iXbSymbolContext_Lock(pContext);

// Accept request if library type is inactive.
if (!pContext->library_contexts[library_type].is_active) {
// Then accept the scan request.
Expand Down
72 changes: 36 additions & 36 deletions src/lib/libXbSymbolDatabase.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@
#include <stdarg.h>
#include <stdint.h>
#include <stddef.h>
// TODO: Most compilers haven't include C11's thread support for multi-thread safe.
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_THREADS__)
#define MULTI_THREAD_SAFE true
#include <threads.h>
#endif

#ifdef _MSC_VER
#include <intrin.h>
Expand Down Expand Up @@ -141,9 +136,9 @@ typedef struct _iXbSymbolContext {
XbSDBSectionHeader section_input;
eScanStage scan_stage;
iXbSymbolLibraryContext library_contexts[LT_COUNT];
#ifdef MULTI_THREAD_SAFE
mtx_t mutex;
#endif
void* mtx_opaque_ptr;
xb_mutex_lock_t lock_fn;
xb_mutex_unlock_t unlock_fn;
} iXbSymbolContext;

typedef const struct _PairScanLibSec {
Expand Down Expand Up @@ -296,24 +291,20 @@ static xb_xbe_type GetXbeType(const xbe_header* pXbeHeader)

static bool iXbSymbolContext_Lock(iXbSymbolContext* pContext)
{
#ifdef MULTI_THREAD_SAFE
// Lock to this thread only during the scan process until the scan is done.
int mtxStatus = mtx_lock(&pContext->mutex);
if (mtxStatus != thrd_success) {
output_message_format(&pContext->output, XB_OUTPUT_MESSAGE_ERROR, "Unable to lock mutex: %d", mtxStatus);
return false;
if (pContext->lock_fn) {
// Lock to this thread only during the scan process until the scan is done.
bool success = pContext->lock_fn(pContext, pContext->mtx_opaque_ptr);
// It is not XbSymbolDatabase's responsible to output an error. That is up to software's responsible.
return success;
}
#endif

return true;
}

static void iXbSymbolContext_Unlock(iXbSymbolContext* pContext)
{
#ifdef MULTI_THREAD_SAFE
// Lock to this thread only during the scan process until the scan is done.
(void)mtx_unlock(&pContext->mutex);
#endif
if (pContext->unlock_fn) {
pContext->unlock_fn(pContext, pContext->mtx_opaque_ptr);
}
}

static bool iXbSymbolContext_AllowSetParameter(iXbSymbolContext* pContext)
Expand Down Expand Up @@ -725,12 +716,6 @@ bool XbSymbolDatabase_CreateXbSymbolContext(XbSymbolContextHandle* ppHandle,

iXbSymbolContext* pContext = (iXbSymbolContext*)*ppHandle;

#ifdef MULTI_THREAD_SAFE
if (mtx_init(&pContext->mutex, mtx_plain) != thrd_success) {
goto ContextCleanup;
}
#endif

pContext->scan_stage = SS_NONE;

pContext->register_func = register_func;
Expand All @@ -742,6 +727,8 @@ bool XbSymbolDatabase_CreateXbSymbolContext(XbSymbolContextHandle* ppHandle,
pContext->output.verbose_level = g_output_verbose_level;
pContext->output.func = g_output_func;
pContext->library_filter = 0;
pContext->lock_fn = NULL;
pContext->unlock_fn = NULL;

// Copy pointers and values to context handler.
pContext->library_input.count = library_input.count;
Expand Down Expand Up @@ -866,20 +853,16 @@ bool XbSymbolDatabase_CreateXbSymbolContext(XbSymbolContextHandle* ppHandle,
void XbSymbolContext_Release(XbSymbolContextHandle pHandle)
{
iXbSymbolContext* pContext = (iXbSymbolContext*)pHandle;
#ifdef MULTI_THREAD_SAFE
(void)mtx_lock(&pContext->mutex);
#endif

(void)iXbSymbolContext_Lock(pContext);

for (unsigned int i = 0; i < LT_COUNT; i++) {
if (pContext->library_contexts[i].is_active) {
output_message_format(&pContext->output, XB_OUTPUT_MESSAGE_DEBUG, "Library type is currently active: %u", i);
}
}

#ifdef MULTI_THREAD_SAFE
(void)mtx_unlock(&pContext->mutex);
mtx_destroy(&pContext->mutex);
#endif
iXbSymbolContext_Unlock(pContext);

free(pHandle);
}
Expand Down Expand Up @@ -933,6 +916,25 @@ bool XbSymbolContext_RegisterLibrary(XbSymbolContextHandle pHandle, uint32_t lib
return true;
}

bool XbSymbolContext_SetMutex(XbSymbolContextHandle pHandle, void* opaque_ptr, xb_mutex_lock_t mutex_lock, xb_mutex_unlock_t mutex_unlock)
{
iXbSymbolContext* pContext = (iXbSymbolContext*)pHandle;

if (!iXbSymbolContext_AllowSetParameter(pContext)) {
return false;
}

// Check to make sure both mutex (un)lock are present.
if (!mutex_lock && !mutex_unlock) {
return false;
}

pContext->mtx_opaque_ptr = opaque_ptr;
pContext->lock_fn = mutex_lock;
pContext->unlock_fn = mutex_unlock;
return true;
}

#include "manual_custom.h"
void XbSymbolContext_ScanManual(XbSymbolContextHandle pHandle)
{
Expand Down Expand Up @@ -987,9 +989,7 @@ void XbSymbolContext_ScanManual(XbSymbolContextHandle pHandle)
pContext->scan_stage = SS_2_SCAN_LIBS;

skipScan:;
#ifdef MULTI_THREAD_SAFE
(void)mtx_unlock(&pContext->mutex);
#endif
iXbSymbolContext_Unlock(pContext);
}

unsigned int XbSymbolContext_ScanLibrary(XbSymbolContextHandle pHandle,
Expand Down
Loading