Unverified Commit a5cb2cc9 by Edward Thomson Committed by GitHub

Merge pull request #5720 from libgit2/ethomson/tlsdata

Thread-local storage: a generic internal library (with no allocations)
parents 1adb8410 20ce17f0
...@@ -960,7 +960,7 @@ int git_attr_session__init(git_attr_session *session, git_repository *repo) ...@@ -960,7 +960,7 @@ int git_attr_session__init(git_attr_session *session, git_repository *repo)
GIT_ASSERT_ARG(repo); GIT_ASSERT_ARG(repo);
memset(session, 0, sizeof(*session)); 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; return 0;
} }
......
...@@ -108,7 +108,7 @@ static int attr_cache_upsert(git_attr_cache *cache, git_attr_file *file) ...@@ -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 * Replace the existing value if another thread has
* created it in the meantime. * created it in the meantime.
*/ */
old = git__swap(entry->file[file->source], file); old = git_atomic_swap(entry->file[file->source], file);
if (old) { if (old) {
GIT_REFCOUNT_OWN(old, NULL); GIT_REFCOUNT_OWN(old, NULL);
...@@ -132,7 +132,7 @@ static int attr_cache_remove(git_attr_cache *cache, git_attr_file *file) ...@@ -132,7 +132,7 @@ static int attr_cache_remove(git_attr_cache *cache, git_attr_file *file)
return error; return error;
if ((entry = attr_cache_lookup_entry(cache, file->entry->path)) != NULL) 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); attr_cache_unlock(cache);
...@@ -321,7 +321,7 @@ static void attr_cache__free(git_attr_cache *cache) ...@@ -321,7 +321,7 @@ static void attr_cache__free(git_attr_cache *cache)
git_strmap_foreach_value(cache->files, entry, { git_strmap_foreach_value(cache->files, entry, {
for (i = 0; i < GIT_ATTR_FILE_NUM_SOURCES; ++i) { 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_REFCOUNT_OWN(file, NULL);
git_attr_file__free(file); git_attr_file__free(file);
} }
...@@ -395,7 +395,7 @@ int git_attr_cache__init(git_repository *repo) ...@@ -395,7 +395,7 @@ int git_attr_cache__init(git_repository *repo)
(ret = git_pool_init(&cache->pool, 1)) < 0) (ret = git_pool_init(&cache->pool, 1)) < 0)
goto cancel; goto cancel;
cache = git__compare_and_swap(&repo->attrcache, NULL, cache); cache = git_atomic_compare_and_swap(&repo->attrcache, NULL, cache);
if (cache) if (cache)
goto cancel; /* raced with another thread, free this but no error */ goto cancel; /* raced with another thread, free this but no error */
...@@ -417,7 +417,7 @@ int git_attr_cache_flush(git_repository *repo) ...@@ -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 /* this could be done less expensively, but for now, we'll just free
* the entire attrcache and let the next use reinitialize it... * 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); attr_cache__free(cache);
return 0; return 0;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "repository.h" #include "repository.h"
#include "commit.h" #include "commit.h"
#include "thread-utils.h" #include "thread.h"
#include "util.h" #include "util.h"
#include "odb.h" #include "odb.h"
#include "object.h" #include "object.h"
...@@ -235,7 +235,7 @@ void git_cached_obj_decref(void *_obj) ...@@ -235,7 +235,7 @@ void git_cached_obj_decref(void *_obj)
{ {
git_cached_obj *obj = _obj; git_cached_obj *obj = _obj;
if (git_atomic_dec(&obj->refcount) == 0) { if (git_atomic32_dec(&obj->refcount) == 0) {
switch (obj->flags) { switch (obj->flags) {
case GIT_CACHE_STORE_RAW: case GIT_CACHE_STORE_RAW:
git_odb_object__free(_obj); git_odb_object__free(_obj);
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include "git2/oid.h" #include "git2/oid.h"
#include "git2/odb.h" #include "git2/odb.h"
#include "thread-utils.h" #include "thread.h"
#include "oidmap.h" #include "oidmap.h"
enum { enum {
...@@ -23,11 +23,11 @@ enum { ...@@ -23,11 +23,11 @@ enum {
}; };
typedef struct { typedef struct {
git_oid oid; git_oid oid;
int16_t type; /* git_object_t value */ int16_t type; /* git_object_t value */
uint16_t flags; /* GIT_CACHE_STORE value */ uint16_t flags; /* GIT_CACHE_STORE value */
size_t size; size_t size;
git_atomic refcount; git_atomic32 refcount;
} git_cached_obj; } git_cached_obj;
typedef struct { typedef struct {
...@@ -61,7 +61,7 @@ GIT_INLINE(size_t) git_cache_size(git_cache *cache) ...@@ -61,7 +61,7 @@ GIT_INLINE(size_t) git_cache_size(git_cache *cache)
GIT_INLINE(void) git_cached_obj_incref(void *_obj) GIT_INLINE(void) git_cached_obj_incref(void *_obj)
{ {
git_cached_obj *obj = _obj; git_cached_obj *obj = _obj;
git_atomic_inc(&obj->refcount); git_atomic32_inc(&obj->refcount);
} }
void git_cached_obj_decref(void *_obj); void git_cached_obj_decref(void *_obj);
......
...@@ -63,7 +63,9 @@ ...@@ -63,7 +63,9 @@
# include <pthread.h> # include <pthread.h>
# include <sched.h> # include <sched.h>
# endif # endif
#define GIT_STDLIB_CALL
#define GIT_LIBGIT2_CALL
#define GIT_SYSTEM_CALL
#ifdef GIT_USE_STAT_ATIMESPEC #ifdef GIT_USE_STAT_ATIMESPEC
# define st_atim st_atimespec # define st_atim st_atimespec
...@@ -78,7 +80,7 @@ ...@@ -78,7 +80,7 @@
#include "git2/types.h" #include "git2/types.h"
#include "git2/errors.h" #include "git2/errors.h"
#include "errors.h" #include "errors.h"
#include "thread-utils.h" #include "thread.h"
#include "integer.h" #include "integer.h"
#include "assert_safe.h" #include "assert_safe.h"
......
...@@ -111,7 +111,7 @@ int git_config__configmap_lookup(int *out, git_config *config, git_configmap_ite ...@@ -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) 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) { if (*out == GIT_CONFIGMAP_NOT_CACHED) {
int error; int error;
...@@ -122,7 +122,7 @@ int git_repository__configmap_lookup(int *out, git_repository *repo, git_configm ...@@ -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) (error = git_config__configmap_lookup(out, config, item)) < 0)
return error; 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; return 0;
......
...@@ -144,7 +144,7 @@ static git_diff_driver_registry *git_repository_driver_registry( ...@@ -144,7 +144,7 @@ static git_diff_driver_registry *git_repository_driver_registry(
{ {
if (!repo->diff_drivers) { if (!repo->diff_drivers) {
git_diff_driver_registry *reg = git_diff_driver_registry_new(); 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 */ if (reg != NULL) /* if we race, free losing allocation */
git_diff_driver_registry_free(reg); git_diff_driver_registry_free(reg);
......
...@@ -461,7 +461,7 @@ static void index_free(git_index *index) ...@@ -461,7 +461,7 @@ static void index_free(git_index *index)
/* index iterators increment the refcount of the index, so if we /* index iterators increment the refcount of the index, so if we
* get here then there should be no outstanding iterators. * get here then there should be no outstanding iterators.
*/ */
if (git_atomic_get(&index->readers)) if (git_atomic32_get(&index->readers))
return; return;
git_index_clear(index); git_index_clear(index);
...@@ -488,14 +488,14 @@ void git_index_free(git_index *index) ...@@ -488,14 +488,14 @@ void git_index_free(git_index *index)
/* call with locked index */ /* call with locked index */
static void index_free_deleted(git_index *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; size_t i;
if (readers > 0 || !index->deleted.length) if (readers > 0 || !index->deleted.length)
return; return;
for (i = 0; i < index->deleted.length; ++i) { 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); index_entry_free(ie);
} }
...@@ -516,7 +516,7 @@ static int index_remove_entry(git_index *index, size_t pos) ...@@ -516,7 +516,7 @@ static int index_remove_entry(git_index *index, size_t pos)
error = git_vector_remove(&index->entries, pos); error = git_vector_remove(&index->entries, pos);
if (!error) { if (!error) {
if (git_atomic_get(&index->readers) > 0) { if (git_atomic32_get(&index->readers) > 0) {
error = git_vector_insert(&index->deleted, entry); error = git_vector_insert(&index->deleted, entry);
} else { } else {
index_entry_free(entry); index_entry_free(entry);
...@@ -2295,7 +2295,7 @@ int git_index_reuc_clear(git_index *index) ...@@ -2295,7 +2295,7 @@ int git_index_reuc_clear(git_index *index)
GIT_ASSERT_ARG(index); GIT_ASSERT_ARG(index);
for (i = 0; i < index->reuc.length; ++i) 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); git_vector_clear(&index->reuc);
...@@ -3197,7 +3197,7 @@ int git_index_read_tree(git_index *index, const git_tree *tree) ...@@ -3197,7 +3197,7 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
/* well, this isn't good */; /* well, this isn't good */;
} else { } else {
git_vector_swap(&entries, &index->entries); 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; index->dirty = 1;
...@@ -3331,7 +3331,7 @@ static int git_index_read_iterator( ...@@ -3331,7 +3331,7 @@ static int git_index_read_iterator(
goto done; goto done;
git_vector_swap(&new_entries, &index->entries); 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) { git_vector_foreach(&remove_entries, i, entry) {
if (index->tree) if (index->tree)
...@@ -3637,7 +3637,7 @@ int git_index_snapshot_new(git_vector *snap, git_index *index) ...@@ -3637,7 +3637,7 @@ int git_index_snapshot_new(git_vector *snap, git_index *index)
GIT_REFCOUNT_INC(index); GIT_REFCOUNT_INC(index);
git_atomic_inc(&index->readers); git_atomic32_inc(&index->readers);
git_vector_sort(&index->entries); git_vector_sort(&index->entries);
error = git_vector_dup(snap, &index->entries, index->entries._cmp); 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) ...@@ -3652,7 +3652,7 @@ void git_index_snapshot_release(git_vector *snap, git_index *index)
{ {
git_vector_free(snap); git_vector_free(snap);
git_atomic_dec(&index->readers); git_atomic32_dec(&index->readers);
git_index_free(index); git_index_free(index);
} }
......
...@@ -33,7 +33,7 @@ struct git_index { ...@@ -33,7 +33,7 @@ struct git_index {
git_idxmap *entries_map; git_idxmap *entries_map;
git_vector deleted; /* deleted entries if readers > 0 */ 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 on_disk:1;
unsigned int ignore_case:1; unsigned int ignore_case:1;
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include "refs.h" #include "refs.h"
#include "runtime.h" #include "runtime.h"
#include "sysdir.h" #include "sysdir.h"
#include "thread-utils.h" #include "thread.h"
#include "threadstate.h" #include "threadstate.h"
#include "git2/global.h" #include "git2/global.h"
#include "streams/registry.h" #include "streams/registry.h"
......
...@@ -79,7 +79,7 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path) ...@@ -79,7 +79,7 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
git__free(packname); git__free(packname);
if (pack != NULL) { if (pack != NULL) {
git_atomic_inc(&pack->refcount); git_atomic32_inc(&pack->refcount);
git_mutex_unlock(&git__mwindow_mutex); git_mutex_unlock(&git__mwindow_mutex);
*out = pack; *out = pack;
return 0; return 0;
...@@ -91,7 +91,7 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path) ...@@ -91,7 +91,7 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
return error; return error;
} }
git_atomic_inc(&pack->refcount); git_atomic32_inc(&pack->refcount);
error = git_strmap_set(git__pack_cache, pack->pack_name, pack); error = git_strmap_set(git__pack_cache, pack->pack_name, pack);
git_mutex_unlock(&git__mwindow_mutex); git_mutex_unlock(&git__mwindow_mutex);
...@@ -118,7 +118,7 @@ int git_mwindow_put_pack(struct git_pack_file *pack) ...@@ -118,7 +118,7 @@ int git_mwindow_put_pack(struct git_pack_file *pack)
/* if we cannot find it, the state is corrupted */ /* if we cannot find it, the state is corrupted */
GIT_ASSERT(git_strmap_exists(git__pack_cache, pack->pack_name)); 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) { if (count == 0) {
git_strmap_delete(git__pack_cache, pack->pack_name); git_strmap_delete(git__pack_cache, pack->pack_name);
pack_to_delete = pack; pack_to_delete = pack;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include "iterator.h" #include "iterator.h"
#include "netops.h" #include "netops.h"
#include "pack.h" #include "pack.h"
#include "thread-utils.h" #include "thread.h"
#include "tree.h" #include "tree.h"
#include "util.h" #include "util.h"
#include "revwalk.h" #include "revwalk.h"
...@@ -1158,7 +1158,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, ...@@ -1158,7 +1158,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
int ret, active_threads = 0; int ret, active_threads = 0;
if (!pb->nr_threads) if (!pb->nr_threads)
pb->nr_threads = git_online_cpus(); pb->nr_threads = git__online_cpus();
if (pb->nr_threads <= 1) { if (pb->nr_threads <= 1) {
find_deltas(pb, list, &list_size, window, depth); find_deltas(pb, list, &list_size, window, depth);
......
...@@ -57,7 +57,7 @@ static git_pack_cache_entry *new_cache_object(git_rawobj *source) ...@@ -57,7 +57,7 @@ static git_pack_cache_entry *new_cache_object(git_rawobj *source)
if (!e) if (!e)
return NULL; return NULL;
git_atomic_inc(&e->refcount); git_atomic32_inc(&e->refcount);
memcpy(&e->raw, source, sizeof(git_rawobj)); memcpy(&e->raw, source, sizeof(git_rawobj));
return e; return e;
...@@ -114,7 +114,7 @@ static git_pack_cache_entry *cache_get(git_pack_cache *cache, off64_t offset) ...@@ -114,7 +114,7 @@ static git_pack_cache_entry *cache_get(git_pack_cache *cache, off64_t offset)
return NULL; return NULL;
if ((entry = git_offmap_get(cache->entries, offset)) != 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++; entry->last_usage = cache->use_ctr++;
} }
git_mutex_unlock(&cache->lock); git_mutex_unlock(&cache->lock);
...@@ -129,7 +129,7 @@ static void free_lowest_entry(git_pack_cache *cache) ...@@ -129,7 +129,7 @@ static void free_lowest_entry(git_pack_cache *cache)
git_pack_cache_entry *entry; git_pack_cache_entry *entry;
git_offmap_foreach(cache->entries, offset, 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; cache->memory_used -= entry->raw.len;
git_offmap_delete(cache->entries, offset); git_offmap_delete(cache->entries, offset);
free_cache_object(entry); free_cache_object(entry);
...@@ -759,7 +759,7 @@ int git_packfile_unpack( ...@@ -759,7 +759,7 @@ int git_packfile_unpack(
GIT_ERROR_CHECK_ALLOC(obj->data); GIT_ERROR_CHECK_ALLOC(obj->data);
memcpy(obj->data, data, obj->len + 1); memcpy(obj->data, data, obj->len + 1);
git_atomic_dec(&cached->refcount); git_atomic32_dec(&cached->refcount);
goto cleanup; goto cleanup;
} }
...@@ -807,7 +807,7 @@ int git_packfile_unpack( ...@@ -807,7 +807,7 @@ int git_packfile_unpack(
} }
if (cached) { if (cached) {
git_atomic_dec(&cached->refcount); git_atomic32_dec(&cached->refcount);
cached = NULL; cached = NULL;
} }
...@@ -821,7 +821,7 @@ cleanup: ...@@ -821,7 +821,7 @@ cleanup:
if (error < 0) { if (error < 0) {
git__free(obj->data); git__free(obj->data);
if (cached) if (cached)
git_atomic_dec(&cached->refcount); git_atomic32_dec(&cached->refcount);
} }
if (elem) if (elem)
......
...@@ -58,7 +58,7 @@ struct git_pack_idx_header { ...@@ -58,7 +58,7 @@ struct git_pack_idx_header {
typedef struct git_pack_cache_entry { typedef struct git_pack_cache_entry {
size_t last_usage; /* enough? */ size_t last_usage; /* enough? */
git_atomic refcount; git_atomic32 refcount;
git_rawobj raw; git_rawobj raw;
} git_pack_cache_entry; } git_pack_cache_entry;
...@@ -86,7 +86,7 @@ struct git_pack_file { ...@@ -86,7 +86,7 @@ struct git_pack_file {
git_mwindow_file mwf; git_mwindow_file mwf;
git_map index_map; git_map index_map;
git_mutex lock; /* protect updates to index_map */ git_mutex lock; /* protect updates to index_map */
git_atomic refcount; git_atomic32 refcount;
uint32_t num_objects; uint32_t num_objects;
uint32_t num_bad_objects; uint32_t num_bad_objects;
......
...@@ -93,7 +93,7 @@ static void set_odb(git_repository *repo, git_odb *odb) ...@@ -93,7 +93,7 @@ static void set_odb(git_repository *repo, git_odb *odb)
GIT_REFCOUNT_INC(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_REFCOUNT_OWN(odb, NULL);
git_odb_free(odb); git_odb_free(odb);
} }
...@@ -106,7 +106,7 @@ static void set_refdb(git_repository *repo, git_refdb *refdb) ...@@ -106,7 +106,7 @@ static void set_refdb(git_repository *repo, git_refdb *refdb)
GIT_REFCOUNT_INC(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_REFCOUNT_OWN(refdb, NULL);
git_refdb_free(refdb); git_refdb_free(refdb);
} }
...@@ -119,7 +119,7 @@ static void set_config(git_repository *repo, git_config *config) ...@@ -119,7 +119,7 @@ static void set_config(git_repository *repo, git_config *config)
GIT_REFCOUNT_INC(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_REFCOUNT_OWN(config, NULL);
git_config_free(config); git_config_free(config);
} }
...@@ -134,7 +134,7 @@ static void set_index(git_repository *repo, git_index *index) ...@@ -134,7 +134,7 @@ static void set_index(git_repository *repo, git_index *index)
GIT_REFCOUNT_INC(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_REFCOUNT_OWN(index, NULL);
git_index_free(index); git_index_free(index);
} }
...@@ -1054,7 +1054,7 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo) ...@@ -1054,7 +1054,7 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
if (!error) { if (!error) {
GIT_REFCOUNT_OWN(config, repo); 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) { if (config != NULL) {
GIT_REFCOUNT_OWN(config, NULL); GIT_REFCOUNT_OWN(config, NULL);
git_config_free(config); git_config_free(config);
...@@ -1107,7 +1107,7 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo) ...@@ -1107,7 +1107,7 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
GIT_ASSERT_ARG(repo); GIT_ASSERT_ARG(repo);
GIT_ASSERT_ARG(out); GIT_ASSERT_ARG(out);
*out = git__load(repo->_odb); *out = git_atomic_load(repo->_odb);
if (*out == NULL) { if (*out == NULL) {
git_buf odb_path = GIT_BUF_INIT; git_buf odb_path = GIT_BUF_INIT;
git_odb *odb; git_odb *odb;
...@@ -1125,14 +1125,14 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo) ...@@ -1125,14 +1125,14 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
return error; return error;
} }
odb = git__compare_and_swap(&repo->_odb, NULL, odb); odb = git_atomic_compare_and_swap(&repo->_odb, NULL, odb);
if (odb != NULL) { if (odb != NULL) {
GIT_REFCOUNT_OWN(odb, NULL); GIT_REFCOUNT_OWN(odb, NULL);
git_odb_free(odb); git_odb_free(odb);
} }
git_buf_dispose(&odb_path); git_buf_dispose(&odb_path);
*out = git__load(repo->_odb); *out = git_atomic_load(repo->_odb);
} }
return error; return error;
...@@ -1170,7 +1170,7 @@ int git_repository_refdb__weakptr(git_refdb **out, git_repository *repo) ...@@ -1170,7 +1170,7 @@ int git_repository_refdb__weakptr(git_refdb **out, git_repository *repo)
if (!error) { if (!error) {
GIT_REFCOUNT_OWN(refdb, repo); 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) { if (refdb != NULL) {
GIT_REFCOUNT_OWN(refdb, NULL); GIT_REFCOUNT_OWN(refdb, NULL);
git_refdb_free(refdb); git_refdb_free(refdb);
...@@ -1218,7 +1218,7 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo) ...@@ -1218,7 +1218,7 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
if (!error) { if (!error) {
GIT_REFCOUNT_OWN(index, repo); 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) { if (index != NULL) {
GIT_REFCOUNT_OWN(index, NULL); GIT_REFCOUNT_OWN(index, NULL);
git_index_free(index); git_index_free(index);
...@@ -3044,8 +3044,8 @@ int git_repository_set_ident(git_repository *repo, const char *name, const char ...@@ -3044,8 +3044,8 @@ int git_repository_set_ident(git_repository *repo, const char *name, const char
GIT_ERROR_CHECK_ALLOC(tmp_email); GIT_ERROR_CHECK_ALLOC(tmp_email);
} }
tmp_name = git__swap(repo->ident_name, tmp_name); tmp_name = git_atomic_swap(repo->ident_name, tmp_name);
tmp_email = git__swap(repo->ident_email, tmp_email); tmp_email = git_atomic_swap(repo->ident_email, tmp_email);
git__free(tmp_name); git__free(tmp_name);
git__free(tmp_email); git__free(tmp_email);
......
...@@ -152,7 +152,7 @@ struct git_repository { ...@@ -152,7 +152,7 @@ struct git_repository {
unsigned int lru_counter; unsigned int lru_counter;
git_atomic attr_session_key; git_atomic32 attr_session_key;
git_configmap_value configmap_cache[GIT_CONFIGMAP_CACHE_MAX]; git_configmap_value configmap_cache[GIT_CONFIGMAP_CACHE_MAX];
git_strmap *submodule_cache; git_strmap *submodule_cache;
......
...@@ -9,9 +9,9 @@ ...@@ -9,9 +9,9 @@
#include "runtime.h" #include "runtime.h"
static git_runtime_shutdown_fn shutdown_callback[32]; 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) static int init_common(git_runtime_init_fn init_fns[], size_t cnt)
{ {
...@@ -34,10 +34,10 @@ static void shutdown_common(void) ...@@ -34,10 +34,10 @@ static void shutdown_common(void)
git_runtime_shutdown_fn cb; git_runtime_shutdown_fn cb;
int pos; int pos;
for (pos = git_atomic_get(&shutdown_callback_count); for (pos = git_atomic32_get(&shutdown_callback_count);
pos > 0; pos > 0;
pos = git_atomic_dec(&shutdown_callback_count)) { pos = git_atomic32_dec(&shutdown_callback_count)) {
cb = git__swap(shutdown_callback[pos - 1], NULL); cb = git_atomic_swap(shutdown_callback[pos - 1], NULL);
if (cb != NULL) if (cb != NULL)
cb(); cb();
...@@ -46,12 +46,12 @@ static void shutdown_common(void) ...@@ -46,12 +46,12 @@ static void shutdown_common(void)
int git_runtime_shutdown_register(git_runtime_shutdown_fn callback) 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) { if (count > (int)ARRAY_SIZE(shutdown_callback) || count == 0) {
git_error_set(GIT_ERROR_INVALID, git_error_set(GIT_ERROR_INVALID,
"too many shutdown callbacks registered"); "too many shutdown callbacks registered");
git_atomic_dec(&shutdown_callback_count); git_atomic32_dec(&shutdown_callback_count);
return -1; return -1;
} }
...@@ -116,7 +116,7 @@ int git_runtime_init(git_runtime_init_fn init_fns[], size_t cnt) ...@@ -116,7 +116,7 @@ int git_runtime_init(git_runtime_init_fn init_fns[], size_t cnt)
return -1; return -1;
/* Only do work on a 0 -> 1 transition of the refcount */ /* 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) if (init_common(init_fns, cnt) < 0)
ret = -1; ret = -1;
} }
...@@ -136,7 +136,7 @@ int git_runtime_shutdown(void) ...@@ -136,7 +136,7 @@ int git_runtime_shutdown(void)
return -1; return -1;
/* Only do work on a 1 -> 0 transition of the refcount */ /* 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(); shutdown_common();
/* Exit the lock */ /* Exit the lock */
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include "util.h" #include "util.h"
#include "futils.h" #include "futils.h"
#include "vector.h" #include "vector.h"
#include "thread-utils.h" #include "thread.h"
#include "pool.h" #include "pool.h"
#include "strmap.h" #include "strmap.h"
......
/*
* 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;
}
/*
* 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
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with * This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#ifndef INCLUDE_thread_utils_h__ #ifndef INCLUDE_thread_h__
#define INCLUDE_thread_utils_h__ #define INCLUDE_thread_h__
#if defined(GIT_THREADS) #if defined(GIT_THREADS)
...@@ -38,7 +38,7 @@ typedef struct { ...@@ -38,7 +38,7 @@ typedef struct {
#else #else
volatile int val; volatile int val;
#endif #endif
} git_atomic; } git_atomic32;
#ifdef GIT_ARCH_64 #ifdef GIT_ARCH_64
...@@ -58,11 +58,11 @@ typedef git_atomic64 git_atomic_ssize; ...@@ -58,11 +58,11 @@ typedef git_atomic64 git_atomic_ssize;
#else #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_set git_atomic32_set
#define git_atomic_ssize_add git_atomic_add #define git_atomic_ssize_add git_atomic32_add
#define git_atomic_ssize_get git_atomic_get #define git_atomic_ssize_get git_atomic32_get
#endif #endif
...@@ -74,7 +74,7 @@ typedef git_atomic git_atomic_ssize; ...@@ -74,7 +74,7 @@ typedef git_atomic git_atomic_ssize;
# include "unix/pthread.h" # include "unix/pthread.h"
#endif #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) #if defined(GIT_WIN32)
InterlockedExchange(&a->val, (LONG)val); InterlockedExchange(&a->val, (LONG)val);
...@@ -87,7 +87,7 @@ GIT_INLINE(void) git_atomic_set(git_atomic *a, int val) ...@@ -87,7 +87,7 @@ GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
#endif #endif
} }
GIT_INLINE(int) git_atomic_inc(git_atomic *a) GIT_INLINE(int) git_atomic32_inc(git_atomic32 *a)
{ {
#if defined(GIT_WIN32) #if defined(GIT_WIN32)
return InterlockedIncrement(&a->val); return InterlockedIncrement(&a->val);
...@@ -100,7 +100,7 @@ GIT_INLINE(int) git_atomic_inc(git_atomic *a) ...@@ -100,7 +100,7 @@ GIT_INLINE(int) git_atomic_inc(git_atomic *a)
#endif #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) #if defined(GIT_WIN32)
return InterlockedExchangeAdd(&a->val, addend); return InterlockedExchangeAdd(&a->val, addend);
...@@ -113,7 +113,7 @@ GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend) ...@@ -113,7 +113,7 @@ GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend)
#endif #endif
} }
GIT_INLINE(int) git_atomic_dec(git_atomic *a) GIT_INLINE(int) git_atomic32_dec(git_atomic32 *a)
{ {
#if defined(GIT_WIN32) #if defined(GIT_WIN32)
return InterlockedDecrement(&a->val); return InterlockedDecrement(&a->val);
...@@ -126,7 +126,7 @@ GIT_INLINE(int) git_atomic_dec(git_atomic *a) ...@@ -126,7 +126,7 @@ GIT_INLINE(int) git_atomic_dec(git_atomic *a)
#endif #endif
} }
GIT_INLINE(int) git_atomic_get(git_atomic *a) GIT_INLINE(int) git_atomic32_get(git_atomic32 *a)
{ {
#if defined(GIT_WIN32) #if defined(GIT_WIN32)
return (int)InterlockedCompareExchange(&a->val, 0, 0); return (int)InterlockedCompareExchange(&a->val, 0, 0);
...@@ -139,7 +139,7 @@ GIT_INLINE(int) git_atomic_get(git_atomic *a) ...@@ -139,7 +139,7 @@ GIT_INLINE(int) git_atomic_get(git_atomic *a)
#endif #endif
} }
GIT_INLINE(void *) git___compare_and_swap( GIT_INLINE(void *) git_atomic__compare_and_swap(
void * volatile *ptr, void *oldval, void *newval) void * volatile *ptr, void *oldval, void *newval)
{ {
#if defined(GIT_WIN32) #if defined(GIT_WIN32)
...@@ -158,7 +158,7 @@ GIT_INLINE(void *) git___compare_and_swap( ...@@ -158,7 +158,7 @@ GIT_INLINE(void *) git___compare_and_swap(
#endif #endif
} }
GIT_INLINE(volatile void *) git___swap( GIT_INLINE(volatile void *) git_atomic__swap(
void * volatile *ptr, void *newval) void * volatile *ptr, void *newval)
{ {
#if defined(GIT_WIN32) #if defined(GIT_WIN32)
...@@ -174,7 +174,7 @@ GIT_INLINE(volatile void *) git___swap( ...@@ -174,7 +174,7 @@ GIT_INLINE(volatile void *) git___swap(
#endif #endif
} }
GIT_INLINE(volatile void *) git___load(void * volatile *ptr) GIT_INLINE(volatile void *) git_atomic__load(void * volatile *ptr)
{ {
#if defined(GIT_WIN32) #if defined(GIT_WIN32)
void *newval = NULL, *oldval = NULL; void *newval = NULL, *oldval = NULL;
...@@ -268,33 +268,33 @@ GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a) ...@@ -268,33 +268,33 @@ GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a)
#define GIT_RWLOCK_STATIC_INIT 0 #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; a->val = val;
} }
GIT_INLINE(int) git_atomic_inc(git_atomic *a) GIT_INLINE(int) git_atomic32_inc(git_atomic32 *a)
{ {
return ++a->val; 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; a->val += addend;
return a->val; return a->val;
} }
GIT_INLINE(int) git_atomic_dec(git_atomic *a) GIT_INLINE(int) git_atomic32_dec(git_atomic32 *a)
{ {
return --a->val; 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; 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) void * volatile *ptr, void *oldval, void *newval)
{ {
if (*ptr == oldval) if (*ptr == oldval)
...@@ -304,7 +304,7 @@ GIT_INLINE(void *) git___compare_and_swap( ...@@ -304,7 +304,7 @@ GIT_INLINE(void *) git___compare_and_swap(
return oldval; return oldval;
} }
GIT_INLINE(volatile void *) git___swap( GIT_INLINE(volatile void *) git_atomic__swap(
void * volatile *ptr, void *newval) void * volatile *ptr, void *newval)
{ {
volatile void *old = *ptr; volatile void *old = *ptr;
...@@ -312,7 +312,7 @@ GIT_INLINE(volatile void *) git___swap( ...@@ -312,7 +312,7 @@ GIT_INLINE(volatile void *) git___swap(
return old; return old;
} }
GIT_INLINE(volatile void *) git___load(void * volatile *ptr) GIT_INLINE(volatile void *) git_atomic__load(void * volatile *ptr)
{ {
return *ptr; return *ptr;
} }
...@@ -342,14 +342,14 @@ GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a) ...@@ -342,14 +342,14 @@ GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a)
/* Atomically replace oldval with newval /* Atomically replace oldval with newval
* @return oldval if it was replaced or newval if it was not * @return oldval if it was replaced or newval if it was not
*/ */
#define git__compare_and_swap(P,O,N) \ #define git_atomic_compare_and_swap(P,O,N) \
git___compare_and_swap((void * volatile *)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) #define git_atomic_load(ptr) \
(void *)git_atomic__load((void * volatile *)&ptr)
extern int git_online_cpus(void);
#if defined(GIT_THREADS) #if defined(GIT_THREADS)
...@@ -367,4 +367,56 @@ extern int git_online_cpus(void); ...@@ -367,4 +367,56 @@ extern int git_online_cpus(void);
#endif #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 #endif
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
#include "threadstate.h" #include "threadstate.h"
#include "runtime.h" #include "runtime.h"
static void threadstate_dispose(git_threadstate *threadstate);
/** /**
* Handle the thread-local state * Handle the thread-local state
* *
...@@ -17,8 +15,7 @@ static void threadstate_dispose(git_threadstate *threadstate); ...@@ -17,8 +15,7 @@ static void threadstate_dispose(git_threadstate *threadstate);
* of `git_libgit2_init` (which itself must be called * of `git_libgit2_init` (which itself must be called
* before calling any other function in the library). * before calling any other function in the library).
* *
* This function allocates a TLS index (using pthreads * This function allocates a TLS index to store the per-
* or fiber-local storage in Win32) to store the per-
* thread state. * thread state.
* *
* Any internal method that requires thread-local state * Any internal method that requires thread-local state
...@@ -30,77 +27,41 @@ static void threadstate_dispose(git_threadstate *threadstate); ...@@ -30,77 +27,41 @@ static void threadstate_dispose(git_threadstate *threadstate);
* (`git_threadstate_global_shutdown`) which will free the * (`git_threadstate_global_shutdown`) which will free the
* TLS index. This shutdown handler will be called by * TLS index. This shutdown handler will be called by
* `git_libgit2_shutdown`. * `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 threadstate_dispose(git_threadstate *threadstate)
static void git_threadstate_global_shutdown(void)
{ {
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); threadstate_dispose(threadstate);
git__free(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) static void git_threadstate_global_shutdown(void)
{ {
git_threadstate *threadstate; git_threadstate *threadstate;
threadstate = pthread_getspecific(tls_key); threadstate = git_tlsdata_get(tls_key);
pthread_setspecific(tls_key, NULL); git_tlsdata_set(tls_key, NULL);
threadstate_dispose(threadstate); threadstate_dispose(threadstate);
git__free(threadstate); git__free(threadstate);
pthread_key_delete(tls_key); git_tlsdata_dispose(tls_key);
}
static void tls_free(void *threadstate)
{
threadstate_dispose(threadstate);
git__free(threadstate);
} }
int git_threadstate_global_init(void) 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 -1;
return git_runtime_shutdown_register(git_threadstate_global_shutdown); return git_runtime_shutdown_register(git_threadstate_global_shutdown);
...@@ -110,46 +71,13 @@ git_threadstate *git_threadstate_get(void) ...@@ -110,46 +71,13 @@ git_threadstate *git_threadstate_get(void)
{ {
git_threadstate *threadstate; git_threadstate *threadstate;
if ((threadstate = pthread_getspecific(tls_key)) != NULL) if ((threadstate = git_tlsdata_get(tls_key)) != NULL)
return threadstate; return threadstate;
if ((threadstate = git__calloc(1, sizeof(git_threadstate))) == NULL || if ((threadstate = git__calloc(1, sizeof(git_threadstate))) == NULL ||
git_buf_init(&threadstate->error_buf, 0) < 0) git_buf_init(&threadstate->error_buf, 0) < 0)
return NULL; return NULL;
pthread_setspecific(tls_key, threadstate); git_tlsdata_set(tls_key, threadstate);
return 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;
}
...@@ -36,7 +36,7 @@ typedef struct { ...@@ -36,7 +36,7 @@ typedef struct {
char *url; char *url;
int direction; int direction;
int flags; int flags;
git_atomic cancelled; git_atomic32 cancelled;
git_repository *repo; git_repository *repo;
git_transport_message_cb progress_cb; git_transport_message_cb progress_cb;
git_transport_message_cb error_cb; git_transport_message_cb error_cb;
...@@ -671,7 +671,7 @@ static void local_cancel(git_transport *transport) ...@@ -671,7 +671,7 @@ static void local_cancel(git_transport *transport)
{ {
transport_local *t = (transport_local *)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) static int local_close(git_transport *transport)
......
...@@ -30,7 +30,7 @@ static int git_smart__recv_cb(gitno_buffer *buf) ...@@ -30,7 +30,7 @@ static int git_smart__recv_cb(gitno_buffer *buf)
if (t->packetsize_cb && !t->cancelled.val) { if (t->packetsize_cb && !t->cancelled.val) {
error = t->packetsize_cb(bytes_read, t->packetsize_payload); error = t->packetsize_cb(bytes_read, t->packetsize_payload);
if (error) { if (error) {
git_atomic_set(&t->cancelled, 1); git_atomic32_set(&t->cancelled, 1);
return GIT_EUSER; return GIT_EUSER;
} }
} }
...@@ -389,7 +389,7 @@ static void git_smart__cancel(git_transport *transport) ...@@ -389,7 +389,7 @@ static void git_smart__cancel(git_transport *transport)
{ {
transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); 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) static int git_smart__is_connected(git_transport *transport)
......
...@@ -153,7 +153,7 @@ typedef struct { ...@@ -153,7 +153,7 @@ typedef struct {
git_vector refs; git_vector refs;
git_vector heads; git_vector heads;
git_vector common; git_vector common;
git_atomic cancelled; git_atomic32 cancelled;
packetsize_cb packetsize_cb; packetsize_cb packetsize_cb;
void *packetsize_payload; void *packetsize_payload;
unsigned rpc : 1, unsigned rpc : 1,
......
...@@ -535,7 +535,7 @@ int git_smart__download_pack( ...@@ -535,7 +535,7 @@ int git_smart__download_pack(
/* We might have something in the buffer already from negotiate_fetch */ /* We might have something in the buffer already from negotiate_fetch */
if (t->buffer.offset > 0 && !t->cancelled.val) if (t->buffer.offset > 0 && !t->cancelled.val)
if (t->packetsize_cb(t->buffer.offset, t->packetsize_payload)) 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 || if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 ||
......
...@@ -13,6 +13,11 @@ ...@@ -13,6 +13,11 @@
# include "win32/utf-conv.h" # include "win32/utf-conv.h"
# include "win32/w32_buffer.h" # include "win32/w32_buffer.h"
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef HAVE_QSORT_S # ifdef HAVE_QSORT_S
# include <search.h> # include <search.h>
# endif # endif
...@@ -22,6 +27,10 @@ ...@@ -22,6 +27,10 @@
# include <Shlwapi.h> # include <Shlwapi.h>
#endif #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) int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
{ {
const char *p; const char *p;
...@@ -678,7 +687,7 @@ typedef struct { ...@@ -678,7 +687,7 @@ typedef struct {
void *payload; void *payload;
} git__qsort_r_glue; } 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) void *payload, const void *a, const void *b)
{ {
git__qsort_r_glue *glue = payload; git__qsort_r_glue *glue = payload;
...@@ -893,3 +902,43 @@ int git__getenv(git_buf *out, const char *name) ...@@ -893,3 +902,43 @@ int git__getenv(git_buf *out, const char *name)
return git_buf_puts(out, val); return git_buf_puts(out, val);
} }
#endif #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;
}
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include "buffer.h" #include "buffer.h"
#include "common.h" #include "common.h"
#include "strnlen.h" #include "strnlen.h"
#include "thread-utils.h" #include "thread.h"
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#define bitsizeof(x) (CHAR_BIT * sizeof(x)) #define bitsizeof(x) (CHAR_BIT * sizeof(x))
...@@ -169,29 +169,29 @@ extern int git__strncasecmp(const char *a, const char *b, size_t sz); ...@@ -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); extern int git__strcasesort_cmp(const char *a, const char *b);
typedef struct { typedef struct {
git_atomic refcount; git_atomic32 refcount;
void *owner; void *owner;
} git_refcount; } git_refcount;
typedef void (*git_refcount_freeptr)(void *r); typedef void (*git_refcount_freeptr)(void *r);
#define GIT_REFCOUNT_INC(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) { \ #define GIT_REFCOUNT_DEC(_r, do_free) { \
git_refcount *r = &(_r)->rc; \ 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); } \ if (val <= 0 && r->owner == NULL) { do_free(_r); } \
} }
#define GIT_REFCOUNT_OWN(r, o) { \ #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[] = { static signed char from_hex[] = {
...@@ -414,6 +414,8 @@ GIT_INLINE(double) git__timer(void) ...@@ -414,6 +414,8 @@ GIT_INLINE(double) git__timer(void)
extern int git__getenv(git_buf *out, const char *name); extern int git__getenv(git_buf *out, const char *name);
extern int git__online_cpus(void);
GIT_INLINE(int) git__noop(void) { return 0; } GIT_INLINE(int) git__noop(void) { return 0; }
#include "alloc.h" #include "alloc.h"
......
...@@ -23,6 +23,14 @@ typedef SSIZE_T ssize_t; ...@@ -23,6 +23,14 @@ typedef SSIZE_T ssize_t;
#endif #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 #endif
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
static git_repository *_repo; static git_repository *_repo;
static git_tree *_a, *_b; static git_tree *_a, *_b;
static git_atomic _counts[4]; static git_atomic32 _counts[4];
static int _check_counts; static int _check_counts;
#ifdef GIT_WIN32 #ifdef GIT_WIN32
static int _retries; static int _retries;
...@@ -66,10 +66,10 @@ static void free_trees(void) ...@@ -66,10 +66,10 @@ static void free_trees(void)
git_tree_free(_b); _b = NULL; git_tree_free(_b); _b = NULL;
if (_check_counts) { if (_check_counts) {
cl_assert_equal_i(288, git_atomic_get(&_counts[0])); cl_assert_equal_i(288, git_atomic32_get(&_counts[0]));
cl_assert_equal_i(112, git_atomic_get(&_counts[1])); cl_assert_equal_i(112, git_atomic32_get(&_counts[1]));
cl_assert_equal_i( 80, git_atomic_get(&_counts[2])); cl_assert_equal_i( 80, git_atomic32_get(&_counts[2]));
cl_assert_equal_i( 96, git_atomic_get(&_counts[3])); cl_assert_equal_i( 96, git_atomic32_get(&_counts[3]));
} }
} }
...@@ -107,14 +107,14 @@ static void *run_index_diffs(void *arg) ...@@ -107,14 +107,14 @@ static void *run_index_diffs(void *arg)
/* keep some diff stats to make sure results are as expected */ /* keep some diff stats to make sure results are as expected */
i = git_diff_num_deltas(diff); 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; exp[0] = (int)i;
while (i > 0) { while (i > 0) {
switch (git_diff_get_delta(diff, --i)->status) { switch (git_diff_get_delta(diff, --i)->status) {
case GIT_DELTA_MODIFIED: exp[1]++; git_atomic_inc(&_counts[1]); break; case GIT_DELTA_MODIFIED: exp[1]++; git_atomic32_inc(&_counts[1]); break;
case GIT_DELTA_ADDED: exp[2]++; git_atomic_inc(&_counts[2]); break; case GIT_DELTA_ADDED: exp[2]++; git_atomic32_inc(&_counts[2]); break;
case GIT_DELTA_DELETED: exp[3]++; git_atomic_inc(&_counts[3]); break; case GIT_DELTA_DELETED: exp[3]++; git_atomic32_inc(&_counts[3]); break;
default: break; default: break;
} }
} }
......
#include "thread-utils.h" #include "thread.h"
void run_in_parallel( void run_in_parallel(
int repeats, int repeats,
......
#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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment