Skip to content

Commit

Permalink
threads: introduce git_thread_exit
Browse files Browse the repository at this point in the history
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 *`.
  • Loading branch information
Edward Thomson committed Nov 18, 2016
1 parent a6763ff commit 82f1589
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ typedef struct {
git_error error_t;
git_buf error_buf;
char oid_fmt[GIT_OID_HEXSZ+1];

/* On Windows, this is the current child thread that was started by
* `git_thread_create`. This is used to set the thread's exit code
* when terminated by `git_thread_exit`. It is unused on POSIX.
*/
git_thread *current_thread;
} git_global_st;

#ifdef GIT_OPENSSL
Expand Down
2 changes: 2 additions & 0 deletions src/unix/pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ typedef struct {
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)
#define git_thread_currentid() ((size_t)(pthread_self()))
#define git_thread_exit(retval) pthread_exit(retval)

/* Git Mutex */
#define git_mutex pthread_mutex_t
Expand Down
18 changes: 18 additions & 0 deletions src/win32/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
{
git_thread *thread = lpParameter;

/* Set the current thread for `git_thread_exit` */
GIT_GLOBAL->current_thread = thread;

thread->result = thread->proc(thread->param);

git__free_tls_data();
Expand Down Expand Up @@ -95,6 +98,21 @@ int git_thread_join(
return 0;
}

void git_thread_exit(void *value)
{
assert(GIT_GLOBAL->current_thread);
GIT_GLOBAL->current_thread->result = value;

git__free_tls_data();

ExitThread(CLEAN_THREAD_EXIT);
}

size_t git_thread_currentid(void)
{
return GetCurrentThreadId();
}

int git_mutex_init(git_mutex *GIT_RESTRICT mutex)
{
InitializeCriticalSection(mutex);
Expand Down
2 changes: 2 additions & 0 deletions src/win32/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ int git_thread_create(git_thread *GIT_RESTRICT,
void *(*) (void *),
void *GIT_RESTRICT);
int git_thread_join(git_thread *, void **);
size_t git_thread_currentid(void);
void git_thread_exit(void *);

int git_mutex_init(git_mutex *GIT_RESTRICT mutex);
int git_mutex_free(git_mutex *);
Expand Down
27 changes: 27 additions & 0 deletions tests/threads/basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,30 @@ void test_threads_basic__set_error(void)
{
run_in_parallel(1, 4, set_error, NULL, NULL);
}

static void *return_normally(void *param)
{
return param;
}

static void *exit_abruptly(void *param)
{
git_thread_exit(param);
return NULL;
}

void test_threads_basic__exit(void)
{
git_thread thread;
void *result;

/* Ensure that the return value of the threadproc is returned. */
cl_git_pass(git_thread_create(&thread, return_normally, (void *)424242));
cl_git_pass(git_thread_join(&thread, &result));
cl_assert_equal_sz(424242, (size_t)result);

/* Ensure that the return value of `git_thread_exit` is returned. */
cl_git_pass(git_thread_create(&thread, return_normally, (void *)232323));
cl_git_pass(git_thread_join(&thread, &result));
cl_assert_equal_sz(232323, (size_t)result);
}

0 comments on commit 82f1589

Please sign in to comment.