#include "orconfig.h"
#ifdef _WIN32
#ifndef WINVER
#error "orconfig.h didn't define WINVER"
#endif
#ifndef _WIN32_WINNT
#error "orconfig.h didn't define _WIN32_WINNT"
#endif
#if WINVER < 0x0600
#error "winver too low"
#endif
#if _WIN32_WINNT < 0x0600
#error "winver too low"
#endif
#include <windows.h>
#include <process.h>
#include <time.h>
#include "lib/thread/threads.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/log/win32err.h"
int
spawn_func(void (*func)(void *), void *data)
{
int rv;
rv = (int)_beginthread(func, 0, data);
if (rv == (int)-1)
return -1;
return 0;
}
void
spawn_exit(void)
{
_endthread();
tor_assert(0);
_exit(0); }
unsigned long
tor_get_thread_id(void)
{
return (unsigned long)GetCurrentThreadId();
}
int
tor_cond_init(tor_cond_t *cond)
{
InitializeConditionVariable(&cond->cond);
return 0;
}
void
tor_cond_uninit(tor_cond_t *cond)
{
(void) cond;
}
void
tor_cond_signal_one(tor_cond_t *cond)
{
WakeConditionVariable(&cond->cond);
}
void
tor_cond_signal_all(tor_cond_t *cond)
{
WakeAllConditionVariable(&cond->cond);
}
int
tor_threadlocal_init(tor_threadlocal_t *threadlocal)
{
threadlocal->index = TlsAlloc();
return (threadlocal->index == TLS_OUT_OF_INDEXES) ? -1 : 0;
}
void
tor_threadlocal_destroy(tor_threadlocal_t *threadlocal)
{
TlsFree(threadlocal->index);
memset(threadlocal, 0, sizeof(tor_threadlocal_t));
}
void *
tor_threadlocal_get(tor_threadlocal_t *threadlocal)
{
void *value = TlsGetValue(threadlocal->index);
if (value == NULL) {
DWORD err = GetLastError();
if (err != ERROR_SUCCESS) {
char *msg = format_win32_error(err);
log_err(LD_GENERAL, "Error retrieving thread-local value: %s", msg);
tor_free(msg);
tor_assert(err == ERROR_SUCCESS);
}
}
return value;
}
void
tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value)
{
BOOL ok = TlsSetValue(threadlocal->index, value);
if (!ok) {
DWORD err = GetLastError();
char *msg = format_win32_error(err);
log_err(LD_GENERAL, "Error adjusting thread-local value: %s", msg);
tor_free(msg);
tor_assert(ok);
}
}
int
tor_cond_wait(tor_cond_t *cond, tor_mutex_t *lock_, const struct timeval *tv)
{
tor_assert(lock_->type == NON_RECURSIVE);
SRWLOCK *lock = &lock_->mutex;
DWORD ms = INFINITE;
if (tv) {
ms = tv->tv_sec*1000 + (tv->tv_usec+999)/1000;
}
BOOL ok = SleepConditionVariableSRW(&cond->cond, lock, ms, 0);
if (!ok) {
DWORD err = GetLastError();
if (err == ERROR_TIMEOUT) {
return 1;
}
char *msg = format_win32_error(err);
log_err(LD_GENERAL, "Error waiting for condition variable: %s", msg);
tor_free(msg);
return -1;
}
return 0;
}
void
tor_threads_init(void)
{
set_main_thread();
}
#endif