Skip to content

Commit 82f1589

Browse files
author
Edward Thomson
committed
threads: introduce git_thread_exit
Introduce `git_thread_exit`, which will allow threads to terminate at an arbitrary time, returning a `void *`. On Windows, this means that we need to store the current `git_thread` in TLS, so that we can set its `return` value when terminating. We cannot simply use `ExitThread`, since Win32 returns `DWORD`s from threads; we return `void *`.
1 parent a6763ff commit 82f1589

File tree

5 files changed

+55
-0
lines changed

5 files changed

+55
-0
lines changed

src/global.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ typedef struct {
1616
git_error error_t;
1717
git_buf error_buf;
1818
char oid_fmt[GIT_OID_HEXSZ+1];
19+
20+
/* On Windows, this is the current child thread that was started by
21+
* `git_thread_create`. This is used to set the thread's exit code
22+
* when terminated by `git_thread_exit`. It is unused on POSIX.
23+
*/
24+
git_thread *current_thread;
1925
} git_global_st;
2026

2127
#ifdef GIT_OPENSSL

src/unix/pthread.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ typedef struct {
1717
pthread_create(&(git_thread_ptr)->thread, NULL, start_routine, arg)
1818
#define git_thread_join(git_thread_ptr, status) \
1919
pthread_join((git_thread_ptr)->thread, status)
20+
#define git_thread_currentid() ((size_t)(pthread_self()))
21+
#define git_thread_exit(retval) pthread_exit(retval)
2022

2123
/* Git Mutex */
2224
#define git_mutex pthread_mutex_t

src/win32/thread.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
2626
{
2727
git_thread *thread = lpParameter;
2828

29+
/* Set the current thread for `git_thread_exit` */
30+
GIT_GLOBAL->current_thread = thread;
31+
2932
thread->result = thread->proc(thread->param);
3033

3134
git__free_tls_data();
@@ -95,6 +98,21 @@ int git_thread_join(
9598
return 0;
9699
}
97100

101+
void git_thread_exit(void *value)
102+
{
103+
assert(GIT_GLOBAL->current_thread);
104+
GIT_GLOBAL->current_thread->result = value;
105+
106+
git__free_tls_data();
107+
108+
ExitThread(CLEAN_THREAD_EXIT);
109+
}
110+
111+
size_t git_thread_currentid(void)
112+
{
113+
return GetCurrentThreadId();
114+
}
115+
98116
int git_mutex_init(git_mutex *GIT_RESTRICT mutex)
99117
{
100118
InitializeCriticalSection(mutex);

src/win32/thread.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ int git_thread_create(git_thread *GIT_RESTRICT,
4141
void *(*) (void *),
4242
void *GIT_RESTRICT);
4343
int git_thread_join(git_thread *, void **);
44+
size_t git_thread_currentid(void);
45+
void git_thread_exit(void *);
4446

4547
int git_mutex_init(git_mutex *GIT_RESTRICT mutex);
4648
int git_mutex_free(git_mutex *);

tests/threads/basic.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,30 @@ void test_threads_basic__set_error(void)
4848
{
4949
run_in_parallel(1, 4, set_error, NULL, NULL);
5050
}
51+
52+
static void *return_normally(void *param)
53+
{
54+
return param;
55+
}
56+
57+
static void *exit_abruptly(void *param)
58+
{
59+
git_thread_exit(param);
60+
return NULL;
61+
}
62+
63+
void test_threads_basic__exit(void)
64+
{
65+
git_thread thread;
66+
void *result;
67+
68+
/* Ensure that the return value of the threadproc is returned. */
69+
cl_git_pass(git_thread_create(&thread, return_normally, (void *)424242));
70+
cl_git_pass(git_thread_join(&thread, &result));
71+
cl_assert_equal_sz(424242, (size_t)result);
72+
73+
/* Ensure that the return value of `git_thread_exit` is returned. */
74+
cl_git_pass(git_thread_create(&thread, return_normally, (void *)232323));
75+
cl_git_pass(git_thread_join(&thread, &result));
76+
cl_assert_equal_sz(232323, (size_t)result);
77+
}

0 commit comments

Comments
 (0)