Commit bb0edf87 by Edward Thomson Committed by GitHub

Merge pull request #3830 from pks-t/pks/thread-namespacing

Thread namespacing
parents c80efb5f aab266c9
......@@ -45,7 +45,7 @@
# include "win32/error.h"
# include "win32/version.h"
# ifdef GIT_THREADS
# include "win32/pthread.h"
# include "win32/thread.h"
# endif
# if defined(GIT_MSVC_CRTDBG)
# include "win32/w32_stack.h"
......
......@@ -134,7 +134,7 @@ static int synchronized_threads_init(void)
_tls_index = TlsAlloc();
win32_pthread_initialize();
git_threads_init();
if (git_mutex_init(&git__mwindow_mutex))
return -1;
......
......@@ -1186,7 +1186,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
git_mutex_init(&p[i].mutex);
git_cond_init(&p[i].cond);
ret = git_thread_create(&p[i].thread, NULL,
ret = git_thread_create(&p[i].thread,
threaded_find_deltas, &p[i]);
if (ret) {
giterr_set(GITERR_THREAD, "unable to create thread");
......
......@@ -40,58 +40,12 @@ typedef git_atomic git_atomic_ssize;
#ifdef GIT_THREADS
#if !defined(GIT_WIN32)
typedef struct {
pthread_t thread;
} git_thread;
#define git_thread_create(git_thread_ptr, attr, start_routine, arg) \
pthread_create(&(git_thread_ptr)->thread, attr, start_routine, arg)
#define git_thread_join(git_thread_ptr, status) \
pthread_join((git_thread_ptr)->thread, status)
#endif
/* Pthreads Mutex */
#define git_mutex pthread_mutex_t
#define git_mutex_init(a) pthread_mutex_init(a, NULL)
#define git_mutex_lock(a) pthread_mutex_lock(a)
#define git_mutex_unlock(a) pthread_mutex_unlock(a)
#define git_mutex_free(a) pthread_mutex_destroy(a)
/* Pthreads condition vars */
#define git_cond pthread_cond_t
#define git_cond_init(c) pthread_cond_init(c, NULL)
#define git_cond_free(c) pthread_cond_destroy(c)
#define git_cond_wait(c, l) pthread_cond_wait(c, l)
#define git_cond_signal(c) pthread_cond_signal(c)
#define git_cond_broadcast(c) pthread_cond_broadcast(c)
/* Pthread (-ish) rwlock
*
* This differs from normal pthreads rwlocks in two ways:
* 1. Separate APIs for releasing read locks and write locks (as
* opposed to the pure POSIX API which only has one unlock fn)
* 2. You should not use recursive read locks (i.e. grabbing a read
* lock in a thread that already holds a read lock) because the
* Windows implementation doesn't support it
*/
#define git_rwlock pthread_rwlock_t
#define git_rwlock_init(a) pthread_rwlock_init(a, NULL)
#define git_rwlock_rdlock(a) pthread_rwlock_rdlock(a)
#define git_rwlock_rdunlock(a) pthread_rwlock_rdunlock(a)
#define git_rwlock_wrlock(a) pthread_rwlock_wrlock(a)
#define git_rwlock_wrunlock(a) pthread_rwlock_wrunlock(a)
#define git_rwlock_free(a) pthread_rwlock_destroy(a)
#define GIT_RWLOCK_STATIC_INIT PTHREAD_RWLOCK_INITIALIZER
#ifndef GIT_WIN32
#define pthread_rwlock_rdunlock pthread_rwlock_unlock
#define pthread_rwlock_wrunlock pthread_rwlock_unlock
#ifdef GIT_WIN32
# include "win32/thread.h"
#else
# include "unix/pthread.h"
#endif
GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
{
#if defined(GIT_WIN32)
......@@ -178,7 +132,7 @@ GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
#else
#define git_thread unsigned int
#define git_thread_create(thread, attr, start_routine, arg) 0
#define git_thread_create(thread, start_routine, arg) 0
#define git_thread_join(id, status) (void)0
/* Pthreads Mutex */
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_unix_pthread_h__
#define INCLUDE_unix_pthread_h__
typedef struct {
pthread_t thread;
} git_thread;
#define git_threads_init() (void)0
#define git_thread_create(git_thread_ptr, start_routine, arg) \
pthread_create(&(git_thread_ptr)->thread, NULL, start_routine, arg)
#define git_thread_join(git_thread_ptr, status) \
pthread_join((git_thread_ptr)->thread, status)
/* Git Mutex */
#define git_mutex pthread_mutex_t
#define git_mutex_init(a) pthread_mutex_init(a, NULL)
#define git_mutex_lock(a) pthread_mutex_lock(a)
#define git_mutex_unlock(a) pthread_mutex_unlock(a)
#define git_mutex_free(a) pthread_mutex_destroy(a)
/* Git condition vars */
#define git_cond pthread_cond_t
#define git_cond_init(c) pthread_cond_init(c, NULL)
#define git_cond_free(c) pthread_cond_destroy(c)
#define git_cond_wait(c, l) pthread_cond_wait(c, l)
#define git_cond_signal(c) pthread_cond_signal(c)
#define git_cond_broadcast(c) pthread_cond_broadcast(c)
/* Pthread (-ish) rwlock
*
* This differs from normal pthreads rwlocks in two ways:
* 1. Separate APIs for releasing read locks and write locks (as
* opposed to the pure POSIX API which only has one unlock fn)
* 2. You should not use recursive read locks (i.e. grabbing a read
* lock in a thread that already holds a read lock) because the
* Windows implementation doesn't support it
*/
#define git_rwlock pthread_rwlock_t
#define git_rwlock_init(a) pthread_rwlock_init(a, NULL)
#define git_rwlock_rdlock(a) pthread_rwlock_rdlock(a)
#define git_rwlock_rdunlock(a) pthread_rwlock_unlock(a)
#define git_rwlock_wrlock(a) pthread_rwlock_wrlock(a)
#define git_rwlock_wrunlock(a) pthread_rwlock_unlock(a)
#define git_rwlock_free(a) pthread_rwlock_destroy(a)
#define GIT_RWLOCK_STATIC_INIT PTHREAD_RWLOCK_INITIALIZER
#endif /* INCLUDE_unix_pthread_h__ */
......@@ -16,7 +16,7 @@
#include <io.h>
#include <direct.h>
#ifdef GIT_THREADS
#include "win32/pthread.h"
#include "win32/thread.h"
#endif
#include "git2.h"
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef GIT_PTHREAD_H
#define GIT_PTHREAD_H
#include "../common.h"
#if defined (_MSC_VER)
# define GIT_RESTRICT __restrict
#else
# define GIT_RESTRICT __restrict__
#endif
typedef struct {
HANDLE thread;
void *(*proc)(void *);
void *param;
void *result;
} git_win32_thread;
typedef int pthread_mutexattr_t;
typedef int pthread_condattr_t;
typedef int pthread_attr_t;
typedef int pthread_rwlockattr_t;
typedef CRITICAL_SECTION pthread_mutex_t;
typedef HANDLE pthread_cond_t;
typedef struct { void *Ptr; } GIT_SRWLOCK;
typedef struct {
union {
GIT_SRWLOCK srwl;
CRITICAL_SECTION csec;
} native;
} pthread_rwlock_t;
#define PTHREAD_MUTEX_INITIALIZER {(void*)-1}
int git_win32__thread_create(
git_win32_thread *GIT_RESTRICT,
const pthread_attr_t *GIT_RESTRICT,
void *(*) (void *),
void *GIT_RESTRICT);
int git_win32__thread_join(
git_win32_thread *,
void **);
#ifdef GIT_THREADS
typedef git_win32_thread git_thread;
#define git_thread_create(git_thread_ptr, attr, start_routine, arg) \
git_win32__thread_create(git_thread_ptr, attr, start_routine, arg)
#define git_thread_join(git_thread_ptr, status) \
git_win32__thread_join(git_thread_ptr, status)
#endif
int pthread_mutex_init(
pthread_mutex_t *GIT_RESTRICT mutex,
const pthread_mutexattr_t *GIT_RESTRICT mutexattr);
int pthread_mutex_destroy(pthread_mutex_t *);
int pthread_mutex_lock(pthread_mutex_t *);
int pthread_mutex_unlock(pthread_mutex_t *);
int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
int pthread_cond_destroy(pthread_cond_t *);
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
int pthread_cond_signal(pthread_cond_t *);
/* pthread_cond_broadcast is not supported on Win32 yet. */
int pthread_num_processors_np(void);
int pthread_rwlock_init(
pthread_rwlock_t *GIT_RESTRICT lock,
const pthread_rwlockattr_t *GIT_RESTRICT attr);
int pthread_rwlock_rdlock(pthread_rwlock_t *);
int pthread_rwlock_rdunlock(pthread_rwlock_t *);
int pthread_rwlock_wrlock(pthread_rwlock_t *);
int pthread_rwlock_wrunlock(pthread_rwlock_t *);
int pthread_rwlock_destroy(pthread_rwlock_t *);
extern int win32_pthread_initialize(void);
#endif
......@@ -5,18 +5,26 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "pthread.h"
#include "thread.h"
#include "../global.h"
#define CLEAN_THREAD_EXIT 0x6F012842
typedef void (WINAPI *win32_srwlock_fn)(GIT_SRWLOCK *);
static win32_srwlock_fn win32_srwlock_initialize;
static win32_srwlock_fn win32_srwlock_acquire_shared;
static win32_srwlock_fn win32_srwlock_release_shared;
static win32_srwlock_fn win32_srwlock_acquire_exclusive;
static win32_srwlock_fn win32_srwlock_release_exclusive;
/* The thread procedure stub used to invoke the caller's procedure
* and capture the return value for later collection. Windows will
* only hold a DWORD, but we need to be able to store an entire
* void pointer. This requires the indirection. */
static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
{
git_win32_thread *thread = lpParameter;
git_thread *thread = lpParameter;
thread->result = thread->proc(thread->param);
......@@ -25,14 +33,31 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
return CLEAN_THREAD_EXIT;
}
int git_win32__thread_create(
git_win32_thread *GIT_RESTRICT thread,
const pthread_attr_t *GIT_RESTRICT attr,
int git_threads_init(void)
{
HMODULE hModule = GetModuleHandleW(L"kernel32");
if (hModule) {
win32_srwlock_initialize = (win32_srwlock_fn)
GetProcAddress(hModule, "InitializeSRWLock");
win32_srwlock_acquire_shared = (win32_srwlock_fn)
GetProcAddress(hModule, "AcquireSRWLockShared");
win32_srwlock_release_shared = (win32_srwlock_fn)
GetProcAddress(hModule, "ReleaseSRWLockShared");
win32_srwlock_acquire_exclusive = (win32_srwlock_fn)
GetProcAddress(hModule, "AcquireSRWLockExclusive");
win32_srwlock_release_exclusive = (win32_srwlock_fn)
GetProcAddress(hModule, "ReleaseSRWLockExclusive");
}
return 0;
}
int git_thread_create(
git_thread *GIT_RESTRICT thread,
void *(*start_routine)(void*),
void *GIT_RESTRICT arg)
{
GIT_UNUSED(attr);
thread->result = NULL;
thread->param = arg;
thread->proc = start_routine;
......@@ -42,8 +67,8 @@ int git_win32__thread_create(
return thread->thread ? 0 : -1;
}
int git_win32__thread_join(
git_win32_thread *thread,
int git_thread_join(
git_thread *thread,
void **value_ptr)
{
DWORD exit;
......@@ -70,39 +95,32 @@ int git_win32__thread_join(
return 0;
}
int pthread_mutex_init(
pthread_mutex_t *GIT_RESTRICT mutex,
const pthread_mutexattr_t *GIT_RESTRICT mutexattr)
int git_mutex_init(git_mutex *GIT_RESTRICT mutex)
{
GIT_UNUSED(mutexattr);
InitializeCriticalSection(mutex);
return 0;
}
int pthread_mutex_destroy(pthread_mutex_t *mutex)
int git_mutex_free(git_mutex *mutex)
{
DeleteCriticalSection(mutex);
return 0;
}
int pthread_mutex_lock(pthread_mutex_t *mutex)
int git_mutex_lock(git_mutex *mutex)
{
EnterCriticalSection(mutex);
return 0;
}
int pthread_mutex_unlock(pthread_mutex_t *mutex)
int git_mutex_unlock(git_mutex *mutex)
{
LeaveCriticalSection(mutex);
return 0;
}
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
int git_cond_init(git_cond *cond)
{
/* We don't support non-default attributes. */
if (attr)
return EINVAL;
/* This is an auto-reset event. */
*cond = CreateEventW(NULL, FALSE, FALSE, NULL);
assert(*cond);
......@@ -112,7 +130,7 @@ int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
return *cond ? 0 : ENOMEM;
}
int pthread_cond_destroy(pthread_cond_t *cond)
int git_cond_free(git_cond *cond)
{
BOOL closed;
......@@ -127,7 +145,7 @@ int pthread_cond_destroy(pthread_cond_t *cond)
return 0;
}
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
int git_cond_wait(git_cond *cond, git_mutex *mutex)
{
int error;
DWORD wait_result;
......@@ -136,7 +154,7 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
return EINVAL;
/* The caller must be holding the mutex. */
error = pthread_mutex_unlock(mutex);
error = git_mutex_unlock(mutex);
if (error)
return error;
......@@ -145,10 +163,10 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
assert(WAIT_OBJECT_0 == wait_result);
GIT_UNUSED(wait_result);
return pthread_mutex_lock(mutex);
return git_mutex_lock(mutex);
}
int pthread_cond_signal(pthread_cond_t *cond)
int git_cond_signal(git_cond *cond)
{
BOOL signaled;
......@@ -162,36 +180,8 @@ int pthread_cond_signal(pthread_cond_t *cond)
return 0;
}
/* pthread_cond_broadcast is not implemented because doing so with just
* Win32 events is quite complicated, and no caller in libgit2 uses it
* yet.
*/
int pthread_num_processors_np(void)
{
DWORD_PTR p, s;
int n = 0;
if (GetProcessAffinityMask(GetCurrentProcess(), &p, &s))
for (; p; p >>= 1)
n += p&1;
return n ? n : 1;
}
typedef void (WINAPI *win32_srwlock_fn)(GIT_SRWLOCK *);
static win32_srwlock_fn win32_srwlock_initialize;
static win32_srwlock_fn win32_srwlock_acquire_shared;
static win32_srwlock_fn win32_srwlock_release_shared;
static win32_srwlock_fn win32_srwlock_acquire_exclusive;
static win32_srwlock_fn win32_srwlock_release_exclusive;
int pthread_rwlock_init(
pthread_rwlock_t *GIT_RESTRICT lock,
const pthread_rwlockattr_t *GIT_RESTRICT attr)
int git_rwlock_init(git_rwlock *GIT_RESTRICT lock)
{
GIT_UNUSED(attr);
if (win32_srwlock_initialize)
win32_srwlock_initialize(&lock->native.srwl);
else
......@@ -200,7 +190,7 @@ int pthread_rwlock_init(
return 0;
}
int pthread_rwlock_rdlock(pthread_rwlock_t *lock)
int git_rwlock_rdlock(git_rwlock *lock)
{
if (win32_srwlock_acquire_shared)
win32_srwlock_acquire_shared(&lock->native.srwl);
......@@ -210,7 +200,7 @@ int pthread_rwlock_rdlock(pthread_rwlock_t *lock)
return 0;
}
int pthread_rwlock_rdunlock(pthread_rwlock_t *lock)
int git_rwlock_rdunlock(git_rwlock *lock)
{
if (win32_srwlock_release_shared)
win32_srwlock_release_shared(&lock->native.srwl);
......@@ -220,7 +210,7 @@ int pthread_rwlock_rdunlock(pthread_rwlock_t *lock)
return 0;
}
int pthread_rwlock_wrlock(pthread_rwlock_t *lock)
int git_rwlock_wrlock(git_rwlock *lock)
{
if (win32_srwlock_acquire_exclusive)
win32_srwlock_acquire_exclusive(&lock->native.srwl);
......@@ -230,7 +220,7 @@ int pthread_rwlock_wrlock(pthread_rwlock_t *lock)
return 0;
}
int pthread_rwlock_wrunlock(pthread_rwlock_t *lock)
int git_rwlock_wrunlock(git_rwlock *lock)
{
if (win32_srwlock_release_exclusive)
win32_srwlock_release_exclusive(&lock->native.srwl);
......@@ -240,30 +230,10 @@ int pthread_rwlock_wrunlock(pthread_rwlock_t *lock)
return 0;
}
int pthread_rwlock_destroy(pthread_rwlock_t *lock)
int git_rwlock_free(git_rwlock *lock)
{
if (!win32_srwlock_initialize)
DeleteCriticalSection(&lock->native.csec);
git__memzero(lock, sizeof(*lock));
return 0;
}
int win32_pthread_initialize(void)
{
HMODULE hModule = GetModuleHandleW(L"kernel32");
if (hModule) {
win32_srwlock_initialize = (win32_srwlock_fn)
GetProcAddress(hModule, "InitializeSRWLock");
win32_srwlock_acquire_shared = (win32_srwlock_fn)
GetProcAddress(hModule, "AcquireSRWLockShared");
win32_srwlock_release_shared = (win32_srwlock_fn)
GetProcAddress(hModule, "ReleaseSRWLockShared");
win32_srwlock_acquire_exclusive = (win32_srwlock_fn)
GetProcAddress(hModule, "AcquireSRWLockExclusive");
win32_srwlock_release_exclusive = (win32_srwlock_fn)
GetProcAddress(hModule, "ReleaseSRWLockExclusive");
}
return 0;
}
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_win32_thread_h__
#define INCLUDE_win32_thread_h__
#include "../common.h"
#if defined (_MSC_VER)
# define GIT_RESTRICT __restrict
#else
# define GIT_RESTRICT __restrict__
#endif
typedef struct {
HANDLE thread;
void *(*proc)(void *);
void *param;
void *result;
} git_thread;
typedef CRITICAL_SECTION git_mutex;
typedef HANDLE git_cond;
typedef struct { void *Ptr; } GIT_SRWLOCK;
typedef struct {
union {
GIT_SRWLOCK srwl;
CRITICAL_SECTION csec;
} native;
} git_rwlock;
int git_threads_init(void);
int git_thread_create(git_thread *GIT_RESTRICT,
void *(*) (void *),
void *GIT_RESTRICT);
int git_thread_join(git_thread *, void **);
int git_mutex_init(git_mutex *GIT_RESTRICT mutex);
int git_mutex_free(git_mutex *);
int git_mutex_lock(git_mutex *);
int git_mutex_unlock(git_mutex *);
int git_cond_init(git_cond *);
int git_cond_free(git_cond *);
int git_cond_wait(git_cond *, git_mutex *);
int git_cond_signal(git_cond *);
int git_rwlock_init(git_rwlock *GIT_RESTRICT lock);
int git_rwlock_rdlock(git_rwlock *);
int git_rwlock_rdunlock(git_rwlock *);
int git_rwlock_wrlock(git_rwlock *);
int git_rwlock_wrunlock(git_rwlock *);
int git_rwlock_free(git_rwlock *);
#endif /* INCLUDE_win32_thread_h__ */
......@@ -220,7 +220,7 @@ void test_object_cache__threadmania(void)
fn = (th & 1) ? cache_parsed : cache_raw;
#ifdef GIT_THREADS
cl_git_pass(git_thread_create(&t[th], NULL, fn, data));
cl_git_pass(git_thread_create(&t[th], fn, data));
#else
cl_assert(fn(data) == data);
git__free(data);
......@@ -267,7 +267,7 @@ void test_object_cache__fast_thread_rush(void)
data[th] = th;
#ifdef GIT_THREADS
cl_git_pass(
git_thread_create(&t[th], NULL, cache_quick, &data[th]));
git_thread_create(&t[th], cache_quick, &data[th]));
#else
cl_assert(cache_quick(&data[th]) == &data[th]);
#endif
......
......@@ -75,7 +75,7 @@ void test_threads_refdb__iterator(void)
for (t = 0; t < THREADS; ++t) {
id[t] = t;
#ifdef GIT_THREADS
cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t]));
cl_git_pass(git_thread_create(&th[t], iterate_refs, &id[t]));
#else
th[t] = t;
iterate_refs(&id[t]);
......@@ -196,7 +196,7 @@ void test_threads_refdb__edit_while_iterate(void)
* for now by just running on a single thread...
*/
/* #ifdef GIT_THREADS */
/* cl_git_pass(git_thread_create(&th[t], NULL, fn, &id[t])); */
/* cl_git_pass(git_thread_create(&th[t], fn, &id[t])); */
/* #else */
fn(&id[t]);
/* #endif */
......@@ -211,7 +211,7 @@ void test_threads_refdb__edit_while_iterate(void)
for (t = 0; t < THREADS; ++t) {
id[t] = t;
cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t]));
cl_git_pass(git_thread_create(&th[t], iterate_refs, &id[t]));
}
for (t = 0; t < THREADS; ++t) {
......
......@@ -24,7 +24,7 @@ void run_in_parallel(
for (t = 0; t < threads; ++t) {
id[t] = t;
#ifdef GIT_THREADS
cl_git_pass(git_thread_create(&th[t], NULL, func, &id[t]));
cl_git_pass(git_thread_create(&th[t], func, &id[t]));
#else
cl_assert(func(&id[t]) == &id[t]);
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment