/* * Copyright (C) 2009 Andrzej K. Haczewski * * DISCLAIMER: The implementation is Git-specific, it is subset of original * Pthreads API, without lots of other features that Git doesn't use. * Git also makes sure that the passed arguments are valid, so there's * no need for double-checking. */ #include "../../git-compat-util.h" #include "pthread.h" #include #include static unsigned __stdcall win32_start_routine(void *arg) { pthread_t *thread = arg; thread->tid = GetCurrentThreadId(); thread->arg = thread->start_routine(thread->arg); return 0; } int pthread_create(pthread_t *thread, const void *attr UNUSED, void *(*start_routine)(void *), void *arg) { thread->arg = arg; thread->start_routine = start_routine; thread->handle = (HANDLE)_beginthreadex(NULL, 0, win32_start_routine, thread, 0, NULL); if (!thread->handle) return errno; else return 0; } int win32_pthread_join(pthread_t *thread, void **value_ptr) { DWORD result = WaitForSingleObject(thread->handle, INFINITE); switch (result) { case WAIT_OBJECT_0: if (value_ptr) *value_ptr = thread->arg; CloseHandle(thread->handle); return 0; case WAIT_ABANDONED: CloseHandle(thread->handle); return EINVAL; default: /* the wait failed, so do not detach */ return err_win_to_posix(GetLastError()); } } pthread_t pthread_self(void) { pthread_t t = { NULL }; t.tid = GetCurrentThreadId(); return t; } int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { if (SleepConditionVariableCS(cond, mutex, INFINITE) == 0) return err_win_to_posix(GetLastError()); return 0; } int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { struct timeval now; long long now_ms, deadline_ms; DWORD timeout_ms; gettimeofday(&now, NULL); now_ms = (long long)now.tv_sec * 1000 + now.tv_usec / 1000; deadline_ms = (long long)abstime->tv_sec * 1000 + abstime->tv_nsec / 1000000; if (deadline_ms <= now_ms) return ETIMEDOUT; else timeout_ms = (DWORD)(deadline_ms - now_ms); if (SleepConditionVariableCS(cond, mutex, timeout_ms) == 0) { DWORD err = GetLastError(); if (err == ERROR_TIMEOUT) return ETIMEDOUT; return err_win_to_posix(err); } return 0; }