compat / win32 / pthread.hon commit Merge branch 'mh/blame-worktree' (4762bf3)
   1/*
   2 * Header used to adapt pthread-based POSIX code to Windows API threads.
   3 *
   4 * Copyright (C) 2009 Andrzej K. Haczewski <ahaczewski@gmail.com>
   5 */
   6
   7#ifndef PTHREAD_H
   8#define PTHREAD_H
   9
  10#ifndef WIN32_LEAN_AND_MEAN
  11#define WIN32_LEAN_AND_MEAN
  12#endif
  13
  14#include <windows.h>
  15
  16/*
  17 * Defines that adapt Windows API threads to pthreads API
  18 */
  19#define pthread_mutex_t CRITICAL_SECTION
  20
  21static inline int return_0(int i) {
  22        return 0;
  23}
  24#define pthread_mutex_init(a,b) return_0((InitializeCriticalSection((a)), 0))
  25#define pthread_mutex_destroy(a) DeleteCriticalSection((a))
  26#define pthread_mutex_lock EnterCriticalSection
  27#define pthread_mutex_unlock LeaveCriticalSection
  28
  29typedef int pthread_mutexattr_t;
  30#define pthread_mutexattr_init(a) (*(a) = 0)
  31#define pthread_mutexattr_destroy(a) do {} while (0)
  32#define pthread_mutexattr_settype(a, t) 0
  33#define PTHREAD_MUTEX_RECURSIVE 0
  34
  35/*
  36 * Implement simple condition variable for Windows threads, based on ACE
  37 * implementation.
  38 *
  39 * See original implementation: http://bit.ly/1vkDjo
  40 * ACE homepage: http://www.cse.wustl.edu/~schmidt/ACE.html
  41 * See also: http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
  42 */
  43typedef struct {
  44        LONG waiters;
  45        int was_broadcast;
  46        CRITICAL_SECTION waiters_lock;
  47        HANDLE sema;
  48        HANDLE continue_broadcast;
  49} pthread_cond_t;
  50
  51extern int pthread_cond_init(pthread_cond_t *cond, const void *unused);
  52extern int pthread_cond_destroy(pthread_cond_t *cond);
  53extern int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex);
  54extern int pthread_cond_signal(pthread_cond_t *cond);
  55extern int pthread_cond_broadcast(pthread_cond_t *cond);
  56
  57/*
  58 * Simple thread creation implementation using pthread API
  59 */
  60typedef struct {
  61        HANDLE handle;
  62        void *(*start_routine)(void*);
  63        void *arg;
  64        DWORD tid;
  65} pthread_t;
  66
  67extern int pthread_create(pthread_t *thread, const void *unused,
  68                          void *(*start_routine)(void*), void *arg);
  69
  70/*
  71 * To avoid the need of copying a struct, we use small macro wrapper to pass
  72 * pointer to win32_pthread_join instead.
  73 */
  74#define pthread_join(a, b) win32_pthread_join(&(a), (b))
  75
  76extern int win32_pthread_join(pthread_t *thread, void **value_ptr);
  77
  78#define pthread_equal(t1, t2) ((t1).tid == (t2).tid)
  79extern pthread_t pthread_self(void);
  80
  81static inline void NORETURN pthread_exit(void *ret)
  82{
  83        ExitThread((DWORD)(intptr_t)ret);
  84}
  85
  86typedef DWORD pthread_key_t;
  87static inline int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *value))
  88{
  89        return (*keyp = TlsAlloc()) == TLS_OUT_OF_INDEXES ? EAGAIN : 0;
  90}
  91
  92static inline int pthread_key_delete(pthread_key_t key)
  93{
  94        return TlsFree(key) ? 0 : EINVAL;
  95}
  96
  97static inline int pthread_setspecific(pthread_key_t key, const void *value)
  98{
  99        return TlsSetValue(key, (void *)value) ? 0 : EINVAL;
 100}
 101
 102static inline void *pthread_getspecific(pthread_key_t key)
 103{
 104        return TlsGetValue(key);
 105}
 106
 107#ifndef __MINGW64_VERSION_MAJOR
 108static inline int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
 109{
 110        return 0;
 111}
 112#endif
 113
 114#endif /* PTHREAD_H */