Rizin
unix-like reverse engineering framework and cli tools
thread.c File Reference
#include <rz_util.h>
#include "thread.h"

Go to the source code of this file.

Functions

static RZ_TH_RET_T thread_main_function (void *_th)
 
RZ_IPI RZ_TH_TID rz_th_self (void)
 
RZ_API bool rz_th_set_name (RZ_NONNULL RzThread *th, RZ_NONNULL const char *name)
 Sets the name of the thread. More...
 
RZ_API bool rz_th_get_name (RZ_NONNULL RzThread *th, RZ_NONNULL RZ_OUT char *name, size_t len)
 Gets the name of the thread and writes it into the output buffer. More...
 
RZ_API bool rz_th_set_affinity (RZ_NONNULL RzThread *th, int cpuid)
 Sets the thread cpu affinity. More...
 
RZ_API RZ_OWN RzThreadrz_th_new (RZ_NONNULL RzThreadFunction function, RZ_NULLABLE void *user)
 Creates and starts a new thread. More...
 
RZ_API bool rz_th_wait (RZ_NONNULL RzThread *th)
 Awaits indefinetely for a thread to join. More...
 
RZ_API void rz_th_free (RZ_NULLABLE RzThread *th)
 Frees a RzThread structure. More...
 
RZ_API RZ_OWN void * rz_th_get_user (RZ_NONNULL RzThread *th)
 Returns user pointer of thread. More...
 
RZ_API RZ_OWN void * rz_th_get_retv (RZ_NONNULL RzThread *th)
 Returns return value of the thread. More...
 
RZ_API bool rz_th_yield (void)
 Yield the processor. More...
 

Function Documentation

◆ rz_th_free()

RZ_API void rz_th_free ( RZ_NULLABLE RzThread th)

Frees a RzThread structure.

Parameters
thThe RzThread to free

Definition at line 246 of file thread.c.

246  {
247  if (!th) {
248  return;
249  }
250 #if __WINDOWS__
251  CloseHandle(th->tid);
252 #endif
253  free(th);
254 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130

References free().

Referenced by create_string_search_thread(), create_thread_interval(), rz_basefind(), rz_subprocess_fini(), rz_test_main(), rz_th_pool_free(), and task_free().

◆ rz_th_get_name()

RZ_API bool rz_th_get_name ( RZ_NONNULL RzThread th,
RZ_NONNULL RZ_OUT char *  name,
size_t  len 
)

Gets the name of the thread and writes it into the output buffer.

Parameters
thThe thread from which the name is taken
nameThe output buffer name to use to copy the name
lenThe output buffer length
Returns
On success returns true, otherwise false

Definition at line 86 of file thread.c.

86  {
87  rz_return_val_if_fail(th && name && len > 0, false);
88 
89 #if defined(HAVE_PTHREAD_NP) && HAVE_PTHREAD_NP
90 #if __linux__ || __NetBSD__ || (__APPLE__ && defined(MAC_OS_X_VERSION_10_6)) || __sun
91  if (pthread_getname_np(th->tid, name, len) != 0) {
92  RZ_LOG_ERROR("thread: Failed to get thread name\n");
93  return false;
94  }
95 #elif (__FreeBSD__ && __FreeBSD_version >= 1200000) || __DragonFly__ || (__OpenBSD__ && OpenBSD >= 201905)
96  pthread_get_name_np(th->tid, name, len);
97 #elif defined(__HAIKU__)
98  thread_info ti;
99  size_t flen = len < B_OS_NAME_LENGTH ? len : B_OS_NAME_LENGTH;
100 
101  if (get_thread_info((thread_id)th->tid, &ti) != B_OK) {
102  RZ_LOG_ERROR("thread: Failed to get thread name\n");
103  return false;
104  }
105 
106  rz_str_ncpy(name, ti.name, flen);
107 #else
108 #pragma message("warning rz_th_getname not implemented")
109 #endif
110 #endif
111  return true;
112 }
size_t len
Definition: 6502dis.c:15
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API size_t rz_str_ncpy(char *dst, const char *src, size_t n)
Secure string copy with null terminator.
Definition: str.c:923
Definition: z80asm.h:102
char name[1]
Definition: z80asm.h:104

References len, name::name, RZ_LOG_ERROR, rz_return_val_if_fail, and rz_str_ncpy().

◆ rz_th_get_retv()

RZ_API RZ_OWN void* rz_th_get_retv ( RZ_NONNULL RzThread th)

Returns return value of the thread.

Parameters
thThe thread to get the return value from
Returns
returns a pointer set when the thread returns

Definition at line 275 of file thread.c.

275  {
277  return th->retv;
278 }
#define NULL
Definition: cris-opc.c:27

References NULL, and rz_return_val_if_fail.

◆ rz_th_get_user()

RZ_API RZ_OWN void* rz_th_get_user ( RZ_NONNULL RzThread th)

Returns user pointer of thread.

Parameters
thThe thread to get the user pointer from
Returns
user pointer set by the rz_th_new user parameter

Definition at line 263 of file thread.c.

263  {
265  return th->user;
266 }

References NULL, and rz_return_val_if_fail.

Referenced by basefind_stop_all_search_threads(), basefind_thread_ui(), interrupt_thread(), rz_basefind(), rz_bin_file_strings(), and rz_core_wait().

◆ rz_th_new()

RZ_API RZ_OWN RzThread* rz_th_new ( RZ_NONNULL RzThreadFunction  function,
RZ_NULLABLE void *  user 
)

Creates and starts a new thread.

Parameters
functionThe callback to call when the thread starts.
userA pointer to a user structure to pass to the callback function
Returns
On success returns a valid pointer, otherwise NULL.

Definition at line 198 of file thread.c.

198  {
199  rz_return_val_if_fail(function, NULL);
200 
201  RzThread *th = RZ_NEW0(RzThread);
202  if (!th) {
203  RZ_LOG_ERROR("thread: Failed to allocate RzThread\n");
204  return NULL;
205  }
206 
207  th->function = function;
208  th->user = user;
209 
210 #if HAVE_PTHREAD
211  if (!pthread_create(&th->tid, NULL, thread_main_function, th)) {
212  return th;
213  }
214 #elif __WINDOWS__
215  if ((th->tid = CreateThread(NULL, 0, thread_main_function, th, 0, 0))) {
216  return th;
217  }
218 #endif
219  RZ_LOG_ERROR("thread: Failed to start the RzThread\n");
220  free(th);
221  return NULL;
222 }
static RZ_TH_RET_T thread_main_function(void *_th)
Definition: thread.c:13
#define RZ_NEW0(x)
Definition: rz_types.h:284
Definition: thread.h:84
RZ_TH_TID tid
Thread identifier.
Definition: thread.h:85
void * user
User defined thread data to pass (can be NULL).
Definition: thread.h:87
RzThreadFunction function
User defined thread function.
Definition: thread.h:86

References free(), rz_th_t::function, NULL, RZ_LOG_ERROR, RZ_NEW0, rz_return_val_if_fail, thread_main_function(), rz_th_t::tid, and rz_th_t::user.

Referenced by create_string_search_thread(), create_thread_interval(), rz_basefind(), rz_core_rtr_cmd(), rz_core_task_enqueue(), rz_run_config_env(), rz_subprocess_init(), and rz_test_main().

◆ rz_th_self()

RZ_IPI RZ_TH_TID rz_th_self ( void  )

Definition at line 25 of file thread.c.

25  {
26 #if HAVE_PTHREAD
27  return pthread_self();
28 #elif __WINDOWS__
29  return GetCurrentThread();
30 #else
31 #pragma message("Not implemented on this platform")
32  return (RZ_TH_TID)-1;
33 #endif
34 }

◆ rz_th_set_affinity()

RZ_API bool rz_th_set_affinity ( RZ_NONNULL RzThread th,
int  cpuid 
)

Sets the thread cpu affinity.

Parameters
thThe thread to change the cpu affinity
cpuidThe cpuid to set to the thread.
Returns
On success returns true, otherwise false.

Definition at line 122 of file thread.c.

122  {
123  rz_return_val_if_fail(th, false);
124 
125 #if __linux__
126 #if defined(__GLIBC__) && defined(__GLIBC_MINOR__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 2)
127  // Old versions of GNU libc don't have this feature
128 #pragma message("warning rz_th_setaffinity not implemented")
129 #else
130  cpu_set_t c;
131  CPU_ZERO(&c);
132  CPU_SET(cpuid, &c);
133 
134  if (sched_setaffinity((pid_t)(ut64)th->tid, sizeof(c), &c) != 0) {
135  RZ_LOG_ERROR("thread: Failed to set cpu affinity\n");
136  return false;
137  }
138 #endif
139 #elif __FreeBSD__ || __DragonFly__
140  cpuset_t c;
141  CPU_ZERO(&c);
142  CPU_SET(cpuid, &c);
143 
144  if (pthread_setaffinity_np(th->tid, sizeof(c), &c) != 0) {
145  RZ_LOG_ERROR("thread: Failed to set cpu affinity\n");
146  return false;
147  }
148 #elif __NetBSD__
149  cpuset_t *c;
150  c = cpuset_create();
151 
152  if (pthread_setaffinity_np(th->tid, cpuset_size(c), c) != 0) {
153  cpuset_destroy(c);
154  RZ_LOG_ERROR("thread: Failed to set cpu affinity\n");
155  return false;
156  }
157 
158  cpuset_destroy(c);
159 #elif __APPLE__
160  thread_affinity_policy_data_t c = { cpuid };
161  if (thread_policy_set(pthread_mach_thread_np(th->tid),
162  THREAD_AFFINITY_POLICY, (thread_policy_t)&c, 1) != KERN_SUCCESS) {
163  RZ_LOG_ERROR("thread: Failed to set cpu affinity\n");
164  return false;
165  }
166 #elif __WINDOWS__
167  if (SetThreadAffinityMask(th->tid, (DWORD_PTR)1 << cpuid) == 0) {
168  RZ_LOG_ERROR("thread: Failed to set cpu affinity\n");
169  return false;
170  }
171 #elif __sun
172  psetid_t c;
173 
174  pset_create(&c);
175  pset_assign(c, cpuid, NULL);
176 
177  if (pset_bind(c, P_PID, getpid(), NULL)) {
178  pset_destroy(c);
179  RZ_LOG_ERROR("thread: Failed to set cpu affinity\n");
180  return false;
181  }
182 
183  pset_destroy(c);
184 #else
185 #pragma message("warning rz_th_setaffinity not implemented")
186 #endif
187  return true;
188 }
int pid_t
Definition: sftypes.h:38
#define c(i)
Definition: sha256.c:43
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References c, NULL, RZ_LOG_ERROR, rz_return_val_if_fail, and ut64().

Referenced by rz_core_rtr_cmd().

◆ rz_th_set_name()

RZ_API bool rz_th_set_name ( RZ_NONNULL RzThread th,
RZ_NONNULL const char *  name 
)

Sets the name of the thread.

Parameters
thThe thread to rename
nameThe name to assign to the thread
Returns
On success returns true, otherwise false

Definition at line 44 of file thread.c.

44  {
45  rz_return_val_if_fail(th && name, false);
46 
47 #if defined(HAVE_PTHREAD_NP) && HAVE_PTHREAD_NP
48 #if __linux__ || __sun
49  if (pthread_setname_np(th->tid, name) != 0) {
50  RZ_LOG_ERROR("thread: Failed to set thread name\n");
51  return false;
52  }
53 #elif __APPLE__ && defined(MAC_OS_X_VERSION_10_6)
54  if (pthread_setname_np(name) != 0) {
55  RZ_LOG_ERROR("thread: Failed to set thread name\n");
56  return false;
57  }
58 #elif __FreeBSD__ || __OpenBSD__ || __DragonFly__ || __sun
59  pthread_set_name_np(th->tid, name);
60 #elif __NetBSD__
61  if (pthread_setname_np(th->tid, "%s", (void *)name) != 0) {
62  RZ_LOG_ERROR("thread: Failed to set thread name\n");
63  return false;
64  }
65 #elif __HAIKU__
66  if (rename_thread((thread_id)th->tid, name) != B_OK) {
67  RZ_LOG_ERROR("thread: Failed to set thread name\n");
68  return false;
69  }
70 #else
71 #pragma message("warning rz_th_setname not implemented")
72 #endif
73 #endif
74  return true;
75 }

References RZ_LOG_ERROR, and rz_return_val_if_fail.

Referenced by rz_core_rtr_cmd().

◆ rz_th_wait()

RZ_API bool rz_th_wait ( RZ_NONNULL RzThread th)

Awaits indefinetely for a thread to join.

Parameters
[in]thThe thread to await for.
Returns
On graceful stop returns true, otherwise false

Definition at line 231 of file thread.c.

231  {
232  rz_return_val_if_fail(th, false);
233 #if HAVE_PTHREAD
234  void *thret = NULL;
235  return pthread_join(th->tid, &thret) == 0;
236 #elif __WINDOWS__
237  return WaitForSingleObject(th->tid, INFINITE) == 0; // WAIT_OBJECT_0
238 #endif
239 }

References NULL, and rz_return_val_if_fail.

Referenced by interrupt_thread(), rz_basefind(), rz_core_wait(), rz_subprocess_fini(), rz_test_main(), rz_th_pool_wait(), and task_free().

◆ rz_th_yield()

RZ_API bool rz_th_yield ( void  )

Yield the processor.

Returns
On success returns true, otherwise false

Definition at line 285 of file thread.c.

285  {
286 #if __WINDOWS__
287  return SwitchToThread() != 0;
288 #else
289  // sched_yield is not available everywhere.
290  // usleep is more portable.
291  rz_sys_usleep(1);
292  return true;
293 #endif
294 }
RZ_API int rz_sys_usleep(int usecs)
Sleep for usecs microseconds.
Definition: sys.c:317

References rz_sys_usleep().

◆ thread_main_function()

static RZ_TH_RET_T thread_main_function ( void *  _th)
static

Definition at line 13 of file thread.c.

13  {
14 #if HAVE_PTHREAD
15 #ifndef __ANDROID__
16  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
17  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
18 #endif
19 #endif
20  RzThread *th = (RzThread *)_th;
21  th->retv = th->function(th->user);
22  return NULL;
23 }
void * retv
Thread return value.
Definition: thread.h:88

References rz_th_t::function, NULL, rz_th_t::retv, and rz_th_t::user.

Referenced by rz_th_new().