Unverified Commit c3512fe6 by Edward Thomson Committed by GitHub

Merge branch 'main' into multi-pack-index-odb-write

parents ea285904 78cd7624
{
"postCreateCommand": "bash .devcontainer/setup.sh"
}
#!/bin/sh
set -e
sudo apt-get update
sudo apt-get -y --no-install-recommends install cmake
mkdir build
cd build
cmake ..
\ No newline at end of file
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/libgit2_clar",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
\ No newline at end of file
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Build",
"type": "shell",
"command": "cd build && cmake --build . --parallel",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "new"
}
},
{
"label": "Run Tests",
"type": "shell",
"command": "build/libgit2_clar -v",
"group": "test",
"presentation": {
"reveal": "always",
"panel": "new"
}
}
]
}
\ No newline at end of file
......@@ -56,6 +56,7 @@ ELSE()
MESSAGE(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}")
ENDIF()
list(APPEND SRC_SHA1 "hash/sha1.h")
list(SORT SRC_SHA1)
ADD_FEATURE_INFO(SHA ON "using ${USE_SHA1}")
......@@ -41,8 +41,8 @@
typedef git_array_t(char) git_array_generic_t;
/* use a generic array for growth so this can return the new item */
GIT_INLINE(void *) git_array_grow(void *_a, size_t item_size)
/* use a generic array for growth, return 0 on success */
GIT_INLINE(int) git_array_grow(void *_a, size_t item_size)
{
volatile git_array_generic_t *a = _a;
size_t new_size;
......@@ -59,18 +59,18 @@ GIT_INLINE(void *) git_array_grow(void *_a, size_t item_size)
if ((new_array = git__reallocarray(a->ptr, new_size, item_size)) == NULL)
goto on_oom;
a->ptr = new_array; a->asize = new_size; a->size++;
return a->ptr + (a->size - 1) * item_size;
a->ptr = new_array;
a->asize = new_size;
return 0;
on_oom:
git_array_clear(*a);
return NULL;
return -1;
}
#define git_array_alloc(a) \
(((a).size >= (a).asize) ? \
git_array_grow(&(a), sizeof(*(a).ptr)) : \
((a).ptr ? &(a).ptr[(a).size++] : (void *)NULL))
(((a).size < (a).asize || git_array_grow(&(a), sizeof(*(a).ptr)) == 0) ? \
&(a).ptr[(a).size++] : (void *)NULL)
#define git_array_last(a) ((a).size ? &(a).ptr[(a).size - 1] : (void *)NULL)
......
......@@ -127,7 +127,7 @@ static int attr_cache_remove(git_attr_cache *cache, git_attr_file *file)
{
int error = 0;
git_attr_file_entry *entry;
git_attr_file *old = NULL;
git_attr_file *oldfile = NULL;
if (!file)
return 0;
......@@ -136,13 +136,13 @@ 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_atomic_compare_and_swap(&entry->file[file->source.type], file, NULL);
oldfile = git_atomic_compare_and_swap(&entry->file[file->source.type], file, NULL);
attr_cache_unlock(cache);
if (old) {
GIT_REFCOUNT_OWN(old, NULL);
git_attr_file__free(old);
if (oldfile == file) {
GIT_REFCOUNT_OWN(file, NULL);
git_attr_file__free(file);
}
return error;
......@@ -401,8 +401,7 @@ int git_attr_cache__init(git_repository *repo)
(ret = git_pool_init(&cache->pool, 1)) < 0)
goto cancel;
cache = git_atomic_compare_and_swap(&repo->attrcache, NULL, cache);
if (cache)
if (git_atomic_compare_and_swap(&repo->attrcache, NULL, cache) != NULL)
goto cancel; /* raced with another thread, free this but no error */
git_config_free(cfg);
......
......@@ -162,37 +162,6 @@ done:
return error;
}
static int update_remote_head_byname(
git_repository *repo,
const char *remote_name,
const char *tracking_branch_name,
const char *reflog_message)
{
git_buf tracking_head_name = GIT_BUF_INIT;
git_reference *remote_head = NULL;
int error;
if ((error = git_buf_printf(&tracking_head_name,
"%s%s/%s",
GIT_REFS_REMOTES_DIR,
remote_name,
GIT_HEAD_FILE)) < 0)
goto cleanup;
error = git_reference_symbolic_create(
&remote_head,
repo,
git_buf_cstr(&tracking_head_name),
tracking_branch_name,
true,
reflog_message);
cleanup:
git_reference_free(remote_head);
git_buf_dispose(&tracking_head_name);
return error;
}
static int update_remote_head(
git_repository *repo,
git_remote *remote,
......@@ -200,7 +169,9 @@ static int update_remote_head(
const char *reflog_message)
{
git_refspec *refspec;
git_buf tracking_branch_name = GIT_BUF_INIT;
git_reference *remote_head = NULL;
git_buf remote_head_name = GIT_BUF_INIT;
git_buf remote_branch_name = GIT_BUF_INIT;
int error;
/* Determine the remote tracking ref name from the local branch */
......@@ -213,19 +184,30 @@ static int update_remote_head(
}
if ((error = git_refspec_transform(
&tracking_branch_name,
&remote_branch_name,
refspec,
git_buf_cstr(target))) < 0)
goto cleanup;
error = update_remote_head_byname(
repo,
if ((error = git_buf_printf(&remote_head_name,
"%s%s/%s",
GIT_REFS_REMOTES_DIR,
git_remote_name(remote),
git_buf_cstr(&tracking_branch_name),
GIT_HEAD_FILE)) < 0)
goto cleanup;
error = git_reference_symbolic_create(
&remote_head,
repo,
git_buf_cstr(&remote_head_name),
git_buf_cstr(&remote_branch_name),
true,
reflog_message);
cleanup:
git_buf_dispose(&tracking_branch_name);
git_reference_free(remote_head);
git_buf_dispose(&remote_branch_name);
git_buf_dispose(&remote_head_name);
return error;
}
......@@ -277,19 +259,20 @@ cleanup:
static int update_head_to_branch(
git_repository *repo,
const char *remote_name,
git_remote *remote,
const char *branch,
const char *reflog_message)
{
int retcode;
git_buf remote_branch_name = GIT_BUF_INIT;
git_reference* remote_ref = NULL;
git_buf default_branch = GIT_BUF_INIT;
GIT_ASSERT_ARG(remote_name);
GIT_ASSERT_ARG(remote);
GIT_ASSERT_ARG(branch);
if ((retcode = git_buf_printf(&remote_branch_name, GIT_REFS_REMOTES_DIR "%s/%s",
remote_name, branch)) < 0 )
git_remote_name(remote), branch)) < 0 )
goto cleanup;
if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0)
......@@ -299,11 +282,18 @@ static int update_head_to_branch(
reflog_message)) < 0)
goto cleanup;
retcode = update_remote_head_byname(repo, remote_name, remote_branch_name.ptr, reflog_message);
if ((retcode = git_remote_default_branch(&default_branch, remote)) < 0)
goto cleanup;
if (!git_remote__matching_refspec(remote, git_buf_cstr(&default_branch)))
goto cleanup;
retcode = update_remote_head(repo, remote, &default_branch, reflog_message);
cleanup:
git_reference_free(remote_ref);
git_buf_dispose(&remote_branch_name);
git_buf_dispose(&default_branch);
return retcode;
}
......@@ -388,8 +378,7 @@ static int checkout_branch(git_repository *repo, git_remote *remote, const git_c
int error;
if (branch)
error = update_head_to_branch(repo, git_remote_name(remote), branch,
reflog_message);
error = update_head_to_branch(repo, remote, branch, reflog_message);
/* Point HEAD to the same ref as the remote's head */
else
error = update_head_to_remote(repo, remote, reflog_message);
......
......@@ -141,18 +141,23 @@ static int diff_driver_funcname(const git_config_entry *entry, void *payload)
static git_diff_driver_registry *git_repository_driver_registry(
git_repository *repo)
{
if (!repo->diff_drivers) {
git_diff_driver_registry *reg = git_diff_driver_registry_new();
reg = git_atomic_compare_and_swap(&repo->diff_drivers, NULL, reg);
git_diff_driver_registry *reg = git_atomic_load(repo->diff_drivers), *newreg;
if (reg)
return reg;
if (reg != NULL) /* if we race, free losing allocation */
git_diff_driver_registry_free(reg);
}
if (!repo->diff_drivers)
newreg = git_diff_driver_registry_new();
if (!newreg) {
git_error_set(GIT_ERROR_REPOSITORY, "unable to create diff driver registry");
return repo->diff_drivers;
return newreg;
}
reg = git_atomic_compare_and_swap(&repo->diff_drivers, NULL, newreg);
if (!reg) {
reg = newreg;
} else {
/* if we race, free losing allocation */
git_diff_driver_registry_free(newreg);
}
return reg;
}
static int diff_driver_alloc(
......
......@@ -1093,8 +1093,7 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
if (!error) {
GIT_REFCOUNT_OWN(config, repo);
config = git_atomic_compare_and_swap(&repo->_config, NULL, config);
if (config != NULL) {
if (git_atomic_compare_and_swap(&repo->_config, NULL, config) != NULL) {
GIT_REFCOUNT_OWN(config, NULL);
git_config_free(config);
}
......@@ -1164,8 +1163,7 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
return error;
}
odb = git_atomic_compare_and_swap(&repo->_odb, NULL, odb);
if (odb != NULL) {
if (git_atomic_compare_and_swap(&repo->_odb, NULL, odb) != NULL) {
GIT_REFCOUNT_OWN(odb, NULL);
git_odb_free(odb);
}
......@@ -1209,8 +1207,7 @@ int git_repository_refdb__weakptr(git_refdb **out, git_repository *repo)
if (!error) {
GIT_REFCOUNT_OWN(refdb, repo);
refdb = git_atomic_compare_and_swap(&repo->_refdb, NULL, refdb);
if (refdb != NULL) {
if (git_atomic_compare_and_swap(&repo->_refdb, NULL, refdb) != NULL) {
GIT_REFCOUNT_OWN(refdb, NULL);
git_refdb_free(refdb);
}
......@@ -1257,8 +1254,7 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
if (!error) {
GIT_REFCOUNT_OWN(index, repo);
index = git_atomic_compare_and_swap(&repo->_index, NULL, index);
if (index != NULL) {
if (git_atomic_compare_and_swap(&repo->_index, NULL, index) != NULL) {
GIT_REFCOUNT_OWN(index, NULL);
git_index_free(index);
}
......
......@@ -74,6 +74,9 @@ typedef git_atomic32 git_atomic_ssize;
# include "unix/pthread.h"
#endif
/*
* Atomically sets the contents of *a to be val.
*/
GIT_INLINE(void) git_atomic32_set(git_atomic32 *a, int val)
{
#if defined(GIT_WIN32)
......@@ -87,6 +90,10 @@ GIT_INLINE(void) git_atomic32_set(git_atomic32 *a, int val)
#endif
}
/*
* Atomically increments the contents of *a by 1, and stores the result back into *a.
* @return the result of the operation.
*/
GIT_INLINE(int) git_atomic32_inc(git_atomic32 *a)
{
#if defined(GIT_WIN32)
......@@ -100,10 +107,14 @@ GIT_INLINE(int) git_atomic32_inc(git_atomic32 *a)
#endif
}
/*
* Atomically adds the contents of *a and addend, and stores the result back into *a.
* @return the result of the operation.
*/
GIT_INLINE(int) git_atomic32_add(git_atomic32 *a, int32_t addend)
{
#if defined(GIT_WIN32)
return InterlockedExchangeAdd(&a->val, addend);
return InterlockedAdd(&a->val, addend);
#elif defined(GIT_BUILTIN_ATOMIC)
return __atomic_add_fetch(&a->val, addend, __ATOMIC_SEQ_CST);
#elif defined(GIT_BUILTIN_SYNC)
......@@ -113,6 +124,10 @@ GIT_INLINE(int) git_atomic32_add(git_atomic32 *a, int32_t addend)
#endif
}
/*
* Atomically decrements the contents of *a by 1, and stores the result back into *a.
* @return the result of the operation.
*/
GIT_INLINE(int) git_atomic32_dec(git_atomic32 *a)
{
#if defined(GIT_WIN32)
......@@ -126,6 +141,10 @@ GIT_INLINE(int) git_atomic32_dec(git_atomic32 *a)
#endif
}
/*
* Atomically gets the contents of *a.
* @return the contents of *a.
*/
GIT_INLINE(int) git_atomic32_get(git_atomic32 *a)
{
#if defined(GIT_WIN32)
......@@ -143,16 +162,13 @@ GIT_INLINE(void *) git_atomic__compare_and_swap(
void * volatile *ptr, void *oldval, void *newval)
{
#if defined(GIT_WIN32)
volatile void *foundval;
foundval = InterlockedCompareExchangePointer((volatile PVOID *)ptr, newval, oldval);
return (foundval == oldval) ? oldval : newval;
return InterlockedCompareExchangePointer((volatile PVOID *)ptr, newval, oldval);
#elif defined(GIT_BUILTIN_ATOMIC)
bool success = __atomic_compare_exchange(ptr, &oldval, &newval, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return success ? oldval : newval;
void *foundval = oldval;
__atomic_compare_exchange(ptr, &foundval, &newval, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return foundval;
#elif defined(GIT_BUILTIN_SYNC)
volatile void *foundval;
foundval = __sync_val_compare_and_swap(ptr, oldval, newval);
return (foundval == oldval) ? oldval : newval;
return __sync_val_compare_and_swap(ptr, oldval, newval);
#else
# error "Unsupported architecture for atomic operations"
#endif
......@@ -164,11 +180,11 @@ GIT_INLINE(volatile void *) git_atomic__swap(
#if defined(GIT_WIN32)
return InterlockedExchangePointer(ptr, newval);
#elif defined(GIT_BUILTIN_ATOMIC)
void * volatile foundval;
void * volatile foundval = NULL;
__atomic_exchange(ptr, &newval, &foundval, __ATOMIC_SEQ_CST);
return foundval;
#elif defined(GIT_BUILTIN_SYNC)
return __sync_lock_test_and_set(ptr, newval);
return (volatile void *)__sync_lock_test_and_set(ptr, newval);
#else
# error "Unsupported architecture for atomic operations"
#endif
......@@ -178,9 +194,7 @@ GIT_INLINE(volatile void *) git_atomic__load(void * volatile *ptr)
{
#if defined(GIT_WIN32)
void *newval = NULL, *oldval = NULL;
volatile void *foundval = NULL;
foundval = InterlockedCompareExchangePointer((volatile PVOID *)ptr, newval, oldval);
return foundval;
return (volatile void *)InterlockedCompareExchangePointer((volatile PVOID *)ptr, newval, oldval);
#elif defined(GIT_BUILTIN_ATOMIC)
return (volatile void *)__atomic_load_n(ptr, __ATOMIC_SEQ_CST);
#elif defined(GIT_BUILTIN_SYNC)
......@@ -192,10 +206,14 @@ GIT_INLINE(volatile void *) git_atomic__load(void * volatile *ptr)
#ifdef GIT_ARCH_64
/*
* Atomically adds the contents of *a and addend, and stores the result back into *a.
* @return the result of the operation.
*/
GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
{
#if defined(GIT_WIN32)
return InterlockedExchangeAdd64(&a->val, addend);
return InterlockedAdd64(&a->val, addend);
#elif defined(GIT_BUILTIN_ATOMIC)
return __atomic_add_fetch(&a->val, addend, __ATOMIC_SEQ_CST);
#elif defined(GIT_BUILTIN_SYNC)
......@@ -205,6 +223,9 @@ GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
#endif
}
/*
* Atomically sets the contents of *a to be val.
*/
GIT_INLINE(void) git_atomic64_set(git_atomic64 *a, int64_t val)
{
#if defined(GIT_WIN32)
......@@ -218,6 +239,10 @@ GIT_INLINE(void) git_atomic64_set(git_atomic64 *a, int64_t val)
#endif
}
/*
* Atomically gets the contents of *a.
* @return the contents of *a.
*/
GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a)
{
#if defined(GIT_WIN32)
......@@ -297,11 +322,10 @@ GIT_INLINE(int) git_atomic32_get(git_atomic32 *a)
GIT_INLINE(void *) git_atomic__compare_and_swap(
void * volatile *ptr, void *oldval, void *newval)
{
if (*ptr == oldval)
void *foundval = *ptr;
if (foundval == oldval)
*ptr = newval;
else
oldval = newval;
return oldval;
return foundval;
}
GIT_INLINE(volatile void *) git_atomic__swap(
......@@ -339,17 +363,50 @@ GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a)
#endif
/* Atomically replace oldval with newval
* @return oldval if it was replaced or newval if it was not
/*
* Atomically replace the contents of *ptr (if they are equal to oldval) with
* newval. ptr must point to a pointer or a value that is the same size as a
* pointer. This is semantically compatible with:
*
* #define git_atomic_compare_and_swap(ptr, oldval, newval) \
* ({ \
* void *foundval = *ptr; \
* if (foundval == oldval) \
* *ptr = newval; \
* foundval; \
* })
*
* @return the original contents of *ptr.
*/
#define git_atomic_compare_and_swap(P,O,N) \
git_atomic__compare_and_swap((void * volatile *)P, O, N)
#define git_atomic_compare_and_swap(ptr, oldval, newval) \
git_atomic__compare_and_swap((void * volatile *)ptr, oldval, newval)
#define git_atomic_swap(ptr, val) \
(void *)git_atomic__swap((void * volatile *)&ptr, val)
/*
* Atomically replace the contents of v with newval. v must be the same size as
* a pointer. This is semantically compatible with:
*
* #define git_atomic_swap(v, newval) \
* ({ \
* volatile void *old = v; \
* v = newval; \
* old; \
* })
*
* @return the original contents of v.
*/
#define git_atomic_swap(v, newval) \
(void *)git_atomic__swap((void * volatile *)&(v), newval)
#define git_atomic_load(ptr) \
(void *)git_atomic__load((void * volatile *)&ptr)
/*
* Atomically reads the contents of v. v must be the same size as a pointer.
* This is semantically compatible with:
*
* #define git_atomic_load(v) v
*
* @return the contents of v.
*/
#define git_atomic_load(v) \
(void *)git_atomic__load((void * volatile *)&(v))
#if defined(GIT_THREADS)
......
......@@ -172,7 +172,7 @@ void test_clone_nonetwork__can_checkout_given_branch(void)
cl_git_pass(git_reference_lookup(&remote_head, g_repo, "refs/remotes/origin/HEAD"));
cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC, git_reference_type(remote_head));
cl_assert_equal_s("refs/remotes/origin/test", git_reference_symbolic_target(remote_head));
cl_assert_equal_s("refs/remotes/origin/master", git_reference_symbolic_target(remote_head));
git_reference_free(remote_head);
}
......
......@@ -964,7 +964,7 @@ void test_config_read__get_mapped(void)
" key9 = off\n");
cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
// check parsing bool and string
/* check parsing bool and string */
cl_git_pass(git_config_get_mapped(&val, cfg, "header.key1", _test_map1, ARRAY_SIZE(_test_map1)));
cl_assert_equal_i(val, MAP_TRUE);
cl_git_pass(git_config_get_mapped(&val, cfg, "header.key2", _test_map1, ARRAY_SIZE(_test_map1)));
......@@ -986,7 +986,7 @@ void test_config_read__get_mapped(void)
cl_git_fail(git_config_get_mapped(&val, cfg, "header.key7", _test_map1, ARRAY_SIZE(_test_map1)));
// check parsing int values
/* check parsing int values */
cl_git_pass(git_config_get_mapped(&val, cfg, "header.key1", _test_map2, ARRAY_SIZE(_test_map2)));
cl_git_pass(git_config_get_int32(&known_good, cfg, "header.key1"));
cl_assert_equal_i(val, known_good);
......
......@@ -107,4 +107,4 @@ void test_pack_midx__odb_create(void)
git_buf_dispose(&expected_midx);
cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES));
}
}
\ No newline at end of file
......@@ -72,7 +72,7 @@ void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id,
.strings = &refspec_strs,
};
// create two commits in repo 1 and a reference to them
/* create two commits in repo 1 and a reference to them */
{
git_oid empty_tree_id;
git_tree *empty_tree;
......@@ -92,7 +92,7 @@ void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id,
git_treebuilder_free(tb);
}
// fetch the reference via the remote
/* fetch the reference via the remote */
{
git_remote *remote;
......@@ -103,7 +103,7 @@ void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id,
git_remote_free(remote);
}
// assert that repo2 references the second commit
/* assert that repo2 references the second commit */
{
const git_oid *target;
git_reference *ref;
......@@ -113,7 +113,7 @@ void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id,
git_reference_free(ref);
}
// set the reference in repo1 to point to the older commit
/* set the reference in repo1 to point to the older commit */
{
git_reference *ref;
git_reference *ref2;
......@@ -124,7 +124,7 @@ void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id,
git_reference_free(ref2);
}
// fetch the reference again
/* fetch the reference again */
{
git_remote *remote;
......@@ -144,7 +144,7 @@ void test_remote_fetch__dont_update_refs_if_not_descendant_and_not_force(void) {
do_time_travelling_fetch(&commit1id, &commit2id, false);
// assert that the reference in repo2 has not changed
/* assert that the reference in repo2 has not changed */
cl_git_pass(git_reference_lookup(&ref, repo2, REPO2_REFNAME));
target = git_reference_target(ref);
cl_assert_equal_b(git_oid_cmp(target, &commit2id), 0);
......@@ -160,7 +160,7 @@ void test_remote_fetch__do_update_refs_if_not_descendant_and_force(void) {
do_time_travelling_fetch(&commit1id, &commit2id, true);
// assert that the reference in repo2 has changed
/* assert that the reference in repo2 has changed */
cl_git_pass(git_reference_lookup(&ref, repo2, REPO2_REFNAME));
target = git_reference_target(ref);
cl_assert_equal_b(git_oid_cmp(target, &commit1id), 0);
......
#include "clar_libgit2.h"
void test_threads_atomic__atomic32_set(void)
{
git_atomic32 v = {0};
git_atomic32_set(&v, 1);
cl_assert_equal_i(v.val, 1);
}
void test_threads_atomic__atomic32_get(void)
{
git_atomic32 v = {1};
cl_assert_equal_i(git_atomic32_get(&v), 1);
}
void test_threads_atomic__atomic32_inc(void)
{
git_atomic32 v = {0};
cl_assert_equal_i(git_atomic32_inc(&v), 1);
cl_assert_equal_i(v.val, 1);
}
void test_threads_atomic__atomic32_add(void)
{
git_atomic32 v = {0};
cl_assert_equal_i(git_atomic32_add(&v, 1), 1);
cl_assert_equal_i(v.val, 1);
}
void test_threads_atomic__atomic32_dec(void)
{
git_atomic32 v = {1};
cl_assert_equal_i(git_atomic32_dec(&v), 0);
cl_assert_equal_i(v.val, 0);
}
void test_threads_atomic__atomic64_set(void)
{
#ifndef GIT_ARCH_64
cl_skip();
#else
git_atomic64 v = {0};
git_atomic64_set(&v, 1);
cl_assert_equal_i(v.val, 1);
#endif
}
void test_threads_atomic__atomic64_get(void)
{
#ifndef GIT_ARCH_64
cl_skip();
#else
git_atomic64 v = {1};
cl_assert_equal_i(git_atomic64_get(&v), 1);
#endif
}
void test_threads_atomic__atomic64_add(void)
{
#ifndef GIT_ARCH_64
cl_skip();
#else
git_atomic64 v = {0};
cl_assert_equal_i(git_atomic64_add(&v, 1), 1);
cl_assert_equal_i(v.val, 1);
#endif
}
void test_threads_atomic__cas_pointer(void)
{
int *value = NULL;
int newvalue1 = 1, newvalue2 = 2;
/* value is updated */
cl_assert_equal_p(git_atomic_compare_and_swap(&value, NULL, &newvalue1), NULL);
cl_assert_equal_p(value, &newvalue1);
/* value is not updated */
cl_assert_equal_p(git_atomic_compare_and_swap(&value, NULL, &newvalue2), &newvalue1);
cl_assert_equal_p(value, &newvalue1);
}
void test_threads_atomic__cas_intptr(void)
{
intptr_t value = 0;
intptr_t oldvalue;
intptr_t newvalue;
/* value is updated */
oldvalue = 0;
newvalue = 1;
cl_assert_equal_i((intptr_t)git_atomic_compare_and_swap(&value, (void *)oldvalue, (void *)newvalue), 0);
cl_assert_equal_i(value, 1);
/* value is not updated */
oldvalue = 0;
newvalue = 2;
cl_assert_equal_i((intptr_t)git_atomic_compare_and_swap(&value, (void *)oldvalue, (void *)newvalue), 1);
cl_assert_equal_i(value, 1);
}
void test_threads_atomic__swap(void)
{
int *value = NULL;
int newvalue = 1;
cl_assert_equal_p(git_atomic_swap(value, &newvalue), NULL);
cl_assert_equal_p(value, &newvalue);
cl_assert_equal_p(git_atomic_swap(value, NULL), &newvalue);
cl_assert_equal_p(value, NULL);
}
void test_threads_atomic__load_ptr(void)
{
int value = 1;
int *ptr = &value;
cl_assert_equal_p(git_atomic_load(ptr), &value);
}
void test_threads_atomic__load_intptr(void)
{
intptr_t value = 1;
cl_assert_equal_i((intptr_t)git_atomic_load(value), 1);
}
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