Skip to content

Commit

Permalink
Add N_THREAD_LIMIT to limit the max number of threads (upper limit).
Browse files Browse the repository at this point in the history
  • Loading branch information
wargio committed May 23, 2024
1 parent 1d9ae2a commit ec4003f
Show file tree
Hide file tree
Showing 15 changed files with 87 additions and 56 deletions.
4 changes: 2 additions & 2 deletions binrz/rz-test/rz-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ static bool rz_test_chdir_fromtest(const char *test_path) {
}

int rz_test_main(int argc, const char **argv) {
size_t n_threads = RZ_THREAD_POOL_ALL_CORES;
size_t n_threads = RZ_THREAD_N_CORES_ALL_AVAILABLE;
bool verbose = false;
bool nothing = false;
bool quiet = false;
Expand Down Expand Up @@ -536,7 +536,7 @@ int rz_test_main(int argc, const char **argv) {
return -1;
}

eprintf("Using %" PFMTSZu " threads\n", rz_th_request_physical_cores(n_threads));
eprintf("Using %d threads\n", rz_th_max_threads(n_threads));

state.data.time_start = rz_time_now_mono();
rz_th_iterate_pvector(&state.db->tests, worker_thread, n_threads, &state);
Expand Down
2 changes: 1 addition & 1 deletion librz/arch/similarity.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ static RZ_OWN RzAnalysisMatchResult *analysis_match_result_new(RZ_NONNULL RzAnal
RzAnalysisMatchResult *result = NULL;
RzList *unmatch_a = rz_list_newf((RzListFree)free);
RzList *unmatch_b = rz_list_clone(list_b);
RzThreadPool *pool = rz_th_pool_new(RZ_THREAD_POOL_ALL_CORES);
RzThreadPool *pool = rz_th_pool_new(RZ_THREAD_N_CORES_ALL_AVAILABLE);
RzThread *user_thread = NULL;
SharedContext shared = { 0 };
MatchUIInfo ui_info = { 0 };
Expand Down
2 changes: 1 addition & 1 deletion librz/bin/bfile_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ static void scan_cfstring_table(RzBinFile *bf, HtUP *strings_db, RzPVector /*<Rz
*/
RZ_API void rz_bin_string_search_opt_init(RZ_NONNULL RzBinStringSearchOpt *opt) {
rz_return_if_fail(opt);
opt->max_threads = RZ_THREAD_POOL_ALL_CORES;
opt->max_threads = RZ_THREAD_N_CORES_ALL_AVAILABLE;
opt->min_length = RZ_BIN_STRING_SEARCH_MIN_STRING;
opt->buffer_size = RZ_BIN_STRING_SEARCH_BUFFER_SIZE;
opt->max_uni_blocks = RZ_BIN_STRING_SEARCH_MAX_UNI_BLOCKS;
Expand Down
16 changes: 8 additions & 8 deletions librz/core/cbin.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@

#define LOAD_BSS_MALLOC 0

#define IS_MODE_SET(mode) ((mode)&RZ_MODE_SET)
#define IS_MODE_SIMPLE(mode) ((mode)&RZ_MODE_SIMPLE)
#define IS_MODE_SIMPLEST(mode) ((mode)&RZ_MODE_SIMPLEST)
#define IS_MODE_JSON(mode) ((mode)&RZ_MODE_JSON)
#define IS_MODE_RZCMD(mode) ((mode)&RZ_MODE_RIZINCMD)
#define IS_MODE_EQUAL(mode) ((mode)&RZ_MODE_EQUAL)
#define IS_MODE_SET(mode) ((mode) & RZ_MODE_SET)
#define IS_MODE_SIMPLE(mode) ((mode) & RZ_MODE_SIMPLE)
#define IS_MODE_SIMPLEST(mode) ((mode) & RZ_MODE_SIMPLEST)
#define IS_MODE_JSON(mode) ((mode) & RZ_MODE_JSON)
#define IS_MODE_RZCMD(mode) ((mode) & RZ_MODE_RIZINCMD)
#define IS_MODE_EQUAL(mode) ((mode) & RZ_MODE_EQUAL)
#define IS_MODE_NORMAL(mode) (!(mode))
#define IS_MODE_CLASSDUMP(mode) ((mode)&RZ_MODE_CLASSDUMP)
#define IS_MODE_CLASSDUMP(mode) ((mode) & RZ_MODE_CLASSDUMP)

// dup from cmd_info
#define PAIR_WIDTH "9"
Expand Down Expand Up @@ -2595,7 +2595,7 @@ RZ_API bool rz_core_bin_basefind_print(RzCore *core, ut32 pointer_size, RzCmdSta
// ensure the last printed line is actually the last expected line
// this depends on the number of the threads requested and available
// this requires to be called before checking the results
int n_cores = (int)rz_th_request_physical_cores(options.max_threads);
int n_cores = (int)rz_th_max_threads(options.max_threads);
rz_cons_gotoxy(1, begin_line + n_cores);
}

Expand Down
10 changes: 5 additions & 5 deletions librz/core/cconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -1114,12 +1114,12 @@ static bool cb_str_escbslash(void *user, void *data) {
static bool cb_str_search_max_threads(void *user, void *data) {
RzCore *core = (RzCore *)user;
RzConfigNode *node = (RzConfigNode *)data;
size_t max_threads = rz_th_physical_core_number();
RzThreadNCores max_threads = rz_th_max_threads(node->i_value);
if (node->value[0] == '?') {
rz_cons_printf("%" PFMTSZu "\n", max_threads);
rz_cons_printf("%d\n", max_threads);
return false;
}
core->bin->str_search_cfg.max_threads = RZ_MIN(max_threads, node->i_value);
core->bin->str_search_cfg.max_threads = max_threads;
return true;
}

Expand Down Expand Up @@ -3692,7 +3692,7 @@ RZ_API int rz_core_config_init(RzCore *core) {

/* string search options */
SETB("str.search.reload", true, "When enabled, any change to any option `str.search.*` will reload the bin strings.");
SETICB("str.search.max_threads", RZ_THREAD_POOL_ALL_CORES, &cb_str_search_max_threads, "Maximum core number (0 for all cores).");
SETICB("str.search.max_threads", RZ_THREAD_N_CORES_ALL_AVAILABLE, &cb_str_search_max_threads, "Maximum core number (0 for all cores).");
SETICB("str.search.min_length", RZ_BIN_STRING_SEARCH_MIN_STRING, &cb_str_search_min_length, "Smallest string length that is possible to find.");
SETICB("str.search.buffer_size", RZ_BIN_STRING_SEARCH_BUFFER_SIZE, &cb_str_search_buffer_size, "Maximum buffer size, which will also determine the maximum string length.");
SETICB("str.search.max_uni_blocks", RZ_BIN_STRING_SEARCH_MAX_UNI_BLOCKS, &cb_str_search_max_uni_blocks, "Maximum number of unicode blocks.");
Expand Down Expand Up @@ -3780,7 +3780,7 @@ RZ_API int rz_core_config_init(RzCore *core) {
SETI("basefind.alignment", RZ_BASEFIND_BASE_ALIGNMENT, "Basefind alignment in bytes");
SETI("basefind.min.score", RZ_BASEFIND_SCORE_MIN_VALUE, "Basefind min score value to consider it valid");
SETI("basefind.min.string", RZ_BASEFIND_STRING_MIN_LENGTH, "Basefind min string size to find to consider it valid");
SETI("basefind.max.threads", RZ_THREAD_POOL_ALL_CORES, "Basefind max threads number (when 0 uses all available cores)");
SETI("basefind.max.threads", RZ_THREAD_N_CORES_ALL_AVAILABLE, "Basefind max threads number (when 0 uses all available cores)");

/* nkeys */
SETPREF("key.s", "", "override step into action");
Expand Down
2 changes: 1 addition & 1 deletion librz/include/rz_basefind.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ typedef struct rz_basefind_info_t {
typedef bool (*RzBaseFindThreadInfoCb)(const RzBaseFindThreadInfo *th_info, void *user);

typedef struct rz_basefind_options_t {
size_t max_threads; ///< Max requested number of threads (not guaranteed).
RzThreadNCores max_threads; ///< Max requested number of threads (not guaranteed).
ut32 pointer_size; ///< Pointer size in bits (32 or 64)
ut64 start_address; ///< Start search address
ut64 end_address; ///< End search address
Expand Down
5 changes: 3 additions & 2 deletions librz/include/rz_bin.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <rz_io.h>
#include <rz_cons.h>
#include <rz_list.h>
#include <rz_th.h>
#include <rz_util/ht_pu.h>
#include <rz_demangler.h>
#include <rz_hash.h>
Expand Down Expand Up @@ -164,7 +165,7 @@ typedef enum {
} RzBinLanguage;

#define RZ_BIN_LANGUAGE_MASK(x) ((x) & ~RZ_BIN_LANGUAGE_BLOCKS)
#define RZ_BIN_LANGUAGE_HAS_BLOCKS(x) ((x)&RZ_BIN_LANGUAGE_BLOCKS)
#define RZ_BIN_LANGUAGE_HAS_BLOCKS(x) ((x) & RZ_BIN_LANGUAGE_BLOCKS)

enum {
RZ_BIN_CLASS_PRIVATE,
Expand Down Expand Up @@ -200,7 +201,7 @@ typedef enum {
} RzBinStringSearchMode;

typedef struct rz_bin_string_search_opt_t {
size_t max_threads; ///< Maximum thread number (normally set to RZ_THREAD_POOL_ALL_CORES).
RzThreadNCores max_threads; ///< Maximum thread number (normally set to RZ_THREAD_N_CORES_ALL_AVAILABLE).
size_t min_length; ///< Smallest string length that is possible to find.
size_t buffer_size; ///< Maximum buffer size, which will also determine the maximum string length.
size_t max_uni_blocks; ///< Maximum number of unicode blocks
Expand Down
21 changes: 13 additions & 8 deletions librz/include/rz_th.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@
extern "C" {
#endif

#define RZ_THREAD_POOL_ALL_CORES (0)
#define RZ_THREAD_QUEUE_UNLIMITED (0)
typedef enum {
RZ_THREAD_N_CORES_ALL_AVAILABLE = 0,
} RzThreadNCores;

typedef enum {
RZ_THREAD_QUEUE_UNLIMITED = 0,
} RzThreadQueueSize;

typedef struct rz_th_sem_t RzThreadSemaphore;
typedef struct rz_th_lock_t RzThreadLock;
Expand Down Expand Up @@ -61,17 +66,17 @@ RZ_API void rz_th_cond_signal_all(RZ_NONNULL RzThreadCond *cond);
RZ_API void rz_th_cond_wait(RZ_NONNULL RzThreadCond *cond, RZ_NONNULL RzThreadLock *lock);
RZ_API void rz_th_cond_free(RZ_NULLABLE RzThreadCond *cond);

RZ_API size_t rz_th_physical_core_number();
RZ_API size_t rz_th_request_physical_cores(size_t max_cores);
RZ_API RzThreadNCores rz_th_physical_core_number();
RZ_API RzThreadNCores rz_th_max_threads(RzThreadNCores requested);

RZ_API RZ_OWN RzThreadPool *rz_th_pool_new(size_t max_threads);
RZ_API RZ_OWN RzThreadPool *rz_th_pool_new(RzThreadNCores max_threads);
RZ_API void rz_th_pool_free(RZ_NULLABLE RzThreadPool *pool);
RZ_API bool rz_th_pool_add_thread(RZ_NONNULL RzThreadPool *pool, RZ_NONNULL RzThread *thread);
RZ_API RZ_BORROW RzThread *rz_th_pool_get_thread(RZ_NONNULL RzThreadPool *pool, size_t index);
RZ_API bool rz_th_pool_wait(RZ_NONNULL RzThreadPool *pool);
RZ_API size_t rz_th_pool_size(RZ_NONNULL RzThreadPool *pool);

RZ_API RZ_OWN RzThreadQueue *rz_th_queue_new(size_t max_size, RZ_NULLABLE RzListFree qfree);
RZ_API RZ_OWN RzThreadQueue *rz_th_queue_new(RzThreadQueueSize max_size, RZ_NULLABLE RzListFree qfree);
RZ_API RZ_OWN RzThreadQueue *rz_th_queue_from_list(RZ_NONNULL RZ_BORROW RzList /*<void *>*/ *list, RZ_NULLABLE RzListFree qfree);
RZ_API RZ_OWN RzThreadQueue *rz_th_queue_from_pvector(RZ_NONNULL RZ_BORROW RzPVector /*<void *>*/ *vector, RZ_NULLABLE RzListFree qfree);
RZ_API void rz_th_queue_free(RZ_NULLABLE RzThreadQueue *queue);
Expand All @@ -88,8 +93,8 @@ RZ_API void rz_atomic_bool_free(RZ_NULLABLE RzAtomicBool *tbool);
RZ_API bool rz_atomic_bool_get(RZ_NONNULL RzAtomicBool *tbool);
RZ_API void rz_atomic_bool_set(RZ_NONNULL RzAtomicBool *tbool, bool value);

RZ_API bool rz_th_iterate_list(RZ_NONNULL const RzList /*<void *>*/ *list, RZ_NONNULL RzThreadIterator iterator, size_t max_threads, RZ_NULLABLE void *user);
RZ_API bool rz_th_iterate_pvector(RZ_NONNULL const RzPVector /*<void *>*/ *pvec, RZ_NONNULL RzThreadIterator iterator, size_t max_threads, RZ_NULLABLE void *user);
RZ_API bool rz_th_iterate_list(RZ_NONNULL const RzList /*<void *>*/ *list, RZ_NONNULL RzThreadIterator iterator, RzThreadNCores max_threads, RZ_NULLABLE void *user);
RZ_API bool rz_th_iterate_pvector(RZ_NONNULL const RzPVector /*<void *>*/ *pvec, RZ_NONNULL RzThreadIterator iterator, RzThreadNCores max_threads, RZ_NULLABLE void *user);

#endif /* RZ_API */

Expand Down
1 change: 1 addition & 0 deletions librz/include/rz_userconf.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#define IS_IOS @IS_IOS@
#define RZ_BUILD_DEBUG @RZ_BUILD_DEBUG@
#define WITH_SWIFT_DEMANGLER @WITH_SWIFT_DEMANGLER@
#define N_THREAD_LIMIT @N_THREAD_LIMIT@
#define HAVE_COPYFILE @HAVE_COPYFILE@
#define HAVE_COPY_FILE_RANGE @HAVE_COPY_FILE_RANGE@
#define HAVE_BACKTRACE @HAVE_BACKTRACE@
Expand Down
6 changes: 3 additions & 3 deletions librz/util/thread_iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <rz_th.h>
#include <rz_util.h>

static bool th_run_iterator(RzThreadFunction th_cb, void *context, size_t max_threads) {
static bool th_run_iterator(RzThreadFunction th_cb, void *context, RzThreadNCores max_threads) {
RzThreadPool *pool = rz_th_pool_new(max_threads);
if (!pool) {
RZ_LOG_ERROR("th: failed to allocate thread pool\n");
Expand Down Expand Up @@ -70,7 +70,7 @@ static void *thread_iterate_list_cb(th_list_ctx_t *context) {
*
* \return On error returns false, otherwise true.
*/
RZ_API bool rz_th_iterate_list(RZ_NONNULL const RzList /*<void *>*/ *list, RZ_NONNULL RzThreadIterator iterator, size_t max_threads, RZ_NULLABLE void *user) {
RZ_API bool rz_th_iterate_list(RZ_NONNULL const RzList /*<void *>*/ *list, RZ_NONNULL RzThreadIterator iterator, RzThreadNCores max_threads, RZ_NULLABLE void *user) {
rz_return_val_if_fail(list && iterator, false);
if (rz_list_length(list) < 1) {
// nothing to do, but return true
Expand Down Expand Up @@ -138,7 +138,7 @@ static void *thread_iterate_pvec_cb(th_vec_ctx_t *context) {
*
* \return On error returns false, otherwise true.
*/
RZ_API bool rz_th_iterate_pvector(RZ_NONNULL const RzPVector /*<void *>*/ *pvec, RZ_NONNULL RzThreadIterator iterator, size_t max_threads, RZ_NULLABLE void *user) {
RZ_API bool rz_th_iterate_pvector(RZ_NONNULL const RzPVector /*<void *>*/ *pvec, RZ_NONNULL RzThreadIterator iterator, RzThreadNCores max_threads, RZ_NULLABLE void *user) {
rz_return_val_if_fail(pvec && iterator, false);
if (rz_pvector_len(pvec) < 1) {
// nothing to do, but return true
Expand Down
35 changes: 20 additions & 15 deletions librz/util/thread_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <rz_th.h>
#include "thread.h"
#include <rz_userconf.h>

/**
* \brief RzThreadPool is a structure which handles n-threads threads
Expand All @@ -19,11 +20,11 @@ struct rz_th_pool_t {
*
* \return The number of available physical cores (always >= 1)
*/
RZ_API size_t rz_th_physical_core_number() {
RZ_API RzThreadNCores rz_th_physical_core_number() {
#ifdef __WINDOWS__
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
return sysinfo.dwNumberOfProcessors;
return (RzThreadNCores)sysinfo.dwNumberOfProcessors;
#elif __APPLE__ || __FreeBSD__ || __OpenBSD__ || __DragonFly__ || __NetBSD__
int os_status = 0;
int mib[4];
Expand Down Expand Up @@ -57,30 +58,34 @@ RZ_API size_t rz_th_physical_core_number() {
// this is needed because the upper bits are set on bsd platforms
n_cpus &= UT32_MAX;

return n_cpus;
return (RzThreadNCores)n_cpus;
#elif __HAIKU__
system_info info;
get_system_info(&info);
return info.cpu_count;
return (RzThreadNCores)info.cpu_count;
#else
return sysconf(_SC_NPROCESSORS_ONLN);
return (RzThreadNCores)sysconf(_SC_NPROCESSORS_ONLN);
#endif
}

/**
* \brief Returns the maximum number of cores available regardless of the number of cores requested.
* When set to 0, it will be the max number of physical cores.
* \brief Returns the maximum number of threads available unless it exeeds N_THREAD_LIMIT.
* When set to 0, it will be the max number of cores.
*
* \param[in] max_cores The maximum number of physical cores to request
* \param[in] max_threads The maximum number of threads to request
*
* \return The actual max number of cores available
* \return The max number of threads requested
*/
RZ_API size_t rz_th_request_physical_cores(size_t max_cores) {
size_t n_cores = rz_th_physical_core_number();
if (!max_cores) {
RZ_API RzThreadNCores rz_th_max_threads(RzThreadNCores requested) {
const size_t n_thread_limit = N_THREAD_LIMIT;
RzThreadNCores n_cores = rz_th_physical_core_number();
if (requested <= RZ_THREAD_N_CORES_ALL_AVAILABLE) {
return n_cores;
} else if (n_thread_limit < (size_t)requested) {
RZ_LOG_WARN("The number of requested threads is higher than the thread limit (%" PFMTSZu ").\n", n_thread_limit);
return n_thread_limit;
}
return RZ_MIN(n_cores, max_cores);
return requested;
}

/**
Expand All @@ -93,13 +98,13 @@ RZ_API size_t rz_th_request_physical_cores(size_t max_cores) {
* \param max_threads The maximum number of threads needed in the pool
* \return RzThreadPool The RzThreadPool structure
*/
RZ_API RZ_OWN RzThreadPool *rz_th_pool_new(size_t max_threads) {
RZ_API RZ_OWN RzThreadPool *rz_th_pool_new(RzThreadNCores max_threads) {
RzThreadPool *pool = RZ_NEW0(RzThreadPool);
if (!pool) {
return NULL;
}

pool->size = rz_th_request_physical_cores(max_threads);
pool->size = (size_t)rz_th_max_threads(max_threads);
pool->threads = RZ_NEWS0(RzThread *, pool->size);
if (!pool->threads) {
free(pool);
Expand Down
4 changes: 2 additions & 2 deletions librz/util/thread_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
struct rz_th_queue_t {
RzThreadLock *lock;
RzThreadCond *cond;
size_t max_size;
RzThreadQueueSize max_size;
RzList /*<void *>*/ *list;
};

Expand All @@ -29,7 +29,7 @@ struct rz_th_queue_t {
*
* \return On success returns a valid pointer, otherwise NULL
*/
RZ_API RZ_OWN RzThreadQueue *rz_th_queue_new(size_t max_size, RZ_NULLABLE RzListFree qfree) {
RZ_API RZ_OWN RzThreadQueue *rz_th_queue_new(RzThreadQueueSize max_size, RZ_NULLABLE RzListFree qfree) {
RzThreadQueue *queue = RZ_NEW0(RzThreadQueue);
if (!queue) {
return NULL;
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ foreach it : ccs
it_userconf.set10('HAVE_PTHREAD', have_pthread)
it_userconf.set10('HAVE_LZMA', get_option('use_lzma'))
it_userconf.set10('HAVE_ZLIB', get_option('use_zlib'))
it_userconf.set10('N_THREAD_LIMIT', get_option('n_thread_limit'))
it_userconf.set10('SUPPORTS_PCRE2_JIT', pcre2_jit_supported)

if it_machine.system() == 'freebsd' or it_machine.system() == 'dragonfly'
Expand Down
1 change: 1 addition & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ option('blob', type: 'boolean', value: false, description: 'Compile just one bin
option('subprojects_check', type: 'boolean', value: true, description: 'Check if git subprojects are up-to-date. Might be useful to disable this when developing on a different subproject version')
option('portable', type: 'boolean', value: false, description: 'Make rizin installation moveable, by using relative paths instead of absolute ones')
option('extra_prefix', type: 'string', value: '', description: 'Extra load path prefix (absolute path) for plugins, sdb, sigdb, etc.')
option('n_thread_limit', type: 'integer', min: 1, value: 32767)

option('rizin_wwwroot', type: 'string', value: '', description: 'Install path for www files')
option('rizin_sdb', type: 'string', value: '', description: 'Install path for all SDB files')
Expand Down
Loading

0 comments on commit ec4003f

Please sign in to comment.