/* radare - LGPL - Copyright 2009-2017 - pancake */ #include #if __WINDOWS__ && !defined(__CYGWIN__) static DWORD WINAPI _r_th_launcher(void *_th) { #else static void *_r_th_launcher(void *_th) { #endif int ret; RThread *th = _th; th->ready = true; #if __UNIX__ if (th->delay > 0) { sleep (th->delay); } else if (th->delay < 0) { r_th_lock_wait (th->lock); } #else if (th->delay < 0) { r_th_lock_wait (th->lock); } #endif do { // CID 1378280: API usage errors (LOCK) // "r_th_lock_leave" unlocks "th->lock->lock" while it is unlocked. r_th_lock_leave (th->lock); th->running = true; ret = th->fun (th); th->running = false; r_th_lock_enter (th->lock); } while (ret); #if HAVE_PTHREAD pthread_exit (&ret); #endif return 0; } R_API int r_th_push_task(struct r_th_t *th, void *user) { int ret = true; th->user = user; r_th_lock_leave (th->lock); return ret; } R_API RThread *r_th_new(R_TH_FUNCTION(fun), void *user, int delay) { RThread *th = R_NEW0 (RThread); if (th) { th->lock = r_th_lock_new (false); th->running = false; th->fun = fun; th->user = user; th->delay = delay; th->breaked = false; th->ready = false; #if HAVE_PTHREAD pthread_create (&th->tid, NULL, _r_th_launcher, th); #elif __WINDOWS__ && !defined(__CYGWIN__) th->tid = CreateThread (NULL, 0, _r_th_launcher, th, 0, 0); #endif } return th; } R_API void r_th_break(RThread *th) { th->breaked = true; } R_API int r_th_kill(RThread *th, int force) { if (!th) { return false; } th->breaked = true; r_th_break (th); r_th_wait (th); #if HAVE_PTHREAD #ifdef __ANDROID__ pthread_kill (th->tid, 9); #else pthread_cancel (th->tid); #endif #elif __WINDOWS__ && !defined(__CYGWIN__) TerminateThread (th->tid, -1); #endif return 0; } R_API bool r_th_start(RThread *th, int enable) { bool ret = true; if (enable) { if (!th->running) { // start thread while (!th->ready) { /* spinlock */ } r_th_lock_leave (th->lock); } } else { if (th->running) { // stop thread r_th_kill (th, 0); r_th_lock_enter (th->lock); // deadlock? } } th->running = enable; return ret; } R_API int r_th_wait(struct r_th_t *th) { int ret = false; void *thret; if (th) { #if HAVE_PTHREAD ret = pthread_join (th->tid, &thret); #elif __WINDOWS__ && !defined(__CYGWIN__) ret = WaitForSingleObject (th->tid, INFINITE); #endif th->running = false; } return ret; } R_API int r_th_wait_async(struct r_th_t *th) { return th->running; } R_API void *r_th_free(struct r_th_t *th) { r_th_kill (th, true); #if __WINDOWS__ && !defined(__CYGWIN__) CloseHandle (th->tid); #endif r_th_lock_free (th->lock); free (th); return NULL; } #if 0 // Thread Pipes typedef struct r_th_pipe_t { RList *msglist; RThread *th; //RThreadLock *lock; } RThreadPipe; r_th_pipe_new(); #endif