-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MSVC: Windows-native implementation for subset of Pthreads API
This patch implements native to Windows subset of pthreads API used by Git. It allows to remove Pthreads for Win32 dependency for MSVC, msysgit and Cygwin. [J6t: If the MinGW build was built as part of the msysgit build environment, then threading was already enabled because the pthreads-win32 package is available in msysgit. With this patch, we can now enable threaded code unconditionally.] Signed-off-by: Andrzej K. Haczewski <ahaczewski@gmail.com> Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
- Loading branch information
Andrzej K. Haczewski
authored and
Junio C Hamano
committed
Jan 17, 2010
1 parent
b6f714f
commit 44626dc
Showing
6 changed files
with
217 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/* | ||
* Copyright (C) 2009 Andrzej K. Haczewski <ahaczewski@gmail.com> | ||
* | ||
* DISCLAMER: 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 <errno.h> | ||
#include <limits.h> | ||
|
||
static unsigned __stdcall win32_start_routine(void *arg) | ||
{ | ||
pthread_t *thread = arg; | ||
thread->arg = thread->start_routine(thread->arg); | ||
return 0; | ||
} | ||
|
||
int pthread_create(pthread_t *thread, const void *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; | ||
return 0; | ||
case WAIT_ABANDONED: | ||
return EINVAL; | ||
default: | ||
return err_win_to_posix(GetLastError()); | ||
} | ||
} | ||
|
||
int pthread_cond_init(pthread_cond_t *cond, const void *unused) | ||
{ | ||
cond->waiters = 0; | ||
|
||
cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL); | ||
if (!cond->sema) | ||
die("CreateSemaphore() failed"); | ||
return 0; | ||
} | ||
|
||
int pthread_cond_destroy(pthread_cond_t *cond) | ||
{ | ||
CloseHandle(cond->sema); | ||
cond->sema = NULL; | ||
|
||
return 0; | ||
} | ||
|
||
int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex) | ||
{ | ||
InterlockedIncrement(&cond->waiters); | ||
|
||
/* | ||
* Unlock external mutex and wait for signal. | ||
* NOTE: we've held mutex locked long enough to increment | ||
* waiters count above, so there's no problem with | ||
* leaving mutex unlocked before we wait on semaphore. | ||
*/ | ||
LeaveCriticalSection(mutex); | ||
|
||
/* let's wait - ignore return value */ | ||
WaitForSingleObject(cond->sema, INFINITE); | ||
|
||
/* we're done waiting, so make sure we decrease waiters count */ | ||
InterlockedDecrement(&cond->waiters); | ||
|
||
/* lock external mutex again */ | ||
EnterCriticalSection(mutex); | ||
|
||
return 0; | ||
} | ||
|
||
int pthread_cond_signal(pthread_cond_t *cond) | ||
{ | ||
/* | ||
* Access to waiters count is atomic; see "Interlocked Variable Access" | ||
* http://msdn.microsoft.com/en-us/library/ms684122(VS.85).aspx | ||
*/ | ||
int have_waiters = cond->waiters > 0; | ||
|
||
/* | ||
* Signal only when there are waiters | ||
*/ | ||
if (have_waiters) | ||
return ReleaseSemaphore(cond->sema, 1, NULL) ? | ||
0 : err_win_to_posix(GetLastError()); | ||
else | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* | ||
* Header used to adapt pthread-based POSIX code to Windows API threads. | ||
* | ||
* Copyright (C) 2009 Andrzej K. Haczewski <ahaczewski@gmail.com> | ||
*/ | ||
|
||
#ifndef PTHREAD_H | ||
#define PTHREAD_H | ||
|
||
#ifndef WIN32_LEAN_AND_MEAN | ||
#define WIN32_LEAN_AND_MEAN | ||
#endif | ||
|
||
#include <windows.h> | ||
|
||
/* | ||
* Defines that adapt Windows API threads to pthreads API | ||
*/ | ||
#define pthread_mutex_t CRITICAL_SECTION | ||
|
||
#define pthread_mutex_init(a,b) InitializeCriticalSection((a)) | ||
#define pthread_mutex_destroy(a) DeleteCriticalSection((a)) | ||
#define pthread_mutex_lock EnterCriticalSection | ||
#define pthread_mutex_unlock LeaveCriticalSection | ||
|
||
/* | ||
* Implement simple condition variable for Windows threads, based on ACE | ||
* implementation. | ||
* | ||
* See original implementation: http://bit.ly/1vkDjo | ||
* ACE homepage: http://www.cse.wustl.edu/~schmidt/ACE.html | ||
* See also: http://www.cse.wustl.edu/~schmidt/win32-cv-1.html | ||
*/ | ||
typedef struct { | ||
volatile LONG waiters; | ||
HANDLE sema; | ||
} pthread_cond_t; | ||
|
||
extern int pthread_cond_init(pthread_cond_t *cond, const void *unused); | ||
|
||
extern int pthread_cond_destroy(pthread_cond_t *cond); | ||
|
||
extern int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex); | ||
|
||
extern int pthread_cond_signal(pthread_cond_t *cond); | ||
|
||
/* | ||
* Simple thread creation implementation using pthread API | ||
*/ | ||
typedef struct { | ||
HANDLE handle; | ||
void *(*start_routine)(void*); | ||
void *arg; | ||
} pthread_t; | ||
|
||
extern int pthread_create(pthread_t *thread, const void *unused, | ||
void *(*start_routine)(void*), void *arg); | ||
|
||
/* | ||
* To avoid the need of copying a struct, we use small macro wrapper to pass | ||
* pointer to win32_pthread_join instead. | ||
*/ | ||
#define pthread_join(a, b) win32_pthread_join(&(a), (b)) | ||
|
||
extern int win32_pthread_join(pthread_t *thread, void **value_ptr); | ||
|
||
#endif /* PTHREAD_H */ |