Skip to content

Commit

Permalink
Merge pull request #167 from RadWolfie/impl-mutex-callback
Browse files Browse the repository at this point in the history
Implement Multi-Threading's Mutex Callback APIs
  • Loading branch information
ergo720 authored Nov 24, 2022
2 parents e80ff0d + 1076f03 commit 51488b6
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 102 deletions.
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

0 comments on commit 51488b6

Please sign in to comment.