diff options
| author | Vicent Marti <tanoku@gmail.com> | 2011-03-15 21:04:41 +0200 |
|---|---|---|
| committer | Vicent Marti <tanoku@gmail.com> | 2011-03-15 21:14:07 +0200 |
| commit | bbcc7ffc690c4065954102530447aef4e8ccf895 (patch) | |
| tree | 94566de36b18a1345a83a33fd8be9df0a35afe35 /src | |
| parent | b5abb881a623b8b492e0375b8e9c8936079c39bb (diff) | |
| download | libgit2-bbcc7ffc690c4065954102530447aef4e8ccf895.tar.gz | |
Add proper threading support to libgit2
We now depend on libpthread on all Unix platforms (should be installed
by default) and use a simple wrapper for Windows threads under Win32.
Signed-off-by: Vicent Marti <tanoku@gmail.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/common.h | 5 | ||||
| -rw-r--r-- | src/thread-utils.h | 121 | ||||
| -rw-r--r-- | src/win32/pthread.c | 120 | ||||
| -rw-r--r-- | src/win32/pthread.h | 67 |
4 files changed, 209 insertions, 104 deletions
diff --git a/src/common.h b/src/common.h index 1ca00471b..723085a2b 100644 --- a/src/common.h +++ b/src/common.h @@ -11,9 +11,6 @@ #include "git2/thread-utils.h" #include "cc-compat.h" -#ifdef GIT_HAS_PTHREAD -# include <pthread.h> -#endif #ifdef GIT_HAVE_INTTYPES_H # include <inttypes.h> #endif @@ -34,6 +31,7 @@ # include <windows.h> # include "msvc-compat.h" # include "mingw-compat.h" +# include "win32/pthread.h" # define snprintf _snprintf @@ -43,6 +41,7 @@ typedef SSIZE_T ssize_t; # include <unistd.h> # include <arpa/inet.h> +# include <pthread.h> #endif diff --git a/src/thread-utils.h b/src/thread-utils.h index 0029e4bc1..e8372e731 100644 --- a/src/thread-utils.h +++ b/src/thread-utils.h @@ -1,108 +1,27 @@ #ifndef INCLUDE_thread_utils_h__ #define INCLUDE_thread_utils_h__ -#if defined(GIT_HAS_PTHREAD) - typedef pthread_t git_thread; -# define git_thread_create(thread, attr, start_routine, arg) pthread_create(thread, attr, start_routine, arg) -# define git_thread_kill(thread) pthread_cancel(thread) -# define git_thread_exit(status) pthread_exit(status) -# define git_thread_join(id, status) pthread_join(id, status) - /* Pthreads Mutex */ - typedef pthread_mutex_t git_lck; -# define GITLCK_INIT PTHREAD_MUTEX_INITIALIZER -# define gitlck_init(a) pthread_mutex_init(a, NULL) -# define gitlck_lock(a) pthread_mutex_lock(a) -# define gitlck_unlock(a) pthread_mutex_unlock(a) -# define gitlck_free(a) pthread_mutex_destroy(a) - - /* Pthreads condition vars */ - typedef pthread_cond_t git_cnd; -# define GITCND_INIT PTHREAD_COND_INITIALIZER -# define gitcnd_init(c, a) pthread_cond_init(c, a) -# define gitcnd_free(c) pthread_cond_destroy(c) -# define gitcnd_wait(c, l) pthread_cond_wait(c, l) -# define gitcnd_signal(c) pthread_cond_signal(c) -# define gitcnd_broadcast(c) pthread_cond_broadcast(c) - -# if defined(GIT_HAS_ASM_ATOMIC) -# include <asm/atomic.h> - typedef atomic_t git_refcnt; -# define gitrc_init(a, v) atomic_set(a, v) -# define gitrc_inc(a) atomic_inc_return(a) -# define gitrc_dec(a) atomic_dec_and_test(a) -# define gitrc_free(a) (void)0 -# elif defined(GIT_WIN32) - typedef long git_refcnt; -# define gitrc_init(a, v) (*a = v) -# define gitrc_inc(a) (InterlockedIncrement(a)) -# define gitrc_dec(a) (!InterlockedDecrement(a)) -# define gitrc_free(a) (void)0 -# else - typedef struct { git_lck lock; int counter; } git_refcnt; - - /** Initialize to 0. No memory barrier is issued. */ - GIT_INLINE(void) gitrc_init(git_refcnt *p, int value) - { - gitlck_init(&p->lock); - p->counter = value; - } - - /** - * Increment. - * - * Atomically increments @p by 1. A memory barrier is also - * issued before and after the operation. - * - * @param p pointer of type git_refcnt - */ - GIT_INLINE(void) gitrc_inc(git_refcnt *p) - { - gitlck_lock(&p->lock); - p->counter++; - gitlck_unlock(&p->lock); - } - - /** - * Decrement and test. - * - * Atomically decrements @p by 1 and returns true if the - * result is 0, or false for all other cases. A memory - * barrier is also issued before and after the operation. - * - * @param p pointer of type git_refcnt - */ - GIT_INLINE(int) gitrc_dec(git_refcnt *p) - { - int c; - gitlck_lock(&p->lock); - c = --p->counter; - gitlck_unlock(&p->lock); - return !c; - } - - /** Free any resources associated with the counter. */ -# define gitrc_free(p) gitlck_free(&(p)->lock) -# endif - -#elif defined(GIT_THREADS) -# error GIT_THREADS but no git_lck implementation - -#else - /* no threads support */ - typedef struct { int dummy; } git_lck; -# define GIT_MUTEX_INIT {} -# define gitlck_init(a) (void)0 -# define gitlck_lock(a) (void)0 -# define gitlck_unlock(a) (void)0 -# define gitlck_free(a) (void)0 - - typedef struct { int counter; } git_refcnt; -# define gitrc_init(a,v) ((a)->counter = v) -# define gitrc_inc(a) ((a)->counter++) -# define gitrc_dec(a) (--(a)->counter == 0) -# define gitrc_free(a) (void)0 -#endif +#define git_thread pthread_t +#define git_thread_create(thread, attr, start_routine, arg) pthread_create(thread, attr, start_routine, arg) +#define git_thread_kill(thread) pthread_cancel(thread) +#define git_thread_exit(status) pthread_exit(status) +#define git_thread_join(id, status) pthread_join(id, status) + +/* 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, a) pthread_cond_init(c, a) +#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) extern int git_online_cpus(void); diff --git a/src/win32/pthread.c b/src/win32/pthread.c new file mode 100644 index 000000000..fffff81df --- /dev/null +++ b/src/win32/pthread.c @@ -0,0 +1,120 @@ +/* + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, + * as published by the Free Software Foundation. + * + * In addition to the permissions in the GNU General Public License, + * the authors give you unlimited permission to link the compiled + * version of this file into combinations with other programs, + * and to distribute those combinations without any restriction + * coming from the use of this file. (The General Public License + * restrictions do apply in other respects; for example, they cover + * modification of the file, and distribution when not linked into + * a combined executable.) + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * Original code by Ramiro Polla (Public Domain) + */ + +#include "pthread.h" + +int pthread_create(pthread_t *GIT_RESTRICT thread, + const pthread_attr_t *GIT_RESTRICT GIT_UNUSED(attr), + void *(*start_routine)(void*), void *GIT_RESTRICT arg) +{ + GIT_UNUSED_ARG(attr); + *thread = (pthread_t) CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, arg, 0, NULL); + return *thread ? GIT_SUCCESS : GIT_EOSERR; +} + +int pthread_cond_signal(pthread_cond_t *cond) +{ + WakeConditionVariable(cond); + return 0; +} + +int pthread_cond_wait(pthread_cond_t *GIT_RESTRICT cond, + pthread_mutex_t *GIT_RESTRICT mutex) +{ + int ret; + ret = SleepConditionVariableCS(cond, mutex, INFINITE); + return -(!ret); +} + +int pthread_mutex_lock(pthread_mutex_t *mutex) +{ + EnterCriticalSection(mutex); + return 0; +} + +int pthread_mutex_unlock(pthread_mutex_t *mutex) +{ + LeaveCriticalSection(mutex); + return 0; +} + +int pthread_join(pthread_t thread, void **value_ptr) +{ + int ret; + ret = WaitForSingleObject(thread, INFINITE); + if (ret && value_ptr) + GetExitCodeThread(thread, (void*) value_ptr); + return -(!!ret); +} + +int pthread_cond_broadcast(pthread_cond_t *cond) +{ + WakeAllConditionVariable(cond); + return 0; +} + +int pthread_mutex_destroy(pthread_mutex_t *mutex) +{ + int ret; + ret = CloseHandle(mutex); + return -(!ret); +} + +int pthread_cond_destroy(pthread_cond_t *GIT_UNUSED(cond)) +{ + GIT_UNUSED_ARG(cond); + return 0; +} + +int pthread_cond_init(pthread_cond_t *GIT_RESTRICT cond, + const pthread_condattr_t *GIT_RESTRICT GIT_UNUSED(condattr)) +{ + GIT_UNUSED_ARG(condattr); + InitializeConditionVariable(cond); + return 0; +} + +int pthread_mutex_init(pthread_mutex_t *GIT_RESTRICT mutex, + const pthread_mutexattr_t *GIT_RESTRICT GIT_UNUSED(mutexattr)) +{ + GIT_UNUSED_ARG(mutexattr); + InitializeCriticalSection(mutex); + return 0; +} + +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; +} + diff --git a/src/win32/pthread.h b/src/win32/pthread.h new file mode 100644 index 000000000..ff694e303 --- /dev/null +++ b/src/win32/pthread.h @@ -0,0 +1,67 @@ +/* + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, + * as published by the Free Software Foundation. + * + * In addition to the permissions in the GNU General Public License, + * the authors give you unlimited permission to link the compiled + * version of this file into combinations with other programs, + * and to distribute those combinations without any restriction + * coming from the use of this file. (The General Public License + * restrictions do apply in other respects; for example, they cover + * modification of the file, and distribution when not linked into + * a combined executable.) + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * Original code by Ramiro Polla (Public Domain) + */ + +#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 int pthread_mutexattr_t; +typedef int pthread_condattr_t; +typedef int pthread_attr_t; +typedef CRITICAL_SECTION pthread_mutex_t; +typedef CONDITION_VARIABLE pthread_cond_t; +typedef HANDLE pthread_t; + +#define PTHREAD_MUTEX_INITIALIZER {(void*)-1}; + +int pthread_create(pthread_t *GIT_RESTRICT, + const pthread_attr_t *GIT_RESTRICT, + void *(*start_routine)(void*), void *__restrict); + +int pthread_join(pthread_t, void **); + +int pthread_mutex_init(pthread_mutex_t *GIT_RESTRICT, const pthread_mutexattr_t *GIT_RESTRICT); +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 *GIT_RESTRICT, const pthread_condattr_t *GIT_RESTRICT); +int pthread_cond_destroy(pthread_cond_t *); +int pthread_cond_broadcast(pthread_cond_t *); +int pthread_cond_signal(pthread_cond_t *); +int pthread_cond_wait(pthread_cond_t *GIT_RESTRICT, pthread_mutex_t *GIT_RESTRICT); + +int pthread_num_processors_np(void); + +#endif
\ No newline at end of file |
