2 * Copyright (C) the libgit2 contributors. All rights reserved.
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
11 #define CLEAN_THREAD_EXIT 0x6F012842
13 typedef void (WINAPI
*win32_srwlock_fn
)(GIT_SRWLOCK
*);
15 static win32_srwlock_fn win32_srwlock_initialize
;
16 static win32_srwlock_fn win32_srwlock_acquire_shared
;
17 static win32_srwlock_fn win32_srwlock_release_shared
;
18 static win32_srwlock_fn win32_srwlock_acquire_exclusive
;
19 static win32_srwlock_fn win32_srwlock_release_exclusive
;
21 /* The thread procedure stub used to invoke the caller's procedure
22 * and capture the return value for later collection. Windows will
23 * only hold a DWORD, but we need to be able to store an entire
24 * void pointer. This requires the indirection. */
25 static DWORD WINAPI
git_win32__threadproc(LPVOID lpParameter
)
27 git_thread
*thread
= lpParameter
;
29 thread
->result
= thread
->proc(thread
->param
);
33 return CLEAN_THREAD_EXIT
;
36 int git_threads_init(void)
38 HMODULE hModule
= GetModuleHandleW(L
"kernel32");
41 win32_srwlock_initialize
= (win32_srwlock_fn
)
42 GetProcAddress(hModule
, "InitializeSRWLock");
43 win32_srwlock_acquire_shared
= (win32_srwlock_fn
)
44 GetProcAddress(hModule
, "AcquireSRWLockShared");
45 win32_srwlock_release_shared
= (win32_srwlock_fn
)
46 GetProcAddress(hModule
, "ReleaseSRWLockShared");
47 win32_srwlock_acquire_exclusive
= (win32_srwlock_fn
)
48 GetProcAddress(hModule
, "AcquireSRWLockExclusive");
49 win32_srwlock_release_exclusive
= (win32_srwlock_fn
)
50 GetProcAddress(hModule
, "ReleaseSRWLockExclusive");
56 int git_thread_create(
57 git_thread
*GIT_RESTRICT thread
,
58 void *(*start_routine
)(void*),
59 void *GIT_RESTRICT arg
)
61 thread
->result
= NULL
;
63 thread
->proc
= start_routine
;
64 thread
->thread
= CreateThread(
65 NULL
, 0, git_win32__threadproc
, thread
, 0, NULL
);
67 return thread
->thread
? 0 : -1;
76 if (WaitForSingleObject(thread
->thread
, INFINITE
) != WAIT_OBJECT_0
)
79 if (!GetExitCodeThread(thread
->thread
, &exit
)) {
80 CloseHandle(thread
->thread
);
84 /* Check for the thread having exited uncleanly. If exit was unclean,
85 * then we don't have a return value to give back to the caller. */
86 if (exit
!= CLEAN_THREAD_EXIT
) {
88 thread
->result
= NULL
;
92 *value_ptr
= thread
->result
;
94 CloseHandle(thread
->thread
);
98 int git_mutex_init(git_mutex
*GIT_RESTRICT mutex
)
100 InitializeCriticalSection(mutex
);
104 int git_mutex_free(git_mutex
*mutex
)
106 DeleteCriticalSection(mutex
);
110 int git_mutex_lock(git_mutex
*mutex
)
112 EnterCriticalSection(mutex
);
116 int git_mutex_unlock(git_mutex
*mutex
)
118 LeaveCriticalSection(mutex
);
122 int git_cond_init(git_cond
*cond
)
124 /* This is an auto-reset event. */
125 *cond
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
128 /* If we can't create the event, claim that the reason was out-of-memory.
129 * The actual reason can be fetched with GetLastError(). */
130 return *cond
? 0 : ENOMEM
;
133 int git_cond_free(git_cond
*cond
)
140 closed
= CloseHandle(*cond
);
148 int git_cond_wait(git_cond
*cond
, git_mutex
*mutex
)
156 /* The caller must be holding the mutex. */
157 error
= git_mutex_unlock(mutex
);
162 wait_result
= WaitForSingleObject(*cond
, INFINITE
);
163 assert(WAIT_OBJECT_0
== wait_result
);
164 GIT_UNUSED(wait_result
);
166 return git_mutex_lock(mutex
);
169 int git_cond_signal(git_cond
*cond
)
176 signaled
= SetEvent(*cond
);
178 GIT_UNUSED(signaled
);
183 int git_rwlock_init(git_rwlock
*GIT_RESTRICT lock
)
185 if (win32_srwlock_initialize
)
186 win32_srwlock_initialize(&lock
->native
.srwl
);
188 InitializeCriticalSection(&lock
->native
.csec
);
193 int git_rwlock_rdlock(git_rwlock
*lock
)
195 if (win32_srwlock_acquire_shared
)
196 win32_srwlock_acquire_shared(&lock
->native
.srwl
);
198 EnterCriticalSection(&lock
->native
.csec
);
203 int git_rwlock_rdunlock(git_rwlock
*lock
)
205 if (win32_srwlock_release_shared
)
206 win32_srwlock_release_shared(&lock
->native
.srwl
);
208 LeaveCriticalSection(&lock
->native
.csec
);
213 int git_rwlock_wrlock(git_rwlock
*lock
)
215 if (win32_srwlock_acquire_exclusive
)
216 win32_srwlock_acquire_exclusive(&lock
->native
.srwl
);
218 EnterCriticalSection(&lock
->native
.csec
);
223 int git_rwlock_wrunlock(git_rwlock
*lock
)
225 if (win32_srwlock_release_exclusive
)
226 win32_srwlock_release_exclusive(&lock
->native
.srwl
);
228 LeaveCriticalSection(&lock
->native
.csec
);
233 int git_rwlock_free(git_rwlock
*lock
)
235 if (!win32_srwlock_initialize
)
236 DeleteCriticalSection(&lock
->native
.csec
);
237 git__memzero(lock
, sizeof(*lock
));