Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Unity-Technologies/libatomic_ops.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Peterson <joshuap@unity3d.com>2019-05-15 22:03:32 +0300
committerGitHub <noreply@github.com>2019-05-15 22:03:32 +0300
commitaf8fe9c5e67de215f63e635cfd2f43eafaf40d80 (patch)
treed6a5b0189b08f92f72100f7420d57ec4a337b25a
parent46722271b57ce1dccf8440cd53fe894ed355c282 (diff)
parente83ba1ffe3c1fe092068b26cab4e3bb0523ae44c (diff)
Merge pull request #1 from Unity-Technologies/remove-gpl-code
Remove GPL licensed code from the repo
-rw-r--r--src/atomic_ops_malloc.c305
-rw-r--r--src/atomic_ops_malloc.h44
-rw-r--r--src/atomic_ops_stack.c281
-rw-r--r--src/atomic_ops_stack.h188
-rw-r--r--tests/Makefile.am100
-rw-r--r--tests/list_atomic.template117
-rw-r--r--tests/run_parallel.h212
-rw-r--r--tests/test_atomic.c204
-rw-r--r--tests/test_atomic_include.template351
-rw-r--r--tests/test_malloc.c228
-rw-r--r--tests/test_stack.c326
11 files changed, 0 insertions, 2356 deletions
diff --git a/src/atomic_ops_malloc.c b/src/atomic_ops_malloc.c
deleted file mode 100644
index 60757cf..0000000
--- a/src/atomic_ops_malloc.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
- *
- * This file may be redistributed and/or modified under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2, or (at your option) any later version.
- *
- * It is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License in the
- * file COPYING for more details.
- */
-
-#if defined(HAVE_CONFIG_H)
-# include "config.h"
-#endif
-
-#define AO_REQUIRE_CAS
-#include "atomic_ops_malloc.h"
-
-#include <string.h> /* for ffs, which is assumed reentrant. */
-#include <stdlib.h>
-#include <assert.h>
-
-#ifdef AO_TRACE_MALLOC
-# include <stdio.h>
-# include <pthread.h>
-#endif
-
-#if (defined(_WIN32_WCE) || defined(__MINGW32CE__)) && !defined(abort)
-# define abort() _exit(-1) /* there is no abort() in WinCE */
-#endif
-
-/*
- * We round up each allocation request to the next power of two
- * minus one word.
- * We keep one stack of free objects for each size. Each object
- * has an initial word (offset -sizeof(AO_t) from the visible pointer)
- * which contains either
- * The binary log of the object size in bytes (small objects)
- * The object size (a multiple of CHUNK_SIZE) for large objects.
- * The second case only arises if mmap-based allocation is supported.
- * We align the user-visible part of each object on a GRANULARITY
- * byte boundary. That means that the actual (hidden) start of
- * the object starts a word before this boundary.
- */
-
-#ifndef LOG_MAX_SIZE
-# define LOG_MAX_SIZE 16
- /* We assume that 2**LOG_MAX_SIZE is a multiple of page size. */
-#endif
-
-#ifndef ALIGNMENT
-# define ALIGNMENT 16
- /* Assumed to be at least sizeof(AO_t). */
-#endif
-
-#define CHUNK_SIZE (1 << LOG_MAX_SIZE)
-
-#ifndef AO_INITIAL_HEAP_SIZE
-# define AO_INITIAL_HEAP_SIZE (2*(LOG_MAX_SIZE+1)*CHUNK_SIZE)
-#endif
-
-char AO_initial_heap[AO_INITIAL_HEAP_SIZE];
-
-static volatile AO_t initial_heap_ptr = (AO_t)AO_initial_heap;
-
-#if defined(HAVE_MMAP)
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#if defined(MAP_ANONYMOUS) || defined(MAP_ANON)
-# define USE_MMAP_ANON
-#endif
-
-#ifdef USE_MMAP_FIXED
-# define GC_MMAP_FLAGS (MAP_FIXED | MAP_PRIVATE)
- /* Seems to yield better performance on Solaris 2, but can */
- /* be unreliable if something is already mapped at the address. */
-#else
-# define GC_MMAP_FLAGS MAP_PRIVATE
-#endif
-
-#ifdef USE_MMAP_ANON
-# ifdef MAP_ANONYMOUS
-# define OPT_MAP_ANON MAP_ANONYMOUS
-# else
-# define OPT_MAP_ANON MAP_ANON
-# endif
-#else
-# define OPT_MAP_ANON 0
-#endif
-
-static volatile AO_t mmap_enabled = 0;
-
-void
-AO_malloc_enable_mmap(void)
-{
-# if defined(__sun)
- AO_store_release(&mmap_enabled, 1);
- /* Workaround for Sun CC */
-# else
- AO_store(&mmap_enabled, 1);
-# endif
-}
-
-static char *get_mmaped(size_t sz)
-{
- char * result;
-# ifdef USE_MMAP_ANON
-# define zero_fd -1
-# else
- int zero_fd;
-# endif
-
- assert(!(sz & (CHUNK_SIZE - 1)));
- if (!mmap_enabled)
- return 0;
-
-# ifndef USE_MMAP_ANON
- zero_fd = open("/dev/zero", O_RDONLY);
- if (zero_fd == -1)
- return 0;
-# endif
- result = mmap(0, sz, PROT_READ | PROT_WRITE,
- GC_MMAP_FLAGS | OPT_MAP_ANON, zero_fd, 0/* offset */);
-# ifndef USE_MMAP_ANON
- close(zero_fd);
-# endif
- if (result == MAP_FAILED)
- result = 0;
- return result;
-}
-
-/* Allocate an object of size (incl. header) of size > CHUNK_SIZE. */
-/* sz includes space for an AO_t-sized header. */
-static char *
-AO_malloc_large(size_t sz)
-{
- char * result;
- /* The header will force us to waste ALIGNMENT bytes, incl. header. */
- sz += ALIGNMENT;
- /* Round to multiple of CHUNK_SIZE. */
- sz = (sz + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1);
- result = get_mmaped(sz);
- if (result == 0) return 0;
- result += ALIGNMENT;
- ((AO_t *)result)[-1] = (AO_t)sz;
- return result;
-}
-
-static void
-AO_free_large(char * p)
-{
- AO_t sz = ((AO_t *)p)[-1];
- if (munmap(p - ALIGNMENT, (size_t)sz) != 0)
- abort(); /* Programmer error. Not really async-signal-safe, but ... */
-}
-
-
-#else /* No MMAP */
-
-void
-AO_malloc_enable_mmap(void)
-{
-}
-
-#define get_mmaped(sz) ((char*)0)
-#define AO_malloc_large(sz) ((char*)0)
-#define AO_free_large(p) abort()
- /* Programmer error. Not really async-signal-safe, but ... */
-
-#endif /* No MMAP */
-
-static char *
-get_chunk(void)
-{
- char *my_chunk_ptr;
-
- for (;;) {
- char *initial_ptr = (char *)AO_load(&initial_heap_ptr);
-
- my_chunk_ptr = (char *)(((AO_t)initial_ptr + (ALIGNMENT - 1))
- & ~(ALIGNMENT - 1));
- if (initial_ptr != my_chunk_ptr)
- {
- /* Align correctly. If this fails, someone else did it for us. */
- (void)AO_compare_and_swap_acquire(&initial_heap_ptr,
- (AO_t)initial_ptr, (AO_t)my_chunk_ptr);
- }
-
- if (my_chunk_ptr - AO_initial_heap > AO_INITIAL_HEAP_SIZE - CHUNK_SIZE)
- break;
- if (AO_compare_and_swap(&initial_heap_ptr, (AO_t)my_chunk_ptr,
- (AO_t)(my_chunk_ptr + CHUNK_SIZE))) {
- return my_chunk_ptr;
- }
- }
-
- /* We failed. The initial heap is used up. */
- my_chunk_ptr = get_mmaped(CHUNK_SIZE);
- assert (!((AO_t)my_chunk_ptr & (ALIGNMENT-1)));
- return my_chunk_ptr;
-}
-
-/* Object free lists. Ith entry corresponds to objects */
-/* of total size 2**i bytes. */
-AO_stack_t AO_free_list[LOG_MAX_SIZE+1];
-
-/* Break up the chunk, and add it to the object free list for */
-/* the given size. We have exclusive access to chunk. */
-static void add_chunk_as(void * chunk, unsigned log_sz)
-{
- size_t ofs, limit;
- size_t sz = (size_t)1 << log_sz;
-
- assert (CHUNK_SIZE >= sz);
- limit = (size_t)CHUNK_SIZE - sz;
- for (ofs = ALIGNMENT - sizeof(AO_t); ofs <= limit; ofs += sz) {
- AO_stack_push(&AO_free_list[log_sz], (AO_t *)((char *)chunk + ofs));
- }
-}
-
-static const int msbs[16] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};
-
-/* Return the position of the most significant set bit in the */
-/* argument. */
-/* We follow the conventions of ffs(), i.e. the least */
-/* significant bit is number one. */
-static int msb(size_t s)
-{
- int result = 0;
- int v;
- if ((s & 0xff) != s) {
- /* The following is a tricky code ought to be equivalent to */
- /* "(v = s >> 32) != 0" but suppresses warnings on 32-bit arch's. */
- if (sizeof(size_t) > 4 && (v = s >> (sizeof(size_t) > 4 ? 32 : 0)) != 0)
- {
- s = v;
- result += 32;
- }
- if ((s >> 16) != 0)
- {
- s >>= 16;
- result += 16;
- }
- if ((s >> 8) != 0)
- {
- s >>= 8;
- result += 8;
- }
- }
- if (s > 15)
- {
- s >>= 4;
- result += 4;
- }
- result += msbs[s];
- return result;
-}
-
-void *
-AO_malloc(size_t sz)
-{
- AO_t *result;
- int log_sz;
-
- if (sz > CHUNK_SIZE)
- return AO_malloc_large(sz);
- log_sz = msb(sz + (sizeof(AO_t) - 1));
- result = AO_stack_pop(AO_free_list+log_sz);
- while (0 == result) {
- void * chunk = get_chunk();
- if (0 == chunk) return 0;
- add_chunk_as(chunk, log_sz);
- result = AO_stack_pop(AO_free_list+log_sz);
- }
- *result = log_sz;
-# ifdef AO_TRACE_MALLOC
- fprintf(stderr, "%x: AO_malloc(%lu) = %p\n",
- (int)pthread_self(), (unsigned long)sz, result+1);
-# endif
- return result + 1;
-}
-
-void
-AO_free(void *p)
-{
- char *base = (char *)p - sizeof(AO_t);
- int log_sz;
-
- if (0 == p) return;
- log_sz = (int)(*(AO_t *)base);
-# ifdef AO_TRACE_MALLOC
- fprintf(stderr, "%x: AO_free(%p sz:%lu)\n", (int)pthread_self(), p,
- (unsigned long)(log_sz > LOG_MAX_SIZE? log_sz : (1 << log_sz)));
-# endif
- if (log_sz > LOG_MAX_SIZE)
- AO_free_large(p);
- else
- AO_stack_push(AO_free_list+log_sz, (AO_t *)base);
-}
diff --git a/src/atomic_ops_malloc.h b/src/atomic_ops_malloc.h
deleted file mode 100644
index e324d5b..0000000
--- a/src/atomic_ops_malloc.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* Almost lock-free malloc implementation based on stack implementation. */
-/* See doc/README_malloc.txt file for detailed usage rules. */
-
-#ifndef AO_MALLOC_H
-#define AO_MALLOC_H
-
-#include "atomic_ops_stack.h"
-
-#include <stddef.h> /* for size_t */
-
-#ifdef AO_STACK_IS_LOCK_FREE
-# define AO_MALLOC_IS_LOCK_FREE
-#endif
-
-void AO_free(void *);
-
-void * AO_malloc(size_t);
-
-/* Allow use of mmap to grow the heap. No-op on some platforms. */
-void AO_malloc_enable_mmap(void);
-
-#endif /* !AO_MALLOC_H */
diff --git a/src/atomic_ops_stack.c b/src/atomic_ops_stack.c
deleted file mode 100644
index 642bac0..0000000
--- a/src/atomic_ops_stack.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
- *
- * This file may be redistributed and/or modified under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2, or (at your option) any later version.
- *
- * It is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License in the
- * file COPYING for more details.
- */
-
-#if defined(HAVE_CONFIG_H)
-# include "config.h"
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#define AO_REQUIRE_CAS
-#include "atomic_ops_stack.h"
-
-#ifdef AO_USE_ALMOST_LOCK_FREE
-
- void AO_pause(int); /* defined in atomic_ops.c */
-
-/* LIFO linked lists based on compare-and-swap. We need to avoid */
-/* the case of a node deletion and reinsertion while I'm deleting */
-/* it, since that may cause my CAS to succeed eventhough the next */
-/* pointer is now wrong. Our solution is not fully lock-free, but it */
-/* is good enough for signal handlers, provided we have a suitably low */
-/* bound on the number of recursive signal handler reentries. */
-/* A list consists of a first pointer and a blacklist */
-/* of pointer values that are currently being removed. No list element */
-/* on the blacklist may be inserted. If we would otherwise do so, we */
-/* are allowed to insert a variant that differs only in the least */
-/* significant, ignored, bits. If the list is full, we wait. */
-
-/* Crucial observation: A particular padded pointer x (i.e. pointer */
-/* plus arbitrary low order bits) can never be newly inserted into */
-/* a list while it's in the corresponding auxiliary data structure. */
-
-/* The second argument is a pointer to the link field of the element */
-/* to be inserted. */
-/* Both list headers and link fields contain "perturbed" pointers, i.e. */
-/* pointers with extra bits "or"ed into the low order bits. */
-void
-AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x,
- AO_stack_aux *a)
-{
- AO_t x_bits = (AO_t)x;
- AO_t next;
-
- /* No deletions of x can start here, since x is not currently in the */
- /* list. */
- retry:
-# if AO_BL_SIZE == 2
- {
- /* Start all loads as close to concurrently as possible. */
- AO_t entry1 = AO_load(a -> AO_stack_bl);
- AO_t entry2 = AO_load(a -> AO_stack_bl + 1);
- if (entry1 == x_bits || entry2 == x_bits)
- {
- /* Entry is currently being removed. Change it a little. */
- ++x_bits;
- if ((x_bits & AO_BIT_MASK) == 0)
- /* Version count overflowed; */
- /* EXTREMELY unlikely, but possible. */
- x_bits = (AO_t)x;
- goto retry;
- }
- }
-# else
- {
- int i;
- for (i = 0; i < AO_BL_SIZE; ++i)
- {
- if (AO_load(a -> AO_stack_bl + i) == x_bits)
- {
- /* Entry is currently being removed. Change it a little. */
- ++x_bits;
- if ((x_bits & AO_BIT_MASK) == 0)
- /* Version count overflowed; */
- /* EXTREMELY unlikely, but possible. */
- x_bits = (AO_t)x;
- goto retry;
- }
- }
- }
-# endif
- /* x_bits is not currently being deleted */
- do
- {
- next = AO_load(list);
- *x = next;
- }
- while (AO_EXPECT_FALSE(!AO_compare_and_swap_release(list, next, x_bits)));
-}
-
-/*
- * I concluded experimentally that checking a value first before
- * performing a compare-and-swap is usually beneficial on X86, but
- * slows things down appreciably with contention on Itanium.
- * Since the Itanium behavior makes more sense to me (more cache line
- * movement unless we're mostly reading, but back-off should guard
- * against that), we take Itanium as the default. Measurements on
- * other multiprocessor architectures would be useful. (On a uniprocessor,
- * the initial check is almost certainly a very small loss.) - HB
- */
-#ifdef __i386__
-# define PRECHECK(a) (a) == 0 &&
-#else
-# define PRECHECK(a)
-#endif
-
-AO_t *
-AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux * a)
-{
- unsigned i;
- int j = 0;
- AO_t first;
- AO_t * first_ptr;
- AO_t next;
-
- retry:
- first = AO_load(list);
- if (0 == first) return 0;
- /* Insert first into aux black list. */
- /* This may spin if more than AO_BL_SIZE removals using auxiliary */
- /* structure a are currently in progress. */
- for (i = 0; ; )
- {
- if (PRECHECK(a -> AO_stack_bl[i])
- AO_compare_and_swap_acquire(a->AO_stack_bl+i, 0, first))
- break;
- ++i;
- if ( i >= AO_BL_SIZE )
- {
- i = 0;
- AO_pause(++j);
- }
- }
- assert(i < AO_BL_SIZE);
- assert(a -> AO_stack_bl[i] == first);
- /* First is on the auxiliary black list. It may be removed by */
- /* another thread before we get to it, but a new insertion of x */
- /* cannot be started here. */
- /* Only we can remove it from the black list. */
- /* We need to make sure that first is still the first entry on the */
- /* list. Otherwise it's possible that a reinsertion of it was */
- /* already started before we added the black list entry. */
-# if defined(__alpha__) && (__GNUC__ == 4)
- if (first != AO_load(list))
- /* Workaround __builtin_expect bug found in */
- /* gcc-4.6.3/alpha causing test_stack failure. */
-# else
- if (AO_EXPECT_FALSE(first != AO_load(list)))
-# endif
- {
- AO_store_release(a->AO_stack_bl+i, 0);
- goto retry;
- }
- first_ptr = AO_REAL_NEXT_PTR(first);
- next = AO_load(first_ptr);
-# if defined(__alpha__) && (__GNUC__ == 4)
- if (!AO_compare_and_swap_release(list, first, next))
-# else
- if (AO_EXPECT_FALSE(!AO_compare_and_swap_release(list, first, next)))
-# endif
- {
- AO_store_release(a->AO_stack_bl+i, 0);
- goto retry;
- }
- assert(*list != first);
- /* Since we never insert an entry on the black list, this cannot have */
- /* succeeded unless first remained on the list while we were running. */
- /* Thus its next link cannot have changed out from under us, and we */
- /* removed exactly one entry and preserved the rest of the list. */
- /* Note that it is quite possible that an additional entry was */
- /* inserted and removed while we were running; this is OK since the */
- /* part of the list following first must have remained unchanged, and */
- /* first must again have been at the head of the list when the */
- /* compare_and_swap succeeded. */
- AO_store_release(a->AO_stack_bl+i, 0);
- return first_ptr;
-}
-
-#else /* ! USE_ALMOST_LOCK_FREE */
-
-/* Better names for fields in AO_stack_t */
-#define ptr AO_val2
-#define version AO_val1
-
-#if defined(AO_HAVE_compare_double_and_swap_double)
-
-void AO_stack_push_release(AO_stack_t *list, AO_t *element)
-{
- AO_t next;
-
- do {
- next = AO_load(&(list -> ptr));
- *element = next;
- } while (AO_EXPECT_FALSE(!AO_compare_and_swap_release(&(list -> ptr),
- next, (AO_t)element)));
- /* This uses a narrow CAS here, an old optimization suggested */
- /* by Treiber. Pop is still safe, since we run into the ABA */
- /* problem only if there were both intervening "pop"s and "push"es. */
- /* In that case we still see a change in the version number. */
-}
-
-AO_t *AO_stack_pop_acquire(AO_stack_t *list)
-{
-# ifdef __clang__
- AO_t *volatile cptr;
- /* Use volatile to workaround a bug in */
- /* clang-1.1/x86 causing test_stack failure. */
-# else
- AO_t *cptr;
-# endif
- AO_t next;
- AO_t cversion;
-
- do {
- /* Version must be loaded first. */
- cversion = AO_load_acquire(&(list -> version));
- cptr = (AO_t *)AO_load(&(list -> ptr));
- if (cptr == 0) return 0;
- next = *cptr;
- } while (AO_EXPECT_FALSE(!AO_compare_double_and_swap_double_release(list,
- cversion, (AO_t)cptr,
- cversion+1, (AO_t)next)));
- return cptr;
-}
-
-
-#elif defined(AO_HAVE_compare_and_swap_double)
-
-/* Needed for future IA64 processors. No current clients? */
-
-#error Untested! Probably doesnt work.
-
-/* We have a wide CAS, but only does an AO_t-wide comparison. */
-/* We can't use the Treiber optimization, since we only check */
-/* for an unchanged version number, not an unchanged pointer. */
-void AO_stack_push_release(AO_stack_t *list, AO_t *element)
-{
- AO_t version;
- AO_t next_ptr;
-
- do {
- /* Again version must be loaded first, for different reason. */
- version = AO_load_acquire(&(list -> version));
- next_ptr = AO_load(&(list -> ptr));
- *element = next_ptr;
- } while (!AO_compare_and_swap_double_release(
- list, version,
- version+1, (AO_t) element));
-}
-
-AO_t *AO_stack_pop_acquire(AO_stack_t *list)
-{
- AO_t *cptr;
- AO_t next;
- AO_t cversion;
-
- do {
- cversion = AO_load_acquire(&(list -> version));
- cptr = (AO_t *)AO_load(&(list -> ptr));
- if (cptr == 0) return 0;
- next = *cptr;
- } while (!AO_compare_double_and_swap_double_release
- (list, cversion, (AO_t) cptr, cversion+1, next));
- return cptr;
-}
-
-
-#endif /* AO_HAVE_compare_and_swap_double */
-
-#endif /* ! USE_ALMOST_LOCK_FREE */
diff --git a/src/atomic_ops_stack.h b/src/atomic_ops_stack.h
deleted file mode 100644
index 1ca5f40..0000000
--- a/src/atomic_ops_stack.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * The implementation of the routines described here is covered by the GPL.
- * This header file is covered by the following license:
- */
-
-/*
- * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* Almost lock-free LIFO linked lists (linked stacks). */
-#ifndef AO_STACK_H
-#define AO_STACK_H
-
-#include "atomic_ops.h"
-
-#if !defined(AO_HAVE_compare_double_and_swap_double) \
- && !defined(AO_HAVE_compare_double_and_swap) \
- && defined(AO_HAVE_compare_and_swap)
-# define AO_USE_ALMOST_LOCK_FREE
-#else
- /* If we have no compare-and-swap operation defined, we assume */
- /* that we will actually be using CAS emulation. If we do that, */
- /* it's cheaper to use the version-based implementation. */
-# define AO_STACK_IS_LOCK_FREE
-#endif
-
-/*
- * These are not guaranteed to be completely lock-free.
- * List insertion may spin under extremely unlikely conditions.
- * It cannot deadlock due to recursive reentry unless AO_list_remove
- * is called while at least AO_BL_SIZE activations of
- * AO_list_remove are currently active in the same thread, i.e.
- * we must have at least AO_BL_SIZE recursive signal handler
- * invocations.
- *
- * All operations take an AO_list_aux argument. It is safe to
- * share a single AO_list_aux structure among all lists, but that
- * may increase contention. Any given list must always be accessed
- * with the same AO_list_aux structure.
- *
- * We make some machine-dependent assumptions:
- * - We have a compare-and-swap operation.
- * - At least _AO_N_BITS low order bits in pointers are
- * zero and normally unused.
- * - size_t and pointers have the same size.
- *
- * We do use a fully lock-free implementation if double-width
- * compare-and-swap operations are available.
- */
-
-#ifdef AO_USE_ALMOST_LOCK_FREE
-/* The number of low order pointer bits we can use for a small */
-/* version number. */
-# if defined(__LP64__) || defined(_LP64) || defined(_WIN64)
- /* WIN64 isn't really supported yet. */
-# define AO_N_BITS 3
-# else
-# define AO_N_BITS 2
-# endif
-
-# define AO_BIT_MASK ((1 << AO_N_BITS) - 1)
-/*
- * AO_stack_aux should be treated as opaque.
- * It is fully defined here, so it can be allocated, and to facilitate
- * debugging.
- */
-#ifndef AO_BL_SIZE
-# define AO_BL_SIZE 2
-#endif
-
-#if AO_BL_SIZE > (1 << AO_N_BITS)
-# error AO_BL_SIZE too big
-#endif
-
-typedef struct AO__stack_aux {
- volatile AO_t AO_stack_bl[AO_BL_SIZE];
-} AO_stack_aux;
-
-/* The stack implementation knows only about the location of */
-/* link fields in nodes, and nothing about the rest of the */
-/* stack elements. Link fields hold an AO_t, which is not */
-/* necessarily a real pointer. This converts the AO_t to a */
-/* real (AO_t *) which is either o, or points at the link */
-/* field in the next node. */
-#define AO_REAL_NEXT_PTR(x) (AO_t *)((x) & ~AO_BIT_MASK)
-
-/* The following two routines should not normally be used directly. */
-/* We make them visible here for the rare cases in which it makes sense */
-/* to share the an AO_stack_aux between stacks. */
-void
-AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x,
- AO_stack_aux *);
-
-AO_t *
-AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux *);
-
-/* And now AO_stack_t for the real interface: */
-
-typedef struct AO__stack {
- volatile AO_t AO_ptr;
- AO_stack_aux AO_aux;
-} AO_stack_t;
-
-#define AO_STACK_INITIALIZER {0,{{0}}}
-
-AO_INLINE void AO_stack_init(AO_stack_t *list)
-{
-# if AO_BL_SIZE == 2
- list -> AO_aux.AO_stack_bl[0] = 0;
- list -> AO_aux.AO_stack_bl[1] = 0;
-# else
- int i;
- for (i = 0; i < AO_BL_SIZE; ++i)
- list -> AO_aux.AO_stack_bl[i] = 0;
-# endif
- list -> AO_ptr = 0;
-}
-
-/* Convert an AO_stack_t to a pointer to the link field in */
-/* the first element. */
-#define AO_REAL_HEAD_PTR(x) AO_REAL_NEXT_PTR((x).AO_ptr)
-
-#define AO_stack_push_release(l, e) \
- AO_stack_push_explicit_aux_release(&((l)->AO_ptr), e, &((l)->AO_aux))
-#define AO_HAVE_stack_push_release
-
-#define AO_stack_pop_acquire(l) \
- AO_stack_pop_explicit_aux_acquire(&((l)->AO_ptr), &((l)->AO_aux))
-#define AO_HAVE_stack_pop_acquire
-
-# else /* Use fully non-blocking data structure, wide CAS */
-
-#ifndef AO_HAVE_double_t
- /* Can happen if we're using CAS emulation, since we don't want to */
- /* force that here, in case other atomic_ops clients don't want it. */
-# include "atomic_ops/sysdeps/standard_ao_double_t.h"
-#endif
-
-typedef volatile AO_double_t AO_stack_t;
-/* AO_val1 is version, AO_val2 is pointer. */
-
-#define AO_STACK_INITIALIZER AO_DOUBLE_T_INITIALIZER
-
-AO_INLINE void AO_stack_init(AO_stack_t *list)
-{
- list -> AO_val1 = 0;
- list -> AO_val2 = 0;
-}
-
-#define AO_REAL_HEAD_PTR(x) (AO_t *)((x).AO_val2)
-#define AO_REAL_NEXT_PTR(x) (AO_t *)(x)
-
-void AO_stack_push_release(AO_stack_t *list, AO_t *new_element);
-#define AO_HAVE_stack_push_release
-AO_t * AO_stack_pop_acquire(AO_stack_t *list);
-#define AO_HAVE_stack_pop_acquire
-
-#endif /* Wide CAS case */
-
-#if defined(AO_HAVE_stack_push_release) && !defined(AO_HAVE_stack_push)
-# define AO_stack_push(l, e) AO_stack_push_release(l, e)
-# define AO_HAVE_stack_push
-#endif
-
-#if defined(AO_HAVE_stack_pop_acquire) && !defined(AO_HAVE_stack_pop)
-# define AO_stack_pop(l) AO_stack_pop_acquire(l)
-# define AO_HAVE_stack_pop
-#endif
-
-#endif /* !AO_STACK_H */
diff --git a/tests/Makefile.am b/tests/Makefile.am
deleted file mode 100644
index 6bfe33c..0000000
--- a/tests/Makefile.am
+++ /dev/null
@@ -1,100 +0,0 @@
-EXTRA_DIST=test_atomic_include.template list_atomic.template run_parallel.h \
- test_atomic_include.h list_atomic.c
-# We distribute test_atomic_include.h and list_atomic.c, since it is hard
-# to regenerate them on Windows without sed.
-
-BUILT_SOURCES = test_atomic_include.h list_atomic.i list_atomic.o
-CLEANFILES = list_atomic.i list_atomic.o
-
-AM_CPPFLAGS = \
- -I$(top_builddir)/src -I$(top_srcdir)/src \
- -I$(top_builddir)/tests -I$(top_srcdir)/tests
-
-if HAVE_PTHREAD_H
-TESTS=test_atomic test_atomic_pthreads test_stack test_malloc
-test_atomic_pthreads_SOURCES=$(test_atomic_SOURCES)
-test_atomic_pthreads_CPPFLAGS=-DAO_USE_PTHREAD_DEFS $(AM_CPPFLAGS)
-test_atomic_pthreads_LDADD=$(test_atomic_LDADD)
-else
-TESTS=test_atomic test_stack test_malloc
-endif
-
-check_PROGRAMS=$(TESTS)
-
-test_atomic_SOURCES=test_atomic.c
-test_atomic_LDADD = $(THREADDLLIBS) $(top_builddir)/src/libatomic_ops.la
-
-test_stack_SOURCES=test_stack.c
-test_stack_LDADD = $(THREADDLLIBS) \
- $(top_builddir)/src/libatomic_ops_gpl.la \
- $(top_builddir)/src/libatomic_ops.la
-
-test_malloc_SOURCES=test_malloc.c
-test_malloc_LDADD = $(THREADDLLIBS) \
- $(top_builddir)/src/libatomic_ops_gpl.la \
- $(top_builddir)/src/libatomic_ops.la
-
-test_atomic_include.h: test_atomic_include.template
- sed -e s:XX::g $? > $@
- sed -e s:XX:_release:g $? >> $@
- sed -e s:XX:_acquire:g $? >> $@
- sed -e s:XX:_read:g $? >> $@
- sed -e s:XX:_write:g $? >> $@
- sed -e s:XX:_full:g $? >> $@
- sed -e s:XX:_release_write:g $? >> $@
- sed -e s:XX:_acquire_read:g $? >> $@
-
-list_atomic.c: list_atomic.template
- echo "#include \"atomic_ops.h\"" > $@
- sed -e s:XSIZE_::g -e s:XCTYPE:AO_t:g -e s:XX::g $? >> $@
- sed -e s:XSIZE_::g -e s:XCTYPE:AO_t:g -e s:XX:_release:g $? >> $@
- sed -e s:XSIZE_::g -e s:XCTYPE:AO_t:g -e s:XX:_acquire:g $? >> $@
- sed -e s:XSIZE_::g -e s:XCTYPE:AO_t:g -e s:XX:_read:g $? >> $@
- sed -e s:XSIZE_::g -e s:XCTYPE:AO_t:g -e s:XX:_write:g $? >> $@
- sed -e s:XSIZE_::g -e s:XCTYPE:AO_t:g -e s:XX:_full:g $? >> $@
- sed -e s:XSIZE_::g -e s:XCTYPE:AO_t:g -e s:XX:_release_write:g $? >> $@
- sed -e s:XSIZE_::g -e s:XCTYPE:AO_t:g -e s:XX:_acquire_read:g $? >> $@
- sed -e s:XSIZE_::g -e s:XCTYPE:AO_t:g -e s:XX:_dd_acquire_read:g $? >> $@
- sed -e s:XSIZE:char:g -e s:XCTYPE:unsigned/**/char:g -e s:XX::g $? >> $@
- sed -e s:XSIZE:char:g -e s:XCTYPE:unsigned/**/char:g -e s:XX:_release:g $? >> $@
- sed -e s:XSIZE:char:g -e s:XCTYPE:unsigned/**/char:g -e s:XX:_acquire:g $? >> $@
- sed -e s:XSIZE:char:g -e s:XCTYPE:unsigned/**/char:g -e s:XX:_read:g $? >> $@
- sed -e s:XSIZE:char:g -e s:XCTYPE:unsigned/**/char:g -e s:XX:_write:g $? >> $@
- sed -e s:XSIZE:char:g -e s:XCTYPE:unsigned/**/char:g -e s:XX:_full:g $? >> $@
- sed -e s:XSIZE:char:g -e s:XCTYPE:unsigned/**/char:g -e s:XX:_release_write:g $? >> $@
- sed -e s:XSIZE:char:g -e s:XCTYPE:unsigned/**/char:g -e s:XX:_acquire_read:g $? >> $@
- sed -e s:XSIZE:char:g -e s:XCTYPE:unsigned/**/char:g -e s:XX:_dd_acquire_read:g $? >> $@
- sed -e s:XSIZE:short:g -e s:XCTYPE:unsigned/**/short:g -e s:XX::g $? >> $@
- sed -e s:XSIZE:short:g -e s:XCTYPE:unsigned/**/short:g -e s:XX:_release:g $? >> $@
- sed -e s:XSIZE:short:g -e s:XCTYPE:unsigned/**/short:g -e s:XX:_acquire:g $? >> $@
- sed -e s:XSIZE:short:g -e s:XCTYPE:unsigned/**/short:g -e s:XX:_read:g $? >> $@
- sed -e s:XSIZE:short:g -e s:XCTYPE:unsigned/**/short:g -e s:XX:_write:g $? >> $@
- sed -e s:XSIZE:short:g -e s:XCTYPE:unsigned/**/short:g -e s:XX:_full:g $? >> $@
- sed -e s:XSIZE:short:g -e s:XCTYPE:unsigned/**/short:g -e s:XX:_release_write:g $? >> $@
- sed -e s:XSIZE:short:g -e s:XCTYPE:unsigned/**/short:g -e s:XX:_acquire_read:g $? >> $@
- sed -e s:XSIZE:short:g -e s:XCTYPE:unsigned/**/short:g -e s:XX:_dd_acquire_read:g $? >> $@
- sed -e s:XSIZE:int:g -e s:XCTYPE:unsigned:g -e s:XX::g $? >> $@
- sed -e s:XSIZE:int:g -e s:XCTYPE:unsigned:g -e s:XX:_release:g $? >> $@
- sed -e s:XSIZE:int:g -e s:XCTYPE:unsigned:g -e s:XX:_acquire:g $? >> $@
- sed -e s:XSIZE:int:g -e s:XCTYPE:unsigned:g -e s:XX:_read:g $? >> $@
- sed -e s:XSIZE:int:g -e s:XCTYPE:unsigned:g -e s:XX:_write:g $? >> $@
- sed -e s:XSIZE:int:g -e s:XCTYPE:unsigned:g -e s:XX:_full:g $? >> $@
- sed -e s:XSIZE:int:g -e s:XCTYPE:unsigned:g -e s:XX:_release_write:g $? >> $@
- sed -e s:XSIZE:int:g -e s:XCTYPE:unsigned:g -e s:XX:_acquire_read:g $? >> $@
- sed -e s:XSIZE:int:g -e s:XCTYPE:unsigned:g -e s:XX:_dd_acquire_read:g $? >> $@
- sed -e s:XSIZE:double:g -e s:XCTYPE:AO_double_t:g -e s:XX::g $? >> $@
- sed -e s:XSIZE:double:g -e s:XCTYPE:AO_double_t:g -e s:XX:_release:g $? >> $@
- sed -e s:XSIZE:double:g -e s:XCTYPE:AO_double_t:g -e s:XX:_acquire:g $? >> $@
- sed -e s:XSIZE:double:g -e s:XCTYPE:AO_double_t:g -e s:XX:_read:g $? >> $@
- sed -e s:XSIZE:double:g -e s:XCTYPE:AO_double_t:g -e s:XX:_write:g $? >> $@
- sed -e s:XSIZE:double:g -e s:XCTYPE:AO_double_t:g -e s:XX:_full:g $? >> $@
- sed -e s:XSIZE:double:g -e s:XCTYPE:AO_double_t:g -e s:XX:_release_write:g $? >> $@
- sed -e s:XSIZE:double:g -e s:XCTYPE:AO_double_t:g -e s:XX:_acquire_read:g $? >> $@
- sed -e s:XSIZE:double:g -e s:XCTYPE:AO_double_t:g -e s:XX:_dd_acquire_read:g $? >> $@
-
-list_atomic.i: list_atomic.c
- $(COMPILE) $? -E > $@
-
-# Verify list_atomic.c syntax:
-list_atomic.o: list_atomic.c
- $(COMPILE) -c -o $@ $?
diff --git a/tests/list_atomic.template b/tests/list_atomic.template
deleted file mode 100644
index 3e748f4..0000000
--- a/tests/list_atomic.template
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved.
- *
- * This file is covered by the GNU general public license, version 2.
- * see COPYING for details.
- */
-
-/* This generates a compilable program. But it is really meant to be */
-/* be used only with cc -E, to inspect the expensions generated by */
-/* primitives. */
-
-/* The result will not link or run. */
-
-void XSIZE_list_atomicXX(void)
-{
-# if defined(AO_HAVE_XSIZE_loadXX) || defined(AO_HAVE_XSIZE_storeXX) \
- || defined(AO_HAVE_XSIZE_fetch_and_addXX) \
- || defined(AO_HAVE_XSIZE_fetch_and_add1XX) \
- || defined(AO_HAVE_XSIZE_andXX) \
- || defined(AO_HAVE_XSIZE_compare_and_swapXX) \
- || defined(AO_HAVE_XSIZE_fetch_compare_and_swapXX)
- static volatile XCTYPE val /* = 0 */;
-# endif
-# if defined(AO_HAVE_XSIZE_compare_and_swapXX) \
- || defined(AO_HAVE_XSIZE_fetch_compare_and_swapXX)
- static XCTYPE oldval /* = 0 */;
-# endif
-# if defined(AO_HAVE_XSIZE_storeXX) \
- || defined(AO_HAVE_XSIZE_compare_and_swapXX) \
- || defined(AO_HAVE_XSIZE_fetch_compare_and_swapXX)
- static XCTYPE newval /* = 0 */;
-# endif
-# if defined(AO_HAVE_test_and_setXX)
- AO_TS_t ts;
-# endif
-# if defined(AO_HAVE_XSIZE_fetch_and_addXX) || defined(AO_HAVE_XSIZE_andXX) \
- || defined(AO_HAVE_XSIZE_orXX) || defined(AO_HAVE_XSIZE_xorXX)
- static XCTYPE incr /* = 0 */;
-# endif
-
-# if defined(AO_HAVE_nopXX)
- (void)"AO_nopXX(): ";
- AO_nopXX();
-# else
- (void)"No AO_nopXX";
-# endif
-
-# ifdef AO_HAVE_XSIZE_loadXX
- (void)"AO_XSIZE_loadXX(&val):";
- AO_XSIZE_loadXX(&val);
-# else
- (void)"No AO_XSIZE_loadXX";
-# endif
-# ifdef AO_HAVE_XSIZE_storeXX
- (void)"AO_XSIZE_storeXX(&val, newval):";
- AO_XSIZE_storeXX(&val, newval);
-# else
- (void)"No AO_XSIZE_storeXX";
-# endif
-# ifdef AO_HAVE_XSIZE_fetch_and_addXX
- (void)"AO_XSIZE_fetch_and_addXX(&val, incr):";
- AO_XSIZE_fetch_and_addXX(&val, incr);
-# else
- (void)"No AO_XSIZE_fetch_and_addXX";
-# endif
-# ifdef AO_HAVE_XSIZE_fetch_and_add1XX
- (void)"AO_XSIZE_fetch_and_add1XX(&val):";
- AO_XSIZE_fetch_and_add1XX(&val);
-# else
- (void)"No AO_XSIZE_fetch_and_add1XX";
-# endif
-# ifdef AO_HAVE_XSIZE_fetch_and_sub1XX
- (void)"AO_XSIZE_fetch_and_sub1XX(&val):";
- AO_XSIZE_fetch_and_sub1XX(&val);
-# else
- (void)"No AO_XSIZE_fetch_and_sub1XX";
-# endif
-# ifdef AO_HAVE_XSIZE_andXX
- (void)"AO_XSIZE_andXX(&val, incr):";
- AO_XSIZE_andXX(&val, incr);
-# else
- (void)"No AO_XSIZE_andXX";
-# endif
-# ifdef AO_HAVE_XSIZE_orXX
- (void)"AO_XSIZE_orXX(&val, incr):";
- AO_XSIZE_orXX(&val, incr);
-# else
- (void)"No AO_XSIZE_orXX";
-# endif
-# ifdef AO_HAVE_XSIZE_xorXX
- (void)"AO_XSIZE_xorXX(&val, incr):";
- AO_XSIZE_xorXX(&val, incr);
-# else
- (void)"No AO_XSIZE_xorXX";
-# endif
-# ifdef AO_HAVE_XSIZE_compare_and_swapXX
- (void)"AO_XSIZE_compare_and_swapXX(&val, oldval, newval):";
- AO_XSIZE_compare_and_swapXX(&val, oldval, newval);
-# else
- (void)"No AO_XSIZE_compare_and_swapXX";
-# endif
- /* TODO: Add AO_compare_double_and_swap_doubleXX */
- /* TODO: Add AO_compare_and_swap_doubleXX */
-# ifdef AO_HAVE_XSIZE_fetch_compare_and_swapXX
- (void)"AO_XSIZE_fetch_compare_and_swapXX(&val, oldval, newval):";
- AO_XSIZE_fetch_compare_and_swapXX(&val, oldval, newval);
-# else
- (void)"No AO_XSIZE_fetch_compare_and_swapXX";
-# endif
-
-# if defined(AO_HAVE_test_and_setXX)
- (void)"AO_test_and_setXX(&ts):";
- AO_test_and_setXX(&ts);
-# else
- (void)"No AO_test_and_setXX";
-# endif
-}
diff --git a/tests/run_parallel.h b/tests/run_parallel.h
deleted file mode 100644
index 42110dc..0000000
--- a/tests/run_parallel.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
- *
- * This file is covered by the GNU general public license, version 2.
- * see COPYING for details.
- */
-
-#if defined(_MSC_VER) || \
- defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) || \
- defined(_WIN32_WINCE)
-# define USE_WINTHREADS
-#elif defined(__vxworks)
-# define USE_VXTHREADS
-#else
-# define USE_PTHREADS
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#ifdef USE_PTHREADS
-# include <pthread.h>
-#endif
-
-#ifdef USE_VXTHREADS
-# include <vxworks.h>
-# include <taskLib.h>
-#endif
-
-#ifdef USE_WINTHREADS
-# include <windows.h>
-#endif
-
-#include "atomic_ops.h"
-
-#if (defined(_WIN32_WCE) || defined(__MINGW32CE__)) && !defined(abort)
-# define abort() _exit(-1) /* there is no abort() in WinCE */
-#endif
-
-#ifndef _WIN64
-# define AO_PTRDIFF_T long
-#elif defined(__int64)
-# define AO_PTRDIFF_T __int64
-#else
-# define AO_PTRDIFF_T long long
-#endif
-
-typedef void * (* thr_func)(void *);
-
-typedef int (* test_func)(void); /* Returns != 0 on success */
-
-void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name);
-
-#ifdef USE_PTHREADS
-void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name)
-{
- pthread_attr_t attr;
- pthread_t thr[100];
- int i;
- int code;
-
- printf("Testing %s\n", name);
- if (nthreads > 100)
- {
- fprintf(stderr, "run_parallel: requested too many threads\n");
- abort();
- }
-
-# ifdef _HPUX_SOURCE
- /* Default stack size is too small, especially with the 64 bit ABI */
- /* Increase it. */
- if (pthread_default_stacksize_np(1024*1024, 0) != 0)
- {
- fprintf(stderr, "pthread_default_stacksize_np failed. "
- "OK after first call.\n");
- }
-# endif
-
- pthread_attr_init(&attr);
-
- for (i = 0; i < nthreads; ++i)
- {
- if ((code = pthread_create(thr + i, &attr, f1, (void *)(long)i)) != 0)
- {
- fprintf(stderr, "pthread_create returned %d, thread %d\n", code, i);
- abort();
- }
- }
- for (i = 0; i < nthreads; ++i)
- {
- if ((code = pthread_join(thr[i], NULL)) != 0)
- {
- fprintf(stderr, "pthread_join returned %d, thread %d\n", code, i);
- abort();
- }
- }
- if (t())
- {
- printf("Succeeded\n");
- }
- else
- {
- fprintf(stderr, "Failed\n");
- abort();
- }
- return 0;
-}
-#endif /* USE_PTHREADS */
-
-#ifdef USE_VXTHREADS
-void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name)
-{
- int thr[100];
- int i;
-
- printf("Testing %s\n", name);
- if (nthreads > 100)
- {
- fprintf(stderr, "run_parallel: requested too many threads\n");
- taskSuspend(0);
- }
-
- for (i = 0; i < nthreads; ++i)
- {
- thr[i] = taskSpawn((char*) name, 180, 0, 32768, (FUNCPTR) f1, i,
- 1, 2, 3, 4, 5, 6, 7, 8, 9);
- if (thr[i] == ERROR)
- {
- fprintf(stderr, "taskSpawn failed with %d, thread %d\n",
- errno, i);
- taskSuspend(0);
- }
- }
- for (i = 0; i < nthreads; ++i)
- {
- while (taskIdVerify(thr[i]) == OK)
- taskDelay(60);
- }
- if (t())
- {
- printf("Succeeded\n");
- }
- else
- {
- fprintf(stderr, "Failed\n");
- taskSuspend(0);
- }
- return 0;
-}
-#endif /* USE_VXTHREADS */
-
-#ifdef USE_WINTHREADS
-
-struct tramp_args {
- thr_func fn;
- long arg;
-};
-
-DWORD WINAPI tramp(LPVOID param)
-{
- struct tramp_args *args = (struct tramp_args *)param;
-
- return (DWORD)(AO_PTRDIFF_T)(*args->fn)((LPVOID)(AO_PTRDIFF_T)args->arg);
-}
-
-void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name)
-{
- HANDLE thr[100];
- struct tramp_args args[100];
- int i;
- DWORD code;
-
- printf("Testing %s\n", name);
- if (nthreads > 100)
- {
- fprintf(stderr, "run_parallel: requested too many threads\n");
- abort();
- }
-
- for (i = 0; i < nthreads; ++i)
- {
- args[i].fn = f1;
- args[i].arg = i;
- if ((thr[i] = CreateThread(NULL, 0, tramp, (LPVOID)(args+i), 0, NULL))
- == NULL)
- {
- fprintf(stderr, "CreateThread failed with %lu, thread %d\n",
- (unsigned long)GetLastError(), i);
- abort();
- }
- }
- for (i = 0; i < nthreads; ++i)
- {
- if ((code = WaitForSingleObject(thr[i], INFINITE)) != WAIT_OBJECT_0)
- {
- fprintf(stderr, "WaitForSingleObject returned %lu, thread %d\n",
- (unsigned long)code, i);
- abort();
- }
- }
- if (t())
- {
- printf("Succeeded\n");
- }
- else
- {
- fprintf(stderr, "Failed\n");
- abort();
- }
- return 0;
-}
-#endif /* USE_WINTHREADS */
diff --git a/tests/test_atomic.c b/tests/test_atomic.c
deleted file mode 100644
index 86fede1..0000000
--- a/tests/test_atomic.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
- *
- * This file may be redistributed and/or modified under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2, or (at your option) any later version.
- *
- * It is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License in the
- * file COPYING for more details.
- */
-
-#if defined(HAVE_CONFIG_H)
-# include "config.h"
-#endif
-
-#if defined(AO_NO_PTHREADS) && defined(AO_USE_PTHREAD_DEFS)
-# include <stdio.h>
-
- int main(void)
- {
- printf("test skipped\n");
- return 0;
- }
-
-#else
-
-#include "run_parallel.h"
-
-#include "test_atomic_include.h"
-
-#ifdef AO_USE_PTHREAD_DEFS
-# define NITERS 100000
-#else
-# define NITERS 10000000
-#endif
-
-void * add1sub1_thr(void * id);
-int add1sub1_test(void);
-void * acqrel_thr(void *id);
-int acqrel_test(void);
-void * test_and_set_thr(void * id);
-int test_and_set_test(void);
-
-#if defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1)
-
-AO_t counter = 0;
-
-void * add1sub1_thr(void * id)
-{
- int me = (int)(AO_PTRDIFF_T)id;
-
- int i;
-
- for (i = 0; i < NITERS; ++i)
- if ((me & 1) != 0) {
- (void)AO_fetch_and_sub1(&counter);
- } else {
- (void)AO_fetch_and_add1(&counter);
- }
- return 0;
-}
-
-int add1sub1_test(void)
-{
- return counter == 0;
-}
-
-#endif /* defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1) */
-
-#if defined(AO_HAVE_store_release_write) && defined(AO_HAVE_load_acquire_read)
-
-/* Invariant: counter1 >= counter2 */
-AO_t counter1 = 0;
-AO_t counter2 = 0;
-
-void * acqrel_thr(void *id)
-{
- int me = (int)(AO_PTRDIFF_T)id;
-
- int i;
-
- for (i = 0; i < NITERS; ++i)
- if (me & 1)
- {
- AO_t my_counter1;
- if (me != 1)
- {
- fprintf(stderr, "acqrel test: too many threads\n");
- abort();
- }
- my_counter1 = AO_load(&counter1);
- AO_store(&counter1, my_counter1 + 1);
- AO_store_release_write(&counter2, my_counter1 + 1);
- }
- else
- {
- AO_t my_counter1a, my_counter2a;
- AO_t my_counter1b, my_counter2b;
-
- my_counter2a = AO_load_acquire_read(&counter2);
- my_counter1a = AO_load(&counter1);
- /* Redo this, to make sure that the second load of counter1 */
- /* is not viewed as a common subexpression. */
- my_counter2b = AO_load_acquire_read(&counter2);
- my_counter1b = AO_load(&counter1);
- if (my_counter1a < my_counter2a)
- {
- fprintf(stderr, "Saw release store out of order: %lu < %lu\n",
- (unsigned long)my_counter1a, (unsigned long)my_counter2a);
- abort();
- }
- if (my_counter1b < my_counter2b)
- {
- fprintf(stderr,
- "Saw release store out of order (bad CSE?): %lu < %lu\n",
- (unsigned long)my_counter1b, (unsigned long)my_counter2b);
- abort();
- }
- }
-
- return 0;
-}
-
-int acqrel_test(void)
-{
- return counter1 == NITERS && counter2 == NITERS;
-}
-
-#endif /* AO_HAVE_store_release_write && AO_HAVE_load_acquire_read */
-
-#if defined(AO_HAVE_test_and_set_acquire)
-
-AO_TS_t lock = AO_TS_INITIALIZER;
-
-unsigned long locked_counter;
-volatile unsigned long junk = 13;
-
-void * test_and_set_thr(void * id)
-{
- unsigned long i;
-
- for (i = 0; i < NITERS/10; ++i)
- {
- while (AO_test_and_set_acquire(&lock) != AO_TS_CLEAR);
- ++locked_counter;
- if (locked_counter != 1)
- {
- fprintf(stderr, "Test and set failure 1, counter = %ld, id = %d\n",
- locked_counter, (int)(AO_PTRDIFF_T)id);
- abort();
- }
- locked_counter *= 2;
- locked_counter -= 1;
- locked_counter *= 5;
- locked_counter -= 4;
- if (locked_counter != 1)
- {
- fprintf(stderr, "Test and set failure 2, counter = %ld, id = %d\n",
- locked_counter, (int)(AO_PTRDIFF_T)id);
- abort();
- }
- --locked_counter;
- AO_CLEAR(&lock);
- /* Spend a bit of time outside the lock. */
- junk *= 17;
- junk *= 17;
- }
- return 0;
-}
-
-int test_and_set_test(void)
-{
- return locked_counter == 0;
-}
-
-#endif /* defined(AO_HAVE_test_and_set_acquire) */
-
-int main(void)
-{
- test_atomic();
- test_atomic_acquire();
- test_atomic_release();
- test_atomic_read();
- test_atomic_write();
- test_atomic_full();
- test_atomic_release_write();
- test_atomic_acquire_read();
-# if defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1)
- run_parallel(4, add1sub1_thr, add1sub1_test, "add1/sub1");
-# endif
-# if defined(AO_HAVE_store_release_write) && defined(AO_HAVE_load_acquire_read)
- run_parallel(3, acqrel_thr, acqrel_test,
- "store_release_write/load_acquire_read");
-# endif
-# if defined(AO_HAVE_test_and_set_acquire)
- run_parallel(5, test_and_set_thr, test_and_set_test,
- "test_and_set");
-# endif
- return 0;
-}
-
-#endif /* !AO_NO_PTHREADS || !AO_USE_PTHREAD_DEFS */
diff --git a/tests/test_atomic_include.template b/tests/test_atomic_include.template
deleted file mode 100644
index 60068b5..0000000
--- a/tests/test_atomic_include.template
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved.
- *
- * This file is covered by the GNU general public license, version 2.
- * see COPYING for details.
- */
-
-/* Some basic sanity tests. These do not test the barrier semantics. */
-
-#undef TA_assert
-#define TA_assert(e) \
- if (!(e)) { fprintf(stderr, "Assertion failed %s:%d (barrier: XX)\n", \
- __FILE__, __LINE__), exit(1); }
-
-#undef MISSING
-#define MISSING(name) \
- printf("Missing: %s\n", #name "XX")
-
-void test_atomicXX(void)
-{
- AO_t x;
- unsigned char b;
- unsigned short s;
- unsigned int zz;
-# if defined(AO_HAVE_test_and_setXX)
- AO_TS_t z = AO_TS_INITIALIZER;
-# endif
-# if defined(AO_HAVE_double_compare_and_swapXX) \
- || defined(AO_HAVE_double_loadXX) \
- || defined(AO_HAVE_double_storeXX)
- AO_double_t old_w;
- AO_double_t new_w;
-# endif
-# if defined(AO_HAVE_compare_and_swap_doubleXX) \
- || defined(AO_HAVE_compare_double_and_swap_doubleXX) \
- || defined(AO_HAVE_double_compare_and_swapXX)
- AO_double_t w;
- w.AO_val1 = 0;
- w.AO_val2 = 0;
-# endif
-
-# if defined(AO_HAVE_nopXX)
- AO_nopXX();
-# elif !defined(AO_HAVE_nop) || !defined(AO_HAVE_nop_full) \
- || !defined(AO_HAVE_nop_read) || !defined(AO_HAVE_nop_write)
- MISSING(AO_nop);
-# endif
-# if defined(AO_HAVE_storeXX)
- AO_storeXX(&x, 13);
- TA_assert (x == 13);
-# else
-# if !defined(AO_HAVE_store) || !defined(AO_HAVE_store_full) \
- || !defined(AO_HAVE_store_release) \
- || !defined(AO_HAVE_store_release_write) \
- || !defined(AO_HAVE_store_write)
- MISSING(AO_store);
-# endif
- x = 13;
-# endif
-# if defined(AO_HAVE_loadXX)
- TA_assert(AO_loadXX(&x) == 13);
-# elif !defined(AO_HAVE_load) || !defined(AO_HAVE_load_acquire) \
- || !defined(AO_HAVE_load_acquire_read) \
- || !defined(AO_HAVE_load_dd_acquire_read) \
- || !defined(AO_HAVE_load_full) || !defined(AO_HAVE_load_read)
- MISSING(AO_load);
-# endif
-# if defined(AO_HAVE_test_and_setXX)
- assert(AO_test_and_setXX(&z) == AO_TS_CLEAR);
- assert(AO_test_and_setXX(&z) == AO_TS_SET);
- assert(AO_test_and_setXX(&z) == AO_TS_SET);
- AO_CLEAR(&z);
-# else
- MISSING(AO_test_and_set);
-# endif
-# if defined(AO_HAVE_fetch_and_addXX)
- TA_assert(AO_fetch_and_addXX(&x, 42) == 13);
- TA_assert(AO_fetch_and_addXX(&x, (AO_t)(-42)) == 55);
-# else
- MISSING(AO_fetch_and_add);
-# endif
-# if defined(AO_HAVE_fetch_and_add1XX)
- TA_assert(AO_fetch_and_add1XX(&x) == 13);
-# else
- MISSING(AO_fetch_and_add1);
- ++x;
-# endif
-# if defined(AO_HAVE_fetch_and_sub1XX)
- TA_assert(AO_fetch_and_sub1XX(&x) == 14);
-# else
- MISSING(AO_fetch_and_sub1);
- --x;
-# endif
-# if defined(AO_HAVE_short_storeXX)
- AO_short_storeXX(&s, 13);
-# else
-# if !defined(AO_HAVE_short_store) || !defined(AO_HAVE_short_store_full) \
- || !defined(AO_HAVE_short_store_release) \
- || !defined(AO_HAVE_short_store_release_write) \
- || !defined(AO_HAVE_short_store_write)
- MISSING(AO_short_store);
-# endif
- s = 13;
-# endif
-# if defined(AO_HAVE_short_loadXX)
- TA_assert(AO_short_load(&s) == 13);
-# elif !defined(AO_HAVE_short_load) || !defined(AO_HAVE_short_load_acquire) \
- || !defined(AO_HAVE_short_load_acquire_read) \
- || !defined(AO_HAVE_short_load_dd_acquire_read) \
- || !defined(AO_HAVE_short_load_full) \
- || !defined(AO_HAVE_short_load_read)
- MISSING(AO_short_load);
-# endif
-# if defined(AO_HAVE_short_fetch_and_addXX)
- TA_assert(AO_short_fetch_and_addXX(&s, 42) == 13);
- TA_assert(AO_short_fetch_and_addXX(&s, (unsigned short)-42) == 55);
-# else
- MISSING(AO_short_fetch_and_add);
-# endif
-# if defined(AO_HAVE_short_fetch_and_add1XX)
- TA_assert(AO_short_fetch_and_add1XX(&s) == 13);
-# else
- MISSING(AO_short_fetch_and_add1);
- ++s;
-# endif
-# if defined(AO_HAVE_short_fetch_and_sub1XX)
- TA_assert(AO_short_fetch_and_sub1XX(&s) == 14);
-# else
- MISSING(AO_short_fetch_and_sub1);
- --s;
-# endif
-# if defined(AO_HAVE_char_storeXX)
- AO_char_storeXX(&b, 13);
-# else
-# if !defined(AO_HAVE_char_store) || !defined(AO_HAVE_char_store_full) \
- || !defined(AO_HAVE_char_store_release) \
- || !defined(AO_HAVE_char_store_release_write) \
- || !defined(AO_HAVE_char_store_write)
- MISSING(AO_char_store);
-# endif
- b = 13;
-# endif
-# if defined(AO_HAVE_char_loadXX)
- TA_assert(AO_char_load(&b) == 13);
-# elif !defined(AO_HAVE_char_load) || !defined(AO_HAVE_char_load_acquire) \
- || !defined(AO_HAVE_char_load_acquire_read) \
- || !defined(AO_HAVE_char_load_dd_acquire_read) \
- || !defined(AO_HAVE_char_load_full) || !defined(AO_HAVE_char_load_read)
- MISSING(AO_char_load);
-# endif
-# if defined(AO_HAVE_char_fetch_and_addXX)
- TA_assert(AO_char_fetch_and_addXX(&b, 42) == 13);
- TA_assert(AO_char_fetch_and_addXX(&b, (unsigned char)-42) == 55);
-# else
- MISSING(AO_char_fetch_and_add);
-# endif
-# if defined(AO_HAVE_char_fetch_and_add1XX)
- TA_assert(AO_char_fetch_and_add1XX(&b) == 13);
-# else
- MISSING(AO_char_fetch_and_add1);
- ++b;
-# endif
-# if defined(AO_HAVE_char_fetch_and_sub1XX)
- TA_assert(AO_char_fetch_and_sub1XX(&b) == 14);
-# else
- MISSING(AO_char_fetch_and_sub1);
- --b;
-# endif
-# if defined(AO_HAVE_int_storeXX)
- AO_int_storeXX(&zz, 13);
-# else
-# if !defined(AO_HAVE_int_store) || !defined(AO_HAVE_int_store_full) \
- || !defined(AO_HAVE_int_store_release) \
- || !defined(AO_HAVE_int_store_release_write) \
- || !defined(AO_HAVE_int_store_write)
- MISSING(AO_int_store);
-# endif
- zz = 13;
-# endif
-# if defined(AO_HAVE_int_loadXX)
- TA_assert(AO_int_load(&zz) == 13);
-# elif !defined(AO_HAVE_int_load) || !defined(AO_HAVE_int_load_acquire) \
- || !defined(AO_HAVE_int_load_acquire_read) \
- || !defined(AO_HAVE_int_load_dd_acquire_read) \
- || !defined(AO_HAVE_int_load_full) || !defined(AO_HAVE_int_load_read)
- MISSING(AO_int_load);
-# endif
-# if defined(AO_HAVE_int_fetch_and_addXX)
- TA_assert(AO_int_fetch_and_addXX(&zz, 42) == 13);
- TA_assert(AO_int_fetch_and_addXX(&zz, (unsigned int)-42) == 55);
-# else
- MISSING(AO_int_fetch_and_add);
-# endif
-# if defined(AO_HAVE_int_fetch_and_add1XX)
- TA_assert(AO_int_fetch_and_add1XX(&zz) == 13);
-# else
- MISSING(AO_int_fetch_and_add1);
- ++zz;
-# endif
-# if defined(AO_HAVE_int_fetch_and_sub1XX)
- TA_assert(AO_int_fetch_and_sub1XX(&zz) == 14);
-# else
- MISSING(AO_int_fetch_and_sub1);
- --zz;
-# endif
-# if defined(AO_HAVE_compare_and_swapXX)
- TA_assert(!AO_compare_and_swapXX(&x, 14, 42));
- TA_assert(x == 13);
- TA_assert(AO_compare_and_swapXX(&x, 13, 42));
- TA_assert(x == 42);
-# else
- MISSING(AO_compare_and_swap);
- if (x == 13) x = 42;
-# endif
-# if defined(AO_HAVE_orXX)
- AO_orXX(&x, 66);
- TA_assert(x == 106);
-# else
- MISSING(AO_or);
- x |= 66;
-# endif
-# if defined(AO_HAVE_xorXX)
- AO_xorXX(&x, 181);
- TA_assert(x == 223);
-# else
- MISSING(AO_xor);
- x ^= 181;
-# endif
-# if defined(AO_HAVE_andXX)
- AO_andXX(&x, 57);
- TA_assert(x == 25);
-# else
- MISSING(AO_and);
- x &= 57;
-# endif
-# if defined(AO_HAVE_fetch_compare_and_swapXX)
- TA_assert(AO_fetch_compare_and_swapXX(&x, 14, 117) == 25);
- TA_assert(x == 25);
- TA_assert(AO_fetch_compare_and_swapXX(&x, 25, 117) == 25);
- TA_assert(x == 117);
-# else
- MISSING(AO_fetch_compare_and_swap);
- if (x == 25) x = 117;
-# endif
-# if defined(AO_HAVE_double_loadXX)
- old_w.AO_val1 = 3316;
- old_w.AO_val2 = 2921;
- new_w = AO_double_loadXX(&old_w);
- TA_assert(new_w.AO_val1 == 3316 && new_w.AO_val2 == 2921);
-# elif !defined(AO_HAVE_double_load) \
- || !defined(AO_HAVE_double_load_acquire) \
- || !defined(AO_HAVE_double_load_acquire_read) \
- || !defined(AO_HAVE_double_load_dd_acquire_read) \
- || !defined(AO_HAVE_double_load_full) \
- || !defined(AO_HAVE_double_load_read)
- MISSING(AO_double_load);
-# endif
-# if defined(AO_HAVE_double_storeXX)
- new_w.AO_val1 = 1375;
- new_w.AO_val2 = 8243;
- AO_double_storeXX(&old_w, new_w);
- TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243);
- AO_double_storeXX(&old_w, new_w);
- TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243);
- new_w.AO_val1 ^= old_w.AO_val1;
- new_w.AO_val2 ^= old_w.AO_val2;
- AO_double_storeXX(&old_w, new_w);
- TA_assert(old_w.AO_val1 == 0 && old_w.AO_val2 == 0);
-# elif !defined(AO_HAVE_double_store) \
- || !defined(AO_HAVE_double_store_full) \
- || !defined(AO_HAVE_double_store_release) \
- || !defined(AO_HAVE_double_store_release_write) \
- || !defined(AO_HAVE_double_store_write)
- MISSING(AO_double_store);
-# endif
-# if defined(AO_HAVE_compare_double_and_swap_doubleXX)
- TA_assert(!AO_compare_double_and_swap_doubleXX(&w, 17, 42, 12, 13));
- TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0);
- TA_assert(AO_compare_double_and_swap_doubleXX(&w, 0, 0, 12, 13));
- TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13);
- TA_assert(!AO_compare_double_and_swap_doubleXX(&w, 12, 14, 64, 33));
- TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13);
- TA_assert(!AO_compare_double_and_swap_doubleXX(&w, 11, 13, 85, 82));
- TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13);
- TA_assert(!AO_compare_double_and_swap_doubleXX(&w, 13, 12, 17, 42));
- TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13);
- TA_assert(AO_compare_double_and_swap_doubleXX(&w, 12, 13, 17, 42));
- TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42);
- TA_assert(AO_compare_double_and_swap_doubleXX(&w, 17, 42, 0, 0));
- TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0);
-# else
- MISSING(AO_compare_double_and_swap_double);
-# endif
-# if defined(AO_HAVE_compare_and_swap_doubleXX)
- TA_assert(!AO_compare_and_swap_doubleXX(&w, 17, 12, 13));
- TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0);
- TA_assert(AO_compare_and_swap_doubleXX(&w, 0, 12, 13));
- TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13);
- TA_assert(!AO_compare_and_swap_doubleXX(&w, 13, 12, 33));
- TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13);
- TA_assert(!AO_compare_and_swap_doubleXX(&w, 1213, 48, 86));
- TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13);
- TA_assert(AO_compare_and_swap_doubleXX(&w, 12, 17, 42));
- TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42);
- TA_assert(AO_compare_and_swap_doubleXX(&w, 17, 0, 0));
- TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0);
-# else
- MISSING(AO_compare_and_swap_double);
-# endif
-# if defined(AO_HAVE_double_compare_and_swapXX)
- old_w.AO_val1 = 4116;
- old_w.AO_val2 = 2121;
- new_w.AO_val1 = 8537;
- new_w.AO_val2 = 6410;
- TA_assert(!AO_double_compare_and_swapXX(&w, old_w, new_w));
- TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0);
- TA_assert(AO_double_compare_and_swapXX(&w, w, new_w));
- TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410);
- old_w.AO_val1 = new_w.AO_val1;
- old_w.AO_val2 = 29;
- new_w.AO_val1 = 820;
- new_w.AO_val2 = 5917;
- TA_assert(!AO_double_compare_and_swapXX(&w, old_w, new_w));
- TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410);
- old_w.AO_val1 = 11;
- old_w.AO_val2 = 6410;
- new_w.AO_val1 = 3552;
- new_w.AO_val2 = 1746;
- TA_assert(!AO_double_compare_and_swapXX(&w, old_w, new_w));
- TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410);
- old_w.AO_val1 = old_w.AO_val2;
- old_w.AO_val2 = 8537;
- new_w.AO_val1 = 4116;
- new_w.AO_val2 = 2121;
- TA_assert(!AO_double_compare_and_swapXX(&w, old_w, new_w));
- TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410);
- old_w.AO_val1 = old_w.AO_val2;
- old_w.AO_val2 = 6410;
- new_w.AO_val1 = 1;
- TA_assert(AO_double_compare_and_swapXX(&w, old_w, new_w));
- TA_assert(w.AO_val1 == 1 && w.AO_val2 == 2121);
- old_w.AO_val1 = new_w.AO_val1;
- old_w.AO_val2 = w.AO_val2;
- new_w.AO_val1--;
- new_w.AO_val2 = 0;
- TA_assert(AO_double_compare_and_swapXX(&w, old_w, new_w));
- TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0);
-# else
- MISSING(AO_double_compare_and_swap);
-# endif
-}
diff --git a/tests/test_malloc.c b/tests/test_malloc.c
deleted file mode 100644
index dca06da..0000000
--- a/tests/test_malloc.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
- *
- * This file may be redistributed and/or modified under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2, or (at your option) any later version.
- *
- * It is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License in the
- * file COPYING for more details.
- */
-
-#if defined(HAVE_CONFIG_H)
-# include "config.h"
-#endif
-
-#include "run_parallel.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include "atomic_ops_malloc.h"
-
-#ifndef MAX_NTHREADS
-# define MAX_NTHREADS 100
-#endif
-
-#ifndef DEFAULT_NTHREADS
-# ifdef HAVE_MMAP
-# define DEFAULT_NTHREADS 10
-# else
-# define DEFAULT_NTHREADS 3
-# endif
-#endif
-
-#ifndef N_REVERSALS
-# ifdef AO_USE_PTHREAD_DEFS
-# define N_REVERSALS 4
-# else
-# define N_REVERSALS 1000 /* must be even */
-# endif
-#endif
-
-#ifndef LIST_LENGTH
-# ifdef HAVE_MMAP
-# define LIST_LENGTH 1000
-# else
-# define LIST_LENGTH 100
-# endif
-#endif
-
-#ifndef LARGE_OBJ_SIZE
-# ifdef HAVE_MMAP
-# define LARGE_OBJ_SIZE 200000
-# else
-# define LARGE_OBJ_SIZE 20000
-# endif
-#endif
-
-#ifdef USE_STANDARD_MALLOC
-# define AO_malloc(n) malloc(n)
-# define AO_free(p) free(p)
-# define AO_malloc_enable_mmap()
-#endif
-
-typedef struct list_node {
- struct list_node *next;
- int data;
-} ln;
-
-ln *cons(int d, ln *tail)
-{
- static size_t extra = 0;
- size_t my_extra = extra;
- ln *result;
- int * extras;
- unsigned i;
-
- if (my_extra > 100)
- extra = my_extra = 0;
- else
- ++extra;
- result = AO_malloc(sizeof(ln) + sizeof(int)*my_extra);
- if (result == 0)
- {
- fprintf(stderr, "Out of memory\n");
- /* Normal for more than about 10 threads without mmap? */
- exit(2);
- }
-
- result -> data = d;
- result -> next = tail;
- extras = (int *)(result+1);
- for (i = 0; i < my_extra; ++i) extras[i] = 42;
- return result;
-}
-
-void print_list(ln *l)
-{
- ln *p;
-
- for (p = l; p != 0; p = p -> next)
- {
- printf("%d, ", p -> data);
- }
- printf("\n");
-}
-
-/* Check that l contains numbers from m to n inclusive in ascending order */
-void check_list(ln *l, int m, int n)
-{
- ln *p;
- int i;
-
- for (p = l, i = m; p != 0 && i <= n; p = p -> next, ++i)
- {
- if (i != p -> data)
- {
- fprintf(stderr, "Found %d, expected %d\n", p -> data, i);
- abort();
- }
- }
- if (i <= n)
- {
- fprintf(stderr, "Number not found: %d\n", i);
- abort();
- }
- if (p != 0)
- {
- fprintf(stderr, "Found unexpected number: %d\n", i);
- abort();
- }
-}
-
-/* Create a list of integers from m to n */
-ln *
-make_list(int m, int n)
-{
- if (m > n) return 0;
- return cons(m, make_list(m+1, n));
-}
-
-/* Reverse list x, and concatenate it to y, deallocating no longer needed */
-/* nodes in x. */
-ln *
-reverse(ln *x, ln *y)
-{
- ln * result;
-
- if (x == 0) return y;
- result = reverse(x -> next, cons(x -> data, y));
- AO_free(x);
- return result;
-}
-
-int dummy_test(void) { return 1; }
-
-void * run_one_test(void * arg) {
- ln * x = make_list(1, LIST_LENGTH);
- int i;
- char *p = AO_malloc(LARGE_OBJ_SIZE);
- char *q;
-
- if (0 == p) {
-# ifdef HAVE_MMAP
- fprintf(stderr, "AO_malloc(%d) failed\n", LARGE_OBJ_SIZE);
- abort();
-# else
- fprintf(stderr, "AO_malloc(%d) failed: This is normal without mmap\n",
- LARGE_OBJ_SIZE);
-# endif
- } else {
- p[0] = p[LARGE_OBJ_SIZE/2] = p[LARGE_OBJ_SIZE-1] = 'a';
- q = AO_malloc(LARGE_OBJ_SIZE);
- if (q == 0)
- {
- fprintf(stderr, "Out of memory\n");
- /* Normal for more than about 10 threads without mmap? */
- exit(2);
- }
- q[0] = q[LARGE_OBJ_SIZE/2] = q[LARGE_OBJ_SIZE-1] = 'b';
- if (p[0] != 'a' || p[LARGE_OBJ_SIZE/2] != 'a'
- || p[LARGE_OBJ_SIZE-1] != 'a') {
- fprintf(stderr, "First large allocation smashed\n");
- abort();
- }
- AO_free(p);
- if (q[0] != 'b' || q[LARGE_OBJ_SIZE/2] != 'b'
- || q[LARGE_OBJ_SIZE-1] != 'b') {
- fprintf(stderr, "Second large allocation smashed\n");
- abort();
- }
- AO_free(q);
- }
-# ifdef DEBUG_RUN_ONE_TEST
- x = reverse(x, 0);
- print_list(x);
- x = reverse(x, 0);
- print_list(x);
-# endif
- for (i = 0; i < N_REVERSALS; ++i) {
- x = reverse(x, 0);
- }
- check_list(x, 1, LIST_LENGTH);
- return arg; /* use arg to suppress compiler warning */
-}
-
-int main(int argc, char **argv) {
- int nthreads;
-
- if (1 == argc) {
- nthreads = DEFAULT_NTHREADS;
- } else if (2 == argc) {
- nthreads = atoi(argv[1]);
- if (nthreads < 1 || nthreads > MAX_NTHREADS) {
- fprintf(stderr, "Invalid # of threads argument\n");
- exit(1);
- }
- } else {
- fprintf(stderr, "Usage: %s [# of threads]\n", argv[0]);
- exit(1);
- }
- printf("Performing %d reversals of %d element lists in %d threads\n",
- N_REVERSALS, LIST_LENGTH, nthreads);
- AO_malloc_enable_mmap();
- run_parallel(nthreads, run_one_test, dummy_test, "AO_malloc/AO_free");
- return 0;
-}
diff --git a/tests/test_stack.c b/tests/test_stack.c
deleted file mode 100644
index 8170e5c..0000000
--- a/tests/test_stack.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
- *
- * This file may be redistributed and/or modified under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2, or (at your option) any later version.
- *
- * It is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License in the
- * file COPYING for more details.
- */
-
-#if defined(HAVE_CONFIG_H)
-# include "config.h"
-#endif
-
-#include <stdio.h>
-
-#if defined(__vxworks)
-
- int main(void)
- {
- printf("test skipped\n");
- return 0;
- }
-
-#else
-
-#if ((defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__)) \
- || defined(_MSC_VER) || defined(_WIN32_WINCE)) \
- && !defined(AO_USE_WIN32_PTHREADS)
-# define USE_WINTHREADS
-#endif
-
-#ifdef USE_WINTHREADS
-# include <windows.h>
-#else
-# include <pthread.h>
-#endif
-
-#include <stdlib.h>
-
-#include "atomic_ops_stack.h" /* includes atomic_ops.h as well */
-
-#if (defined(_WIN32_WCE) || defined(__MINGW32CE__)) && !defined(abort)
-# define abort() _exit(-1) /* there is no abort() in WinCE */
-#endif
-
-#ifndef MAX_NTHREADS
-# define MAX_NTHREADS 100
-#endif
-
-#ifdef NO_TIMES
-# define get_msecs() 0
-#elif defined(USE_WINTHREADS) || defined(AO_USE_WIN32_PTHREADS)
-# include <sys/timeb.h>
- long long get_msecs(void)
- {
- struct timeb tb;
-
- ftime(&tb);
- return (long long)tb.time * 1000 + tb.millitm;
- }
-#else /* Unix */
-# include <time.h>
-# include <sys/time.h>
- /* Need 64-bit long long support */
- long long get_msecs(void)
- {
- struct timeval tv;
-
- gettimeofday(&tv, 0);
- return (long long)tv.tv_sec * 1000 + tv.tv_usec/1000;
- }
-#endif /* !NO_TIMES */
-
-typedef struct le {
- AO_t next;
- int data;
-} list_element;
-
-AO_stack_t the_list = AO_STACK_INITIALIZER;
-
-void add_elements(int n)
-{
- list_element * le;
- if (n == 0) return;
- add_elements(n-1);
- le = malloc(sizeof(list_element));
- if (le == 0)
- {
- fprintf(stderr, "Out of memory\n");
- exit(2);
- }
- le -> data = n;
- AO_stack_push(&the_list, (AO_t *)le);
-}
-
-void print_list(void)
-{
- list_element *p;
-
- for (p = (list_element *)AO_REAL_HEAD_PTR(the_list);
- p != 0;
- p = (list_element *)AO_REAL_NEXT_PTR(p -> next))
- printf("%d\n", p -> data);
-}
-
-static char marks[MAX_NTHREADS * (MAX_NTHREADS + 1) / 2 + 1];
-
-void check_list(int n)
-{
- list_element *p;
- int i;
-
- for (i = 1; i <= n; ++i) marks[i] = 0;
-
- for (p = (list_element *)AO_REAL_HEAD_PTR(the_list);
- p != 0;
- p = (list_element *)AO_REAL_NEXT_PTR(p -> next))
- {
- i = p -> data;
- if (i > n || i <= 0)
- {
- fprintf(stderr, "Found erroneous list element %d\n", i);
- abort();
- }
- if (marks[i] != 0)
- {
- fprintf(stderr, "Found duplicate list element %d\n", i);
- abort();
- }
- marks[i] = 1;
- }
-
- for (i = 1; i <= n; ++i)
- if (marks[i] != 1)
- {
- fprintf(stderr, "Missing list element %d\n", i);
- abort();
- }
-}
-
-volatile AO_t ops_performed = 0;
-
-#ifndef LIMIT
- /* Total number of push/pop ops in all threads per test. */
-# ifdef AO_USE_PTHREAD_DEFS
-# define LIMIT 20000
-# else
-# define LIMIT 1000000
-# endif
-#endif
-
-#ifdef AO_HAVE_fetch_and_add
-# define fetch_and_add(addr, val) AO_fetch_and_add(addr, val)
-#else
- /* Fake it. This is really quite unacceptable for timing */
- /* purposes. But as a correctness test, it should be OK. */
- AO_INLINE AO_t fetch_and_add(volatile AO_t * addr, AO_t val)
- {
- AO_t result = AO_load(addr);
- AO_store(addr, result + val);
- return result;
- }
-#endif
-
-#ifdef USE_WINTHREADS
- DWORD WINAPI run_one_test(LPVOID arg)
-#else
- void * run_one_test(void * arg)
-#endif
-{
- list_element * t[MAX_NTHREADS + 1];
- int index = (int)(size_t)arg;
- int i;
- int j = 0;
-
-# ifdef VERBOSE
- printf("starting thread %d\n", index);
-# endif
- while (fetch_and_add(&ops_performed, index + 1) + index + 1 < LIMIT)
- {
- for (i = 0; i < index + 1; ++i)
- {
- t[i] = (list_element *)AO_stack_pop(&the_list);
- if (0 == t[i])
- {
- fprintf(stderr, "FAILED\n");
- abort();
- }
- }
- for (i = 0; i < index + 1; ++i)
- {
- AO_stack_push(&the_list, (AO_t *)t[i]);
- }
- j += (index + 1);
- }
-# ifdef VERBOSE
- printf("finished thread %d: %d total ops\n", index, j);
-# endif
- return 0;
-}
-
-#ifndef N_EXPERIMENTS
-# define N_EXPERIMENTS 1
-#endif
-
-unsigned long times[MAX_NTHREADS + 1][N_EXPERIMENTS];
-
-int main(int argc, char **argv)
-{
- int nthreads;
- int max_nthreads;
- int exper_n;
-
- if (1 == argc)
- max_nthreads = 4;
- else if (2 == argc)
- {
- max_nthreads = atoi(argv[1]);
- if (max_nthreads < 1 || max_nthreads > MAX_NTHREADS)
- {
- fprintf(stderr, "Invalid max # of threads argument\n");
- exit(1);
- }
- }
- else
- {
- fprintf(stderr, "Usage: %s [max # of threads]\n", argv[0]);
- exit(1);
- }
- for (exper_n = 0; exper_n < N_EXPERIMENTS; ++ exper_n)
- for (nthreads = 1; nthreads <= max_nthreads; ++nthreads)
- {
- int i;
-# ifdef USE_WINTHREADS
- DWORD thread_id;
- HANDLE thread[MAX_NTHREADS];
-# else
- pthread_t thread[MAX_NTHREADS];
-# endif
- int list_length = nthreads*(nthreads+1)/2;
- long long start_time;
- list_element * le;
-
-# ifdef VERBOSE
- printf("Before add_elements: exper_n=%d, nthreads=%d,"
- " max_nthreads=%d, list_length=%d\n",
- exper_n, nthreads, max_nthreads, list_length);
-# endif
- add_elements(list_length);
-# ifdef VERBOSE
- printf("Initial list (nthreads = %d):\n", nthreads);
- print_list();
-# endif
- ops_performed = 0;
- start_time = get_msecs();
- for (i = 1; i < nthreads; ++i) {
- int code;
-
-# ifdef USE_WINTHREADS
- thread[i] = CreateThread(NULL, 0, run_one_test, (LPVOID)(size_t)i,
- 0, &thread_id);
- code = thread[i] != NULL ? 0 : (int)GetLastError();
-# else
- code = pthread_create(&thread[i], 0, run_one_test,
- (void *)(size_t)i);
-# endif
- if (code != 0) {
- fprintf(stderr, "Thread creation failed %u\n", (unsigned)code);
- exit(3);
- }
- }
- /* We use the main thread to run one test. This allows gprof */
- /* profiling to work, for example. */
- run_one_test(0);
- for (i = 1; i < nthreads; ++i) {
- int code;
-
-# ifdef USE_WINTHREADS
- code = WaitForSingleObject(thread[i], INFINITE) == WAIT_OBJECT_0 ?
- 0 : (int)GetLastError();
-# else
- code = pthread_join(thread[i], 0);
-# endif
- if (code != 0) {
- fprintf(stderr, "Thread join failed %u\n", (unsigned)code);
- abort();
- }
- }
- times[nthreads][exper_n] = (unsigned long)(get_msecs() - start_time);
- # ifdef VERBOSE
- printf("%d %lu\n", nthreads,
- (unsigned long)(get_msecs() - start_time));
- printf("final list (should be reordered initial list):\n");
- print_list();
- # endif
- check_list(list_length);
- while ((le = (list_element *)AO_stack_pop(&the_list)) != 0)
- free(le);
- }
- for (nthreads = 1; nthreads <= max_nthreads; ++nthreads)
- {
- unsigned long sum = 0;
-
- printf("About %d pushes + %d pops in %d threads:",
- LIMIT, LIMIT, nthreads);
- for (exper_n = 0; exper_n < N_EXPERIMENTS; ++exper_n)
- {
-# if defined(VERBOSE)
- printf(" [%lu]", times[nthreads][exper_n]);
-# endif
- sum += times[nthreads][exper_n];
- }
-# ifndef NO_TIMES
- printf(" %lu msecs\n", (sum + N_EXPERIMENTS/2)/N_EXPERIMENTS);
-# else
- printf(" completed\n");
-# endif
- }
- return 0;
-}
-
-#endif