windows_threads.cpp
#include "HalideRuntime.h"
#include "runtime_internal.h"
// TODO: consider getting rid of this
#define MAX_THREADS 256
extern "C" {
#ifdef BITS_64
#define WIN32API
#else
#define WIN32API __stdcall
#endif
// These sizes are large enough for 32-bit and 64-bit
typedef uint64_t ConditionVariable;
typedef uint64_t InitOnce;
typedef void * Thread;
typedef struct {
uint64_t buf[5];
} CriticalSection;
extern WIN32API Thread CreateThread(void *, size_t, void *(*fn)(void *), void *, int32_t, int32_t *);
extern WIN32API void InitializeConditionVariable(ConditionVariable *);
extern WIN32API void WakeConditionVariable(ConditionVariable *);
extern WIN32API void SleepConditionVariableCS(ConditionVariable *, CriticalSection *, int);
extern WIN32API void InitializeCriticalSection(CriticalSection *);
extern WIN32API void DeleteCriticalSection(CriticalSection *);
extern WIN32API void EnterCriticalSection(CriticalSection *);
extern WIN32API void LeaveCriticalSection(CriticalSection *);
extern WIN32API int32_t WaitForSingleObject(Thread, int32_t timeout);
} // extern "C"
namespace Halide { namespace Runtime { namespace Internal {
struct spawned_thread {
void(*f)(void *);
void *closure;
Thread handle;
};
WEAK void *spawn_thread_helper(void *arg) {
spawned_thread *t = (spawned_thread *)arg;
t->f(t->closure);
return NULL;
}
}}} // namespace Halide::Runtime::Internal
extern "C" {
WEAK int halide_host_cpu_count() {
// Apparently a standard windows environment variable
char *num_cores = getenv("NUMBER_OF_PROCESSORS");
if (num_cores) {
return atoi(num_cores);
} else {
return 8;
}
}
WEAK halide_thread *halide_spawn_thread(void(*f)(void *), void *closure) {
spawned_thread *t = (spawned_thread *)malloc(sizeof(spawned_thread));
t->f = f;
t->closure = closure;
t->handle = CreateThread(NULL, 0, spawn_thread_helper, t, 0, NULL);
return (halide_thread *)t;
}
WEAK void halide_join_thread(halide_thread *thread_arg) {
spawned_thread *thread = (spawned_thread *)thread_arg;
WaitForSingleObject(thread->handle, -1);
free(thread);
}
} // extern "C"
namespace Halide { namespace Runtime { namespace Internal {
namespace Synchronization {
struct thread_parker {
CriticalSection critical_section;
ConditionVariable condvar;
bool should_park;
#if __cplusplus >= 201103L
thread_parker(const thread_parker &) = delete;
#endif
__attribute__((always_inline)) thread_parker() : should_park(false) {
InitializeCriticalSection(&critical_section);
InitializeConditionVariable(&condvar);
should_park = false;
}
__attribute__((always_inline)) ~thread_parker() {
// Windows ConditionVariable objects do not need to be deleted. There is no API to do so.
DeleteCriticalSection(&critical_section);
}
__attribute__((always_inline)) void prepare_park() {
should_park = true;
}
__attribute__((always_inline)) void park() {
EnterCriticalSection(&critical_section);
while (should_park) {
SleepConditionVariableCS(&condvar, &critical_section, -1);
}
LeaveCriticalSection(&critical_section);
}
__attribute__((always_inline)) void unpark_start() {
EnterCriticalSection(&critical_section);
}
__attribute__((always_inline)) void unpark() {
should_park = false;
WakeConditionVariable(&condvar);
}
__attribute__((always_inline)) void unpark_finish() {
LeaveCriticalSection(&critical_section);
}
};
}}}} // namespace Halide::Runtime::Internal::Synchronization
#include "synchronization_common.h"
#include "thread_pool_common.h"