git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

Windows/pthread.h

      1 /* Very minimal pthread implementation for Windows */
      2 #include <Windows.h>
      3 #include <assert.h>
      4 
      5 typedef HANDLE pthread_t;
      6 typedef struct pthread_attr_s pthread_attr_t;
      7 
      8 static inline int pthread_create(pthread_t *pthread,
      9                                  const pthread_attr_t *attrs,
     10                                  LPTHREAD_START_ROUTINE function,
     11                                  void *context)
     12 {
     13     assert(!attrs);
     14     *pthread = CreateThread(NULL, 0, function,
     15                             context, 0, NULL);
     16     return *pthread? 0 : GetLastError();
     17 }
     18 
     19 
     20 typedef struct {
     21     unsigned status;
     22     CRITICAL_SECTION cs;
     23 } pthread_mutex_t;
     24 #define PTHREAD_MUTEX_INITIALIZER {0,}
     25 
     26 static inline CRITICAL_SECTION *pthread_mutex_to_cs(pthread_mutex_t *mutex)
     27 {
     28 retry:
     29     if (mutex->status == 2) return &mutex->cs;
     30     
     31     unsigned expected = 0;
     32     unsigned desired = 1;
     33     if (__atomic_compare_exchange(&mutex->status, &expected, &desired, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) {
     34         InitializeCriticalSection(&mutex->cs);
     35         mutex->status = 2;
     36         return &mutex->cs;
     37     }
     38     goto retry;
     39 }
     40 
     41 static inline int pthread_mutex_lock(pthread_mutex_t *mutex)
     42 {
     43     EnterCriticalSection(pthread_mutex_to_cs(mutex));
     44     return 0;
     45 }
     46 
     47 static inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
     48 {
     49     LeaveCriticalSection(pthread_mutex_to_cs(mutex));
     50     return 0;
     51 }
     52 
     53 typedef struct {
     54     unsigned status;
     55     CONDITION_VARIABLE cond;
     56 } pthread_cond_t;
     57 #define PTHREAD_COND_INITIALIZER {0,}
     58 
     59 static inline CONDITION_VARIABLE *pthread_cond_to_win(pthread_cond_t *cond)
     60 {
     61 retry:
     62     if (cond->status == 2) return &cond->cond;
     63     
     64     unsigned expected = 0;
     65     unsigned desired = 1;
     66     if (__atomic_compare_exchange(&cond->status, &expected, &desired, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) {
     67         InitializeConditionVariable(&cond->cond);
     68         cond->status = 2;
     69         return &cond->cond;
     70     }
     71     goto retry;
     72 }
     73 
     74 
     75 static inline int pthread_cond_signal(pthread_cond_t *cond)
     76 {
     77     WakeConditionVariable(pthread_cond_to_win(cond));
     78     return 0;
     79 }
     80 
     81 static inline int pthread_cond_wait(pthread_cond_t *cond,
     82                                     pthread_mutex_t *mutex)
     83 {
     84     // Mutex is locked therefore already initialized
     85     return SleepConditionVariableCS(pthread_cond_to_win(cond), &mutex->cs, INFINITE);
     86 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.