1 /* Copyright (C) 2010-2020 The RetroArch team
3 * ---------------------------------------------------------------------------------------
4 * The following license statement only applies to this file (rthreads.c).
5 * ---------------------------------------------------------------------------------------
7 * Permission is hereby granted, free of charge,
8 * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #define _POSIX_C_SOURCE 199309
33 #include <rthreads/rthreads.h>
35 /* with RETRO_WIN32_USE_PTHREADS, pthreads can be used even on win32. Maybe only supported in MSVC>=2005 */
37 #if defined(_WIN32) && !defined(RETRO_WIN32_USE_PTHREADS)
38 #define USE_WIN32_THREADS
42 #define WIN32_LEAN_AND_MEAN
44 #define _WIN32_WINNT 0x0500 /*_WIN32_WINNT_WIN2K */
50 #include <ogc/lwp_watchdog.h>
51 #include "gx_pthread.h"
53 #include "ctr_pthread.h"
59 #if defined(VITA) || defined(BSD) || defined(ORBIS) || defined(__mips__) || defined(_3DS)
64 #include <mach/clock.h>
65 #include <mach/mach.h>
76 #ifdef USE_WIN32_THREADS
86 #ifdef USE_WIN32_THREADS
87 CRITICAL_SECTION lock;
93 #ifdef USE_WIN32_THREADS
94 /* The syntax we'll use is mind-bending unless we use a struct. Plus, we might want to store more info later */
95 /* This will be used as a linked list immplementing a queue of waiting threads */
98 struct queue_entry *next;
104 #ifdef USE_WIN32_THREADS
105 /* With this implementation of scond, we don't have any way of waking
106 * (or even identifying) specific threads
107 * But we need to wake them in the order indicated by the queue.
108 * This potato token will get get passed around every waiter.
109 * The bearer can test whether he's next, and hold onto the potato if he is.
110 * When he's done he can then put it back into play to progress
111 * the queue further */
114 /* The primary signalled event. Hot potatoes are passed until this is set. */
117 /* the head of the queue; NULL if queue is empty */
118 struct queue_entry *head;
120 /* equivalent to the queue length */
123 /* how many waiters in the queue have been conceptually wakened by signals
124 * (even if we haven't managed to actually wake them yet) */
127 /* used to control access to this scond, in case the user fails */
135 #ifdef USE_WIN32_THREADS
136 static DWORD CALLBACK thread_wrap(void *data_)
138 static void *thread_wrap(void *data_)
141 struct thread_data *data = (struct thread_data*)data_;
144 data->func(data->userdata);
151 * @start_routine : thread entry callback function
152 * @userdata : pointer to userdata that will be made
153 * available in thread entry callback function
155 * Create a new thread.
157 * Returns: pointer to new thread if successful, otherwise NULL.
159 sthread_t *sthread_create(void (*thread_func)(void*), void *userdata)
161 return sthread_create_with_priority(thread_func, userdata, 0);
164 /* TODO/FIXME - this needs to be implemented for Switch/3DS */
165 #if !defined(SWITCH) && !defined(USE_WIN32_THREADS) && !defined(_3DS) && !defined(GEKKO) && !defined(__HAIKU__) && !defined(EMSCRIPTEN)
166 #define HAVE_THREAD_ATTR
170 * sthread_create_with_priority:
171 * @start_routine : thread entry callback function
172 * @userdata : pointer to userdata that will be made
173 * available in thread entry callback function
174 * @thread_priority : thread priority hint value from [1-100]
176 * Create a new thread. It is possible for the caller to give a hint
177 * for the thread's priority from [1-100]. Any passed in @thread_priority
178 * values that are outside of this range will cause sthread_create() to
179 * create a new thread using the operating system's default thread
182 * Returns: pointer to new thread if successful, otherwise NULL.
184 sthread_t *sthread_create_with_priority(void (*thread_func)(void*), void *userdata, int thread_priority)
186 #ifdef HAVE_THREAD_ATTR
187 pthread_attr_t thread_attr;
188 bool thread_attr_needed = false;
190 bool thread_created = false;
191 struct thread_data *data = NULL;
192 sthread_t *thread = (sthread_t*)malloc(sizeof(*thread));
197 if (!(data = (struct thread_data*)malloc(sizeof(*data))))
203 data->func = thread_func;
204 data->userdata = userdata;
207 #ifdef USE_WIN32_THREADS
208 thread->thread = CreateThread(NULL, 0, thread_wrap,
209 data, 0, &thread->id);
210 thread_created = !!thread->thread;
212 #ifdef HAVE_THREAD_ATTR
213 pthread_attr_init(&thread_attr);
215 if ((thread_priority >= 1) && (thread_priority <= 100))
217 struct sched_param sp;
218 memset(&sp, 0, sizeof(struct sched_param));
219 sp.sched_priority = thread_priority;
220 pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);
221 pthread_attr_setschedparam(&thread_attr, &sp);
223 thread_attr_needed = true;
227 pthread_attr_setstacksize(&thread_attr , 0x10000 );
228 thread_attr_needed = true;
229 #elif defined(__APPLE__)
230 /* Default stack size on Apple is 512Kb;
231 * for PS2 disc scanning and other reasons, we'd like 2MB. */
232 pthread_attr_setstacksize(&thread_attr , 0x200000 );
233 thread_attr_needed = true;
236 if (thread_attr_needed)
237 thread_created = pthread_create(&thread->id, &thread_attr, thread_wrap, data) == 0;
239 thread_created = pthread_create(&thread->id, NULL, thread_wrap, data) == 0;
241 pthread_attr_destroy(&thread_attr);
243 thread_created = pthread_create(&thread->id, NULL, thread_wrap, data) == 0;
257 * @thread : pointer to thread object
259 * Detach a thread. When a detached thread terminates, its
260 * resources are automatically released back to the system
261 * without the need for another thread to join with the
264 * Returns: 0 on success, otherwise it returns a non-zero error number.
266 int sthread_detach(sthread_t *thread)
268 #ifdef USE_WIN32_THREADS
269 CloseHandle(thread->thread);
273 int ret = pthread_detach(thread->id);
281 * @thread : pointer to thread object
283 * Join with a terminated thread. Waits for the thread specified by
284 * @thread to terminate. If that thread has already terminated, then
285 * it will return immediately. The thread specified by @thread must
288 * Returns: 0 on success, otherwise it returns a non-zero error number.
290 void sthread_join(sthread_t *thread)
294 #ifdef USE_WIN32_THREADS
295 WaitForSingleObject(thread->thread, INFINITE);
296 CloseHandle(thread->thread);
298 pthread_join(thread->id, NULL);
306 * @thread : pointer to thread object
308 * Returns: true (1) if calling thread is the specified thread
310 bool sthread_isself(sthread_t *thread)
312 #ifdef USE_WIN32_THREADS
313 return thread ? GetCurrentThreadId() == thread->id : false;
315 return thread ? pthread_equal(pthread_self(), thread->id) : false;
323 * Create and initialize a new mutex. Must be manually
326 * Returns: pointer to a new mutex if successful, otherwise NULL.
328 slock_t *slock_new(void)
330 slock_t *lock = (slock_t*)calloc(1, sizeof(*lock));
333 #ifdef USE_WIN32_THREADS
334 InitializeCriticalSection(&lock->lock);
336 if (pthread_mutex_init(&lock->lock, NULL) != 0)
347 * @lock : pointer to mutex object
351 void slock_free(slock_t *lock)
356 #ifdef USE_WIN32_THREADS
357 DeleteCriticalSection(&lock->lock);
359 pthread_mutex_destroy(&lock->lock);
366 * @lock : pointer to mutex object
368 * Locks a mutex. If a mutex is already locked by
369 * another thread, the calling thread shall block until
370 * the mutex becomes available.
372 void slock_lock(slock_t *lock)
376 #ifdef USE_WIN32_THREADS
377 EnterCriticalSection(&lock->lock);
379 pthread_mutex_lock(&lock->lock);
385 * @lock : pointer to mutex object
387 * Attempts to lock a mutex. If a mutex is already locked by
388 * another thread, return false. If the lock is acquired, return true.
390 bool slock_try_lock(slock_t *lock)
392 #ifdef USE_WIN32_THREADS
393 return lock && TryEnterCriticalSection(&lock->lock);
395 return lock && (pthread_mutex_trylock(&lock->lock) == 0);
401 * @lock : pointer to mutex object
405 void slock_unlock(slock_t *lock)
409 #ifdef USE_WIN32_THREADS
410 LeaveCriticalSection(&lock->lock);
412 pthread_mutex_unlock(&lock->lock);
419 * Creates and initializes a condition variable. Must
422 * Returns: pointer to new condition variable on success,
425 scond_t *scond_new(void)
427 scond_t *cond = (scond_t*)calloc(1, sizeof(*cond));
432 #ifdef USE_WIN32_THREADS
433 /* This is very complex because recreating condition variable semantics
434 * with Win32 parts is not easy.
436 * The main problem is that a condition variable can't be used to
437 * "pre-wake" a thread (it will get wakened only after it's waited).
439 * Whereas a win32 event can pre-wake a thread (the event will be set
440 * in advance, so a 'waiter' won't even have to wait on it).
442 * Keep in mind a condition variable can apparently pre-wake a thread,
443 * insofar as spurious wakeups are always possible,
444 * but nobody will be expecting this and it does not need to be simulated.
446 * Moreover, we won't be doing this, because it counts as a spurious wakeup
447 * -- someone else with a genuine claim must get wakened, in any case.
449 * Therefore we choose to wake only one of the correct waiting threads.
450 * So at the very least, we need to do something clever. But there's
452 * We don't even have a straightforward way in win32 to satisfy
453 * pthread_cond_wait's atomicity requirement. The bulk of this
454 * algorithm is solving that.
456 * Note: We might could simplify this using vista+ condition variables,
457 * but we wanted an XP compatible solution. */
458 if (!(cond->event = CreateEvent(NULL, FALSE, FALSE, NULL)))
460 if (!(cond->hot_potato = CreateEvent(NULL, FALSE, FALSE, NULL)))
462 CloseHandle(cond->event);
466 InitializeCriticalSection(&cond->cs);
468 if (pthread_cond_init(&cond->cond, NULL) != 0)
481 * @cond : pointer to condition variable object
483 * Frees a condition variable.
485 void scond_free(scond_t *cond)
490 #ifdef USE_WIN32_THREADS
491 CloseHandle(cond->event);
492 CloseHandle(cond->hot_potato);
493 DeleteCriticalSection(&cond->cs);
495 pthread_cond_destroy(&cond->cond);
500 #ifdef USE_WIN32_THREADS
501 static bool _scond_wait_win32(scond_t *cond, slock_t *lock, DWORD dwMilliseconds)
503 struct queue_entry myentry;
504 struct queue_entry **ptr;
506 #if _WIN32_WINNT >= 0x0500 || defined(_XBOX)
507 static LARGE_INTEGER performanceCounterFrequency;
508 LARGE_INTEGER tsBegin;
509 static bool first_init = true;
511 static bool beginPeriod = false;
515 DWORD dwFinalTimeout = dwMilliseconds; /* Careful! in case we begin in the head,
516 we don't do the hot potato stuff,
517 so this timeout needs presetting. */
519 /* Reminder: `lock` is held before this is called. */
520 /* however, someone else may have called scond_signal without the lock. soo... */
521 EnterCriticalSection(&cond->cs);
523 /* since this library is meant for realtime game software
524 * I have no problem setting this to 1 and forgetting about it. */
525 #if _WIN32_WINNT >= 0x0500 || defined(_XBOX)
528 performanceCounterFrequency.QuadPart = 0;
532 if (performanceCounterFrequency.QuadPart == 0)
533 QueryPerformanceFrequency(&performanceCounterFrequency);
542 /* Now we can take a good timestamp for use in faking the timeout ourselves. */
543 /* But don't bother unless we need to (to save a little time) */
544 if (dwMilliseconds != INFINITE)
545 #if _WIN32_WINNT >= 0x0500 || defined(_XBOX)
546 QueryPerformanceCounter(&tsBegin);
548 tsBegin = timeGetTime();
551 /* add ourselves to a queue of waiting threads */
554 /* walk to the end of the linked list */
556 ptr = &((*ptr)->next);
563 /* now the conceptual lock release and condition block are supposed to be atomic.
564 * we can't do that in Windows, but we can simulate the effects by using
565 * the queue, by the following analysis:
566 * What happens if they aren't atomic?
568 * 1. a signaller can rush in and signal, expecting a waiter to get it;
569 * but the waiter wouldn't, because he isn't blocked yet.
570 * Solution: Win32 events make this easy. The event will sit there enabled
572 * 2. a signaller can rush in and signal, and then turn right around and wait.
573 * Solution: the signaller will get queued behind the waiter, who's
574 * enqueued before he releases the mutex. */
576 /* It's my turn if I'm the head of the queue.
577 * Check to see if it's my turn. */
578 while (cond->head != &myentry)
580 /* It isn't my turn: */
581 DWORD timeout = INFINITE;
583 /* As long as someone is even going to be able to wake up
584 * when they receive the potato, keep it going round. */
585 if (cond->wakens > 0)
586 SetEvent(cond->hot_potato);
588 /* Assess the remaining timeout time */
589 if (dwMilliseconds != INFINITE)
591 #if _WIN32_WINNT >= 0x0500 || defined(_XBOX)
595 QueryPerformanceCounter(&now);
596 elapsed = now.QuadPart - tsBegin.QuadPart;
598 elapsed /= performanceCounterFrequency.QuadPart;
600 DWORD now = timeGetTime();
601 DWORD elapsed = now - tsBegin;
604 /* Try one last time with a zero timeout (keeps the code simpler) */
605 if (elapsed > dwMilliseconds)
606 elapsed = dwMilliseconds;
608 timeout = dwMilliseconds - elapsed;
611 /* Let someone else go */
612 LeaveCriticalSection(&lock->lock);
613 LeaveCriticalSection(&cond->cs);
615 /* Wait a while to catch the hot potato..
616 * someone else should get a chance to go */
617 /* After all, it isn't my turn (and it must be someone else's) */
619 waitResult = WaitForSingleObject(cond->hot_potato, timeout);
621 /* I should come out of here with the main lock taken */
622 EnterCriticalSection(&lock->lock);
623 EnterCriticalSection(&cond->cs);
625 if (waitResult == WAIT_TIMEOUT)
627 /* Out of time! Now, let's think about this. I do have the potato now--
628 * maybe it's my turn, and I have the event?
629 * If that's the case, I could proceed right now without aborting
632 * However.. I DID wait a real long time. The caller was willing
635 * I choose to give him one last chance with a zero timeout
638 if (cond->head == &myentry)
645 /* It's not our turn and we're out of time. Give up.
646 * Remove ourself from the queue and bail. */
647 struct queue_entry *curr = cond->head;
649 while (curr->next != &myentry)
651 curr->next = myentry.next;
653 LeaveCriticalSection(&cond->cs);
660 /* It's my turn now -- and I hold the potato */
662 /* I still have the main lock, in any case */
663 /* I need to release it so that someone can set the event */
664 LeaveCriticalSection(&lock->lock);
665 LeaveCriticalSection(&cond->cs);
667 /* Wait for someone to actually signal this condition */
668 /* We're the only waiter waiting on the event right now -- everyone else
669 * is waiting on something different */
670 waitResult = WaitForSingleObject(cond->event, dwFinalTimeout);
672 /* Take the main lock so we can do work. Nobody else waits on this lock
673 * for very long, so even though it's GO TIME we won't have to wait long */
674 EnterCriticalSection(&lock->lock);
675 EnterCriticalSection(&cond->cs);
677 /* Remove ourselves from the queue */
678 cond->head = myentry.next;
681 if (waitResult == WAIT_TIMEOUT)
683 /* Oops! ran out of time in the final wait. Just bail. */
684 LeaveCriticalSection(&cond->cs);
688 /* If any other wakenings are pending, go ahead and set it up */
689 /* There may actually be no waiters. That's OK. The first waiter will come in,
690 * find it's his turn, and immediately get the signaled event */
692 if (cond->wakens > 0)
694 SetEvent(cond->event);
696 /* Progress the queue: Put the hot potato back into play. It'll be
697 * tossed around until next in line gets it */
698 SetEvent(cond->hot_potato);
701 LeaveCriticalSection(&cond->cs);
708 * @cond : pointer to condition variable object
709 * @lock : pointer to mutex object
711 * Block on a condition variable (i.e. wait on a condition).
713 void scond_wait(scond_t *cond, slock_t *lock)
715 #ifdef USE_WIN32_THREADS
716 _scond_wait_win32(cond, lock, INFINITE);
718 pthread_cond_wait(&cond->cond, &lock->lock);
724 * @cond : pointer to condition variable object
726 * Broadcast a condition. Unblocks all threads currently blocked
727 * on the specified condition variable @cond.
729 int scond_broadcast(scond_t *cond)
731 #ifdef USE_WIN32_THREADS
732 /* Remember, we currently have mutex */
733 if (cond->waiters != 0)
735 /* Awaken everything which is currently queued up */
736 if (cond->wakens == 0)
737 SetEvent(cond->event);
738 cond->wakens = cond->waiters;
740 /* Since there is now at least one pending waken, the potato must be in play */
741 SetEvent(cond->hot_potato);
745 return pthread_cond_broadcast(&cond->cond);
751 * @cond : pointer to condition variable object
753 * Signal a condition. Unblocks at least one of the threads currently blocked
754 * on the specified condition variable @cond.
756 void scond_signal(scond_t *cond)
758 #ifdef USE_WIN32_THREADS
760 /* Unfortunately, pthread_cond_signal does not require that the
761 * lock be held in advance */
762 /* To avoid stomping on the condvar from other threads, we need
763 * to control access to it with this */
764 EnterCriticalSection(&cond->cs);
766 /* remember: we currently have mutex */
767 if (cond->waiters == 0)
769 LeaveCriticalSection(&cond->cs);
773 /* wake up the next thing in the queue */
774 if (cond->wakens == 0)
775 SetEvent(cond->event);
779 /* The data structure is done being modified.. I think we can leave the CS now.
780 * This would prevent some other thread from receiving the hot potato and then
781 * immediately stalling for the critical section.
782 * But remember, we were trying to replicate a semantic where this entire
783 * scond_signal call was controlled (by the user) by a lock.
784 * So in case there's trouble with this, we can move it after SetEvent() */
785 LeaveCriticalSection(&cond->cs);
787 /* Since there is now at least one pending waken, the potato must be in play */
788 SetEvent(cond->hot_potato);
791 pthread_cond_signal(&cond->cond);
796 * scond_wait_timeout:
797 * @cond : pointer to condition variable object
798 * @lock : pointer to mutex object
799 * @timeout_us : timeout (in microseconds)
801 * Try to block on a condition variable (i.e. wait on a condition) until
802 * @timeout_us elapses.
804 * Returns: false (0) if timeout elapses before condition variable is
805 * signaled or broadcast, otherwise true (1).
807 bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us)
809 #ifdef USE_WIN32_THREADS
810 /* How to convert a microsecond (us) timeout to millisecond (ms)?
812 * Someone asking for a 0 timeout clearly wants immediate timeout.
813 * Someone asking for a 1 timeout clearly wants an actual timeout
814 * of the minimum length */
815 /* The implementation of a 0 timeout here with pthreads is sketchy.
816 * It isn't clear what happens if pthread_cond_timedwait is called with NOW.
817 * Moreover, it is possible that this thread gets pre-empted after the
818 * clock_gettime but before the pthread_cond_timedwait.
819 * In order to help smoke out problems caused by this strange usage,
820 * let's treat a 0 timeout as always timing out.
824 else if (timeout_us < 1000)
825 return _scond_wait_win32(cond, lock, 1);
826 /* Someone asking for 1000 or 1001 timeout shouldn't
827 * accidentally get 2ms. */
828 return _scond_wait_win32(cond, lock, timeout_us / 1000);
830 int64_t seconds, remainder;
833 /* OSX doesn't have clock_gettime. */
836 host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
837 clock_get_time(cclock, &mts);
838 mach_port_deallocate(mach_task_self(), cclock);
839 now.tv_sec = mts.tv_sec;
840 now.tv_nsec = mts.tv_nsec;
841 #elif !defined(__PSL1GHT__) && defined(__PS3__)
844 sys_time_get_current_time(&s, &n);
848 int tickms = ps2_clock();
849 now.tv_sec = tickms / 1000;
850 now.tv_nsec = tickms * 1000;
851 #elif !defined(DINGUX_BETA) && (defined(__mips__) || defined(VITA) || defined(_3DS))
853 gettimeofday(&tm, NULL);
854 now.tv_sec = tm.tv_sec;
855 now.tv_nsec = tm.tv_usec * 1000;
856 #elif defined(RETRO_WIN32_USE_PTHREADS)
859 /* Avoid gettimeofday due to it being reported to be broken */
860 const uint64_t tickms = gettime() / TB_TIMER_CLOCK;
861 now.tv_sec = tickms / 1000;
862 now.tv_nsec = tickms * 1000;
864 clock_gettime(CLOCK_REALTIME, &now);
867 seconds = timeout_us / INT64_C(1000000);
868 remainder = timeout_us % INT64_C(1000000);
870 now.tv_sec += seconds;
871 now.tv_nsec += remainder * INT64_C(1000);
873 if (now.tv_nsec > 1000000000)
875 now.tv_nsec -= 1000000000;
879 return (pthread_cond_timedwait(&cond->cond, &lock->lock, &now) == 0);
883 #ifdef HAVE_THREAD_STORAGE
884 bool sthread_tls_create(sthread_tls_t *tls)
886 #ifdef USE_WIN32_THREADS
887 return (*tls = TlsAlloc()) != TLS_OUT_OF_INDEXES;
889 return pthread_key_create((pthread_key_t*)tls, NULL) == 0;
893 bool sthread_tls_delete(sthread_tls_t *tls)
895 #ifdef USE_WIN32_THREADS
896 return TlsFree(*tls) != 0;
898 return pthread_key_delete(*tls) == 0;
902 void *sthread_tls_get(sthread_tls_t *tls)
904 #ifdef USE_WIN32_THREADS
905 return TlsGetValue(*tls);
907 return pthread_getspecific(*tls);
911 bool sthread_tls_set(sthread_tls_t *tls, const void *data)
913 #ifdef USE_WIN32_THREADS
914 return TlsSetValue(*tls, (void*)data) != 0;
916 return pthread_setspecific(*tls, data) == 0;
921 uintptr_t sthread_get_thread_id(sthread_t *thread)
924 return (uintptr_t)thread->id;
928 uintptr_t sthread_get_current_thread_id(void)
930 #ifdef USE_WIN32_THREADS
931 return (uintptr_t)GetCurrentThreadId();
933 return (uintptr_t)pthread_self();