summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2020-12-09 13:25:23 +0000
committerGitHub <noreply@github.com>2020-12-09 13:25:23 +0000
commita5cb2cc9f547d9defaf51b2af25ba2fa9d9015a0 (patch)
tree99c9a2b17ced475c01ef209e4636d03777bcbcd3
parent1adb84107f406a00178296257289663860d277ae (diff)
parent20ce17f06d27a92ada11fa5d15108532223e9884 (diff)
downloadlibgit2-a5cb2cc9f547d9defaf51b2af25ba2fa9d9015a0.tar.gz
Merge pull request #5720 from libgit2/ethomson/tlsdata
Thread-local storage: a generic internal library (with no allocations)
-rw-r--r--src/attr_file.c2
-rw-r--r--src/attrcache.c10
-rw-r--r--src/cache.c4
-rw-r--r--src/cache.h14
-rw-r--r--src/common.h6
-rw-r--r--src/config_cache.c4
-rw-r--r--src/diff_driver.c2
-rw-r--r--src/index.c18
-rw-r--r--src/index.h2
-rw-r--r--src/libgit2.c2
-rw-r--r--src/mwindow.c6
-rw-r--r--src/pack-objects.c4
-rw-r--r--src/pack.c12
-rw-r--r--src/pack.h4
-rw-r--r--src/repository.c24
-rw-r--r--src/repository.h2
-rw-r--r--src/runtime.c18
-rw-r--r--src/sortedcache.h2
-rw-r--r--src/thread-utils.c58
-rw-r--r--src/thread.c140
-rw-r--r--src/thread.h (renamed from src/thread-utils.h)110
-rw-r--r--src/threadstate.c102
-rw-r--r--src/transports/local.c4
-rw-r--r--src/transports/smart.c4
-rw-r--r--src/transports/smart.h2
-rw-r--r--src/transports/smart_protocol.c2
-rw-r--r--src/util.c51
-rw-r--r--src/util.h16
-rw-r--r--src/win32/msvc-compat.h10
-rw-r--r--tests/threads/diff.c18
-rw-r--r--tests/threads/thread_helpers.h2
-rw-r--r--tests/threads/tlsdata.c65
32 files changed, 454 insertions, 266 deletions
diff --git a/src/attr_file.c b/src/attr_file.c
index 0781c1d61..adc56d53e 100644
--- a/src/attr_file.c
+++ b/src/attr_file.c
@@ -960,7 +960,7 @@ int git_attr_session__init(git_attr_session *session, git_repository *repo)
GIT_ASSERT_ARG(repo);
memset(session, 0, sizeof(*session));
- session->key = git_atomic_inc(&repo->attr_session_key);
+ session->key = git_atomic32_inc(&repo->attr_session_key);
return 0;
}
diff --git a/src/attrcache.c b/src/attrcache.c
index 47fb675e0..2485b0599 100644
--- a/src/attrcache.c
+++ b/src/attrcache.c
@@ -108,7 +108,7 @@ static int attr_cache_upsert(git_attr_cache *cache, git_attr_file *file)
* Replace the existing value if another thread has
* created it in the meantime.
*/
- old = git__swap(entry->file[file->source], file);
+ old = git_atomic_swap(entry->file[file->source], file);
if (old) {
GIT_REFCOUNT_OWN(old, NULL);
@@ -132,7 +132,7 @@ static int attr_cache_remove(git_attr_cache *cache, git_attr_file *file)
return error;
if ((entry = attr_cache_lookup_entry(cache, file->entry->path)) != NULL)
- old = git__compare_and_swap(&entry->file[file->source], file, NULL);
+ old = git_atomic_compare_and_swap(&entry->file[file->source], file, NULL);
attr_cache_unlock(cache);
@@ -321,7 +321,7 @@ static void attr_cache__free(git_attr_cache *cache)
git_strmap_foreach_value(cache->files, entry, {
for (i = 0; i < GIT_ATTR_FILE_NUM_SOURCES; ++i) {
- if ((file = git__swap(entry->file[i], NULL)) != NULL) {
+ if ((file = git_atomic_swap(entry->file[i], NULL)) != NULL) {
GIT_REFCOUNT_OWN(file, NULL);
git_attr_file__free(file);
}
@@ -395,7 +395,7 @@ int git_attr_cache__init(git_repository *repo)
(ret = git_pool_init(&cache->pool, 1)) < 0)
goto cancel;
- cache = git__compare_and_swap(&repo->attrcache, NULL, cache);
+ cache = git_atomic_compare_and_swap(&repo->attrcache, NULL, cache);
if (cache)
goto cancel; /* raced with another thread, free this but no error */
@@ -417,7 +417,7 @@ int git_attr_cache_flush(git_repository *repo)
/* this could be done less expensively, but for now, we'll just free
* the entire attrcache and let the next use reinitialize it...
*/
- if (repo && (cache = git__swap(repo->attrcache, NULL)) != NULL)
+ if (repo && (cache = git_atomic_swap(repo->attrcache, NULL)) != NULL)
attr_cache__free(cache);
return 0;
diff --git a/src/cache.c b/src/cache.c
index a76da50d7..2f68e357c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -9,7 +9,7 @@
#include "repository.h"
#include "commit.h"
-#include "thread-utils.h"
+#include "thread.h"
#include "util.h"
#include "odb.h"
#include "object.h"
@@ -235,7 +235,7 @@ void git_cached_obj_decref(void *_obj)
{
git_cached_obj *obj = _obj;
- if (git_atomic_dec(&obj->refcount) == 0) {
+ if (git_atomic32_dec(&obj->refcount) == 0) {
switch (obj->flags) {
case GIT_CACHE_STORE_RAW:
git_odb_object__free(_obj);
diff --git a/src/cache.h b/src/cache.h
index 1e6179236..42c4fa80d 100644
--- a/src/cache.h
+++ b/src/cache.h
@@ -13,7 +13,7 @@
#include "git2/oid.h"
#include "git2/odb.h"
-#include "thread-utils.h"
+#include "thread.h"
#include "oidmap.h"
enum {
@@ -23,11 +23,11 @@ enum {
};
typedef struct {
- git_oid oid;
- int16_t type; /* git_object_t value */
- uint16_t flags; /* GIT_CACHE_STORE value */
- size_t size;
- git_atomic refcount;
+ git_oid oid;
+ int16_t type; /* git_object_t value */
+ uint16_t flags; /* GIT_CACHE_STORE value */
+ size_t size;
+ git_atomic32 refcount;
} git_cached_obj;
typedef struct {
@@ -61,7 +61,7 @@ GIT_INLINE(size_t) git_cache_size(git_cache *cache)
GIT_INLINE(void) git_cached_obj_incref(void *_obj)
{
git_cached_obj *obj = _obj;
- git_atomic_inc(&obj->refcount);
+ git_atomic32_inc(&obj->refcount);
}
void git_cached_obj_decref(void *_obj);
diff --git a/src/common.h b/src/common.h
index 2b1a4a456..bda3edbc1 100644
--- a/src/common.h
+++ b/src/common.h
@@ -63,7 +63,9 @@
# include <pthread.h>
# include <sched.h>
# endif
-#define GIT_STDLIB_CALL
+
+#define GIT_LIBGIT2_CALL
+#define GIT_SYSTEM_CALL
#ifdef GIT_USE_STAT_ATIMESPEC
# define st_atim st_atimespec
@@ -78,7 +80,7 @@
#include "git2/types.h"
#include "git2/errors.h"
#include "errors.h"
-#include "thread-utils.h"
+#include "thread.h"
#include "integer.h"
#include "assert_safe.h"
diff --git a/src/config_cache.c b/src/config_cache.c
index 1a28ba96c..2f0455af9 100644
--- a/src/config_cache.c
+++ b/src/config_cache.c
@@ -111,7 +111,7 @@ int git_config__configmap_lookup(int *out, git_config *config, git_configmap_ite
int git_repository__configmap_lookup(int *out, git_repository *repo, git_configmap_item item)
{
- *out = (int)(intptr_t)git__load(repo->configmap_cache[(int)item]);
+ *out = (int)(intptr_t)git_atomic_load(repo->configmap_cache[(int)item]);
if (*out == GIT_CONFIGMAP_NOT_CACHED) {
int error;
@@ -122,7 +122,7 @@ int git_repository__configmap_lookup(int *out, git_repository *repo, git_configm
(error = git_config__configmap_lookup(out, config, item)) < 0)
return error;
- git__compare_and_swap(&repo->configmap_cache[(int)item], &oldval, out);
+ git_atomic_compare_and_swap(&repo->configmap_cache[(int)item], &oldval, out);
}
return 0;
diff --git a/src/diff_driver.c b/src/diff_driver.c
index 606c391e4..6b19012c7 100644
--- a/src/diff_driver.c
+++ b/src/diff_driver.c
@@ -144,7 +144,7 @@ static git_diff_driver_registry *git_repository_driver_registry(
{
if (!repo->diff_drivers) {
git_diff_driver_registry *reg = git_diff_driver_registry_new();
- reg = git__compare_and_swap(&repo->diff_drivers, NULL, reg);
+ reg = git_atomic_compare_and_swap(&repo->diff_drivers, NULL, reg);
if (reg != NULL) /* if we race, free losing allocation */
git_diff_driver_registry_free(reg);
diff --git a/src/index.c b/src/index.c
index d9116c412..7ebe07582 100644
--- a/src/index.c
+++ b/src/index.c
@@ -461,7 +461,7 @@ static void index_free(git_index *index)
/* index iterators increment the refcount of the index, so if we
* get here then there should be no outstanding iterators.
*/
- if (git_atomic_get(&index->readers))
+ if (git_atomic32_get(&index->readers))
return;
git_index_clear(index);
@@ -488,14 +488,14 @@ void git_index_free(git_index *index)
/* call with locked index */
static void index_free_deleted(git_index *index)
{
- int readers = (int)git_atomic_get(&index->readers);
+ int readers = (int)git_atomic32_get(&index->readers);
size_t i;
if (readers > 0 || !index->deleted.length)
return;
for (i = 0; i < index->deleted.length; ++i) {
- git_index_entry *ie = git__swap(index->deleted.contents[i], NULL);
+ git_index_entry *ie = git_atomic_swap(index->deleted.contents[i], NULL);
index_entry_free(ie);
}
@@ -516,7 +516,7 @@ static int index_remove_entry(git_index *index, size_t pos)
error = git_vector_remove(&index->entries, pos);
if (!error) {
- if (git_atomic_get(&index->readers) > 0) {
+ if (git_atomic32_get(&index->readers) > 0) {
error = git_vector_insert(&index->deleted, entry);
} else {
index_entry_free(entry);
@@ -2295,7 +2295,7 @@ int git_index_reuc_clear(git_index *index)
GIT_ASSERT_ARG(index);
for (i = 0; i < index->reuc.length; ++i)
- index_entry_reuc_free(git__swap(index->reuc.contents[i], NULL));
+ index_entry_reuc_free(git_atomic_swap(index->reuc.contents[i], NULL));
git_vector_clear(&index->reuc);
@@ -3197,7 +3197,7 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
/* well, this isn't good */;
} else {
git_vector_swap(&entries, &index->entries);
- entries_map = git__swap(index->entries_map, entries_map);
+ entries_map = git_atomic_swap(index->entries_map, entries_map);
}
index->dirty = 1;
@@ -3331,7 +3331,7 @@ static int git_index_read_iterator(
goto done;
git_vector_swap(&new_entries, &index->entries);
- new_entries_map = git__swap(index->entries_map, new_entries_map);
+ new_entries_map = git_atomic_swap(index->entries_map, new_entries_map);
git_vector_foreach(&remove_entries, i, entry) {
if (index->tree)
@@ -3637,7 +3637,7 @@ int git_index_snapshot_new(git_vector *snap, git_index *index)
GIT_REFCOUNT_INC(index);
- git_atomic_inc(&index->readers);
+ git_atomic32_inc(&index->readers);
git_vector_sort(&index->entries);
error = git_vector_dup(snap, &index->entries, index->entries._cmp);
@@ -3652,7 +3652,7 @@ void git_index_snapshot_release(git_vector *snap, git_index *index)
{
git_vector_free(snap);
- git_atomic_dec(&index->readers);
+ git_atomic32_dec(&index->readers);
git_index_free(index);
}
diff --git a/src/index.h b/src/index.h
index 54402f563..a365867d0 100644
--- a/src/index.h
+++ b/src/index.h
@@ -33,7 +33,7 @@ struct git_index {
git_idxmap *entries_map;
git_vector deleted; /* deleted entries if readers > 0 */
- git_atomic readers; /* number of active iterators */
+ git_atomic32 readers; /* number of active iterators */
unsigned int on_disk:1;
unsigned int ignore_case:1;
diff --git a/src/libgit2.c b/src/libgit2.c
index 9e5112dbf..e41988c8e 100644
--- a/src/libgit2.c
+++ b/src/libgit2.c
@@ -22,7 +22,7 @@
#include "refs.h"
#include "runtime.h"
#include "sysdir.h"
-#include "thread-utils.h"
+#include "thread.h"
#include "threadstate.h"
#include "git2/global.h"
#include "streams/registry.h"
diff --git a/src/mwindow.c b/src/mwindow.c
index 4f105e659..7832d9c8b 100644
--- a/src/mwindow.c
+++ b/src/mwindow.c
@@ -79,7 +79,7 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
git__free(packname);
if (pack != NULL) {
- git_atomic_inc(&pack->refcount);
+ git_atomic32_inc(&pack->refcount);
git_mutex_unlock(&git__mwindow_mutex);
*out = pack;
return 0;
@@ -91,7 +91,7 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
return error;
}
- git_atomic_inc(&pack->refcount);
+ git_atomic32_inc(&pack->refcount);
error = git_strmap_set(git__pack_cache, pack->pack_name, pack);
git_mutex_unlock(&git__mwindow_mutex);
@@ -118,7 +118,7 @@ int git_mwindow_put_pack(struct git_pack_file *pack)
/* if we cannot find it, the state is corrupted */
GIT_ASSERT(git_strmap_exists(git__pack_cache, pack->pack_name));
- count = git_atomic_dec(&pack->refcount);
+ count = git_atomic32_dec(&pack->refcount);
if (count == 0) {
git_strmap_delete(git__pack_cache, pack->pack_name);
pack_to_delete = pack;
diff --git a/src/pack-objects.c b/src/pack-objects.c
index 03d05b7e7..f9d8bfd35 100644
--- a/src/pack-objects.c
+++ b/src/pack-objects.c
@@ -12,7 +12,7 @@
#include "iterator.h"
#include "netops.h"
#include "pack.h"
-#include "thread-utils.h"
+#include "thread.h"
#include "tree.h"
#include "util.h"
#include "revwalk.h"
@@ -1158,7 +1158,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
int ret, active_threads = 0;
if (!pb->nr_threads)
- pb->nr_threads = git_online_cpus();
+ pb->nr_threads = git__online_cpus();
if (pb->nr_threads <= 1) {
find_deltas(pb, list, &list_size, window, depth);
diff --git a/src/pack.c b/src/pack.c
index b88c52acf..a9140c63d 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -57,7 +57,7 @@ static git_pack_cache_entry *new_cache_object(git_rawobj *source)
if (!e)
return NULL;
- git_atomic_inc(&e->refcount);
+ git_atomic32_inc(&e->refcount);
memcpy(&e->raw, source, sizeof(git_rawobj));
return e;
@@ -114,7 +114,7 @@ static git_pack_cache_entry *cache_get(git_pack_cache *cache, off64_t offset)
return NULL;
if ((entry = git_offmap_get(cache->entries, offset)) != NULL) {
- git_atomic_inc(&entry->refcount);
+ git_atomic32_inc(&entry->refcount);
entry->last_usage = cache->use_ctr++;
}
git_mutex_unlock(&cache->lock);
@@ -129,7 +129,7 @@ static void free_lowest_entry(git_pack_cache *cache)
git_pack_cache_entry *entry;
git_offmap_foreach(cache->entries, offset, entry, {
- if (entry && git_atomic_get(&entry->refcount) == 0) {
+ if (entry && git_atomic32_get(&entry->refcount) == 0) {
cache->memory_used -= entry->raw.len;
git_offmap_delete(cache->entries, offset);
free_cache_object(entry);
@@ -759,7 +759,7 @@ int git_packfile_unpack(
GIT_ERROR_CHECK_ALLOC(obj->data);
memcpy(obj->data, data, obj->len + 1);
- git_atomic_dec(&cached->refcount);
+ git_atomic32_dec(&cached->refcount);
goto cleanup;
}
@@ -807,7 +807,7 @@ int git_packfile_unpack(
}
if (cached) {
- git_atomic_dec(&cached->refcount);
+ git_atomic32_dec(&cached->refcount);
cached = NULL;
}
@@ -821,7 +821,7 @@ cleanup:
if (error < 0) {
git__free(obj->data);
if (cached)
- git_atomic_dec(&cached->refcount);
+ git_atomic32_dec(&cached->refcount);
}
if (elem)
diff --git a/src/pack.h b/src/pack.h
index 7c3be079e..1d077240d 100644
--- a/src/pack.h
+++ b/src/pack.h
@@ -58,7 +58,7 @@ struct git_pack_idx_header {
typedef struct git_pack_cache_entry {
size_t last_usage; /* enough? */
- git_atomic refcount;
+ git_atomic32 refcount;
git_rawobj raw;
} git_pack_cache_entry;
@@ -86,7 +86,7 @@ struct git_pack_file {
git_mwindow_file mwf;
git_map index_map;
git_mutex lock; /* protect updates to index_map */
- git_atomic refcount;
+ git_atomic32 refcount;
uint32_t num_objects;
uint32_t num_bad_objects;
diff --git a/src/repository.c b/src/repository.c
index bef84caaf..3b6bcbe86 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -93,7 +93,7 @@ static void set_odb(git_repository *repo, git_odb *odb)
GIT_REFCOUNT_INC(odb);
}
- if ((odb = git__swap(repo->_odb, odb)) != NULL) {
+ if ((odb = git_atomic_swap(repo->_odb, odb)) != NULL) {
GIT_REFCOUNT_OWN(odb, NULL);
git_odb_free(odb);
}
@@ -106,7 +106,7 @@ static void set_refdb(git_repository *repo, git_refdb *refdb)
GIT_REFCOUNT_INC(refdb);
}
- if ((refdb = git__swap(repo->_refdb, refdb)) != NULL) {
+ if ((refdb = git_atomic_swap(repo->_refdb, refdb)) != NULL) {
GIT_REFCOUNT_OWN(refdb, NULL);
git_refdb_free(refdb);
}
@@ -119,7 +119,7 @@ static void set_config(git_repository *repo, git_config *config)
GIT_REFCOUNT_INC(config);
}
- if ((config = git__swap(repo->_config, config)) != NULL) {
+ if ((config = git_atomic_swap(repo->_config, config)) != NULL) {
GIT_REFCOUNT_OWN(config, NULL);
git_config_free(config);
}
@@ -134,7 +134,7 @@ static void set_index(git_repository *repo, git_index *index)
GIT_REFCOUNT_INC(index);
}
- if ((index = git__swap(repo->_index, index)) != NULL) {
+ if ((index = git_atomic_swap(repo->_index, index)) != NULL) {
GIT_REFCOUNT_OWN(index, NULL);
git_index_free(index);
}
@@ -1054,7 +1054,7 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
if (!error) {
GIT_REFCOUNT_OWN(config, repo);
- config = git__compare_and_swap(&repo->_config, NULL, config);
+ config = git_atomic_compare_and_swap(&repo->_config, NULL, config);
if (config != NULL) {
GIT_REFCOUNT_OWN(config, NULL);
git_config_free(config);
@@ -1107,7 +1107,7 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
GIT_ASSERT_ARG(repo);
GIT_ASSERT_ARG(out);
- *out = git__load(repo->_odb);
+ *out = git_atomic_load(repo->_odb);
if (*out == NULL) {
git_buf odb_path = GIT_BUF_INIT;
git_odb *odb;
@@ -1125,14 +1125,14 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
return error;
}
- odb = git__compare_and_swap(&repo->_odb, NULL, odb);
+ odb = git_atomic_compare_and_swap(&repo->_odb, NULL, odb);
if (odb != NULL) {
GIT_REFCOUNT_OWN(odb, NULL);
git_odb_free(odb);
}
git_buf_dispose(&odb_path);
- *out = git__load(repo->_odb);
+ *out = git_atomic_load(repo->_odb);
}
return error;
@@ -1170,7 +1170,7 @@ int git_repository_refdb__weakptr(git_refdb **out, git_repository *repo)
if (!error) {
GIT_REFCOUNT_OWN(refdb, repo);
- refdb = git__compare_and_swap(&repo->_refdb, NULL, refdb);
+ refdb = git_atomic_compare_and_swap(&repo->_refdb, NULL, refdb);
if (refdb != NULL) {
GIT_REFCOUNT_OWN(refdb, NULL);
git_refdb_free(refdb);
@@ -1218,7 +1218,7 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
if (!error) {
GIT_REFCOUNT_OWN(index, repo);
- index = git__compare_and_swap(&repo->_index, NULL, index);
+ index = git_atomic_compare_and_swap(&repo->_index, NULL, index);
if (index != NULL) {
GIT_REFCOUNT_OWN(index, NULL);
git_index_free(index);
@@ -3044,8 +3044,8 @@ int git_repository_set_ident(git_repository *repo, const char *name, const char
GIT_ERROR_CHECK_ALLOC(tmp_email);
}
- tmp_name = git__swap(repo->ident_name, tmp_name);
- tmp_email = git__swap(repo->ident_email, tmp_email);
+ tmp_name = git_atomic_swap(repo->ident_name, tmp_name);
+ tmp_email = git_atomic_swap(repo->ident_email, tmp_email);
git__free(tmp_name);
git__free(tmp_email);
diff --git a/src/repository.h b/src/repository.h
index de009ba5e..4b1222e3a 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -152,7 +152,7 @@ struct git_repository {
unsigned int lru_counter;
- git_atomic attr_session_key;
+ git_atomic32 attr_session_key;
git_configmap_value configmap_cache[GIT_CONFIGMAP_CACHE_MAX];
git_strmap *submodule_cache;
diff --git a/src/runtime.c b/src/runtime.c
index a214b435e..b61c3c4ba 100644
--- a/src/runtime.c
+++ b/src/runtime.c
@@ -9,9 +9,9 @@
#include "runtime.h"
static git_runtime_shutdown_fn shutdown_callback[32];
-static git_atomic shutdown_callback_count;
+static git_atomic32 shutdown_callback_count;
-static git_atomic init_count;
+static git_atomic32 init_count;
static int init_common(git_runtime_init_fn init_fns[], size_t cnt)
{
@@ -34,10 +34,10 @@ static void shutdown_common(void)
git_runtime_shutdown_fn cb;
int pos;
- for (pos = git_atomic_get(&shutdown_callback_count);
+ for (pos = git_atomic32_get(&shutdown_callback_count);
pos > 0;
- pos = git_atomic_dec(&shutdown_callback_count)) {
- cb = git__swap(shutdown_callback[pos - 1], NULL);
+ pos = git_atomic32_dec(&shutdown_callback_count)) {
+ cb = git_atomic_swap(shutdown_callback[pos - 1], NULL);
if (cb != NULL)
cb();
@@ -46,12 +46,12 @@ static void shutdown_common(void)
int git_runtime_shutdown_register(git_runtime_shutdown_fn callback)
{
- int count = git_atomic_inc(&shutdown_callback_count);
+ int count = git_atomic32_inc(&shutdown_callback_count);
if (count > (int)ARRAY_SIZE(shutdown_callback) || count == 0) {
git_error_set(GIT_ERROR_INVALID,
"too many shutdown callbacks registered");
- git_atomic_dec(&shutdown_callback_count);
+ git_atomic32_dec(&shutdown_callback_count);
return -1;
}
@@ -116,7 +116,7 @@ int git_runtime_init(git_runtime_init_fn init_fns[], size_t cnt)
return -1;
/* Only do work on a 0 -> 1 transition of the refcount */
- if ((ret = git_atomic_inc(&init_count)) == 1) {
+ if ((ret = git_atomic32_inc(&init_count)) == 1) {
if (init_common(init_fns, cnt) < 0)
ret = -1;
}
@@ -136,7 +136,7 @@ int git_runtime_shutdown(void)
return -1;
/* Only do work on a 1 -> 0 transition of the refcount */
- if ((ret = git_atomic_dec(&init_count)) == 0)
+ if ((ret = git_atomic32_dec(&init_count)) == 0)
shutdown_common();
/* Exit the lock */
diff --git a/src/sortedcache.h b/src/sortedcache.h
index e553d01dd..ca8b10674 100644
--- a/src/sortedcache.h
+++ b/src/sortedcache.h
@@ -12,7 +12,7 @@
#include "util.h"
#include "futils.h"
#include "vector.h"
-#include "thread-utils.h"
+#include "thread.h"
#include "pool.h"
#include "strmap.h"
diff --git a/src/thread-utils.c b/src/thread-utils.c
deleted file mode 100644
index e5ec6a843..000000000
--- a/src/thread-utils.c
+++ /dev/null
@@ -1,58 +0,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.
- */
-
-#include "common.h"
-#include "thread-utils.h"
-
-#ifdef _WIN32
-#ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-#endif
-# include <windows.h>
-#elif defined(hpux) || defined(__hpux) || defined(_hpux)
-# include <sys/pstat.h>
-#endif
-
-/*
- * By doing this in two steps we can at least get
- * the function to be somewhat coherent, even
- * with this disgusting nest of #ifdefs.
- */
-#ifndef _SC_NPROCESSORS_ONLN
-# ifdef _SC_NPROC_ONLN
-# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
-# elif defined _SC_CRAY_NCPU
-# define _SC_NPROCESSORS_ONLN _SC_CRAY_NCPU
-# endif
-#endif
-
-int git_online_cpus(void)
-{
-#ifdef _SC_NPROCESSORS_ONLN
- long ncpus;
-#endif
-
-#ifdef _WIN32
- SYSTEM_INFO info;
- GetSystemInfo(&info);
-
- if ((int)info.dwNumberOfProcessors > 0)
- return (int)info.dwNumberOfProcessors;
-#elif defined(hpux) || defined(__hpux) || defined(_hpux)
- struct pst_dynamic psd;
-
- if (!pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0))
- return (int)psd.psd_proc_cnt;
-#endif
-
-#ifdef _SC_NPROCESSORS_ONLN
- if ((ncpus = (long)sysconf(_SC_NPROCESSORS_ONLN)) > 0)
- return (int)ncpus;
-#endif
-
- return 1;
-}
diff --git a/src/thread.c b/src/thread.c
new file mode 100644
index 000000000..3171771d7
--- /dev/null
+++ b/src/thread.c
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+#include "common.h"
+
+#if !defined(GIT_THREADS)
+
+#define TLSDATA_MAX 16
+
+typedef struct {
+ void *value;
+ void (GIT_SYSTEM_CALL *destroy_fn)(void *);
+} tlsdata_value;
+
+static tlsdata_value tlsdata_values[TLSDATA_MAX];
+static int tlsdata_cnt = 0;
+
+int git_tlsdata_init(git_tlsdata_key *key, void (GIT_SYSTEM_CALL *destroy_fn)(void *))
+{
+ if (tlsdata_cnt >= TLSDATA_MAX)
+ return -1;
+
+ tlsdata_values[tlsdata_cnt].value = NULL;
+ tlsdata_values[tlsdata_cnt].destroy_fn = destroy_fn;
+
+ *key = tlsdata_cnt;
+ tlsdata_cnt++;
+
+ return 0;
+}
+
+int git_tlsdata_set(git_tlsdata_key key, void *value)
+{
+ if (key < 0 || key > tlsdata_cnt)
+ return -1;
+
+ tlsdata_values[key].value = value;
+ return 0;
+}
+
+void *git_tlsdata_get(git_tlsdata_key key)
+{
+ if (key < 0 || key > tlsdata_cnt)
+ return NULL;
+
+ return tlsdata_values[key].value;
+}
+
+int git_tlsdata_dispose(git_tlsdata_key key)
+{
+ void *value;
+ void (*destroy_fn)(void *) = NULL;
+
+ if (key < 0 || key > tlsdata_cnt)
+ return -1;
+
+ value = tlsdata_values[key].value;
+ destroy_fn = tlsdata_values[key].destroy_fn;
+
+ tlsdata_values[key].value = NULL;
+ tlsdata_values[key].destroy_fn = NULL;
+
+ if (value && destroy_fn)
+ destroy_fn(value);
+
+ return 0;
+}
+
+#elif defined(GIT_WIN32)
+
+int git_tlsdata_init(git_tlsdata_key *key, void (GIT_SYSTEM_CALL *destroy_fn)(void *))
+{
+ DWORD fls_index = FlsAlloc(destroy_fn);
+
+ if (fls_index == FLS_OUT_OF_INDEXES)
+ return -1;
+
+ *key = fls_index;
+ return 0;
+}
+
+int git_tlsdata_set(git_tlsdata_key key, void *value)
+{
+ if (!FlsSetValue(key, value))
+ return -1;
+
+ return 0;
+}
+
+void *git_tlsdata_get(git_tlsdata_key key)
+{
+ return FlsGetValue(key);
+}
+
+int git_tlsdata_dispose(git_tlsdata_key key)
+{
+ if (!FlsFree(key))
+ return -1;
+
+ return 0;
+}
+
+#elif defined(_POSIX_THREADS)
+
+int git_tlsdata_init(git_tlsdata_key *key, void (GIT_SYSTEM_CALL *destroy_fn)(void *))
+{
+ if (pthread_key_create(key, destroy_fn) != 0)
+ return -1;
+
+ return 0;
+}
+
+int git_tlsdata_set(git_tlsdata_key key, void *value)
+{
+ if (pthread_setspecific(key, value) != 0)
+ return -1;
+
+ return 0;
+}
+
+void *git_tlsdata_get(git_tlsdata_key key)
+{
+ return pthread_getspecific(key);
+}
+
+int git_tlsdata_dispose(git_tlsdata_key key)
+{
+ if (pthread_key_delete(key) != 0)
+ return -1;
+
+ return 0;
+}
+
+#else
+# error unknown threading model
+#endif
diff --git a/src/thread-utils.h b/src/thread.h
index d71fabe10..b4f869243 100644
--- a/src/thread-utils.h
+++ b/src/thread.h
@@ -4,8 +4,8 @@
* 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_thread_utils_h__
-#define INCLUDE_thread_utils_h__
+#ifndef INCLUDE_thread_h__
+#define INCLUDE_thread_h__
#if defined(GIT_THREADS)
@@ -38,7 +38,7 @@ typedef struct {
#else
volatile int val;
#endif
-} git_atomic;
+} git_atomic32;
#ifdef GIT_ARCH_64
@@ -58,11 +58,11 @@ typedef git_atomic64 git_atomic_ssize;
#else
-typedef git_atomic git_atomic_ssize;
+typedef git_atomic32 git_atomic_ssize;
-#define git_atomic_ssize_set git_atomic_set
-#define git_atomic_ssize_add git_atomic_add
-#define git_atomic_ssize_get git_atomic_get
+#define git_atomic_ssize_set git_atomic32_set
+#define git_atomic_ssize_add git_atomic32_add
+#define git_atomic_ssize_get git_atomic32_get
#endif
@@ -74,7 +74,7 @@ typedef git_atomic git_atomic_ssize;
# include "unix/pthread.h"
#endif
-GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
+GIT_INLINE(void) git_atomic32_set(git_atomic32 *a, int val)
{
#if defined(GIT_WIN32)
InterlockedExchange(&a->val, (LONG)val);
@@ -87,7 +87,7 @@ GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
#endif
}
-GIT_INLINE(int) git_atomic_inc(git_atomic *a)
+GIT_INLINE(int) git_atomic32_inc(git_atomic32 *a)
{
#if defined(GIT_WIN32)
return InterlockedIncrement(&a->val);
@@ -100,7 +100,7 @@ GIT_INLINE(int) git_atomic_inc(git_atomic *a)
#endif
}
-GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend)
+GIT_INLINE(int) git_atomic32_add(git_atomic32 *a, int32_t addend)
{
#if defined(GIT_WIN32)
return InterlockedExchangeAdd(&a->val, addend);
@@ -113,7 +113,7 @@ GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend)
#endif
}
-GIT_INLINE(int) git_atomic_dec(git_atomic *a)
+GIT_INLINE(int) git_atomic32_dec(git_atomic32 *a)
{
#if defined(GIT_WIN32)
return InterlockedDecrement(&a->val);
@@ -126,7 +126,7 @@ GIT_INLINE(int) git_atomic_dec(git_atomic *a)
#endif
}
-GIT_INLINE(int) git_atomic_get(git_atomic *a)
+GIT_INLINE(int) git_atomic32_get(git_atomic32 *a)
{
#if defined(GIT_WIN32)
return (int)InterlockedCompareExchange(&a->val, 0, 0);
@@ -139,7 +139,7 @@ GIT_INLINE(int) git_atomic_get(git_atomic *a)
#endif
}
-GIT_INLINE(void *) git___compare_and_swap(
+GIT_INLINE(void *) git_atomic__compare_and_swap(
void * volatile *ptr, void *oldval, void *newval)
{
#if defined(GIT_WIN32)
@@ -158,7 +158,7 @@ GIT_INLINE(void *) git___compare_and_swap(
#endif
}
-GIT_INLINE(volatile void *) git___swap(
+GIT_INLINE(volatile void *) git_atomic__swap(
void * volatile *ptr, void *newval)
{
#if defined(GIT_WIN32)
@@ -174,7 +174,7 @@ GIT_INLINE(volatile void *) git___swap(
#endif
}
-GIT_INLINE(volatile void *) git___load(void * volatile *ptr)
+GIT_INLINE(volatile void *) git_atomic__load(void * volatile *ptr)
{
#if defined(GIT_WIN32)
void *newval = NULL, *oldval = NULL;
@@ -268,33 +268,33 @@ GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a)
#define GIT_RWLOCK_STATIC_INIT 0
-GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
+GIT_INLINE(void) git_atomic32_set(git_atomic32 *a, int val)
{
a->val = val;
}
-GIT_INLINE(int) git_atomic_inc(git_atomic *a)
+GIT_INLINE(int) git_atomic32_inc(git_atomic32 *a)
{
return ++a->val;
}
-GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend)
+GIT_INLINE(int) git_atomic32_add(git_atomic32 *a, int32_t addend)
{
a->val += addend;
return a->val;
}
-GIT_INLINE(int) git_atomic_dec(git_atomic *a)
+GIT_INLINE(int) git_atomic32_dec(git_atomic32 *a)
{
return --a->val;
}
-GIT_INLINE(int) git_atomic_get(git_atomic *a)
+GIT_INLINE(int) git_atomic32_get(git_atomic32 *a)
{
return (int)a->val;
}
-GIT_INLINE(void *) git___compare_and_swap(
+GIT_INLINE(void *) git_atomic__compare_and_swap(
void * volatile *ptr, void *oldval, void *newval)
{
if (*ptr == oldval)
@@ -304,7 +304,7 @@ GIT_INLINE(void *) git___compare_and_swap(
return oldval;
}
-GIT_INLINE(volatile void *) git___swap(
+GIT_INLINE(volatile void *) git_atomic__swap(
void * volatile *ptr, void *newval)
{
volatile void *old = *ptr;
@@ -312,7 +312,7 @@ GIT_INLINE(volatile void *) git___swap(
return old;
}
-GIT_INLINE(volatile void *) git___load(void * volatile *ptr)
+GIT_INLINE(volatile void *) git_atomic__load(void * volatile *ptr)
{
return *ptr;
}
@@ -342,14 +342,14 @@ GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a)
/* Atomically replace oldval with newval
* @return oldval if it was replaced or newval if it was not
*/
-#define git__compare_and_swap(P,O,N) \
- git___compare_and_swap((void * volatile *)P, O, N)
+#define git_atomic_compare_and_swap(P,O,N) \
+ git_atomic__compare_and_swap((void * volatile *)P, O, N)
-#define git__swap(ptr, val) (void *)git___swap((void * volatile *)&ptr, val)
+#define git_atomic_swap(ptr, val) \
+ (void *)git_atomic__swap((void * volatile *)&ptr, val)
-#define git__load(ptr) (void *)git___load((void * volatile *)&ptr)
-
-extern int git_online_cpus(void);
+#define git_atomic_load(ptr) \
+ (void *)git_atomic__load((void * volatile *)&ptr)
#if defined(GIT_THREADS)
@@ -367,4 +367,56 @@ extern int git_online_cpus(void);
#endif
+/* Thread-local data */
+
+#if !defined(GIT_THREADS)
+# define git_tlsdata_key int
+#elif defined(GIT_WIN32)
+# define git_tlsdata_key DWORD
+#elif defined(_POSIX_THREADS)
+# define git_tlsdata_key pthread_key_t
+#else
+# error unknown threading model
+#endif
+
+/**
+ * Create a thread-local data key. The destroy function will be
+ * called upon thread exit. On some platforms, it may be called
+ * when all threads have deleted their keys.
+ *
+ * Note that the tlsdata functions do not set an error message on
+ * failure; this is because the error handling in libgit2 is itself
+ * handled by thread-local data storage.
+ *
+ * @param key the tlsdata key
+ * @param destroy_fn function pointer called upon thread exit
+ * @return 0 on success, non-zero on failure
+ */
+int git_tlsdata_init(git_tlsdata_key *key, void (GIT_SYSTEM_CALL *destroy_fn)(void *));
+
+/**
+ * Set a the thread-local value for the given key.
+ *
+ * @param key the tlsdata key to store data on
+ * @param value the pointer to store
+ * @return 0 on success, non-zero on failure
+ */
+int git_tlsdata_set(git_tlsdata_key key, void *value);
+
+/**
+ * Get the thread-local value for the given key.
+ *
+ * @param key the tlsdata key to retrieve the value of
+ * @return the pointer stored with git_tlsdata_set
+ */
+void *git_tlsdata_get(git_tlsdata_key key);
+
+/**
+ * Delete the given thread-local key.
+ *
+ * @param key the tlsdata key to dispose
+ * @return 0 on success, non-zero on failure
+ */
+int git_tlsdata_dispose(git_tlsdata_key key);
+
#endif
diff --git a/src/threadstate.c b/src/threadstate.c
index 1c5ac6091..6031e8280 100644
--- a/src/threadstate.c
+++ b/src/threadstate.c
@@ -8,8 +8,6 @@
#include "threadstate.h"
#include "runtime.h"
-static void threadstate_dispose(git_threadstate *threadstate);
-
/**
* Handle the thread-local state
*
@@ -17,8 +15,7 @@ static void threadstate_dispose(git_threadstate *threadstate);
* of `git_libgit2_init` (which itself must be called
* before calling any other function in the library).
*
- * This function allocates a TLS index (using pthreads
- * or fiber-local storage in Win32) to store the per-
+ * This function allocates a TLS index to store the per-
* thread state.
*
* Any internal method that requires thread-local state
@@ -30,77 +27,41 @@ static void threadstate_dispose(git_threadstate *threadstate);
* (`git_threadstate_global_shutdown`) which will free the
* TLS index. This shutdown handler will be called by
* `git_libgit2_shutdown`.
- *
- * If libgit2 is built without threading support, the
- * `git_threadstate_get()` call returns a pointer to a single,
- * statically allocated global state. The `git_thread_`
- * functions are not available in that case.
*/
-#if defined(GIT_THREADS) && defined(GIT_WIN32)
+static git_tlsdata_key tls_key;
-static DWORD fls_index;
-
-static void git_threadstate_global_shutdown(void)
+static void threadstate_dispose(git_threadstate *threadstate)
{
- FlsFree(fls_index);
+ if (!threadstate)
+ return;
+
+ git__free(threadstate->error_t.message);
+ threadstate->error_t.message = NULL;
}
-static void WINAPI fls_free(void *threadstate)
+static void GIT_SYSTEM_CALL threadstate_free(void *threadstate)
{
threadstate_dispose(threadstate);
git__free(threadstate);
}
-int git_threadstate_global_init(void)
-{
- if ((fls_index = FlsAlloc(fls_free)) == FLS_OUT_OF_INDEXES)
- return -1;
-
- return git_runtime_shutdown_register(git_threadstate_global_shutdown);
-}
-
-git_threadstate *git_threadstate_get(void)
-{
- git_threadstate *threadstate;
-
- if ((threadstate = FlsGetValue(fls_index)) != NULL)
- return threadstate;
-
- if ((threadstate = git__calloc(1, sizeof(git_threadstate))) == NULL ||
- git_buf_init(&threadstate->error_buf, 0) < 0)
- return NULL;
-
- FlsSetValue(fls_index, threadstate);
- return threadstate;
-}
-
-#elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
-
-static pthread_key_t tls_key;
-
static void git_threadstate_global_shutdown(void)
{
git_threadstate *threadstate;
- threadstate = pthread_getspecific(tls_key);
- pthread_setspecific(tls_key, NULL);
+ threadstate = git_tlsdata_get(tls_key);
+ git_tlsdata_set(tls_key, NULL);
threadstate_dispose(threadstate);
git__free(threadstate);
- pthread_key_delete(tls_key);
-}
-
-static void tls_free(void *threadstate)
-{
- threadstate_dispose(threadstate);
- git__free(threadstate);
+ git_tlsdata_dispose(tls_key);
}
int git_threadstate_global_init(void)
{
- if (pthread_key_create(&tls_key, &tls_free) != 0)
+ if (git_tlsdata_init(&tls_key, &threadstate_free) != 0)
return -1;
return git_runtime_shutdown_register(git_threadstate_global_shutdown);
@@ -110,46 +71,13 @@ git_threadstate *git_threadstate_get(void)
{
git_threadstate *threadstate;
- if ((threadstate = pthread_getspecific(tls_key)) != NULL)
+ if ((threadstate = git_tlsdata_get(tls_key)) != NULL)
return threadstate;
if ((threadstate = git__calloc(1, sizeof(git_threadstate))) == NULL ||
git_buf_init(&threadstate->error_buf, 0) < 0)
return NULL;
- pthread_setspecific(tls_key, threadstate);
+ git_tlsdata_set(tls_key, threadstate);
return threadstate;
}
-
-#elif defined(GIT_THREADS)
-# error unknown threading model
-#else
-
-static git_threadstate threadstate;
-
-static void git_threadstate_global_shutdown(void)
-{
- threadstate_dispose(&threadstate);
- memset(&threadstate, 0, sizeof(git_threadstate));
-}
-
-int git_threadstate_global_init(void)
-{
- return git_runtime_shutdown_register(git_threadstate_global_shutdown);
-}
-
-git_threadstate *git_threadstate_get(void)
-{
- return &threadstate;
-}
-
-#endif
-
-static void threadstate_dispose(git_threadstate *threadstate)
-{
- if (!threadstate)
- return;
-
- git__free(threadstate->error_t.message);
- threadstate->error_t.message = NULL;
-}
diff --git a/src/transports/local.c b/src/transports/local.c
index 4af85db81..bb31b1345 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -36,7 +36,7 @@ typedef struct {
char *url;
int direction;
int flags;
- git_atomic cancelled;
+ git_atomic32 cancelled;
git_repository *repo;
git_transport_message_cb progress_cb;
git_transport_message_cb error_cb;
@@ -671,7 +671,7 @@ static void local_cancel(git_transport *transport)
{
transport_local *t = (transport_local *)transport;
- git_atomic_set(&t->cancelled, 1);
+ git_atomic32_set(&t->cancelled, 1);
}
static int local_close(git_transport *transport)
diff --git a/src/transports/smart.c b/src/transports/smart.c
index 3b8a14a4c..da8fe8e22 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -30,7 +30,7 @@ static int git_smart__recv_cb(gitno_buffer *buf)
if (t->packetsize_cb && !t->cancelled.val) {
error = t->packetsize_cb(bytes_read, t->packetsize_payload);
if (error) {
- git_atomic_set(&t->cancelled, 1);
+ git_atomic32_set(&t->cancelled, 1);
return GIT_EUSER;
}
}
@@ -389,7 +389,7 @@ static void git_smart__cancel(git_transport *transport)
{
transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
- git_atomic_set(&t->cancelled, 1);
+ git_atomic32_set(&t->cancelled, 1);
}
static int git_smart__is_connected(git_transport *transport)
diff --git a/src/transports/smart.h b/src/transports/smart.h
index 18e0b7e9f..a05d4c9e3 100644
--- a/src/transports/smart.h
+++ b/src/transports/smart.h
@@ -153,7 +153,7 @@ typedef struct {
git_vector refs;
git_vector heads;
git_vector common;
- git_atomic cancelled;
+ git_atomic32 cancelled;
packetsize_cb packetsize_cb;
void *packetsize_payload;
unsigned rpc : 1,
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index 18dcaa879..9482915d8 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -535,7 +535,7 @@ int git_smart__download_pack(
/* We might have something in the buffer already from negotiate_fetch */
if (t->buffer.offset > 0 && !t->cancelled.val)
if (t->packetsize_cb(t->buffer.offset, t->packetsize_payload))
- git_atomic_set(&t->cancelled, 1);
+ git_atomic32_set(&t->cancelled, 1);
}
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 ||
diff --git a/src/util.c b/src/util.c
index 2efb212bc..87ccf32af 100644
--- a/src/util.c
+++ b/src/util.c
@@ -13,6 +13,11 @@
# include "win32/utf-conv.h"
# include "win32/w32_buffer.h"
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+
# ifdef HAVE_QSORT_S
# include <search.h>
# endif
@@ -22,6 +27,10 @@
# include <Shlwapi.h>
#endif
+#if defined(hpux) || defined(__hpux) || defined(_hpux)
+# include <sys/pstat.h>
+#endif
+
int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
{
const char *p;
@@ -678,7 +687,7 @@ typedef struct {
void *payload;
} git__qsort_r_glue;
-static int GIT_STDLIB_CALL git__qsort_r_glue_cmp(
+static int GIT_LIBGIT2_CALL git__qsort_r_glue_cmp(
void *payload, const void *a, const void *b)
{
git__qsort_r_glue *glue = payload;
@@ -893,3 +902,43 @@ int git__getenv(git_buf *out, const char *name)
return git_buf_puts(out, val);
}
#endif
+
+/*
+ * By doing this in two steps we can at least get
+ * the function to be somewhat coherent, even
+ * with this disgusting nest of #ifdefs.
+ */
+#ifndef _SC_NPROCESSORS_ONLN
+# ifdef _SC_NPROC_ONLN
+# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
+# elif defined _SC_CRAY_NCPU
+# define _SC_NPROCESSORS_ONLN _SC_CRAY_NCPU
+# endif
+#endif
+
+int git__online_cpus(void)
+{
+#ifdef _SC_NPROCESSORS_ONLN
+ long ncpus;
+#endif
+
+#ifdef _WIN32
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+
+ if ((int)info.dwNumberOfProcessors > 0)
+ return (int)info.dwNumberOfProcessors;
+#elif defined(hpux) || defined(__hpux) || defined(_hpux)
+ struct pst_dynamic psd;
+
+ if (!pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0))
+ return (int)psd.psd_proc_cnt;
+#endif
+
+#ifdef _SC_NPROCESSORS_ONLN
+ if ((ncpus = (long)sysconf(_SC_NPROCESSORS_ONLN)) > 0)
+ return (int)ncpus;
+#endif
+
+ return 1;
+}
diff --git a/src/util.h b/src/util.h
index 185a1b129..5076df282 100644
--- a/src/util.h
+++ b/src/util.h
@@ -18,7 +18,7 @@
#include "buffer.h"
#include "common.h"
#include "strnlen.h"
-#include "thread-utils.h"
+#include "thread.h"
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#define bitsizeof(x) (CHAR_BIT * sizeof(x))
@@ -169,29 +169,29 @@ extern int git__strncasecmp(const char *a, const char *b, size_t sz);
extern int git__strcasesort_cmp(const char *a, const char *b);
typedef struct {
- git_atomic refcount;
+ git_atomic32 refcount;
void *owner;
} git_refcount;
typedef void (*git_refcount_freeptr)(void *r);
#define GIT_REFCOUNT_INC(r) { \
- git_atomic_inc(&(r)->rc.refcount); \
+ git_atomic32_inc(&(r)->rc.refcount); \
}
#define GIT_REFCOUNT_DEC(_r, do_free) { \
git_refcount *r = &(_r)->rc; \
- int val = git_atomic_dec(&r->refcount); \
+ int val = git_atomic32_dec(&r->refcount); \
if (val <= 0 && r->owner == NULL) { do_free(_r); } \
}
#define GIT_REFCOUNT_OWN(r, o) { \
- (void)git__swap((r)->rc.owner, o); \
+ (void)git_atomic_swap((r)->rc.owner, o); \
}
-#define GIT_REFCOUNT_OWNER(r) git__load((r)->rc.owner)
+#define GIT_REFCOUNT_OWNER(r) git_atomic_load((r)->rc.owner)
-#define GIT_REFCOUNT_VAL(r) git_atomic_get((r)->rc.refcount)
+#define GIT_REFCOUNT_VAL(r) git_atomic32_get((r)->rc.refcount)
static signed char from_hex[] = {
@@ -414,6 +414,8 @@ GIT_INLINE(double) git__timer(void)
extern int git__getenv(git_buf *out, const char *name);
+extern int git__online_cpus(void);
+
GIT_INLINE(int) git__noop(void) { return 0; }
#include "alloc.h"
diff --git a/src/win32/msvc-compat.h b/src/win32/msvc-compat.h
index 4cf471f1d..03f9f36dc 100644
--- a/src/win32/msvc-compat.h
+++ b/src/win32/msvc-compat.h
@@ -23,6 +23,14 @@ typedef SSIZE_T ssize_t;
#endif
-#define GIT_STDLIB_CALL __cdecl
+/*
+ * Offer GIT_LIBGIT2_CALL for our calling conventions (__cdecl, always).
+ * This is useful for providing callbacks to userspace code.
+ *
+ * Offer GIT_SYSTEM_CALL for the system calling conventions (__stdcall on
+ * Win32). Useful for providing callbacks to system libraries.
+ */
+#define GIT_LIBGIT2_CALL __cdecl
+#define GIT_SYSTEM_CALL NTAPI
#endif
diff --git a/tests/threads/diff.c b/tests/threads/diff.c
index 699642790..04c8cb97f 100644
--- a/tests/threads/diff.c
+++ b/tests/threads/diff.c
@@ -17,7 +17,7 @@
static git_repository *_repo;
static git_tree *_a, *_b;
-static git_atomic _counts[4];
+static git_atomic32 _counts[4];
static int _check_counts;
#ifdef GIT_WIN32
static int _retries;
@@ -66,10 +66,10 @@ static void free_trees(void)
git_tree_free(_b); _b = NULL;
if (_check_counts) {
- cl_assert_equal_i(288, git_atomic_get(&_counts[0]));
- cl_assert_equal_i(112, git_atomic_get(&_counts[1]));
- cl_assert_equal_i( 80, git_atomic_get(&_counts[2]));
- cl_assert_equal_i( 96, git_atomic_get(&_counts[3]));
+ cl_assert_equal_i(288, git_atomic32_get(&_counts[0]));
+ cl_assert_equal_i(112, git_atomic32_get(&_counts[1]));
+ cl_assert_equal_i( 80, git_atomic32_get(&_counts[2]));
+ cl_assert_equal_i( 96, git_atomic32_get(&_counts[3]));
}
}
@@ -107,14 +107,14 @@ static void *run_index_diffs(void *arg)
/* keep some diff stats to make sure results are as expected */
i = git_diff_num_deltas(diff);
- git_atomic_add(&_counts[0], (int32_t)i);
+ git_atomic32_add(&_counts[0], (int32_t)i);
exp[0] = (int)i;
while (i > 0) {
switch (git_diff_get_delta(diff, --i)->status) {
- case GIT_DELTA_MODIFIED: exp[1]++; git_atomic_inc(&_counts[1]); break;
- case GIT_DELTA_ADDED: exp[2]++; git_atomic_inc(&_counts[2]); break;
- case GIT_DELTA_DELETED: exp[3]++; git_atomic_inc(&_counts[3]); break;
+ case GIT_DELTA_MODIFIED: exp[1]++; git_atomic32_inc(&_counts[1]); break;
+ case GIT_DELTA_ADDED: exp[2]++; git_atomic32_inc(&_counts[2]); break;
+ case GIT_DELTA_DELETED: exp[3]++; git_atomic32_inc(&_counts[3]); break;
default: break;
}
}
diff --git a/tests/threads/thread_helpers.h b/tests/threads/thread_helpers.h
index 3c13cfb6b..0f23a4ce0 100644
--- a/tests/threads/thread_helpers.h
+++ b/tests/threads/thread_helpers.h
@@ -1,4 +1,4 @@
-#include "thread-utils.h"
+#include "thread.h"
void run_in_parallel(
int repeats,
diff --git a/tests/threads/tlsdata.c b/tests/threads/tlsdata.c
new file mode 100644
index 000000000..7c69b4444
--- /dev/null
+++ b/tests/threads/tlsdata.c
@@ -0,0 +1,65 @@
+#include "clar_libgit2.h"
+
+#include "thread_helpers.h"
+
+void test_threads_tlsdata__can_set_and_get(void)
+{
+ git_tlsdata_key key_one, key_two, key_three;
+
+ cl_git_pass(git_tlsdata_init(&key_one, NULL));
+ cl_git_pass(git_tlsdata_init(&key_two, NULL));
+ cl_git_pass(git_tlsdata_init(&key_three, NULL));
+
+ cl_git_pass(git_tlsdata_set(key_one, (void *)(size_t)42424242));
+ cl_git_pass(git_tlsdata_set(key_two, (void *)(size_t)0xdeadbeef));
+ cl_git_pass(git_tlsdata_set(key_three, (void *)(size_t)98761234));
+
+ cl_assert_equal_sz((size_t)42424242, git_tlsdata_get(key_one));
+ cl_assert_equal_sz((size_t)0xdeadbeef, git_tlsdata_get(key_two));
+ cl_assert_equal_sz((size_t)98761234, git_tlsdata_get(key_three));
+
+ cl_git_pass(git_tlsdata_dispose(key_one));
+ cl_git_pass(git_tlsdata_dispose(key_two));
+ cl_git_pass(git_tlsdata_dispose(key_three));
+}
+
+#ifdef GIT_THREADS
+
+static void *set_and_get(void *param)
+{
+ git_tlsdata_key *tlsdata_key = (git_tlsdata_key *)param;
+ int val;
+
+ if (git_tlsdata_set(*tlsdata_key, &val) != 0 ||
+ git_tlsdata_get(*tlsdata_key) != &val)
+ return (void *)0;
+
+ return (void *)1;
+}
+
+#endif
+
+#define THREAD_COUNT 10
+
+void test_threads_tlsdata__threads(void)
+{
+#ifdef GIT_THREADS
+ git_thread thread[THREAD_COUNT];
+ git_tlsdata_key tlsdata;
+ int i;
+
+ cl_git_pass(git_tlsdata_init(&tlsdata, NULL));
+
+ for (i = 0; i < THREAD_COUNT; i++)
+ cl_git_pass(git_thread_create(&thread[i], set_and_get, &tlsdata));
+
+ for (i = 0; i < THREAD_COUNT; i++) {
+ void *result;
+
+ cl_git_pass(git_thread_join(&thread[i], &result));
+ cl_assert_equal_sz(1, (size_t)result);
+ }
+
+ cl_git_pass(git_tlsdata_dispose(tlsdata));
+#endif
+}