diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2020-12-09 13:25:23 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-09 13:25:23 +0000 |
commit | a5cb2cc9f547d9defaf51b2af25ba2fa9d9015a0 (patch) | |
tree | 99c9a2b17ced475c01ef209e4636d03777bcbcd3 | |
parent | 1adb84107f406a00178296257289663860d277ae (diff) | |
parent | 20ce17f06d27a92ada11fa5d15108532223e9884 (diff) | |
download | libgit2-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.c | 2 | ||||
-rw-r--r-- | src/attrcache.c | 10 | ||||
-rw-r--r-- | src/cache.c | 4 | ||||
-rw-r--r-- | src/cache.h | 14 | ||||
-rw-r--r-- | src/common.h | 6 | ||||
-rw-r--r-- | src/config_cache.c | 4 | ||||
-rw-r--r-- | src/diff_driver.c | 2 | ||||
-rw-r--r-- | src/index.c | 18 | ||||
-rw-r--r-- | src/index.h | 2 | ||||
-rw-r--r-- | src/libgit2.c | 2 | ||||
-rw-r--r-- | src/mwindow.c | 6 | ||||
-rw-r--r-- | src/pack-objects.c | 4 | ||||
-rw-r--r-- | src/pack.c | 12 | ||||
-rw-r--r-- | src/pack.h | 4 | ||||
-rw-r--r-- | src/repository.c | 24 | ||||
-rw-r--r-- | src/repository.h | 2 | ||||
-rw-r--r-- | src/runtime.c | 18 | ||||
-rw-r--r-- | src/sortedcache.h | 2 | ||||
-rw-r--r-- | src/thread-utils.c | 58 | ||||
-rw-r--r-- | src/thread.c | 140 | ||||
-rw-r--r-- | src/thread.h (renamed from src/thread-utils.h) | 110 | ||||
-rw-r--r-- | src/threadstate.c | 102 | ||||
-rw-r--r-- | src/transports/local.c | 4 | ||||
-rw-r--r-- | src/transports/smart.c | 4 | ||||
-rw-r--r-- | src/transports/smart.h | 2 | ||||
-rw-r--r-- | src/transports/smart_protocol.c | 2 | ||||
-rw-r--r-- | src/util.c | 51 | ||||
-rw-r--r-- | src/util.h | 16 | ||||
-rw-r--r-- | src/win32/msvc-compat.h | 10 | ||||
-rw-r--r-- | tests/threads/diff.c | 18 | ||||
-rw-r--r-- | tests/threads/thread_helpers.h | 2 | ||||
-rw-r--r-- | tests/threads/tlsdata.c | 65 |
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 +} |