diff options
author | Joshua Peterson <joshuap@unity3d.com> | 2019-05-15 22:03:32 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-15 22:03:32 +0300 |
commit | af8fe9c5e67de215f63e635cfd2f43eafaf40d80 (patch) | |
tree | d6a5b0189b08f92f72100f7420d57ec4a337b25a | |
parent | 46722271b57ce1dccf8440cd53fe894ed355c282 (diff) | |
parent | e83ba1ffe3c1fe092068b26cab4e3bb0523ae44c (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.c | 305 | ||||
-rw-r--r-- | src/atomic_ops_malloc.h | 44 | ||||
-rw-r--r-- | src/atomic_ops_stack.c | 281 | ||||
-rw-r--r-- | src/atomic_ops_stack.h | 188 | ||||
-rw-r--r-- | tests/Makefile.am | 100 | ||||
-rw-r--r-- | tests/list_atomic.template | 117 | ||||
-rw-r--r-- | tests/run_parallel.h | 212 | ||||
-rw-r--r-- | tests/test_atomic.c | 204 | ||||
-rw-r--r-- | tests/test_atomic_include.template | 351 | ||||
-rw-r--r-- | tests/test_malloc.c | 228 | ||||
-rw-r--r-- | tests/test_stack.c | 326 |
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 |