Rizin
unix-like reverse engineering framework and cli tools
thread_pool.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2022 deroad <wargio@libero.it>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_th.h>
5 #include "thread.h"
6 
12 struct rz_th_pool_t {
13  size_t size;
15 };
16 
23 #ifdef __WINDOWS__
24  SYSTEM_INFO sysinfo;
25  GetSystemInfo(&sysinfo);
26  return sysinfo.dwNumberOfProcessors;
27 #elif __APPLE__ || __FreeBSD__ || __OpenBSD__ || __DragonFly__ || __NetBSD__
28  int os_status = 0;
29  int mib[4];
30  unsigned long n_cpus = 1;
31  size_t n_cpus_length = sizeof(n_cpus);
32 
33  /* set the mib for hw.ncpu */
34  mib[0] = CTL_HW;
35 #if __NetBSD__
36  mib[1] = HW_NCPUONLINE;
37 #elif __OpenBSD__ || __FreeBSD__ || __DragonFly__
38  mib[1] = HW_NCPU;
39 #else
40  mib[1] = HW_AVAILCPU;
41 #endif
42 
43  os_status = sysctl(mib, 2, &n_cpus, &n_cpus_length, NULL, 0);
44 
45  if (os_status != 0) {
46 #if __OpenBSD__ || __FreeBSD__
47  n_cpus = 1;
48 #else
49  // HW_AVAILCPU does not exist.
50  mib[1] = HW_NCPU;
51  os_status = sysctl(mib, 2, &n_cpus, &n_cpus_length, NULL, 0);
52  if (os_status != 0) {
53  n_cpus = 1;
54  }
55 #endif
56  }
57  // this is needed because the upper bits are set on bsd platforms
58  n_cpus &= UT32_MAX;
59 
60  return n_cpus;
61 #elif __HAIKU__
62  system_info info;
63  get_system_info(&info);
64  return info.cpu_count;
65 #else
66  return sysconf(_SC_NPROCESSORS_ONLN);
67 #endif
68 }
69 
78 RZ_API size_t rz_th_request_physical_cores(size_t max_cores) {
79  size_t n_cores = rz_th_physical_core_number();
80  if (!max_cores) {
81  return n_cores;
82  }
83  return RZ_MIN(n_cores, max_cores);
84 }
85 
96 RZ_API RZ_OWN RzThreadPool *rz_th_pool_new(size_t max_threads) {
98  if (!pool) {
99  return NULL;
100  }
101 
102  pool->size = rz_th_request_physical_cores(max_threads);
103  pool->threads = RZ_NEWS0(RzThread *, pool->size);
104  if (!pool->threads) {
105  free(pool);
106  return NULL;
107  }
108 
109  return pool;
110 }
111 
118  if (!pool) {
119  return;
120  }
121  for (ut32 i = 0; i < pool->size; ++i) {
122  if (pool->threads[i]) {
123  rz_th_free(pool->threads[i]);
124  pool->threads[i] = NULL;
125  }
126  }
127  free(pool->threads);
128  free(pool);
129 }
130 
139  rz_return_val_if_fail(pool && thread, false);
140  for (ut32 i = 0; i < pool->size; ++i) {
141  if (!pool->threads[i]) {
142  RZ_LOG_DEBUG("thread: thread %u added\n", i);
143  pool->threads[i] = thread;
144  return true;
145  }
146  }
147  return false;
148 }
149 
159  rz_return_val_if_fail(pool && index < pool->size, NULL);
160  return pool->threads[index];
161 }
162 
171  rz_return_val_if_fail(pool, false);
172  bool has_exited = true;
173  for (ut32 i = 0; i < pool->size; ++i) {
174  if (pool->threads[i]) {
175  RZ_LOG_DEBUG("thread: waiting for thread %u\n", i);
176  has_exited = has_exited && rz_th_wait(pool->threads[i]);
177  }
178  }
179  return has_exited;
180 }
181 
190  rz_return_val_if_fail(pool, 1);
191  return pool->size;
192 }
lzma_index ** i
Definition: index.h:629
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
#define RZ_API
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
RZ_API void rz_th_free(RZ_NULLABLE RzThread *th)
Frees a RzThread structure.
Definition: thread.c:246
RZ_API bool rz_th_wait(RZ_NONNULL RzThread *th)
Awaits indefinetely for a thread to join.
Definition: thread.c:231
static const char struct stat static buf struct stat static buf static vhangup int struct rusage static rusage sysinfo
Definition: sflib.h:147
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RZ_LOG_DEBUG(fmtstr,...)
Definition: rz_log.h:49
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NONNULL
Definition: rz_types.h:64
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
#define RZ_BORROW
Definition: rz_types.h:63
#define RZ_MIN(x, y)
#define UT32_MAX
Definition: rz_types_base.h:99
RzThreadPool is a structure which handles n-threads threads.
Definition: thread_pool.c:12
RzThread ** threads
Definition: thread_pool.c:14
size_t size
Definition: thread_pool.c:13
Definition: thread.h:84
RZ_API size_t rz_th_request_physical_cores(size_t max_cores)
Returns the maximum number of cores available regardless of the number of cores requested....
Definition: thread_pool.c:78
RZ_API void rz_th_pool_free(RZ_NULLABLE RzThreadPool *pool)
Kills (and frees) the threads and frees the RzThreadPool struct.
Definition: thread_pool.c:117
RZ_API size_t rz_th_physical_core_number()
Returns the number of available physical cores of the host machine.
Definition: thread_pool.c:22
RZ_API RZ_BORROW RzThread * rz_th_pool_get_thread(RZ_NONNULL RzThreadPool *pool, size_t index)
Returns the n-th thread in the thread pool.
Definition: thread_pool.c:158
RZ_API bool rz_th_pool_wait(RZ_NONNULL RzThreadPool *pool)
Waits the end of all the threads in the thread pool.
Definition: thread_pool.c:170
RZ_API bool rz_th_pool_add_thread(RZ_NONNULL RzThreadPool *pool, RZ_NONNULL RzThread *thread)
Adds a thread to the thread pool.
Definition: thread_pool.c:138
RZ_API size_t rz_th_pool_size(RZ_NONNULL RzThreadPool *pool)
Returns the thread pool size.
Definition: thread_pool.c:189
RZ_API RZ_OWN RzThreadPool * rz_th_pool_new(size_t max_threads)
returns a new RzThreadPool structure with a pool of thread
Definition: thread_pool.c:96