diff options
| author | Ivan Maidanski <ivmai@mail.ru> | 2011-07-25 14:02:53 +0400 |
|---|---|---|
| committer | Ivan Maidanski <ivmai@mail.ru> | 2011-07-25 14:12:43 +0400 |
| commit | 1dc2fb35335ad4fad0eaf3555bf078aed0ab88e6 (patch) | |
| tree | 8071766b491247638ce0823cf5f8ece69733fb0a /src | |
| parent | 1fc6ca5b3a64342986e6492fd3fd592440d236e5 (diff) | |
| download | libatomic_ops-1dc2fb35335ad4fad0eaf3555bf078aed0ab88e6.tar.gz | |
libatomic_ops-1.0 tarball importlibatomic_ops-1_0
Diffstat (limited to 'src')
59 files changed, 10040 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..7ca41ff --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS=atomic_ops + +AM_CFLAGS=@PICFLAG@ + +include_HEADERS=atomic_ops.h atomic_ops_stack.h atomic_ops_malloc.h +lib_LIBRARIES = libatomic_ops.a libatomic_ops_gpl.a +if NEED_ASM +libatomic_ops_a_SOURCES = atomic_ops.c atomic_ops_sysdeps.S +else +libatomic_ops_a_SOURCES = atomic_ops.c +endif + +libatomic_ops_gpl_a_SOURCES = atomic_ops_stack.c atomic_ops_malloc.c + +EXTRA_DIST=Makefile.msft + diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..81e8023 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,597 @@ +# Makefile.in generated by automake 1.9.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +SOURCES = $(libatomic_ops_a_SOURCES) $(libatomic_ops_gpl_a_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src +DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" +libLIBRARIES_INSTALL = $(INSTALL_DATA) +LIBRARIES = $(lib_LIBRARIES) +AR = ar +ARFLAGS = cru +libatomic_ops_a_AR = $(AR) $(ARFLAGS) +libatomic_ops_a_LIBADD = +am__libatomic_ops_a_SOURCES_DIST = atomic_ops.c atomic_ops_sysdeps.S +@NEED_ASM_FALSE@am_libatomic_ops_a_OBJECTS = atomic_ops.$(OBJEXT) +@NEED_ASM_TRUE@am_libatomic_ops_a_OBJECTS = atomic_ops.$(OBJEXT) \ +@NEED_ASM_TRUE@ atomic_ops_sysdeps.$(OBJEXT) +libatomic_ops_a_OBJECTS = $(am_libatomic_ops_a_OBJECTS) +libatomic_ops_gpl_a_AR = $(AR) $(ARFLAGS) +libatomic_ops_gpl_a_LIBADD = +am_libatomic_ops_gpl_a_OBJECTS = atomic_ops_stack.$(OBJEXT) \ + atomic_ops_malloc.$(OBJEXT) +libatomic_ops_gpl_a_OBJECTS = $(am_libatomic_ops_gpl_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I. +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +CCASCOMPILE = $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS) +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libatomic_ops_a_SOURCES) $(libatomic_ops_gpl_a_SOURCES) +DIST_SOURCES = $(am__libatomic_ops_a_SOURCES_DIST) \ + $(libatomic_ops_gpl_a_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-exec-recursive install-info-recursive \ + install-recursive installcheck-recursive installdirs-recursive \ + pdf-recursive ps-recursive uninstall-info-recursive \ + uninstall-recursive +includeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(include_HEADERS) +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +NEED_ASM_FALSE = @NEED_ASM_FALSE@ +NEED_ASM_TRUE = @NEED_ASM_TRUE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PICFLAG = @PICFLAG@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +SUBDIRS = atomic_ops +AM_CFLAGS = @PICFLAG@ +include_HEADERS = atomic_ops.h atomic_ops_stack.h atomic_ops_malloc.h +lib_LIBRARIES = libatomic_ops.a libatomic_ops_gpl.a +@NEED_ASM_FALSE@libatomic_ops_a_SOURCES = atomic_ops.c +@NEED_ASM_TRUE@libatomic_ops_a_SOURCES = atomic_ops.c atomic_ops_sysdeps.S +libatomic_ops_gpl_a_SOURCES = atomic_ops_stack.c atomic_ops_malloc.c +EXTRA_DIST = Makefile.msft +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +.SUFFIXES: .S .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status src/config.h +$(srcdir)/config.h.in: $(am__configure_deps) + cd $(top_srcdir) && $(AUTOHEADER) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +install-libLIBRARIES: $(lib_LIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" + @list='$(lib_LIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(libLIBRARIES_INSTALL) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(libLIBRARIES_INSTALL) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + @$(POST_INSTALL) + @list='$(lib_LIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + p=$(am__strip_dir) \ + echo " $(RANLIB) '$(DESTDIR)$(libdir)/$$p'"; \ + $(RANLIB) "$(DESTDIR)$(libdir)/$$p"; \ + else :; fi; \ + done + +uninstall-libLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLIBRARIES: + -test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES) +libatomic_ops.a: $(libatomic_ops_a_OBJECTS) $(libatomic_ops_a_DEPENDENCIES) + -rm -f libatomic_ops.a + $(libatomic_ops_a_AR) libatomic_ops.a $(libatomic_ops_a_OBJECTS) $(libatomic_ops_a_LIBADD) + $(RANLIB) libatomic_ops.a +libatomic_ops_gpl.a: $(libatomic_ops_gpl_a_OBJECTS) $(libatomic_ops_gpl_a_DEPENDENCIES) + -rm -f libatomic_ops_gpl.a + $(libatomic_ops_gpl_a_AR) libatomic_ops_gpl.a $(libatomic_ops_gpl_a_OBJECTS) $(libatomic_ops_gpl_a_LIBADD) + $(RANLIB) libatomic_ops_gpl.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomic_ops.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomic_ops_malloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomic_ops_stack.Po@am__quote@ + +.S.o: + $(CCASCOMPILE) -c $< + +.S.obj: + $(CCASCOMPILE) -c `$(CYGPATH_W) '$<'` + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +uninstall-info-am: +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(mkdir_p) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \ + $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \ + rm -f "$(DESTDIR)$(includedir)/$$f"; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(mkdir_p) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LIBRARIES) $(HEADERS) config.h +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libLIBRARIES mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: install-includeHEADERS + +install-exec-am: install-libLIBRARIES + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-includeHEADERS uninstall-info-am \ + uninstall-libLIBRARIES + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ + clean clean-generic clean-libLIBRARIES clean-recursive ctags \ + ctags-recursive distclean distclean-compile distclean-generic \ + distclean-hdr distclean-recursive distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-exec install-exec-am \ + install-includeHEADERS install-info install-info-am \ + install-libLIBRARIES install-man install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic maintainer-clean-recursive \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am uninstall-includeHEADERS \ + uninstall-info-am uninstall-libLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/Makefile.msft b/src/Makefile.msft new file mode 100644 index 0000000..5b93d27 --- /dev/null +++ b/src/Makefile.msft @@ -0,0 +1,45 @@ +# +# Copyright (c) 2003-2005 Hewlett-Packard Developlment Company, L.P. +# +# The really trivial win32/VC++ Makefile. Note that atomic_ops.c isn't useful. +# And we rely on a pre-built test_atomic_include.h and generalize-small.h, +# since we can't rely on sed. +# Win32 clients only need to include the header files. +# To install, copy atomic_ops.h and the atomic_ops/... tree to your favorite +# include directory. + +#MY_CPU=X86 +#CPU=$(MY_CPU) +#!include <ntwin32.mak> + +LIB_OBJS=atomic_ops_stack.obj atomic_ops_malloc.obj + +all: check + +atomic_ops_stack.obj: + cl -O2 -c -DAO_ASSUME_WINDOWS98 atomic_ops_stack.c + +atomic_ops_malloc.obj: + cl -O2 -c -DAO_ASSUME_WINDOWS98 atomic_ops_malloc.c + +test_atomic: ..\tests\test_atomic.c ..\tests\test_atomic_include.h + cl -O2 -I. -DAO_ASSUME_WINDOWS98 ..\tests\test_atomic.c -o test_atomic + +test_atomic_w95: ..\tests\test_atomic.c ..\tests\test_atomic_include.h + cl -O2 -I. ..\tests\test_atomic.c -o test_atomic_w95 + +test_malloc: ..\tests\test_malloc.c ..\tests\test_atomic_include.h \ + libatomic_ops_gpl.lib + cl -O2 -DAO_ASSUME_WINDOWS98 -I. ..\tests\test_malloc.c -o test_malloc libatomic_ops_gpl.lib + +libatomic_ops_gpl.lib: $(LIB_OBJS) + lib /MACHINE:i386 /out:libatomic_ops_gpl.lib $(LIB_OBJS) + +check: test_atomic test_atomic_w95 test_malloc + echo The following will print lots of \"Missing ...\" messages. + test_atomic_w95 + echo The following will print some \"Missing ...\" messages. + test_atomic + test_malloc + + diff --git a/src/atomic_ops.c b/src/atomic_ops.c new file mode 100644 index 0000000..f01b8d2 --- /dev/null +++ b/src/atomic_ops.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2003 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. + */ + +/* + * Initialized data and out-of-line functions to support atomic_ops.h + * go here. Currently this is needed only for pthread-based atomics + * emulation, or for compare-and-swap emulation. + * Pthreads emulation isn't useful on a native Windows platform, and + * cas emulation is not needed. Thus we skip this on Windows. + */ + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__BORLANDC__) + +#undef AO_REQUIRE_CAS + +#include <pthread.h> +#include <signal.h> +#ifdef _HPUX_SOURCE +# include <sys/time.h> +#else +# include <sys/select.h> +#endif +#include "atomic_ops.h" /* Without cas emulation! */ + +#ifndef AO_HAVE_double_t +# include "atomic_ops/sysdeps/standard_ao_double_t.h" +#endif + +/* + * Lock for pthreads-based implementation. + */ + +pthread_mutex_t AO_pt_lock = PTHREAD_MUTEX_INITIALIZER; + +/* + * Out of line compare-and-swap emulation based on test and set. + * + * We use a small table of locks for different compare_and_swap locations. + * Before we update perform a compare-and-swap, we grap the corresponding + * lock. Different locations may hash to the same lock, but since we + * never acquire more than one lock at a time, this can't deadlock. + * We explicitly disable signals while we perform this operation. + * + * FIXME: We should probably also suppport emulation based on Lamport + * locks, since we may not have test_and_set either. + */ +#define AO_HASH_SIZE 16 + +#define AO_HASH(x) (((unsigned long)(x) >> 12) & (AO_HASH_SIZE-1)) + +AO_TS_t AO_locks[AO_HASH_SIZE] = { + AO_TS_INITIALIZER, AO_TS_INITIALIZER, + AO_TS_INITIALIZER, AO_TS_INITIALIZER, + AO_TS_INITIALIZER, AO_TS_INITIALIZER, + AO_TS_INITIALIZER, AO_TS_INITIALIZER, + AO_TS_INITIALIZER, AO_TS_INITIALIZER, + AO_TS_INITIALIZER, AO_TS_INITIALIZER, + AO_TS_INITIALIZER, AO_TS_INITIALIZER, + AO_TS_INITIALIZER, AO_TS_INITIALIZER, +}; + +static AO_T dummy = 1; + +/* Spin for 2**n units. */ +void AO_spin(int n) +{ + int i; + AO_T j = AO_load(&dummy); + + for (i = 0; i < (2 << n); ++i) + { + j *= 5; + j -= 4; + } + AO_store(&dummy, j); +} + +void AO_pause(int n) +{ + if (n < 12) + AO_spin(n); + else + { + struct timeval tv; + + /* Short async-signal-safe sleep. */ + tv.tv_sec = 0; + tv.tv_usec = (n > 28? 100000 : (1 << (n - 12))); + select(0, 0, 0, 0, &tv); + } +} + +static void lock_ool(volatile AO_TS_t *l) +{ + int i = 0; + + while (AO_test_and_set_acquire(l) == AO_TS_SET) + AO_pause(++i); +} + +AO_INLINE void lock(volatile AO_TS_t *l) +{ + if (AO_test_and_set_acquire(l) == AO_TS_SET) + lock_ool(l); +} + +AO_INLINE void unlock(volatile AO_TS_t *l) +{ + AO_CLEAR(l); +} + +static sigset_t all_sigs; + +static volatile AO_t initialized = 0; + +static volatile AO_TS_t init_lock = AO_TS_INITIALIZER; + +int AO_compare_and_swap_emulation(volatile AO_t *addr, AO_t old, + AO_t new_val) +{ + AO_TS_t *my_lock = AO_locks + AO_HASH(addr); + sigset_t old_sigs; + int result; + + if (!AO_load_acquire(&initialized)) + { + lock(&init_lock); + if (!initialized) sigfillset(&all_sigs); + unlock(&init_lock); + AO_store_release(&initialized, 1); + } + sigprocmask(SIG_BLOCK, &all_sigs, &old_sigs); + /* Neither sigprocmask nor pthread_sigmask is 100% */ + /* guaranteed to work here. Sigprocmask is not */ + /* guaranteed be thread safe, and pthread_sigmask */ + /* is not async-signal-safe. Under linuxthreads, */ + /* sigprocmask may block some pthreads-internal */ + /* signals. So long as we do that for short periods, */ + /* we should be OK. */ + lock(my_lock); + if (*addr == old) + { + *addr = new_val; + result = 1; + } + else + result = 0; + unlock(my_lock); + sigprocmask(SIG_SETMASK, &old_sigs, NULL); + return result; +} + +int AO_compare_double_and_swap_double_emulation(volatile AO_double_t *addr, + AO_t old_val1, AO_t old_val2, + AO_t new_val1, AO_t new_val2) +{ + AO_TS_t *my_lock = AO_locks + AO_HASH(addr); + sigset_t old_sigs; + int result; + + if (!AO_load_acquire(&initialized)) + { + lock(&init_lock); + if (!initialized) sigfillset(&all_sigs); + unlock(&init_lock); + AO_store_release(&initialized, 1); + } + sigprocmask(SIG_BLOCK, &all_sigs, &old_sigs); + /* Neither sigprocmask nor pthread_sigmask is 100% */ + /* guaranteed to work here. Sigprocmask is not */ + /* guaranteed be thread safe, and pthread_sigmask */ + /* is not async-signal-safe. Under linuxthreads, */ + /* sigprocmask may block some pthreads-internal */ + /* signals. So long as we do that for short periods, */ + /* we should be OK. */ + lock(my_lock); + if (addr -> AO_val1 == old_val1 && addr -> AO_val2 == old_val2) + { + addr -> AO_val1 = new_val1; + addr -> AO_val2 = new_val2; + result = 1; + } + else + result = 0; + unlock(my_lock); + sigprocmask(SIG_SETMASK, &old_sigs, NULL); + return result; +} + +void AO_store_full_emulation(volatile AO_t *addr, AO_t val) +{ + AO_TS_t *my_lock = AO_locks + AO_HASH(addr); + lock(my_lock); + *addr = val; + unlock(my_lock); +} + +#else /* Non-posix platform */ + +int AO_non_posix_implementation_is_entirely_in_headers; + +#endif diff --git a/src/atomic_ops.h b/src/atomic_ops.h new file mode 100755 index 0000000..a77bfd6 --- /dev/null +++ b/src/atomic_ops.h @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2003 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. + */ + +#ifndef ATOMIC_OPS_H + +#define ATOMIC_OPS_H + +#include <assert.h> + +/* We define various atomic operations on memory in a */ +/* machine-specific way. Unfortunately, this is complicated */ +/* by the fact that these may or may not be combined with */ +/* various memory barriers. Thus the actual operations we */ +/* define have the form AO_<atomic-op>_<barrier>, for all */ +/* plausible combinations of <atomic-op> and <barrier>. */ +/* This of course results in a mild combinatorial explosion. */ +/* To deal with it, we try to generate derived */ +/* definitions for as many of the combinations as we can, as */ +/* automatically as possible. */ +/* */ +/* Our assumption throughout is that the programmer will */ +/* specify the least demanding operation and memory barrier */ +/* that will guarantee correctness for the implementation. */ +/* Our job is to find the least expensive way to implement it */ +/* on the applicable hardware. In many cases that will */ +/* involve, for example, a stronger memory barrier, or a */ +/* combination of hardware primitives. */ +/* */ +/* Conventions: */ +/* "plain" atomic operations are not guaranteed to include */ +/* a barrier. The suffix in the name specifies the barrier */ +/* type. Suffixes are: */ +/* _release: Earlier operations may not be delayed past it. */ +/* _acquire: Later operations may not move ahead of it. */ +/* _read: Subsequent reads must follow this operation and */ +/* preceding reads. */ +/* _write: Earlier writes precede both this operation and */ +/* later writes. */ +/* _full: Ordered with respect to both earlier and later memops.*/ +/* _release_write: Ordered with respect to earlier writes. */ +/* _acquire_read: Ordered with repsect to later reads. */ +/* */ +/* Currently we try to define the following atomic memory */ +/* operations, in combination with the above barriers: */ +/* AO_nop */ +/* AO_load */ +/* AO_store */ +/* AO_test_and_set (binary) */ +/* AO_fetch_and_add */ +/* AO_fetch_and_add1 */ +/* AO_fetch_and_sub1 */ +/* AO_or */ +/* AO_compare_and_swap */ +/* */ +/* Note that atomicity guarantees are valid only if both */ +/* readers and writers use AO_ operations to access the */ +/* shared value, while ordering constraints are intended to */ +/* apply all memory operations. If a location can potentially */ +/* be accessed simultaneously from multiple threads, and one of */ +/* those accesses may be a write access, then all such */ +/* accesses to that location should be through AO_ primitives. */ +/* However if AO_ operations enforce sufficient ordering to */ +/* ensure that a location x cannot be accessed concurrently, */ +/* or can only be read concurrently, then x can be accessed */ +/* via ordinary references and assignments. */ +/* */ +/* Compare_and_exchange takes an address and an expected old */ +/* value and a new value, and returns an int. Nonzero */ +/* indicates that it succeeded. */ +/* Test_and_set takes an address, atomically replaces it by */ +/* AO_TS_SET, and returns the prior value. */ +/* An AO_TS_t clear location can be reset with the */ +/* AO_CLEAR macro, which normally uses AO_store_release. */ +/* AO_fetch_and_add takes an address and an AO_t increment */ +/* value. The AO_fetch_and_add1 and AO_fetch_and_sub1 variants */ +/* are provided, since they allow faster implementations on */ +/* some hardware. AO_or atomically ors an AO_t value into a */ +/* memory location, but does not provide access to the original.*/ +/* */ +/* We expect this list to grow slowly over time. */ +/* */ +/* Note that AO_nop_full is a full memory barrier. */ +/* */ +/* Note that if some data is initialized with */ +/* data.x = ...; data.y = ...; ... */ +/* AO_store_release_write(&data_is_initialized, 1) */ +/* then data is guaranteed to be initialized after the test */ +/* if (AO_load_release_read(&data_is_initialized)) ... */ +/* succeeds. Furthermore, this should generate near-optimal */ +/* code on all common platforms. */ +/* */ +/* All operations operate on unsigned AO_t, which */ +/* is the natural word size, and usually unsigned long. */ +/* It is possible to check whether a particular operation op */ +/* is available on a particular platform by checking whether */ +/* AO_HAVE_op is defined. We make heavy use of these macros */ +/* internally. */ + +/* The rest of this file basically has three sections: */ +/* */ +/* Some utility and default definitions. */ +/* */ +/* The architecture dependent section: */ +/* This defines atomic operations that have direct hardware */ +/* support on a particular platform, mostly by uncluding the */ +/* appropriate compiler- and hardware-dependent file. */ +/* */ +/* The synthesis section: */ +/* This tries to define other atomic operations in terms of */ +/* those that are explicitly available on the platform. */ +/* This section is hardware independent. */ +/* We make no attempt to synthesize operations in ways that */ +/* effectively introduce locks, except for the debugging/demo */ +/* pthread-based implementation at the beginning. A more */ +/* relistic implementation that falls back to locks could be */ +/* added as a higher layer. But that would sacrifice */ +/* usability from signal handlers. */ +/* The synthesis section is implemented almost entirely in */ +/* atomic_ops_generalize.h. */ + +/* Some common defaults. Overridden for some architectures. */ +#define AO_t unsigned long + /* Could conceivably be redefined below if/when we add */ + /* win64 support. */ + +/* The test_and_set primitive returns an AO_TS_VAL_t value. */ +/* AO_TS_t is the type of an in-memory test-and-set location. */ + +#define AO_TS_INITIALIZER (AO_t)AO_TS_CLEAR + +/* Platform-dependent stuff: */ +#if defined(__GNUC__) || defined(_MSC_VER) || defined(__INTEL_COMPILER) +# define AO_INLINE static __inline +#else +# define AO_INLINE static +#endif + +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) +# define AO_compiler_barrier() __asm__ __volatile__("" : : : "memory") +#elif defined(_MSC_VER) +# define AO_compiler_barrier() __asm { } +#elif defined(__INTEL_COMPILER) +# define AO_compiler_barrier() __memory_barrier() /* Too strong? IA64-only? */ +#elif defined(_HPUX_SOURCE) +# if defined(__ia64) +# include <machine/sys/inline.h> +# define AO_compiler_barrier() _Asm_sched_fence() +# else + /* FIXME - We dont know how to do this. This is a guess. */ + /* And probably a bad one. */ + static volatile int AO_barrier_dummy; +# define AO_compiler_barrier() AO_barrier_dummy = AO_barrier_dummy +# endif +#else + /* We conjecture that the following usually gives us the right */ + /* semantics or an error. */ +# define AO_compiler_barrier() asm("") +#endif + +#if defined(AO_USE_PTHREAD_DEFS) +# include "atomic_ops/sysdeps/generic_pthread.h" +#endif /* AO_USE_PTHREAD_DEFS */ + +#if defined(__GNUC__) && !defined(AO_USE_PTHREAD_DEFS) \ + && !defined(__INTEL_COMPILER) +# if defined(__i386__) +# include "atomic_ops/sysdeps/gcc/x86.h" +# endif /* __i386__ */ +# if defined(__x86_64__) +# include "atomic_ops/sysdeps/gcc/x86_64.h" +# endif /* __i386__ */ +# if defined(__ia64__) +# include "atomic_ops/sysdeps/gcc/ia64.h" +# define AO_GENERALIZE_TWICE +# endif /* __ia64__ */ +# if defined(__hppa__) +# include "atomic_ops/sysdeps/gcc/hppa.h" +# define AO_CAN_EMUL_CAS +# endif /* __hppa__ */ +# if defined(__alpha__) +# include "atomic_ops/sysdeps/gcc/alpha.h" +# define AO_GENERALIZE_TWICE +# endif /* __alpha__ */ +# if defined(__s390__) +# include "atomic_ops/sysdeps/gcc/s390.h" +# endif /* __s390__ */ +# if defined(__sparc__) +# include "atomic_ops/sysdeps/gcc/sparc.h" +# define AO_CAN_EMUL_CAS +# endif /* __sparc__ */ +# if defined(__m68k__) +# include "atomic_ops/sysdeps/gcc/m68k.h" +# endif /* __m68k__ */ +# if defined(__powerpc__) || defined(__ppc__) +# include "atomic_ops/sysdeps/gcc/powerpc.h" +# endif /* __powerpc__ */ +# if defined(__arm__) && !defined(AO_USE_PTHREAD_DEFS) +# include "atomic_ops/sysdeps/gcc/arm.h" +# endif /* __arm__ */ +# if defined(__cris__) || defined(CRIS) +# include "atomic_ops/sysdeps/gcc/cris.h" +# endif +#endif /* __GNUC__ && !AO_USE_PTHREAD_DEFS */ + +#if defined(__INTEL_COMPILER) && !defined(AO_USE_PTHREAD_DEFS) +# if defined(__ia64__) +# include "atomic_ops/sysdeps/icc/ia64.h" +# define AO_GENERALIZE_TWICE +# endif +#endif + +#if defined(_HPUX_SOURCE) && !defined(__GNUC__) && !defined(AO_USE_PTHREAD_DEFS) +# if defined(__ia64) +# include "atomic_ops/sysdeps/hpc/ia64.h" +# define AO_GENERALIZE_TWICE +# else +# include "atomic_ops/sysdeps/hpc/hppa.h" +# define AO_CAN_EMUL_CAS +# endif +#endif + +#if !defined(__GNUC__) && (defined(sparc) || defined(__sparc)) \ + && !defined(AO_USE_PTHREAD_DEFS) +# include "atomic_ops/sysdeps/sunc/sparc.h" +# define AO_CAN_EMUL_CAS +#endif + +#if defined(_MSC_VER) +# if _M_IX86 >= 400 +# include "atomic_ops/sysdeps/msftc/x86.h" +# endif +#endif + +#if defined(AO_REQUIRE_CAS) && !defined(AO_HAVE_compare_and_swap) \ + && !defined(AO_HAVE_compare_and_swap_full) \ + && !defined(AO_HAVE_compare_and_swap_acquire) +# if defined(AO_CAN_EMUL_CAS) +# include "atomic_ops/sysdeps/emul_cas.h" +# else +# error Cannot implement AO_compare_and_swap_full on this architecture. +# endif +#endif /* AO_REQUIRE_CAS && !AO_HAVE_compare_and_swap ... */ + +/* The most common way to clear a test-and-set location */ +/* at the end of a critical section. */ +#if AO_AO_TS_T && !defined(AO_CLEAR) +# define AO_CLEAR(addr) AO_store_release((AO_TS_t *)addr, AO_TS_CLEAR) +#endif +#if AO_CHAR_TS_T && !defined(AO_CLEAR) +# define AO_CLEAR(addr) AO_char_store_release((AO_TS_t *)addr, AO_TS_CLEAR) +#endif + +/* + * The generalization section. + * Theoretically this should repeatedly include atomic_ops_generalize.h. + * In fact, we observe that this converges after a small fixed number + * of iterations, usually one. + */ +#include "atomic_ops/generalize.h" +#ifdef AO_GENERALIZE_TWICE +# include "atomic_ops/generalize.h" +#endif + +/* For compatibility with version 0.4 and earlier */ +#define AO_TS_T AO_TS_t +#define AO_T AO_t +#define AO_TS_VAL AO_TS_VAL_t + +#endif /* ATOMIC_OPS_H */ diff --git a/src/atomic_ops/Makefile.am b/src/atomic_ops/Makefile.am new file mode 100644 index 0000000..a710df0 --- /dev/null +++ b/src/atomic_ops/Makefile.am @@ -0,0 +1,12 @@ +SUBDIRS=sysdeps + +EXTRA_DIST=generalize-small.template + +#Private Headers +private_HEADERS=generalize.h generalize-small.h +privatedir=${includedir}/atomic_ops/ + +generalize-small.h: generalize-small.template + sed -e s:XSIZE:byte:g -e s:XCTYPE:char:g $? > $@ + sed -e s:XSIZE:short:g -e s:XCTYPE:short:g $? >> $@ + sed -e s:XSIZE:int:g -e s:XCTYPE:int:g $? >> $@ diff --git a/src/atomic_ops/Makefile.in b/src/atomic_ops/Makefile.in new file mode 100644 index 0000000..d236333 --- /dev/null +++ b/src/atomic_ops/Makefile.in @@ -0,0 +1,480 @@ +# Makefile.in generated by automake 1.9.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/atomic_ops +DIST_COMMON = $(private_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/src/config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-exec-recursive install-info-recursive \ + install-recursive installcheck-recursive installdirs-recursive \ + pdf-recursive ps-recursive uninstall-info-recursive \ + uninstall-recursive +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(privatedir)" +privateHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(private_HEADERS) +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +NEED_ASM_FALSE = @NEED_ASM_FALSE@ +NEED_ASM_TRUE = @NEED_ASM_TRUE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PICFLAG = @PICFLAG@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +SUBDIRS = sysdeps +EXTRA_DIST = generalize-small.template + +#Private Headers +private_HEADERS = generalize.h generalize-small.h +privatedir = ${includedir}/atomic_ops/ +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/atomic_ops/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/atomic_ops/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +uninstall-info-am: +install-privateHEADERS: $(private_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(privatedir)" || $(mkdir_p) "$(DESTDIR)$(privatedir)" + @list='$(private_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(privateHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(privatedir)/$$f'"; \ + $(privateHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(privatedir)/$$f"; \ + done + +uninstall-privateHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(private_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(privatedir)/$$f'"; \ + rm -f "$(DESTDIR)$(privatedir)/$$f"; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(mkdir_p) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(privatedir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: install-privateHEADERS + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-info-am uninstall-privateHEADERS + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ + clean clean-generic clean-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-recursive distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-privateHEADERS install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic maintainer-clean-recursive \ + mostlyclean mostlyclean-generic mostlyclean-recursive pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-info-am uninstall-privateHEADERS + + +generalize-small.h: generalize-small.template + sed -e s:XSIZE:byte:g -e s:XCTYPE:char:g $? > $@ + sed -e s:XSIZE:short:g -e s:XCTYPE:short:g $? >> $@ + sed -e s:XSIZE:int:g -e s:XCTYPE:int:g $? >> $@ +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/atomic_ops/generalize-small.h b/src/atomic_ops/generalize-small.h new file mode 100644 index 0000000..4e45a0d --- /dev/null +++ b/src/atomic_ops/generalize-small.h @@ -0,0 +1,1725 @@ +/* char_load */ +#if defined(AO_HAVE_char_load_acquire) && !defined(AO_HAVE_char_load) +# define AO_char_load(addr) AO_char_load_acquire(addr) +# define AO_HAVE_char_load +#endif + +#if defined(AO_HAVE_char_load_full) && !defined(AO_HAVE_char_load_acquire) +# define AO_char_load_acquire(addr) AO_char_load_full(addr) +# define AO_HAVE_char_load_acquire +#endif + +#if defined(AO_HAVE_char_load_full) && !defined(AO_HAVE_char_load_read) +# define AO_char_load_read(addr) AO_char_load_full(addr) +# define AO_HAVE_char_load_read +#endif + +#if !defined(AO_HAVE_char_load_acquire_read) && defined(AO_HAVE_char_load_acquire) +# define AO_char_load_acquire_read(addr) AO_char_load_acquire(addr) +# define AO_HAVE_char_load_acquire_read +#endif + +#if defined(AO_HAVE_char_load) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_char_load_acquire) + AO_INLINE unsigned char + AO_char_load_acquire(volatile unsigned char *addr) + { + unsigned char result = AO_char_load(addr); + /* Acquire barrier would be useless, since the load could be delayed */ + /* beyond it. */ + AO_nop_full(); + return result; + } +# define AO_HAVE_char_load_acquire +#endif + +#if defined(AO_HAVE_char_load) && defined(AO_HAVE_nop_read) && \ + !defined(AO_HAVE_char_load_read) + AO_INLINE unsigned char + AO_char_load_read(volatile unsigned char *addr) + { + unsigned char result = AO_char_load(addr); + /* Acquire barrier would be useless, since the load could be delayed */ + /* beyond it. */ + AO_nop_read(); + return result; + } +# define AO_HAVE_char_load_read +#endif + +#if defined(AO_HAVE_char_load_acquire) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_char_load_full) +# define AO_char_load_full(addr) (AO_nop_full(), AO_char_load_acquire(addr)) +# define AO_HAVE_char_load_full +#endif + +#if !defined(AO_HAVE_char_load_acquire_read) && defined(AO_HAVE_char_load_read) +# define AO_char_load_acquire_read(addr) AO_char_load_read(addr) +# define AO_HAVE_char_load_acquire_read +#endif + +#if defined(AO_HAVE_char_load_acquire_read) && !defined(AO_HAVE_char_load) +# define AO_char_load(addr) AO_char_load_acquire_read(addr) +# define AO_HAVE_char_load +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_char_load_acquire_read) +# define AO_char_load_dd_acquire_read(addr) \ + AO_char_load_acquire_read(addr) +# define AO_HAVE_char_load_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_char_load) +# define AO_char_load_dd_acquire_read(addr) \ + AO_char_load(addr) +# define AO_HAVE_char_load_dd_acquire_read +# endif +#endif + + +/* char_store */ + +#if defined(AO_HAVE_char_store_release) && !defined(AO_HAVE_char_store) +# define AO_char_store(addr, val) AO_char_store_release(addr,val) +# define AO_HAVE_char_store +#endif + +#if defined(AO_HAVE_char_store_full) && !defined(AO_HAVE_char_store_release) +# define AO_char_store_release(addr,val) AO_char_store_full(addr,val) +# define AO_HAVE_char_store_release +#endif + +#if defined(AO_HAVE_char_store_full) && !defined(AO_HAVE_char_store_write) +# define AO_char_store_write(addr,val) AO_char_store_full(addr,val) +# define AO_HAVE_char_store_write +#endif + +#if defined(AO_HAVE_char_store_release) && \ + !defined(AO_HAVE_char_store_release_write) +# define AO_char_store_release_write(addr, val) \ + AO_char_store_release(addr,val) +# define AO_HAVE_char_store_release_write +#endif + +#if defined(AO_HAVE_char_store_write) && !defined(AO_HAVE_char_store) +# define AO_char_store(addr, val) AO_char_store_write(addr,val) +# define AO_HAVE_char_store +#endif + +#if defined(AO_HAVE_char_store) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_char_store_release) +# define AO_char_store_release(addr,val) \ + (AO_nop_full(), AO_char_store(addr,val)) +# define AO_HAVE_char_store_release +#endif + +#if defined(AO_HAVE_nop_write) && defined(AO_HAVE_char_store) && \ + !defined(AO_HAVE_char_store_write) +# define AO_char_store_write(addr, val) \ + (AO_nop_write(), AO_char_store(addr,val)) +# define AO_HAVE_char_store_write +#endif + +#if defined(AO_HAVE_char_store_write) && \ + !defined(AO_HAVE_char_store_release_write) +# define AO_char_store_release_write(addr, val) AO_char_store_write(addr,val) +# define AO_HAVE_char_store_release_write +#endif + +#if defined(AO_HAVE_char_store_release) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_char_store_full) +# define AO_char_store_full(addr, val) \ + (AO_char_store_release(addr, val), AO_nop_full()) +# define AO_HAVE_char_store_full +#endif + + +/* char_fetch_and_add */ +#if defined(AO_HAVE_char_compare_and_swap_full) && \ + !defined(AO_HAVE_char_fetch_and_add_full) + AO_INLINE AO_t + AO_char_fetch_and_add_full(volatile unsigned char *addr, + unsigned char incr) + { + unsigned char old; + do + { + old = *addr; + } + while (!AO_char_compare_and_swap_full(addr, old, old+incr)); + return old; + } +# define AO_HAVE_char_fetch_and_add_full +#endif + +#if defined(AO_HAVE_char_compare_and_swap_acquire) && \ + !defined(AO_HAVE_char_fetch_and_add_acquire) + AO_INLINE AO_t + AO_char_fetch_and_add_acquire(volatile unsigned char *addr, + unsigned char incr) + { + unsigned char old; + do + { + old = *addr; + } + while (!AO_char_compare_and_swap_acquire(addr, old, old+incr)); + return old; + } +# define AO_HAVE_char_fetch_and_add_acquire +#endif + +#if defined(AO_HAVE_char_compare_and_swap_release) && \ + !defined(AO_HAVE_char_fetch_and_add_release) + AO_INLINE AO_t + AO_char_fetch_and_add_release(volatile unsigned char *addr, + unsigned char incr) + { + unsigned char old; + do + { + old = *addr; + } + while (!AO_char_compare_and_swap_release(addr, old, old+incr)); + return old; + } +# define AO_HAVE_char_fetch_and_add_release +#endif + +#if defined(AO_HAVE_char_fetch_and_add_full) +# if !defined(AO_HAVE_char_fetch_and_add_release) +# define AO_char_fetch_and_add_release(addr, val) \ + AO_char_fetch_and_add_full(addr, val) +# define AO_HAVE_char_fetch_and_add_release +# endif +# if !defined(AO_HAVE_char_fetch_and_add_acquire) +# define AO_char_fetch_and_add_acquire(addr, val) \ + AO_char_fetch_and_add_full(addr, val) +# define AO_HAVE_char_fetch_and_add_acquire +# endif +# if !defined(AO_HAVE_char_fetch_and_add_write) +# define AO_char_fetch_and_add_write(addr, val) \ + AO_char_fetch_and_add_full(addr, val) +# define AO_HAVE_char_fetch_and_add_write +# endif +# if !defined(AO_HAVE_char_fetch_and_add_read) +# define AO_char_fetch_and_add_read(addr, val) \ + AO_char_fetch_and_add_full(addr, val) +# define AO_HAVE_char_fetch_and_add_read +# endif +#endif /* AO_HAVE_char_fetch_and_add_full */ + +#if !defined(AO_HAVE_char_fetch_and_add) && \ + defined(AO_HAVE_char_fetch_and_add_release) +# define AO_char_fetch_and_add(addr, val) \ + AO_char_fetch_and_add_release(addr, val) +# define AO_HAVE_char_fetch_and_add +#endif +#if !defined(AO_HAVE_char_fetch_and_add) && \ + defined(AO_HAVE_char_fetch_and_add_acquire) +# define AO_char_fetch_and_add(addr, val) \ + AO_char_fetch_and_add_acquire(addr, val) +# define AO_HAVE_char_fetch_and_add +#endif +#if !defined(AO_HAVE_char_fetch_and_add) && \ + defined(AO_HAVE_char_fetch_and_add_write) +# define AO_char_fetch_and_add(addr, val) \ + AO_char_fetch_and_add_write(addr, val) +# define AO_HAVE_char_fetch_and_add +#endif +#if !defined(AO_HAVE_char_fetch_and_add) && \ + defined(AO_HAVE_char_fetch_and_add_read) +# define AO_char_fetch_and_add(addr, val) \ + AO_char_fetch_and_add_read(addr, val) +# define AO_HAVE_char_fetch_and_add +#endif + +#if defined(AO_HAVE_char_fetch_and_add_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_char_fetch_and_add_full) +# define AO_char_fetch_and_add_full(addr, val) \ + (AO_nop_full(), AO_char_fetch_and_add_acquire(addr, val)) +#endif + +#if !defined(AO_HAVE_char_fetch_and_add_release_write) && \ + defined(AO_HAVE_char_fetch_and_add_write) +# define AO_char_fetch_and_add_release_write(addr, val) \ + AO_char_fetch_and_add_write(addr, val) +# define AO_HAVE_char_fetch_and_add_release_write +#endif +#if !defined(AO_HAVE_char_fetch_and_add_release_write) && \ + defined(AO_HAVE_char_fetch_and_add_release) +# define AO_char_fetch_and_add_release_write(addr, val) \ + AO_char_fetch_and_add_release(addr, val) +# define AO_HAVE_char_fetch_and_add_release_write +#endif +#if !defined(AO_HAVE_char_fetch_and_add_acquire_read) && \ + defined(AO_HAVE_char_fetch_and_add_read) +# define AO_char_fetch_and_add_acquire_read(addr, val) \ + AO_char_fetch_and_add_read(addr, val) +# define AO_HAVE_char_fetch_and_add_acquire_read +#endif +#if !defined(AO_HAVE_char_fetch_and_add_acquire_read) && \ + defined(AO_HAVE_char_fetch_and_add_acquire) +# define AO_char_fetch_and_add_acquire_read(addr, val) \ + AO_char_fetch_and_add_acquire(addr, val) +# define AO_HAVE_char_fetch_and_add_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_char_fetch_and_add_acquire_read) +# define AO_char_fetch_and_add_dd_acquire_read(addr, val) \ + AO_char_fetch_and_add_acquire_read(addr, val) +# define AO_HAVE_char_fetch_and_add_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_char_fetch_and_add) +# define AO_char_fetch_and_add_dd_acquire_read(addr, val) \ + AO_char_fetch_and_add(addr, val) +# define AO_HAVE_char_fetch_and_add_dd_acquire_read +# endif +#endif + +/* char_fetch_and_add1 */ + +#if defined(AO_HAVE_char_fetch_and_add_full) &&\ + !defined(AO_HAVE_char_fetch_and_add1_full) +# define AO_char_fetch_and_add1_full(addr) \ + AO_char_fetch_and_add_full(addr,1) +# define AO_HAVE_char_fetch_and_add1_full +#endif +#if defined(AO_HAVE_char_fetch_and_add_release) &&\ + !defined(AO_HAVE_char_fetch_and_add1_release) +# define AO_char_fetch_and_add1_release(addr) \ + AO_char_fetch_and_add_release(addr,1) +# define AO_HAVE_char_fetch_and_add1_release +#endif +#if defined(AO_HAVE_char_fetch_and_add_acquire) &&\ + !defined(AO_HAVE_char_fetch_and_add1_acquire) +# define AO_char_fetch_and_add1_acquire(addr) \ + AO_char_fetch_and_add_acquire(addr,1) +# define AO_HAVE_char_fetch_and_add1_acquire +#endif +#if defined(AO_HAVE_char_fetch_and_add_write) &&\ + !defined(AO_HAVE_char_fetch_and_add1_write) +# define AO_char_fetch_and_add1_write(addr) \ + AO_char_fetch_and_add_write(addr,1) +# define AO_HAVE_char_fetch_and_add1_write +#endif +#if defined(AO_HAVE_char_fetch_and_add_read) &&\ + !defined(AO_HAVE_char_fetch_and_add1_read) +# define AO_char_fetch_and_add1_read(addr) \ + AO_char_fetch_and_add_read(addr,1) +# define AO_HAVE_char_fetch_and_add1_read +#endif +#if defined(AO_HAVE_char_fetch_and_add_release_write) &&\ + !defined(AO_HAVE_char_fetch_and_add1_release_write) +# define AO_char_fetch_and_add1_release_write(addr) \ + AO_char_fetch_and_add_release_write(addr,1) +# define AO_HAVE_char_fetch_and_add1_release_write +#endif +#if defined(AO_HAVE_char_fetch_and_add_acquire_read) &&\ + !defined(AO_HAVE_char_fetch_and_add1_acquire_read) +# define AO_char_fetch_and_add1_acquire_read(addr) \ + AO_char_fetch_and_add_acquire_read(addr,1) +# define AO_HAVE_char_fetch_and_add1_acquire_read +#endif +#if defined(AO_HAVE_char_fetch_and_add) &&\ + !defined(AO_HAVE_char_fetch_and_add1) +# define AO_char_fetch_and_add1(addr) \ + AO_char_fetch_and_add(addr,1) +# define AO_HAVE_char_fetch_and_add1 +#endif + +#if defined(AO_HAVE_char_fetch_and_add1_full) +# if !defined(AO_HAVE_char_fetch_and_add1_release) +# define AO_char_fetch_and_add1_release(addr) \ + AO_char_fetch_and_add1_full(addr) +# define AO_HAVE_char_fetch_and_add1_release +# endif +# if !defined(AO_HAVE_char_fetch_and_add1_acquire) +# define AO_char_fetch_and_add1_acquire(addr) \ + AO_char_fetch_and_add1_full(addr) +# define AO_HAVE_char_fetch_and_add1_acquire +# endif +# if !defined(AO_HAVE_char_fetch_and_add1_write) +# define AO_char_fetch_and_add1_write(addr) \ + AO_char_fetch_and_add1_full(addr) +# define AO_HAVE_char_fetch_and_add1_write +# endif +# if !defined(AO_HAVE_char_fetch_and_add1_read) +# define AO_char_fetch_and_add1_read(addr) \ + AO_char_fetch_and_add1_full(addr) +# define AO_HAVE_char_fetch_and_add1_read +# endif +#endif /* AO_HAVE_char_fetch_and_add1_full */ + +#if !defined(AO_HAVE_char_fetch_and_add1) && \ + defined(AO_HAVE_char_fetch_and_add1_release) +# define AO_char_fetch_and_add1(addr) \ + AO_char_fetch_and_add1_release(addr) +# define AO_HAVE_char_fetch_and_add1 +#endif +#if !defined(AO_HAVE_char_fetch_and_add1) && \ + defined(AO_HAVE_char_fetch_and_add1_acquire) +# define AO_char_fetch_and_add1(addr) \ + AO_char_fetch_and_add1_acquire(addr) +# define AO_HAVE_char_fetch_and_add1 +#endif +#if !defined(AO_HAVE_char_fetch_and_add1) && \ + defined(AO_HAVE_char_fetch_and_add1_write) +# define AO_char_fetch_and_add1(addr) \ + AO_char_fetch_and_add1_write(addr) +# define AO_HAVE_char_fetch_and_add1 +#endif +#if !defined(AO_HAVE_char_fetch_and_add1) && \ + defined(AO_HAVE_char_fetch_and_add1_read) +# define AO_char_fetch_and_add1(addr) \ + AO_char_fetch_and_add1_read(addr) +# define AO_HAVE_char_fetch_and_add1 +#endif + +#if defined(AO_HAVE_char_fetch_and_add1_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_char_fetch_and_add1_full) +# define AO_char_fetch_and_add1_full(addr) \ + (AO_nop_full(), AO_char_fetch_and_add1_acquire(addr)) +# define AO_HAVE_char_fetch_and_add1_full +#endif + +#if !defined(AO_HAVE_char_fetch_and_add1_release_write) && \ + defined(AO_HAVE_char_fetch_and_add1_write) +# define AO_char_fetch_and_add1_release_write(addr) \ + AO_char_fetch_and_add1_write(addr) +# define AO_HAVE_char_fetch_and_add1_release_write +#endif +#if !defined(AO_HAVE_char_fetch_and_add1_release_write) && \ + defined(AO_HAVE_char_fetch_and_add1_release) +# define AO_char_fetch_and_add1_release_write(addr) \ + AO_char_fetch_and_add1_release(addr) +# define AO_HAVE_char_fetch_and_add1_release_write +#endif +#if !defined(AO_HAVE_char_fetch_and_add1_acquire_read) && \ + defined(AO_HAVE_char_fetch_and_add1_read) +# define AO_char_fetch_and_add1_acquire_read(addr) \ + AO_char_fetch_and_add1_read(addr) +# define AO_HAVE_char_fetch_and_add1_acquire_read +#endif +#if !defined(AO_HAVE_char_fetch_and_add1_acquire_read) && \ + defined(AO_HAVE_char_fetch_and_add1_acquire) +# define AO_char_fetch_and_add1_acquire_read(addr) \ + AO_char_fetch_and_add1_acquire(addr) +# define AO_HAVE_char_fetch_and_add1_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_char_fetch_and_add1_acquire_read) +# define AO_char_fetch_and_add1_dd_acquire_read(addr) \ + AO_char_fetch_and_add1_acquire_read(addr) +# define AO_HAVE_char_fetch_and_add1_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_char_fetch_and_add1) +# define AO_char_fetch_and_add1_dd_acquire_read(addr) \ + AO_char_fetch_and_add1(addr) +# define AO_HAVE_char_fetch_and_add1_dd_acquire_read +# endif +#endif + +/* char_fetch_and_sub1 */ + +#if defined(AO_HAVE_char_fetch_and_add_full) &&\ + !defined(AO_HAVE_char_fetch_and_sub1_full) +# define AO_char_fetch_and_sub1_full(addr) \ + AO_char_fetch_and_add_full(addr,(unsigned char)(-1)) +# define AO_HAVE_char_fetch_and_sub1_full +#endif +#if defined(AO_HAVE_char_fetch_and_add_release) &&\ + !defined(AO_HAVE_char_fetch_and_sub1_release) +# define AO_char_fetch_and_sub1_release(addr) \ + AO_char_fetch_and_add_release(addr,(unsigned char)(-1)) +# define AO_HAVE_char_fetch_and_sub1_release +#endif +#if defined(AO_HAVE_char_fetch_and_add_acquire) &&\ + !defined(AO_HAVE_char_fetch_and_sub1_acquire) +# define AO_char_fetch_and_sub1_acquire(addr) \ + AO_char_fetch_and_add_acquire(addr,(unsigned char)(-1)) +# define AO_HAVE_char_fetch_and_sub1_acquire +#endif +#if defined(AO_HAVE_char_fetch_and_add_write) &&\ + !defined(AO_HAVE_char_fetch_and_sub1_write) +# define AO_char_fetch_and_sub1_write(addr) \ + AO_char_fetch_and_add_write(addr,(unsigned char)(-1)) +# define AO_HAVE_char_fetch_and_sub1_write +#endif +#if defined(AO_HAVE_char_fetch_and_add_read) &&\ + !defined(AO_HAVE_char_fetch_and_sub1_read) +# define AO_char_fetch_and_sub1_read(addr) \ + AO_char_fetch_and_add_read(addr,(unsigned char)(-1)) +# define AO_HAVE_char_fetch_and_sub1_read +#endif +#if defined(AO_HAVE_char_fetch_and_add_release_write) &&\ + !defined(AO_HAVE_char_fetch_and_sub1_release_write) +# define AO_char_fetch_and_sub1_release_write(addr) \ + AO_char_fetch_and_add_release_write(addr,(unsigned char)(-1)) +# define AO_HAVE_char_fetch_and_sub1_release_write +#endif +#if defined(AO_HAVE_char_fetch_and_add_acquire_read) &&\ + !defined(AO_HAVE_char_fetch_and_sub1_acquire_read) +# define AO_char_fetch_and_sub1_acquire_read(addr) \ + AO_char_fetch_and_add_acquire_read(addr,(unsigned char)(-1)) +# define AO_HAVE_char_fetch_and_sub1_acquire_read +#endif +#if defined(AO_HAVE_char_fetch_and_add) &&\ + !defined(AO_HAVE_char_fetch_and_sub1) +# define AO_char_fetch_and_sub1(addr) \ + AO_char_fetch_and_add(addr,(unsigned char)(-1)) +# define AO_HAVE_char_fetch_and_sub1 +#endif + +#if defined(AO_HAVE_char_fetch_and_sub1_full) +# if !defined(AO_HAVE_char_fetch_and_sub1_release) +# define AO_char_fetch_and_sub1_release(addr) \ + AO_char_fetch_and_sub1_full(addr) +# define AO_HAVE_char_fetch_and_sub1_release +# endif +# if !defined(AO_HAVE_char_fetch_and_sub1_acquire) +# define AO_char_fetch_and_sub1_acquire(addr) \ + AO_char_fetch_and_sub1_full(addr) +# define AO_HAVE_char_fetch_and_sub1_acquire +# endif +# if !defined(AO_HAVE_char_fetch_and_sub1_write) +# define AO_char_fetch_and_sub1_write(addr) \ + AO_char_fetch_and_sub1_full(addr) +# define AO_HAVE_char_fetch_and_sub1_write +# endif +# if !defined(AO_HAVE_char_fetch_and_sub1_read) +# define AO_char_fetch_and_sub1_read(addr) \ + AO_char_fetch_and_sub1_full(addr) +# define AO_HAVE_char_fetch_and_sub1_read +# endif +#endif /* AO_HAVE_char_fetch_and_sub1_full */ + +#if !defined(AO_HAVE_char_fetch_and_sub1) && \ + defined(AO_HAVE_char_fetch_and_sub1_release) +# define AO_char_fetch_and_sub1(addr) \ + AO_char_fetch_and_sub1_release(addr) +# define AO_HAVE_char_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_char_fetch_and_sub1) && \ + defined(AO_HAVE_char_fetch_and_sub1_acquire) +# define AO_char_fetch_and_sub1(addr) \ + AO_char_fetch_and_sub1_acquire(addr) +# define AO_HAVE_char_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_char_fetch_and_sub1) && \ + defined(AO_HAVE_char_fetch_and_sub1_write) +# define AO_char_fetch_and_sub1(addr) \ + AO_char_fetch_and_sub1_write(addr) +# define AO_HAVE_char_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_char_fetch_and_sub1) && \ + defined(AO_HAVE_char_fetch_and_sub1_read) +# define AO_char_fetch_and_sub1(addr) \ + AO_char_fetch_and_sub1_read(addr) +# define AO_HAVE_char_fetch_and_sub1 +#endif + +#if defined(AO_HAVE_char_fetch_and_sub1_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_char_fetch_and_sub1_full) +# define AO_char_fetch_and_sub1_full(addr) \ + (AO_nop_full(), AO_char_fetch_and_sub1_acquire(addr)) +# define AO_HAVE_char_fetch_and_sub1_full +#endif + +#if !defined(AO_HAVE_char_fetch_and_sub1_release_write) && \ + defined(AO_HAVE_char_fetch_and_sub1_write) +# define AO_char_fetch_and_sub1_release_write(addr) \ + AO_char_fetch_and_sub1_write(addr) +# define AO_HAVE_char_fetch_and_sub1_release_write +#endif +#if !defined(AO_HAVE_char_fetch_and_sub1_release_write) && \ + defined(AO_HAVE_char_fetch_and_sub1_release) +# define AO_char_fetch_and_sub1_release_write(addr) \ + AO_char_fetch_and_sub1_release(addr) +# define AO_HAVE_char_fetch_and_sub1_release_write +#endif +#if !defined(AO_HAVE_char_fetch_and_sub1_acquire_read) && \ + defined(AO_HAVE_char_fetch_and_sub1_read) +# define AO_char_fetch_and_sub1_acquire_read(addr) \ + AO_char_fetch_and_sub1_read(addr) +# define AO_HAVE_char_fetch_and_sub1_acquire_read +#endif +#if !defined(AO_HAVE_char_fetch_and_sub1_acquire_read) && \ + defined(AO_HAVE_char_fetch_and_sub1_acquire) +# define AO_char_fetch_and_sub1_acquire_read(addr) \ + AO_char_fetch_and_sub1_acquire(addr) +# define AO_HAVE_char_fetch_and_sub1_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_char_fetch_and_sub1_acquire_read) +# define AO_char_fetch_and_sub1_dd_acquire_read(addr) \ + AO_char_fetch_and_sub1_acquire_read(addr) +# define AO_HAVE_char_fetch_and_sub1_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_char_fetch_and_sub1) +# define AO_char_fetch_and_sub1_dd_acquire_read(addr) \ + AO_char_fetch_and_sub1(addr) +# define AO_HAVE_char_fetch_and_sub1_dd_acquire_read +# endif +#endif + +/* short_load */ +#if defined(AO_HAVE_short_load_acquire) && !defined(AO_HAVE_short_load) +# define AO_short_load(addr) AO_short_load_acquire(addr) +# define AO_HAVE_short_load +#endif + +#if defined(AO_HAVE_short_load_full) && !defined(AO_HAVE_short_load_acquire) +# define AO_short_load_acquire(addr) AO_short_load_full(addr) +# define AO_HAVE_short_load_acquire +#endif + +#if defined(AO_HAVE_short_load_full) && !defined(AO_HAVE_short_load_read) +# define AO_short_load_read(addr) AO_short_load_full(addr) +# define AO_HAVE_short_load_read +#endif + +#if !defined(AO_HAVE_short_load_acquire_read) && defined(AO_HAVE_short_load_acquire) +# define AO_short_load_acquire_read(addr) AO_short_load_acquire(addr) +# define AO_HAVE_short_load_acquire_read +#endif + +#if defined(AO_HAVE_short_load) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_short_load_acquire) + AO_INLINE unsigned short + AO_short_load_acquire(volatile unsigned short *addr) + { + unsigned short result = AO_short_load(addr); + /* Acquire barrier would be useless, since the load could be delayed */ + /* beyond it. */ + AO_nop_full(); + return result; + } +# define AO_HAVE_short_load_acquire +#endif + +#if defined(AO_HAVE_short_load) && defined(AO_HAVE_nop_read) && \ + !defined(AO_HAVE_short_load_read) + AO_INLINE unsigned short + AO_short_load_read(volatile unsigned short *addr) + { + unsigned short result = AO_short_load(addr); + /* Acquire barrier would be useless, since the load could be delayed */ + /* beyond it. */ + AO_nop_read(); + return result; + } +# define AO_HAVE_short_load_read +#endif + +#if defined(AO_HAVE_short_load_acquire) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_short_load_full) +# define AO_short_load_full(addr) (AO_nop_full(), AO_short_load_acquire(addr)) +# define AO_HAVE_short_load_full +#endif + +#if !defined(AO_HAVE_short_load_acquire_read) && defined(AO_HAVE_short_load_read) +# define AO_short_load_acquire_read(addr) AO_short_load_read(addr) +# define AO_HAVE_short_load_acquire_read +#endif + +#if defined(AO_HAVE_short_load_acquire_read) && !defined(AO_HAVE_short_load) +# define AO_short_load(addr) AO_short_load_acquire_read(addr) +# define AO_HAVE_short_load +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_short_load_acquire_read) +# define AO_short_load_dd_acquire_read(addr) \ + AO_short_load_acquire_read(addr) +# define AO_HAVE_short_load_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_short_load) +# define AO_short_load_dd_acquire_read(addr) \ + AO_short_load(addr) +# define AO_HAVE_short_load_dd_acquire_read +# endif +#endif + + +/* short_store */ + +#if defined(AO_HAVE_short_store_release) && !defined(AO_HAVE_short_store) +# define AO_short_store(addr, val) AO_short_store_release(addr,val) +# define AO_HAVE_short_store +#endif + +#if defined(AO_HAVE_short_store_full) && !defined(AO_HAVE_short_store_release) +# define AO_short_store_release(addr,val) AO_short_store_full(addr,val) +# define AO_HAVE_short_store_release +#endif + +#if defined(AO_HAVE_short_store_full) && !defined(AO_HAVE_short_store_write) +# define AO_short_store_write(addr,val) AO_short_store_full(addr,val) +# define AO_HAVE_short_store_write +#endif + +#if defined(AO_HAVE_short_store_release) && \ + !defined(AO_HAVE_short_store_release_write) +# define AO_short_store_release_write(addr, val) \ + AO_short_store_release(addr,val) +# define AO_HAVE_short_store_release_write +#endif + +#if defined(AO_HAVE_short_store_write) && !defined(AO_HAVE_short_store) +# define AO_short_store(addr, val) AO_short_store_write(addr,val) +# define AO_HAVE_short_store +#endif + +#if defined(AO_HAVE_short_store) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_short_store_release) +# define AO_short_store_release(addr,val) \ + (AO_nop_full(), AO_short_store(addr,val)) +# define AO_HAVE_short_store_release +#endif + +#if defined(AO_HAVE_nop_write) && defined(AO_HAVE_short_store) && \ + !defined(AO_HAVE_short_store_write) +# define AO_short_store_write(addr, val) \ + (AO_nop_write(), AO_short_store(addr,val)) +# define AO_HAVE_short_store_write +#endif + +#if defined(AO_HAVE_short_store_write) && \ + !defined(AO_HAVE_short_store_release_write) +# define AO_short_store_release_write(addr, val) AO_short_store_write(addr,val) +# define AO_HAVE_short_store_release_write +#endif + +#if defined(AO_HAVE_short_store_release) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_short_store_full) +# define AO_short_store_full(addr, val) \ + (AO_short_store_release(addr, val), AO_nop_full()) +# define AO_HAVE_short_store_full +#endif + + +/* short_fetch_and_add */ +#if defined(AO_HAVE_short_compare_and_swap_full) && \ + !defined(AO_HAVE_short_fetch_and_add_full) + AO_INLINE AO_t + AO_short_fetch_and_add_full(volatile unsigned short *addr, + unsigned short incr) + { + unsigned short old; + do + { + old = *addr; + } + while (!AO_short_compare_and_swap_full(addr, old, old+incr)); + return old; + } +# define AO_HAVE_short_fetch_and_add_full +#endif + +#if defined(AO_HAVE_short_compare_and_swap_acquire) && \ + !defined(AO_HAVE_short_fetch_and_add_acquire) + AO_INLINE AO_t + AO_short_fetch_and_add_acquire(volatile unsigned short *addr, + unsigned short incr) + { + unsigned short old; + do + { + old = *addr; + } + while (!AO_short_compare_and_swap_acquire(addr, old, old+incr)); + return old; + } +# define AO_HAVE_short_fetch_and_add_acquire +#endif + +#if defined(AO_HAVE_short_compare_and_swap_release) && \ + !defined(AO_HAVE_short_fetch_and_add_release) + AO_INLINE AO_t + AO_short_fetch_and_add_release(volatile unsigned short *addr, + unsigned short incr) + { + unsigned short old; + do + { + old = *addr; + } + while (!AO_short_compare_and_swap_release(addr, old, old+incr)); + return old; + } +# define AO_HAVE_short_fetch_and_add_release +#endif + +#if defined(AO_HAVE_short_fetch_and_add_full) +# if !defined(AO_HAVE_short_fetch_and_add_release) +# define AO_short_fetch_and_add_release(addr, val) \ + AO_short_fetch_and_add_full(addr, val) +# define AO_HAVE_short_fetch_and_add_release +# endif +# if !defined(AO_HAVE_short_fetch_and_add_acquire) +# define AO_short_fetch_and_add_acquire(addr, val) \ + AO_short_fetch_and_add_full(addr, val) +# define AO_HAVE_short_fetch_and_add_acquire +# endif +# if !defined(AO_HAVE_short_fetch_and_add_write) +# define AO_short_fetch_and_add_write(addr, val) \ + AO_short_fetch_and_add_full(addr, val) +# define AO_HAVE_short_fetch_and_add_write +# endif +# if !defined(AO_HAVE_short_fetch_and_add_read) +# define AO_short_fetch_and_add_read(addr, val) \ + AO_short_fetch_and_add_full(addr, val) +# define AO_HAVE_short_fetch_and_add_read +# endif +#endif /* AO_HAVE_short_fetch_and_add_full */ + +#if !defined(AO_HAVE_short_fetch_and_add) && \ + defined(AO_HAVE_short_fetch_and_add_release) +# define AO_short_fetch_and_add(addr, val) \ + AO_short_fetch_and_add_release(addr, val) +# define AO_HAVE_short_fetch_and_add +#endif +#if !defined(AO_HAVE_short_fetch_and_add) && \ + defined(AO_HAVE_short_fetch_and_add_acquire) +# define AO_short_fetch_and_add(addr, val) \ + AO_short_fetch_and_add_acquire(addr, val) +# define AO_HAVE_short_fetch_and_add +#endif +#if !defined(AO_HAVE_short_fetch_and_add) && \ + defined(AO_HAVE_short_fetch_and_add_write) +# define AO_short_fetch_and_add(addr, val) \ + AO_short_fetch_and_add_write(addr, val) +# define AO_HAVE_short_fetch_and_add +#endif +#if !defined(AO_HAVE_short_fetch_and_add) && \ + defined(AO_HAVE_short_fetch_and_add_read) +# define AO_short_fetch_and_add(addr, val) \ + AO_short_fetch_and_add_read(addr, val) +# define AO_HAVE_short_fetch_and_add +#endif + +#if defined(AO_HAVE_short_fetch_and_add_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_short_fetch_and_add_full) +# define AO_short_fetch_and_add_full(addr, val) \ + (AO_nop_full(), AO_short_fetch_and_add_acquire(addr, val)) +#endif + +#if !defined(AO_HAVE_short_fetch_and_add_release_write) && \ + defined(AO_HAVE_short_fetch_and_add_write) +# define AO_short_fetch_and_add_release_write(addr, val) \ + AO_short_fetch_and_add_write(addr, val) +# define AO_HAVE_short_fetch_and_add_release_write +#endif +#if !defined(AO_HAVE_short_fetch_and_add_release_write) && \ + defined(AO_HAVE_short_fetch_and_add_release) +# define AO_short_fetch_and_add_release_write(addr, val) \ + AO_short_fetch_and_add_release(addr, val) +# define AO_HAVE_short_fetch_and_add_release_write +#endif +#if !defined(AO_HAVE_short_fetch_and_add_acquire_read) && \ + defined(AO_HAVE_short_fetch_and_add_read) +# define AO_short_fetch_and_add_acquire_read(addr, val) \ + AO_short_fetch_and_add_read(addr, val) +# define AO_HAVE_short_fetch_and_add_acquire_read +#endif +#if !defined(AO_HAVE_short_fetch_and_add_acquire_read) && \ + defined(AO_HAVE_short_fetch_and_add_acquire) +# define AO_short_fetch_and_add_acquire_read(addr, val) \ + AO_short_fetch_and_add_acquire(addr, val) +# define AO_HAVE_short_fetch_and_add_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_short_fetch_and_add_acquire_read) +# define AO_short_fetch_and_add_dd_acquire_read(addr, val) \ + AO_short_fetch_and_add_acquire_read(addr, val) +# define AO_HAVE_short_fetch_and_add_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_short_fetch_and_add) +# define AO_short_fetch_and_add_dd_acquire_read(addr, val) \ + AO_short_fetch_and_add(addr, val) +# define AO_HAVE_short_fetch_and_add_dd_acquire_read +# endif +#endif + +/* short_fetch_and_add1 */ + +#if defined(AO_HAVE_short_fetch_and_add_full) &&\ + !defined(AO_HAVE_short_fetch_and_add1_full) +# define AO_short_fetch_and_add1_full(addr) \ + AO_short_fetch_and_add_full(addr,1) +# define AO_HAVE_short_fetch_and_add1_full +#endif +#if defined(AO_HAVE_short_fetch_and_add_release) &&\ + !defined(AO_HAVE_short_fetch_and_add1_release) +# define AO_short_fetch_and_add1_release(addr) \ + AO_short_fetch_and_add_release(addr,1) +# define AO_HAVE_short_fetch_and_add1_release +#endif +#if defined(AO_HAVE_short_fetch_and_add_acquire) &&\ + !defined(AO_HAVE_short_fetch_and_add1_acquire) +# define AO_short_fetch_and_add1_acquire(addr) \ + AO_short_fetch_and_add_acquire(addr,1) +# define AO_HAVE_short_fetch_and_add1_acquire +#endif +#if defined(AO_HAVE_short_fetch_and_add_write) &&\ + !defined(AO_HAVE_short_fetch_and_add1_write) +# define AO_short_fetch_and_add1_write(addr) \ + AO_short_fetch_and_add_write(addr,1) +# define AO_HAVE_short_fetch_and_add1_write +#endif +#if defined(AO_HAVE_short_fetch_and_add_read) &&\ + !defined(AO_HAVE_short_fetch_and_add1_read) +# define AO_short_fetch_and_add1_read(addr) \ + AO_short_fetch_and_add_read(addr,1) +# define AO_HAVE_short_fetch_and_add1_read +#endif +#if defined(AO_HAVE_short_fetch_and_add_release_write) &&\ + !defined(AO_HAVE_short_fetch_and_add1_release_write) +# define AO_short_fetch_and_add1_release_write(addr) \ + AO_short_fetch_and_add_release_write(addr,1) +# define AO_HAVE_short_fetch_and_add1_release_write +#endif +#if defined(AO_HAVE_short_fetch_and_add_acquire_read) &&\ + !defined(AO_HAVE_short_fetch_and_add1_acquire_read) +# define AO_short_fetch_and_add1_acquire_read(addr) \ + AO_short_fetch_and_add_acquire_read(addr,1) +# define AO_HAVE_short_fetch_and_add1_acquire_read +#endif +#if defined(AO_HAVE_short_fetch_and_add) &&\ + !defined(AO_HAVE_short_fetch_and_add1) +# define AO_short_fetch_and_add1(addr) \ + AO_short_fetch_and_add(addr,1) +# define AO_HAVE_short_fetch_and_add1 +#endif + +#if defined(AO_HAVE_short_fetch_and_add1_full) +# if !defined(AO_HAVE_short_fetch_and_add1_release) +# define AO_short_fetch_and_add1_release(addr) \ + AO_short_fetch_and_add1_full(addr) +# define AO_HAVE_short_fetch_and_add1_release +# endif +# if !defined(AO_HAVE_short_fetch_and_add1_acquire) +# define AO_short_fetch_and_add1_acquire(addr) \ + AO_short_fetch_and_add1_full(addr) +# define AO_HAVE_short_fetch_and_add1_acquire +# endif +# if !defined(AO_HAVE_short_fetch_and_add1_write) +# define AO_short_fetch_and_add1_write(addr) \ + AO_short_fetch_and_add1_full(addr) +# define AO_HAVE_short_fetch_and_add1_write +# endif +# if !defined(AO_HAVE_short_fetch_and_add1_read) +# define AO_short_fetch_and_add1_read(addr) \ + AO_short_fetch_and_add1_full(addr) +# define AO_HAVE_short_fetch_and_add1_read +# endif +#endif /* AO_HAVE_short_fetch_and_add1_full */ + +#if !defined(AO_HAVE_short_fetch_and_add1) && \ + defined(AO_HAVE_short_fetch_and_add1_release) +# define AO_short_fetch_and_add1(addr) \ + AO_short_fetch_and_add1_release(addr) +# define AO_HAVE_short_fetch_and_add1 +#endif +#if !defined(AO_HAVE_short_fetch_and_add1) && \ + defined(AO_HAVE_short_fetch_and_add1_acquire) +# define AO_short_fetch_and_add1(addr) \ + AO_short_fetch_and_add1_acquire(addr) +# define AO_HAVE_short_fetch_and_add1 +#endif +#if !defined(AO_HAVE_short_fetch_and_add1) && \ + defined(AO_HAVE_short_fetch_and_add1_write) +# define AO_short_fetch_and_add1(addr) \ + AO_short_fetch_and_add1_write(addr) +# define AO_HAVE_short_fetch_and_add1 +#endif +#if !defined(AO_HAVE_short_fetch_and_add1) && \ + defined(AO_HAVE_short_fetch_and_add1_read) +# define AO_short_fetch_and_add1(addr) \ + AO_short_fetch_and_add1_read(addr) +# define AO_HAVE_short_fetch_and_add1 +#endif + +#if defined(AO_HAVE_short_fetch_and_add1_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_short_fetch_and_add1_full) +# define AO_short_fetch_and_add1_full(addr) \ + (AO_nop_full(), AO_short_fetch_and_add1_acquire(addr)) +# define AO_HAVE_short_fetch_and_add1_full +#endif + +#if !defined(AO_HAVE_short_fetch_and_add1_release_write) && \ + defined(AO_HAVE_short_fetch_and_add1_write) +# define AO_short_fetch_and_add1_release_write(addr) \ + AO_short_fetch_and_add1_write(addr) +# define AO_HAVE_short_fetch_and_add1_release_write +#endif +#if !defined(AO_HAVE_short_fetch_and_add1_release_write) && \ + defined(AO_HAVE_short_fetch_and_add1_release) +# define AO_short_fetch_and_add1_release_write(addr) \ + AO_short_fetch_and_add1_release(addr) +# define AO_HAVE_short_fetch_and_add1_release_write +#endif +#if !defined(AO_HAVE_short_fetch_and_add1_acquire_read) && \ + defined(AO_HAVE_short_fetch_and_add1_read) +# define AO_short_fetch_and_add1_acquire_read(addr) \ + AO_short_fetch_and_add1_read(addr) +# define AO_HAVE_short_fetch_and_add1_acquire_read +#endif +#if !defined(AO_HAVE_short_fetch_and_add1_acquire_read) && \ + defined(AO_HAVE_short_fetch_and_add1_acquire) +# define AO_short_fetch_and_add1_acquire_read(addr) \ + AO_short_fetch_and_add1_acquire(addr) +# define AO_HAVE_short_fetch_and_add1_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_short_fetch_and_add1_acquire_read) +# define AO_short_fetch_and_add1_dd_acquire_read(addr) \ + AO_short_fetch_and_add1_acquire_read(addr) +# define AO_HAVE_short_fetch_and_add1_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_short_fetch_and_add1) +# define AO_short_fetch_and_add1_dd_acquire_read(addr) \ + AO_short_fetch_and_add1(addr) +# define AO_HAVE_short_fetch_and_add1_dd_acquire_read +# endif +#endif + +/* short_fetch_and_sub1 */ + +#if defined(AO_HAVE_short_fetch_and_add_full) &&\ + !defined(AO_HAVE_short_fetch_and_sub1_full) +# define AO_short_fetch_and_sub1_full(addr) \ + AO_short_fetch_and_add_full(addr,(unsigned short)(-1)) +# define AO_HAVE_short_fetch_and_sub1_full +#endif +#if defined(AO_HAVE_short_fetch_and_add_release) &&\ + !defined(AO_HAVE_short_fetch_and_sub1_release) +# define AO_short_fetch_and_sub1_release(addr) \ + AO_short_fetch_and_add_release(addr,(unsigned short)(-1)) +# define AO_HAVE_short_fetch_and_sub1_release +#endif +#if defined(AO_HAVE_short_fetch_and_add_acquire) &&\ + !defined(AO_HAVE_short_fetch_and_sub1_acquire) +# define AO_short_fetch_and_sub1_acquire(addr) \ + AO_short_fetch_and_add_acquire(addr,(unsigned short)(-1)) +# define AO_HAVE_short_fetch_and_sub1_acquire +#endif +#if defined(AO_HAVE_short_fetch_and_add_write) &&\ + !defined(AO_HAVE_short_fetch_and_sub1_write) +# define AO_short_fetch_and_sub1_write(addr) \ + AO_short_fetch_and_add_write(addr,(unsigned short)(-1)) +# define AO_HAVE_short_fetch_and_sub1_write +#endif +#if defined(AO_HAVE_short_fetch_and_add_read) &&\ + !defined(AO_HAVE_short_fetch_and_sub1_read) +# define AO_short_fetch_and_sub1_read(addr) \ + AO_short_fetch_and_add_read(addr,(unsigned short)(-1)) +# define AO_HAVE_short_fetch_and_sub1_read +#endif +#if defined(AO_HAVE_short_fetch_and_add_release_write) &&\ + !defined(AO_HAVE_short_fetch_and_sub1_release_write) +# define AO_short_fetch_and_sub1_release_write(addr) \ + AO_short_fetch_and_add_release_write(addr,(unsigned short)(-1)) +# define AO_HAVE_short_fetch_and_sub1_release_write +#endif +#if defined(AO_HAVE_short_fetch_and_add_acquire_read) &&\ + !defined(AO_HAVE_short_fetch_and_sub1_acquire_read) +# define AO_short_fetch_and_sub1_acquire_read(addr) \ + AO_short_fetch_and_add_acquire_read(addr,(unsigned short)(-1)) +# define AO_HAVE_short_fetch_and_sub1_acquire_read +#endif +#if defined(AO_HAVE_short_fetch_and_add) &&\ + !defined(AO_HAVE_short_fetch_and_sub1) +# define AO_short_fetch_and_sub1(addr) \ + AO_short_fetch_and_add(addr,(unsigned short)(-1)) +# define AO_HAVE_short_fetch_and_sub1 +#endif + +#if defined(AO_HAVE_short_fetch_and_sub1_full) +# if !defined(AO_HAVE_short_fetch_and_sub1_release) +# define AO_short_fetch_and_sub1_release(addr) \ + AO_short_fetch_and_sub1_full(addr) +# define AO_HAVE_short_fetch_and_sub1_release +# endif +# if !defined(AO_HAVE_short_fetch_and_sub1_acquire) +# define AO_short_fetch_and_sub1_acquire(addr) \ + AO_short_fetch_and_sub1_full(addr) +# define AO_HAVE_short_fetch_and_sub1_acquire +# endif +# if !defined(AO_HAVE_short_fetch_and_sub1_write) +# define AO_short_fetch_and_sub1_write(addr) \ + AO_short_fetch_and_sub1_full(addr) +# define AO_HAVE_short_fetch_and_sub1_write +# endif +# if !defined(AO_HAVE_short_fetch_and_sub1_read) +# define AO_short_fetch_and_sub1_read(addr) \ + AO_short_fetch_and_sub1_full(addr) +# define AO_HAVE_short_fetch_and_sub1_read +# endif +#endif /* AO_HAVE_short_fetch_and_sub1_full */ + +#if !defined(AO_HAVE_short_fetch_and_sub1) && \ + defined(AO_HAVE_short_fetch_and_sub1_release) +# define AO_short_fetch_and_sub1(addr) \ + AO_short_fetch_and_sub1_release(addr) +# define AO_HAVE_short_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_short_fetch_and_sub1) && \ + defined(AO_HAVE_short_fetch_and_sub1_acquire) +# define AO_short_fetch_and_sub1(addr) \ + AO_short_fetch_and_sub1_acquire(addr) +# define AO_HAVE_short_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_short_fetch_and_sub1) && \ + defined(AO_HAVE_short_fetch_and_sub1_write) +# define AO_short_fetch_and_sub1(addr) \ + AO_short_fetch_and_sub1_write(addr) +# define AO_HAVE_short_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_short_fetch_and_sub1) && \ + defined(AO_HAVE_short_fetch_and_sub1_read) +# define AO_short_fetch_and_sub1(addr) \ + AO_short_fetch_and_sub1_read(addr) +# define AO_HAVE_short_fetch_and_sub1 +#endif + +#if defined(AO_HAVE_short_fetch_and_sub1_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_short_fetch_and_sub1_full) +# define AO_short_fetch_and_sub1_full(addr) \ + (AO_nop_full(), AO_short_fetch_and_sub1_acquire(addr)) +# define AO_HAVE_short_fetch_and_sub1_full +#endif + +#if !defined(AO_HAVE_short_fetch_and_sub1_release_write) && \ + defined(AO_HAVE_short_fetch_and_sub1_write) +# define AO_short_fetch_and_sub1_release_write(addr) \ + AO_short_fetch_and_sub1_write(addr) +# define AO_HAVE_short_fetch_and_sub1_release_write +#endif +#if !defined(AO_HAVE_short_fetch_and_sub1_release_write) && \ + defined(AO_HAVE_short_fetch_and_sub1_release) +# define AO_short_fetch_and_sub1_release_write(addr) \ + AO_short_fetch_and_sub1_release(addr) +# define AO_HAVE_short_fetch_and_sub1_release_write +#endif +#if !defined(AO_HAVE_short_fetch_and_sub1_acquire_read) && \ + defined(AO_HAVE_short_fetch_and_sub1_read) +# define AO_short_fetch_and_sub1_acquire_read(addr) \ + AO_short_fetch_and_sub1_read(addr) +# define AO_HAVE_short_fetch_and_sub1_acquire_read +#endif +#if !defined(AO_HAVE_short_fetch_and_sub1_acquire_read) && \ + defined(AO_HAVE_short_fetch_and_sub1_acquire) +# define AO_short_fetch_and_sub1_acquire_read(addr) \ + AO_short_fetch_and_sub1_acquire(addr) +# define AO_HAVE_short_fetch_and_sub1_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_short_fetch_and_sub1_acquire_read) +# define AO_short_fetch_and_sub1_dd_acquire_read(addr) \ + AO_short_fetch_and_sub1_acquire_read(addr) +# define AO_HAVE_short_fetch_and_sub1_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_short_fetch_and_sub1) +# define AO_short_fetch_and_sub1_dd_acquire_read(addr) \ + AO_short_fetch_and_sub1(addr) +# define AO_HAVE_short_fetch_and_sub1_dd_acquire_read +# endif +#endif + +/* int_load */ +#if defined(AO_HAVE_int_load_acquire) && !defined(AO_HAVE_int_load) +# define AO_int_load(addr) AO_int_load_acquire(addr) +# define AO_HAVE_int_load +#endif + +#if defined(AO_HAVE_int_load_full) && !defined(AO_HAVE_int_load_acquire) +# define AO_int_load_acquire(addr) AO_int_load_full(addr) +# define AO_HAVE_int_load_acquire +#endif + +#if defined(AO_HAVE_int_load_full) && !defined(AO_HAVE_int_load_read) +# define AO_int_load_read(addr) AO_int_load_full(addr) +# define AO_HAVE_int_load_read +#endif + +#if !defined(AO_HAVE_int_load_acquire_read) && defined(AO_HAVE_int_load_acquire) +# define AO_int_load_acquire_read(addr) AO_int_load_acquire(addr) +# define AO_HAVE_int_load_acquire_read +#endif + +#if defined(AO_HAVE_int_load) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_int_load_acquire) + AO_INLINE unsigned int + AO_int_load_acquire(volatile unsigned int *addr) + { + unsigned int result = AO_int_load(addr); + /* Acquire barrier would be useless, since the load could be delayed */ + /* beyond it. */ + AO_nop_full(); + return result; + } +# define AO_HAVE_int_load_acquire +#endif + +#if defined(AO_HAVE_int_load) && defined(AO_HAVE_nop_read) && \ + !defined(AO_HAVE_int_load_read) + AO_INLINE unsigned int + AO_int_load_read(volatile unsigned int *addr) + { + unsigned int result = AO_int_load(addr); + /* Acquire barrier would be useless, since the load could be delayed */ + /* beyond it. */ + AO_nop_read(); + return result; + } +# define AO_HAVE_int_load_read +#endif + +#if defined(AO_HAVE_int_load_acquire) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_int_load_full) +# define AO_int_load_full(addr) (AO_nop_full(), AO_int_load_acquire(addr)) +# define AO_HAVE_int_load_full +#endif + +#if !defined(AO_HAVE_int_load_acquire_read) && defined(AO_HAVE_int_load_read) +# define AO_int_load_acquire_read(addr) AO_int_load_read(addr) +# define AO_HAVE_int_load_acquire_read +#endif + +#if defined(AO_HAVE_int_load_acquire_read) && !defined(AO_HAVE_int_load) +# define AO_int_load(addr) AO_int_load_acquire_read(addr) +# define AO_HAVE_int_load +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_int_load_acquire_read) +# define AO_int_load_dd_acquire_read(addr) \ + AO_int_load_acquire_read(addr) +# define AO_HAVE_int_load_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_int_load) +# define AO_int_load_dd_acquire_read(addr) \ + AO_int_load(addr) +# define AO_HAVE_int_load_dd_acquire_read +# endif +#endif + + +/* int_store */ + +#if defined(AO_HAVE_int_store_release) && !defined(AO_HAVE_int_store) +# define AO_int_store(addr, val) AO_int_store_release(addr,val) +# define AO_HAVE_int_store +#endif + +#if defined(AO_HAVE_int_store_full) && !defined(AO_HAVE_int_store_release) +# define AO_int_store_release(addr,val) AO_int_store_full(addr,val) +# define AO_HAVE_int_store_release +#endif + +#if defined(AO_HAVE_int_store_full) && !defined(AO_HAVE_int_store_write) +# define AO_int_store_write(addr,val) AO_int_store_full(addr,val) +# define AO_HAVE_int_store_write +#endif + +#if defined(AO_HAVE_int_store_release) && \ + !defined(AO_HAVE_int_store_release_write) +# define AO_int_store_release_write(addr, val) \ + AO_int_store_release(addr,val) +# define AO_HAVE_int_store_release_write +#endif + +#if defined(AO_HAVE_int_store_write) && !defined(AO_HAVE_int_store) +# define AO_int_store(addr, val) AO_int_store_write(addr,val) +# define AO_HAVE_int_store +#endif + +#if defined(AO_HAVE_int_store) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_int_store_release) +# define AO_int_store_release(addr,val) \ + (AO_nop_full(), AO_int_store(addr,val)) +# define AO_HAVE_int_store_release +#endif + +#if defined(AO_HAVE_nop_write) && defined(AO_HAVE_int_store) && \ + !defined(AO_HAVE_int_store_write) +# define AO_int_store_write(addr, val) \ + (AO_nop_write(), AO_int_store(addr,val)) +# define AO_HAVE_int_store_write +#endif + +#if defined(AO_HAVE_int_store_write) && \ + !defined(AO_HAVE_int_store_release_write) +# define AO_int_store_release_write(addr, val) AO_int_store_write(addr,val) +# define AO_HAVE_int_store_release_write +#endif + +#if defined(AO_HAVE_int_store_release) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_int_store_full) +# define AO_int_store_full(addr, val) \ + (AO_int_store_release(addr, val), AO_nop_full()) +# define AO_HAVE_int_store_full +#endif + + +/* int_fetch_and_add */ +#if defined(AO_HAVE_int_compare_and_swap_full) && \ + !defined(AO_HAVE_int_fetch_and_add_full) + AO_INLINE AO_t + AO_int_fetch_and_add_full(volatile unsigned int *addr, + unsigned int incr) + { + unsigned int old; + do + { + old = *addr; + } + while (!AO_int_compare_and_swap_full(addr, old, old+incr)); + return old; + } +# define AO_HAVE_int_fetch_and_add_full +#endif + +#if defined(AO_HAVE_int_compare_and_swap_acquire) && \ + !defined(AO_HAVE_int_fetch_and_add_acquire) + AO_INLINE AO_t + AO_int_fetch_and_add_acquire(volatile unsigned int *addr, + unsigned int incr) + { + unsigned int old; + do + { + old = *addr; + } + while (!AO_int_compare_and_swap_acquire(addr, old, old+incr)); + return old; + } +# define AO_HAVE_int_fetch_and_add_acquire +#endif + +#if defined(AO_HAVE_int_compare_and_swap_release) && \ + !defined(AO_HAVE_int_fetch_and_add_release) + AO_INLINE AO_t + AO_int_fetch_and_add_release(volatile unsigned int *addr, + unsigned int incr) + { + unsigned int old; + do + { + old = *addr; + } + while (!AO_int_compare_and_swap_release(addr, old, old+incr)); + return old; + } +# define AO_HAVE_int_fetch_and_add_release +#endif + +#if defined(AO_HAVE_int_fetch_and_add_full) +# if !defined(AO_HAVE_int_fetch_and_add_release) +# define AO_int_fetch_and_add_release(addr, val) \ + AO_int_fetch_and_add_full(addr, val) +# define AO_HAVE_int_fetch_and_add_release +# endif +# if !defined(AO_HAVE_int_fetch_and_add_acquire) +# define AO_int_fetch_and_add_acquire(addr, val) \ + AO_int_fetch_and_add_full(addr, val) +# define AO_HAVE_int_fetch_and_add_acquire +# endif +# if !defined(AO_HAVE_int_fetch_and_add_write) +# define AO_int_fetch_and_add_write(addr, val) \ + AO_int_fetch_and_add_full(addr, val) +# define AO_HAVE_int_fetch_and_add_write +# endif +# if !defined(AO_HAVE_int_fetch_and_add_read) +# define AO_int_fetch_and_add_read(addr, val) \ + AO_int_fetch_and_add_full(addr, val) +# define AO_HAVE_int_fetch_and_add_read +# endif +#endif /* AO_HAVE_int_fetch_and_add_full */ + +#if !defined(AO_HAVE_int_fetch_and_add) && \ + defined(AO_HAVE_int_fetch_and_add_release) +# define AO_int_fetch_and_add(addr, val) \ + AO_int_fetch_and_add_release(addr, val) +# define AO_HAVE_int_fetch_and_add +#endif +#if !defined(AO_HAVE_int_fetch_and_add) && \ + defined(AO_HAVE_int_fetch_and_add_acquire) +# define AO_int_fetch_and_add(addr, val) \ + AO_int_fetch_and_add_acquire(addr, val) +# define AO_HAVE_int_fetch_and_add +#endif +#if !defined(AO_HAVE_int_fetch_and_add) && \ + defined(AO_HAVE_int_fetch_and_add_write) +# define AO_int_fetch_and_add(addr, val) \ + AO_int_fetch_and_add_write(addr, val) +# define AO_HAVE_int_fetch_and_add +#endif +#if !defined(AO_HAVE_int_fetch_and_add) && \ + defined(AO_HAVE_int_fetch_and_add_read) +# define AO_int_fetch_and_add(addr, val) \ + AO_int_fetch_and_add_read(addr, val) +# define AO_HAVE_int_fetch_and_add +#endif + +#if defined(AO_HAVE_int_fetch_and_add_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_int_fetch_and_add_full) +# define AO_int_fetch_and_add_full(addr, val) \ + (AO_nop_full(), AO_int_fetch_and_add_acquire(addr, val)) +#endif + +#if !defined(AO_HAVE_int_fetch_and_add_release_write) && \ + defined(AO_HAVE_int_fetch_and_add_write) +# define AO_int_fetch_and_add_release_write(addr, val) \ + AO_int_fetch_and_add_write(addr, val) +# define AO_HAVE_int_fetch_and_add_release_write +#endif +#if !defined(AO_HAVE_int_fetch_and_add_release_write) && \ + defined(AO_HAVE_int_fetch_and_add_release) +# define AO_int_fetch_and_add_release_write(addr, val) \ + AO_int_fetch_and_add_release(addr, val) +# define AO_HAVE_int_fetch_and_add_release_write +#endif +#if !defined(AO_HAVE_int_fetch_and_add_acquire_read) && \ + defined(AO_HAVE_int_fetch_and_add_read) +# define AO_int_fetch_and_add_acquire_read(addr, val) \ + AO_int_fetch_and_add_read(addr, val) +# define AO_HAVE_int_fetch_and_add_acquire_read +#endif +#if !defined(AO_HAVE_int_fetch_and_add_acquire_read) && \ + defined(AO_HAVE_int_fetch_and_add_acquire) +# define AO_int_fetch_and_add_acquire_read(addr, val) \ + AO_int_fetch_and_add_acquire(addr, val) +# define AO_HAVE_int_fetch_and_add_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_int_fetch_and_add_acquire_read) +# define AO_int_fetch_and_add_dd_acquire_read(addr, val) \ + AO_int_fetch_and_add_acquire_read(addr, val) +# define AO_HAVE_int_fetch_and_add_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_int_fetch_and_add) +# define AO_int_fetch_and_add_dd_acquire_read(addr, val) \ + AO_int_fetch_and_add(addr, val) +# define AO_HAVE_int_fetch_and_add_dd_acquire_read +# endif +#endif + +/* int_fetch_and_add1 */ + +#if defined(AO_HAVE_int_fetch_and_add_full) &&\ + !defined(AO_HAVE_int_fetch_and_add1_full) +# define AO_int_fetch_and_add1_full(addr) \ + AO_int_fetch_and_add_full(addr,1) +# define AO_HAVE_int_fetch_and_add1_full +#endif +#if defined(AO_HAVE_int_fetch_and_add_release) &&\ + !defined(AO_HAVE_int_fetch_and_add1_release) +# define AO_int_fetch_and_add1_release(addr) \ + AO_int_fetch_and_add_release(addr,1) +# define AO_HAVE_int_fetch_and_add1_release +#endif +#if defined(AO_HAVE_int_fetch_and_add_acquire) &&\ + !defined(AO_HAVE_int_fetch_and_add1_acquire) +# define AO_int_fetch_and_add1_acquire(addr) \ + AO_int_fetch_and_add_acquire(addr,1) +# define AO_HAVE_int_fetch_and_add1_acquire +#endif +#if defined(AO_HAVE_int_fetch_and_add_write) &&\ + !defined(AO_HAVE_int_fetch_and_add1_write) +# define AO_int_fetch_and_add1_write(addr) \ + AO_int_fetch_and_add_write(addr,1) +# define AO_HAVE_int_fetch_and_add1_write +#endif +#if defined(AO_HAVE_int_fetch_and_add_read) &&\ + !defined(AO_HAVE_int_fetch_and_add1_read) +# define AO_int_fetch_and_add1_read(addr) \ + AO_int_fetch_and_add_read(addr,1) +# define AO_HAVE_int_fetch_and_add1_read +#endif +#if defined(AO_HAVE_int_fetch_and_add_release_write) &&\ + !defined(AO_HAVE_int_fetch_and_add1_release_write) +# define AO_int_fetch_and_add1_release_write(addr) \ + AO_int_fetch_and_add_release_write(addr,1) +# define AO_HAVE_int_fetch_and_add1_release_write +#endif +#if defined(AO_HAVE_int_fetch_and_add_acquire_read) &&\ + !defined(AO_HAVE_int_fetch_and_add1_acquire_read) +# define AO_int_fetch_and_add1_acquire_read(addr) \ + AO_int_fetch_and_add_acquire_read(addr,1) +# define AO_HAVE_int_fetch_and_add1_acquire_read +#endif +#if defined(AO_HAVE_int_fetch_and_add) &&\ + !defined(AO_HAVE_int_fetch_and_add1) +# define AO_int_fetch_and_add1(addr) \ + AO_int_fetch_and_add(addr,1) +# define AO_HAVE_int_fetch_and_add1 +#endif + +#if defined(AO_HAVE_int_fetch_and_add1_full) +# if !defined(AO_HAVE_int_fetch_and_add1_release) +# define AO_int_fetch_and_add1_release(addr) \ + AO_int_fetch_and_add1_full(addr) +# define AO_HAVE_int_fetch_and_add1_release +# endif +# if !defined(AO_HAVE_int_fetch_and_add1_acquire) +# define AO_int_fetch_and_add1_acquire(addr) \ + AO_int_fetch_and_add1_full(addr) +# define AO_HAVE_int_fetch_and_add1_acquire +# endif +# if !defined(AO_HAVE_int_fetch_and_add1_write) +# define AO_int_fetch_and_add1_write(addr) \ + AO_int_fetch_and_add1_full(addr) +# define AO_HAVE_int_fetch_and_add1_write +# endif +# if !defined(AO_HAVE_int_fetch_and_add1_read) +# define AO_int_fetch_and_add1_read(addr) \ + AO_int_fetch_and_add1_full(addr) +# define AO_HAVE_int_fetch_and_add1_read +# endif +#endif /* AO_HAVE_int_fetch_and_add1_full */ + +#if !defined(AO_HAVE_int_fetch_and_add1) && \ + defined(AO_HAVE_int_fetch_and_add1_release) +# define AO_int_fetch_and_add1(addr) \ + AO_int_fetch_and_add1_release(addr) +# define AO_HAVE_int_fetch_and_add1 +#endif +#if !defined(AO_HAVE_int_fetch_and_add1) && \ + defined(AO_HAVE_int_fetch_and_add1_acquire) +# define AO_int_fetch_and_add1(addr) \ + AO_int_fetch_and_add1_acquire(addr) +# define AO_HAVE_int_fetch_and_add1 +#endif +#if !defined(AO_HAVE_int_fetch_and_add1) && \ + defined(AO_HAVE_int_fetch_and_add1_write) +# define AO_int_fetch_and_add1(addr) \ + AO_int_fetch_and_add1_write(addr) +# define AO_HAVE_int_fetch_and_add1 +#endif +#if !defined(AO_HAVE_int_fetch_and_add1) && \ + defined(AO_HAVE_int_fetch_and_add1_read) +# define AO_int_fetch_and_add1(addr) \ + AO_int_fetch_and_add1_read(addr) +# define AO_HAVE_int_fetch_and_add1 +#endif + +#if defined(AO_HAVE_int_fetch_and_add1_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_int_fetch_and_add1_full) +# define AO_int_fetch_and_add1_full(addr) \ + (AO_nop_full(), AO_int_fetch_and_add1_acquire(addr)) +# define AO_HAVE_int_fetch_and_add1_full +#endif + +#if !defined(AO_HAVE_int_fetch_and_add1_release_write) && \ + defined(AO_HAVE_int_fetch_and_add1_write) +# define AO_int_fetch_and_add1_release_write(addr) \ + AO_int_fetch_and_add1_write(addr) +# define AO_HAVE_int_fetch_and_add1_release_write +#endif +#if !defined(AO_HAVE_int_fetch_and_add1_release_write) && \ + defined(AO_HAVE_int_fetch_and_add1_release) +# define AO_int_fetch_and_add1_release_write(addr) \ + AO_int_fetch_and_add1_release(addr) +# define AO_HAVE_int_fetch_and_add1_release_write +#endif +#if !defined(AO_HAVE_int_fetch_and_add1_acquire_read) && \ + defined(AO_HAVE_int_fetch_and_add1_read) +# define AO_int_fetch_and_add1_acquire_read(addr) \ + AO_int_fetch_and_add1_read(addr) +# define AO_HAVE_int_fetch_and_add1_acquire_read +#endif +#if !defined(AO_HAVE_int_fetch_and_add1_acquire_read) && \ + defined(AO_HAVE_int_fetch_and_add1_acquire) +# define AO_int_fetch_and_add1_acquire_read(addr) \ + AO_int_fetch_and_add1_acquire(addr) +# define AO_HAVE_int_fetch_and_add1_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_int_fetch_and_add1_acquire_read) +# define AO_int_fetch_and_add1_dd_acquire_read(addr) \ + AO_int_fetch_and_add1_acquire_read(addr) +# define AO_HAVE_int_fetch_and_add1_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_int_fetch_and_add1) +# define AO_int_fetch_and_add1_dd_acquire_read(addr) \ + AO_int_fetch_and_add1(addr) +# define AO_HAVE_int_fetch_and_add1_dd_acquire_read +# endif +#endif + +/* int_fetch_and_sub1 */ + +#if defined(AO_HAVE_int_fetch_and_add_full) &&\ + !defined(AO_HAVE_int_fetch_and_sub1_full) +# define AO_int_fetch_and_sub1_full(addr) \ + AO_int_fetch_and_add_full(addr,(unsigned int)(-1)) +# define AO_HAVE_int_fetch_and_sub1_full +#endif +#if defined(AO_HAVE_int_fetch_and_add_release) &&\ + !defined(AO_HAVE_int_fetch_and_sub1_release) +# define AO_int_fetch_and_sub1_release(addr) \ + AO_int_fetch_and_add_release(addr,(unsigned int)(-1)) +# define AO_HAVE_int_fetch_and_sub1_release +#endif +#if defined(AO_HAVE_int_fetch_and_add_acquire) &&\ + !defined(AO_HAVE_int_fetch_and_sub1_acquire) +# define AO_int_fetch_and_sub1_acquire(addr) \ + AO_int_fetch_and_add_acquire(addr,(unsigned int)(-1)) +# define AO_HAVE_int_fetch_and_sub1_acquire +#endif +#if defined(AO_HAVE_int_fetch_and_add_write) &&\ + !defined(AO_HAVE_int_fetch_and_sub1_write) +# define AO_int_fetch_and_sub1_write(addr) \ + AO_int_fetch_and_add_write(addr,(unsigned int)(-1)) +# define AO_HAVE_int_fetch_and_sub1_write +#endif +#if defined(AO_HAVE_int_fetch_and_add_read) &&\ + !defined(AO_HAVE_int_fetch_and_sub1_read) +# define AO_int_fetch_and_sub1_read(addr) \ + AO_int_fetch_and_add_read(addr,(unsigned int)(-1)) +# define AO_HAVE_int_fetch_and_sub1_read +#endif +#if defined(AO_HAVE_int_fetch_and_add_release_write) &&\ + !defined(AO_HAVE_int_fetch_and_sub1_release_write) +# define AO_int_fetch_and_sub1_release_write(addr) \ + AO_int_fetch_and_add_release_write(addr,(unsigned int)(-1)) +# define AO_HAVE_int_fetch_and_sub1_release_write +#endif +#if defined(AO_HAVE_int_fetch_and_add_acquire_read) &&\ + !defined(AO_HAVE_int_fetch_and_sub1_acquire_read) +# define AO_int_fetch_and_sub1_acquire_read(addr) \ + AO_int_fetch_and_add_acquire_read(addr,(unsigned int)(-1)) +# define AO_HAVE_int_fetch_and_sub1_acquire_read +#endif +#if defined(AO_HAVE_int_fetch_and_add) &&\ + !defined(AO_HAVE_int_fetch_and_sub1) +# define AO_int_fetch_and_sub1(addr) \ + AO_int_fetch_and_add(addr,(unsigned int)(-1)) +# define AO_HAVE_int_fetch_and_sub1 +#endif + +#if defined(AO_HAVE_int_fetch_and_sub1_full) +# if !defined(AO_HAVE_int_fetch_and_sub1_release) +# define AO_int_fetch_and_sub1_release(addr) \ + AO_int_fetch_and_sub1_full(addr) +# define AO_HAVE_int_fetch_and_sub1_release +# endif +# if !defined(AO_HAVE_int_fetch_and_sub1_acquire) +# define AO_int_fetch_and_sub1_acquire(addr) \ + AO_int_fetch_and_sub1_full(addr) +# define AO_HAVE_int_fetch_and_sub1_acquire +# endif +# if !defined(AO_HAVE_int_fetch_and_sub1_write) +# define AO_int_fetch_and_sub1_write(addr) \ + AO_int_fetch_and_sub1_full(addr) +# define AO_HAVE_int_fetch_and_sub1_write +# endif +# if !defined(AO_HAVE_int_fetch_and_sub1_read) +# define AO_int_fetch_and_sub1_read(addr) \ + AO_int_fetch_and_sub1_full(addr) +# define AO_HAVE_int_fetch_and_sub1_read +# endif +#endif /* AO_HAVE_int_fetch_and_sub1_full */ + +#if !defined(AO_HAVE_int_fetch_and_sub1) && \ + defined(AO_HAVE_int_fetch_and_sub1_release) +# define AO_int_fetch_and_sub1(addr) \ + AO_int_fetch_and_sub1_release(addr) +# define AO_HAVE_int_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_int_fetch_and_sub1) && \ + defined(AO_HAVE_int_fetch_and_sub1_acquire) +# define AO_int_fetch_and_sub1(addr) \ + AO_int_fetch_and_sub1_acquire(addr) +# define AO_HAVE_int_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_int_fetch_and_sub1) && \ + defined(AO_HAVE_int_fetch_and_sub1_write) +# define AO_int_fetch_and_sub1(addr) \ + AO_int_fetch_and_sub1_write(addr) +# define AO_HAVE_int_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_int_fetch_and_sub1) && \ + defined(AO_HAVE_int_fetch_and_sub1_read) +# define AO_int_fetch_and_sub1(addr) \ + AO_int_fetch_and_sub1_read(addr) +# define AO_HAVE_int_fetch_and_sub1 +#endif + +#if defined(AO_HAVE_int_fetch_and_sub1_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_int_fetch_and_sub1_full) +# define AO_int_fetch_and_sub1_full(addr) \ + (AO_nop_full(), AO_int_fetch_and_sub1_acquire(addr)) +# define AO_HAVE_int_fetch_and_sub1_full +#endif + +#if !defined(AO_HAVE_int_fetch_and_sub1_release_write) && \ + defined(AO_HAVE_int_fetch_and_sub1_write) +# define AO_int_fetch_and_sub1_release_write(addr) \ + AO_int_fetch_and_sub1_write(addr) +# define AO_HAVE_int_fetch_and_sub1_release_write +#endif +#if !defined(AO_HAVE_int_fetch_and_sub1_release_write) && \ + defined(AO_HAVE_int_fetch_and_sub1_release) +# define AO_int_fetch_and_sub1_release_write(addr) \ + AO_int_fetch_and_sub1_release(addr) +# define AO_HAVE_int_fetch_and_sub1_release_write +#endif +#if !defined(AO_HAVE_int_fetch_and_sub1_acquire_read) && \ + defined(AO_HAVE_int_fetch_and_sub1_read) +# define AO_int_fetch_and_sub1_acquire_read(addr) \ + AO_int_fetch_and_sub1_read(addr) +# define AO_HAVE_int_fetch_and_sub1_acquire_read +#endif +#if !defined(AO_HAVE_int_fetch_and_sub1_acquire_read) && \ + defined(AO_HAVE_int_fetch_and_sub1_acquire) +# define AO_int_fetch_and_sub1_acquire_read(addr) \ + AO_int_fetch_and_sub1_acquire(addr) +# define AO_HAVE_int_fetch_and_sub1_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_int_fetch_and_sub1_acquire_read) +# define AO_int_fetch_and_sub1_dd_acquire_read(addr) \ + AO_int_fetch_and_sub1_acquire_read(addr) +# define AO_HAVE_int_fetch_and_sub1_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_int_fetch_and_sub1) +# define AO_int_fetch_and_sub1_dd_acquire_read(addr) \ + AO_int_fetch_and_sub1(addr) +# define AO_HAVE_int_fetch_and_sub1_dd_acquire_read +# endif +#endif + diff --git a/src/atomic_ops/generalize-small.template b/src/atomic_ops/generalize-small.template new file mode 100644 index 0000000..b7e02b0 --- /dev/null +++ b/src/atomic_ops/generalize-small.template @@ -0,0 +1,575 @@ +/* XSIZE_load */ +#if defined(AO_HAVE_XSIZE_load_acquire) && !defined(AO_HAVE_XSIZE_load) +# define AO_XSIZE_load(addr) AO_XSIZE_load_acquire(addr) +# define AO_HAVE_XSIZE_load +#endif + +#if defined(AO_HAVE_XSIZE_load_full) && !defined(AO_HAVE_XSIZE_load_acquire) +# define AO_XSIZE_load_acquire(addr) AO_XSIZE_load_full(addr) +# define AO_HAVE_XSIZE_load_acquire +#endif + +#if defined(AO_HAVE_XSIZE_load_full) && !defined(AO_HAVE_XSIZE_load_read) +# define AO_XSIZE_load_read(addr) AO_XSIZE_load_full(addr) +# define AO_HAVE_XSIZE_load_read +#endif + +#if !defined(AO_HAVE_XSIZE_load_acquire_read) && defined(AO_HAVE_XSIZE_load_acquire) +# define AO_XSIZE_load_acquire_read(addr) AO_XSIZE_load_acquire(addr) +# define AO_HAVE_XSIZE_load_acquire_read +#endif + +#if defined(AO_HAVE_XSIZE_load) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_XSIZE_load_acquire) + AO_INLINE unsigned XCTYPE + AO_XSIZE_load_acquire(volatile unsigned XCTYPE *addr) + { + unsigned XCTYPE result = AO_XSIZE_load(addr); + /* Acquire barrier would be useless, since the load could be delayed */ + /* beyond it. */ + AO_nop_full(); + return result; + } +# define AO_HAVE_XSIZE_load_acquire +#endif + +#if defined(AO_HAVE_XSIZE_load) && defined(AO_HAVE_nop_read) && \ + !defined(AO_HAVE_XSIZE_load_read) + AO_INLINE unsigned XCTYPE + AO_XSIZE_load_read(volatile unsigned XCTYPE *addr) + { + unsigned XCTYPE result = AO_XSIZE_load(addr); + /* Acquire barrier would be useless, since the load could be delayed */ + /* beyond it. */ + AO_nop_read(); + return result; + } +# define AO_HAVE_XSIZE_load_read +#endif + +#if defined(AO_HAVE_XSIZE_load_acquire) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_XSIZE_load_full) +# define AO_XSIZE_load_full(addr) (AO_nop_full(), AO_XSIZE_load_acquire(addr)) +# define AO_HAVE_XSIZE_load_full +#endif + +#if !defined(AO_HAVE_XSIZE_load_acquire_read) && defined(AO_HAVE_XSIZE_load_read) +# define AO_XSIZE_load_acquire_read(addr) AO_XSIZE_load_read(addr) +# define AO_HAVE_XSIZE_load_acquire_read +#endif + +#if defined(AO_HAVE_XSIZE_load_acquire_read) && !defined(AO_HAVE_XSIZE_load) +# define AO_XSIZE_load(addr) AO_XSIZE_load_acquire_read(addr) +# define AO_HAVE_XSIZE_load +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_XSIZE_load_acquire_read) +# define AO_XSIZE_load_dd_acquire_read(addr) \ + AO_XSIZE_load_acquire_read(addr) +# define AO_HAVE_XSIZE_load_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_XSIZE_load) +# define AO_XSIZE_load_dd_acquire_read(addr) \ + AO_XSIZE_load(addr) +# define AO_HAVE_XSIZE_load_dd_acquire_read +# endif +#endif + + +/* XSIZE_store */ + +#if defined(AO_HAVE_XSIZE_store_release) && !defined(AO_HAVE_XSIZE_store) +# define AO_XSIZE_store(addr, val) AO_XSIZE_store_release(addr,val) +# define AO_HAVE_XSIZE_store +#endif + +#if defined(AO_HAVE_XSIZE_store_full) && !defined(AO_HAVE_XSIZE_store_release) +# define AO_XSIZE_store_release(addr,val) AO_XSIZE_store_full(addr,val) +# define AO_HAVE_XSIZE_store_release +#endif + +#if defined(AO_HAVE_XSIZE_store_full) && !defined(AO_HAVE_XSIZE_store_write) +# define AO_XSIZE_store_write(addr,val) AO_XSIZE_store_full(addr,val) +# define AO_HAVE_XSIZE_store_write +#endif + +#if defined(AO_HAVE_XSIZE_store_release) && \ + !defined(AO_HAVE_XSIZE_store_release_write) +# define AO_XSIZE_store_release_write(addr, val) \ + AO_XSIZE_store_release(addr,val) +# define AO_HAVE_XSIZE_store_release_write +#endif + +#if defined(AO_HAVE_XSIZE_store_write) && !defined(AO_HAVE_XSIZE_store) +# define AO_XSIZE_store(addr, val) AO_XSIZE_store_write(addr,val) +# define AO_HAVE_XSIZE_store +#endif + +#if defined(AO_HAVE_XSIZE_store) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_XSIZE_store_release) +# define AO_XSIZE_store_release(addr,val) \ + (AO_nop_full(), AO_XSIZE_store(addr,val)) +# define AO_HAVE_XSIZE_store_release +#endif + +#if defined(AO_HAVE_nop_write) && defined(AO_HAVE_XSIZE_store) && \ + !defined(AO_HAVE_XSIZE_store_write) +# define AO_XSIZE_store_write(addr, val) \ + (AO_nop_write(), AO_XSIZE_store(addr,val)) +# define AO_HAVE_XSIZE_store_write +#endif + +#if defined(AO_HAVE_XSIZE_store_write) && \ + !defined(AO_HAVE_XSIZE_store_release_write) +# define AO_XSIZE_store_release_write(addr, val) AO_XSIZE_store_write(addr,val) +# define AO_HAVE_XSIZE_store_release_write +#endif + +#if defined(AO_HAVE_XSIZE_store_release) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_XSIZE_store_full) +# define AO_XSIZE_store_full(addr, val) \ + (AO_XSIZE_store_release(addr, val), AO_nop_full()) +# define AO_HAVE_XSIZE_store_full +#endif + + +/* XSIZE_fetch_and_add */ +#if defined(AO_HAVE_XSIZE_compare_and_swap_full) && \ + !defined(AO_HAVE_XSIZE_fetch_and_add_full) + AO_INLINE AO_t + AO_XSIZE_fetch_and_add_full(volatile unsigned XCTYPE *addr, + unsigned XCTYPE incr) + { + unsigned XCTYPE old; + do + { + old = *addr; + } + while (!AO_XSIZE_compare_and_swap_full(addr, old, old+incr)); + return old; + } +# define AO_HAVE_XSIZE_fetch_and_add_full +#endif + +#if defined(AO_HAVE_XSIZE_compare_and_swap_acquire) && \ + !defined(AO_HAVE_XSIZE_fetch_and_add_acquire) + AO_INLINE AO_t + AO_XSIZE_fetch_and_add_acquire(volatile unsigned XCTYPE *addr, + unsigned XCTYPE incr) + { + unsigned XCTYPE old; + do + { + old = *addr; + } + while (!AO_XSIZE_compare_and_swap_acquire(addr, old, old+incr)); + return old; + } +# define AO_HAVE_XSIZE_fetch_and_add_acquire +#endif + +#if defined(AO_HAVE_XSIZE_compare_and_swap_release) && \ + !defined(AO_HAVE_XSIZE_fetch_and_add_release) + AO_INLINE AO_t + AO_XSIZE_fetch_and_add_release(volatile unsigned XCTYPE *addr, + unsigned XCTYPE incr) + { + unsigned XCTYPE old; + do + { + old = *addr; + } + while (!AO_XSIZE_compare_and_swap_release(addr, old, old+incr)); + return old; + } +# define AO_HAVE_XSIZE_fetch_and_add_release +#endif + +#if defined(AO_HAVE_XSIZE_fetch_and_add_full) +# if !defined(AO_HAVE_XSIZE_fetch_and_add_release) +# define AO_XSIZE_fetch_and_add_release(addr, val) \ + AO_XSIZE_fetch_and_add_full(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add_release +# endif +# if !defined(AO_HAVE_XSIZE_fetch_and_add_acquire) +# define AO_XSIZE_fetch_and_add_acquire(addr, val) \ + AO_XSIZE_fetch_and_add_full(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add_acquire +# endif +# if !defined(AO_HAVE_XSIZE_fetch_and_add_write) +# define AO_XSIZE_fetch_and_add_write(addr, val) \ + AO_XSIZE_fetch_and_add_full(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add_write +# endif +# if !defined(AO_HAVE_XSIZE_fetch_and_add_read) +# define AO_XSIZE_fetch_and_add_read(addr, val) \ + AO_XSIZE_fetch_and_add_full(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add_read +# endif +#endif /* AO_HAVE_XSIZE_fetch_and_add_full */ + +#if !defined(AO_HAVE_XSIZE_fetch_and_add) && \ + defined(AO_HAVE_XSIZE_fetch_and_add_release) +# define AO_XSIZE_fetch_and_add(addr, val) \ + AO_XSIZE_fetch_and_add_release(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_add) && \ + defined(AO_HAVE_XSIZE_fetch_and_add_acquire) +# define AO_XSIZE_fetch_and_add(addr, val) \ + AO_XSIZE_fetch_and_add_acquire(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_add) && \ + defined(AO_HAVE_XSIZE_fetch_and_add_write) +# define AO_XSIZE_fetch_and_add(addr, val) \ + AO_XSIZE_fetch_and_add_write(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_add) && \ + defined(AO_HAVE_XSIZE_fetch_and_add_read) +# define AO_XSIZE_fetch_and_add(addr, val) \ + AO_XSIZE_fetch_and_add_read(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add +#endif + +#if defined(AO_HAVE_XSIZE_fetch_and_add_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_XSIZE_fetch_and_add_full) +# define AO_XSIZE_fetch_and_add_full(addr, val) \ + (AO_nop_full(), AO_XSIZE_fetch_and_add_acquire(addr, val)) +#endif + +#if !defined(AO_HAVE_XSIZE_fetch_and_add_release_write) && \ + defined(AO_HAVE_XSIZE_fetch_and_add_write) +# define AO_XSIZE_fetch_and_add_release_write(addr, val) \ + AO_XSIZE_fetch_and_add_write(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add_release_write +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_add_release_write) && \ + defined(AO_HAVE_XSIZE_fetch_and_add_release) +# define AO_XSIZE_fetch_and_add_release_write(addr, val) \ + AO_XSIZE_fetch_and_add_release(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add_release_write +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_add_acquire_read) && \ + defined(AO_HAVE_XSIZE_fetch_and_add_read) +# define AO_XSIZE_fetch_and_add_acquire_read(addr, val) \ + AO_XSIZE_fetch_and_add_read(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add_acquire_read +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_add_acquire_read) && \ + defined(AO_HAVE_XSIZE_fetch_and_add_acquire) +# define AO_XSIZE_fetch_and_add_acquire_read(addr, val) \ + AO_XSIZE_fetch_and_add_acquire(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_XSIZE_fetch_and_add_acquire_read) +# define AO_XSIZE_fetch_and_add_dd_acquire_read(addr, val) \ + AO_XSIZE_fetch_and_add_acquire_read(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_XSIZE_fetch_and_add) +# define AO_XSIZE_fetch_and_add_dd_acquire_read(addr, val) \ + AO_XSIZE_fetch_and_add(addr, val) +# define AO_HAVE_XSIZE_fetch_and_add_dd_acquire_read +# endif +#endif + +/* XSIZE_fetch_and_add1 */ + +#if defined(AO_HAVE_XSIZE_fetch_and_add_full) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_add1_full) +# define AO_XSIZE_fetch_and_add1_full(addr) \ + AO_XSIZE_fetch_and_add_full(addr,1) +# define AO_HAVE_XSIZE_fetch_and_add1_full +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add_release) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_add1_release) +# define AO_XSIZE_fetch_and_add1_release(addr) \ + AO_XSIZE_fetch_and_add_release(addr,1) +# define AO_HAVE_XSIZE_fetch_and_add1_release +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add_acquire) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_add1_acquire) +# define AO_XSIZE_fetch_and_add1_acquire(addr) \ + AO_XSIZE_fetch_and_add_acquire(addr,1) +# define AO_HAVE_XSIZE_fetch_and_add1_acquire +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add_write) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_add1_write) +# define AO_XSIZE_fetch_and_add1_write(addr) \ + AO_XSIZE_fetch_and_add_write(addr,1) +# define AO_HAVE_XSIZE_fetch_and_add1_write +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add_read) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_add1_read) +# define AO_XSIZE_fetch_and_add1_read(addr) \ + AO_XSIZE_fetch_and_add_read(addr,1) +# define AO_HAVE_XSIZE_fetch_and_add1_read +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add_release_write) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_add1_release_write) +# define AO_XSIZE_fetch_and_add1_release_write(addr) \ + AO_XSIZE_fetch_and_add_release_write(addr,1) +# define AO_HAVE_XSIZE_fetch_and_add1_release_write +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add_acquire_read) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_add1_acquire_read) +# define AO_XSIZE_fetch_and_add1_acquire_read(addr) \ + AO_XSIZE_fetch_and_add_acquire_read(addr,1) +# define AO_HAVE_XSIZE_fetch_and_add1_acquire_read +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_add1) +# define AO_XSIZE_fetch_and_add1(addr) \ + AO_XSIZE_fetch_and_add(addr,1) +# define AO_HAVE_XSIZE_fetch_and_add1 +#endif + +#if defined(AO_HAVE_XSIZE_fetch_and_add1_full) +# if !defined(AO_HAVE_XSIZE_fetch_and_add1_release) +# define AO_XSIZE_fetch_and_add1_release(addr) \ + AO_XSIZE_fetch_and_add1_full(addr) +# define AO_HAVE_XSIZE_fetch_and_add1_release +# endif +# if !defined(AO_HAVE_XSIZE_fetch_and_add1_acquire) +# define AO_XSIZE_fetch_and_add1_acquire(addr) \ + AO_XSIZE_fetch_and_add1_full(addr) +# define AO_HAVE_XSIZE_fetch_and_add1_acquire +# endif +# if !defined(AO_HAVE_XSIZE_fetch_and_add1_write) +# define AO_XSIZE_fetch_and_add1_write(addr) \ + AO_XSIZE_fetch_and_add1_full(addr) +# define AO_HAVE_XSIZE_fetch_and_add1_write +# endif +# if !defined(AO_HAVE_XSIZE_fetch_and_add1_read) +# define AO_XSIZE_fetch_and_add1_read(addr) \ + AO_XSIZE_fetch_and_add1_full(addr) +# define AO_HAVE_XSIZE_fetch_and_add1_read +# endif +#endif /* AO_HAVE_XSIZE_fetch_and_add1_full */ + +#if !defined(AO_HAVE_XSIZE_fetch_and_add1) && \ + defined(AO_HAVE_XSIZE_fetch_and_add1_release) +# define AO_XSIZE_fetch_and_add1(addr) \ + AO_XSIZE_fetch_and_add1_release(addr) +# define AO_HAVE_XSIZE_fetch_and_add1 +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_add1) && \ + defined(AO_HAVE_XSIZE_fetch_and_add1_acquire) +# define AO_XSIZE_fetch_and_add1(addr) \ + AO_XSIZE_fetch_and_add1_acquire(addr) +# define AO_HAVE_XSIZE_fetch_and_add1 +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_add1) && \ + defined(AO_HAVE_XSIZE_fetch_and_add1_write) +# define AO_XSIZE_fetch_and_add1(addr) \ + AO_XSIZE_fetch_and_add1_write(addr) +# define AO_HAVE_XSIZE_fetch_and_add1 +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_add1) && \ + defined(AO_HAVE_XSIZE_fetch_and_add1_read) +# define AO_XSIZE_fetch_and_add1(addr) \ + AO_XSIZE_fetch_and_add1_read(addr) +# define AO_HAVE_XSIZE_fetch_and_add1 +#endif + +#if defined(AO_HAVE_XSIZE_fetch_and_add1_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_XSIZE_fetch_and_add1_full) +# define AO_XSIZE_fetch_and_add1_full(addr) \ + (AO_nop_full(), AO_XSIZE_fetch_and_add1_acquire(addr)) +# define AO_HAVE_XSIZE_fetch_and_add1_full +#endif + +#if !defined(AO_HAVE_XSIZE_fetch_and_add1_release_write) && \ + defined(AO_HAVE_XSIZE_fetch_and_add1_write) +# define AO_XSIZE_fetch_and_add1_release_write(addr) \ + AO_XSIZE_fetch_and_add1_write(addr) +# define AO_HAVE_XSIZE_fetch_and_add1_release_write +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_add1_release_write) && \ + defined(AO_HAVE_XSIZE_fetch_and_add1_release) +# define AO_XSIZE_fetch_and_add1_release_write(addr) \ + AO_XSIZE_fetch_and_add1_release(addr) +# define AO_HAVE_XSIZE_fetch_and_add1_release_write +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_add1_acquire_read) && \ + defined(AO_HAVE_XSIZE_fetch_and_add1_read) +# define AO_XSIZE_fetch_and_add1_acquire_read(addr) \ + AO_XSIZE_fetch_and_add1_read(addr) +# define AO_HAVE_XSIZE_fetch_and_add1_acquire_read +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_add1_acquire_read) && \ + defined(AO_HAVE_XSIZE_fetch_and_add1_acquire) +# define AO_XSIZE_fetch_and_add1_acquire_read(addr) \ + AO_XSIZE_fetch_and_add1_acquire(addr) +# define AO_HAVE_XSIZE_fetch_and_add1_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_XSIZE_fetch_and_add1_acquire_read) +# define AO_XSIZE_fetch_and_add1_dd_acquire_read(addr) \ + AO_XSIZE_fetch_and_add1_acquire_read(addr) +# define AO_HAVE_XSIZE_fetch_and_add1_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_XSIZE_fetch_and_add1) +# define AO_XSIZE_fetch_and_add1_dd_acquire_read(addr) \ + AO_XSIZE_fetch_and_add1(addr) +# define AO_HAVE_XSIZE_fetch_and_add1_dd_acquire_read +# endif +#endif + +/* XSIZE_fetch_and_sub1 */ + +#if defined(AO_HAVE_XSIZE_fetch_and_add_full) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_sub1_full) +# define AO_XSIZE_fetch_and_sub1_full(addr) \ + AO_XSIZE_fetch_and_add_full(addr,(unsigned XCTYPE)(-1)) +# define AO_HAVE_XSIZE_fetch_and_sub1_full +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add_release) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_sub1_release) +# define AO_XSIZE_fetch_and_sub1_release(addr) \ + AO_XSIZE_fetch_and_add_release(addr,(unsigned XCTYPE)(-1)) +# define AO_HAVE_XSIZE_fetch_and_sub1_release +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add_acquire) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire) +# define AO_XSIZE_fetch_and_sub1_acquire(addr) \ + AO_XSIZE_fetch_and_add_acquire(addr,(unsigned XCTYPE)(-1)) +# define AO_HAVE_XSIZE_fetch_and_sub1_acquire +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add_write) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_sub1_write) +# define AO_XSIZE_fetch_and_sub1_write(addr) \ + AO_XSIZE_fetch_and_add_write(addr,(unsigned XCTYPE)(-1)) +# define AO_HAVE_XSIZE_fetch_and_sub1_write +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add_read) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_sub1_read) +# define AO_XSIZE_fetch_and_sub1_read(addr) \ + AO_XSIZE_fetch_and_add_read(addr,(unsigned XCTYPE)(-1)) +# define AO_HAVE_XSIZE_fetch_and_sub1_read +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add_release_write) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_sub1_release_write) +# define AO_XSIZE_fetch_and_sub1_release_write(addr) \ + AO_XSIZE_fetch_and_add_release_write(addr,(unsigned XCTYPE)(-1)) +# define AO_HAVE_XSIZE_fetch_and_sub1_release_write +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add_acquire_read) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire_read) +# define AO_XSIZE_fetch_and_sub1_acquire_read(addr) \ + AO_XSIZE_fetch_and_add_acquire_read(addr,(unsigned XCTYPE)(-1)) +# define AO_HAVE_XSIZE_fetch_and_sub1_acquire_read +#endif +#if defined(AO_HAVE_XSIZE_fetch_and_add) &&\ + !defined(AO_HAVE_XSIZE_fetch_and_sub1) +# define AO_XSIZE_fetch_and_sub1(addr) \ + AO_XSIZE_fetch_and_add(addr,(unsigned XCTYPE)(-1)) +# define AO_HAVE_XSIZE_fetch_and_sub1 +#endif + +#if defined(AO_HAVE_XSIZE_fetch_and_sub1_full) +# if !defined(AO_HAVE_XSIZE_fetch_and_sub1_release) +# define AO_XSIZE_fetch_and_sub1_release(addr) \ + AO_XSIZE_fetch_and_sub1_full(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1_release +# endif +# if !defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire) +# define AO_XSIZE_fetch_and_sub1_acquire(addr) \ + AO_XSIZE_fetch_and_sub1_full(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1_acquire +# endif +# if !defined(AO_HAVE_XSIZE_fetch_and_sub1_write) +# define AO_XSIZE_fetch_and_sub1_write(addr) \ + AO_XSIZE_fetch_and_sub1_full(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1_write +# endif +# if !defined(AO_HAVE_XSIZE_fetch_and_sub1_read) +# define AO_XSIZE_fetch_and_sub1_read(addr) \ + AO_XSIZE_fetch_and_sub1_full(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1_read +# endif +#endif /* AO_HAVE_XSIZE_fetch_and_sub1_full */ + +#if !defined(AO_HAVE_XSIZE_fetch_and_sub1) && \ + defined(AO_HAVE_XSIZE_fetch_and_sub1_release) +# define AO_XSIZE_fetch_and_sub1(addr) \ + AO_XSIZE_fetch_and_sub1_release(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_sub1) && \ + defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire) +# define AO_XSIZE_fetch_and_sub1(addr) \ + AO_XSIZE_fetch_and_sub1_acquire(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_sub1) && \ + defined(AO_HAVE_XSIZE_fetch_and_sub1_write) +# define AO_XSIZE_fetch_and_sub1(addr) \ + AO_XSIZE_fetch_and_sub1_write(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_sub1) && \ + defined(AO_HAVE_XSIZE_fetch_and_sub1_read) +# define AO_XSIZE_fetch_and_sub1(addr) \ + AO_XSIZE_fetch_and_sub1_read(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1 +#endif + +#if defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_XSIZE_fetch_and_sub1_full) +# define AO_XSIZE_fetch_and_sub1_full(addr) \ + (AO_nop_full(), AO_XSIZE_fetch_and_sub1_acquire(addr)) +# define AO_HAVE_XSIZE_fetch_and_sub1_full +#endif + +#if !defined(AO_HAVE_XSIZE_fetch_and_sub1_release_write) && \ + defined(AO_HAVE_XSIZE_fetch_and_sub1_write) +# define AO_XSIZE_fetch_and_sub1_release_write(addr) \ + AO_XSIZE_fetch_and_sub1_write(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1_release_write +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_sub1_release_write) && \ + defined(AO_HAVE_XSIZE_fetch_and_sub1_release) +# define AO_XSIZE_fetch_and_sub1_release_write(addr) \ + AO_XSIZE_fetch_and_sub1_release(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1_release_write +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire_read) && \ + defined(AO_HAVE_XSIZE_fetch_and_sub1_read) +# define AO_XSIZE_fetch_and_sub1_acquire_read(addr) \ + AO_XSIZE_fetch_and_sub1_read(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1_acquire_read +#endif +#if !defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire_read) && \ + defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire) +# define AO_XSIZE_fetch_and_sub1_acquire_read(addr) \ + AO_XSIZE_fetch_and_sub1_acquire(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire_read) +# define AO_XSIZE_fetch_and_sub1_dd_acquire_read(addr) \ + AO_XSIZE_fetch_and_sub1_acquire_read(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_XSIZE_fetch_and_sub1) +# define AO_XSIZE_fetch_and_sub1_dd_acquire_read(addr) \ + AO_XSIZE_fetch_and_sub1(addr) +# define AO_HAVE_XSIZE_fetch_and_sub1_dd_acquire_read +# endif +#endif + diff --git a/src/atomic_ops/generalize.h b/src/atomic_ops/generalize.h new file mode 100644 index 0000000..0f42b32 --- /dev/null +++ b/src/atomic_ops/generalize.h @@ -0,0 +1,1292 @@ +/* + * Copyright (c) 2003-2004 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. + */ + +/* + * Generalize atomic operations for atomic_ops.h. + * Should not be included directly. + * + * We make no attempt to define useless operations, such as + * AO_nop_acquire + * AO_nop_release + * + * We have also so far neglected to define some others, which + * do not appear likely to be useful, e.g. stores with acquire + * or read barriers. + * + * This file is sometimes included twice by atomic_ops.h. + * All definitions include explicit checks that we are not replacing + * an earlier definition. In general, more desirable expansions + * appear earlier so that we are more likely to use them. + * + * We only make safe generalizations, except that by default we define + * the ...dd_acquire_read operations to be equivalent to those without + * a barrier. On platforms for which this is unsafe, the platform-specific + * file must define AO_NO_DD_ORDERING. + */ + +#ifndef ATOMIC_OPS_H +# error Atomic_ops_generalize.h should not be included directly. +#endif + +#if AO_CHAR_TS_T +# define AO_TS_COMPARE_AND_SWAP_FULL(a,o,n) \ + AO_char_compare_and_swap_full(a,o,n) +# define AO_TS_COMPARE_AND_SWAP_ACQUIRE(a,o,n) \ + AO_char_compare_and_swap_acquire(a,o,n) +# define AO_TS_COMPARE_AND_SWAP_RELEASE(a,o,n) \ + AO_char_compare_and_swap_release(a,o,n) +# define AO_TS_COMPARE_AND_SWAP(a,o,n) \ + AO_char_compare_and_swap(a,o,n) +#endif + +#if AO_AO_TS_T +# define AO_TS_COMPARE_AND_SWAP_FULL(a,o,n) \ + AO_compare_and_swap_full(a,o,n) +# define AO_TS_COMPARE_AND_SWAP_ACQUIRE(a,o,n) \ + AO_compare_and_swap_acquire(a,o,n) +# define AO_TS_COMPARE_AND_SWAP_RELEASE(a,o,n) \ + AO_compare_and_swap_release(a,o,n) +# define AO_TS_COMPARE_AND_SWAP(a,o,n) \ + AO_compare_and_swap(a,o,n) +#endif + +/* Generate test_and_set_full, if necessary and possible. */ +#if !defined(AO_HAVE_test_and_set) && \ + !defined(AO_HAVE_test_and_set_release) && \ + !defined(AO_HAVE_test_and_set_acquire) && \ + !defined(AO_HAVE_test_and_set_read) && \ + !defined(AO_HAVE_test_and_set_full) +# if AO_AO_TS_T && defined(AO_HAVE_compare_and_swap_full) || \ + AO_CHAR_TS_T && defined(AO_HAVE_char_compare_and_swap_full) + AO_INLINE AO_TS_VAL_t + AO_test_and_set_full(volatile AO_TS_t *addr) + { + if (AO_TS_COMPARE_AND_SWAP_FULL(addr, AO_TS_CLEAR, AO_TS_SET)) + return AO_TS_CLEAR; + else + return AO_TS_SET; + } +# define AO_HAVE_test_and_set_full +# endif /* AO_HAVE_compare_and_swap_full */ + +# if AO_AO_TS_T && defined(AO_HAVE_compare_and_swap_acquire) || \ + AO_CHAR_TS_T && defined(AO_HAVE_char_compare_and_swap_acquire) + AO_INLINE AO_TS_VAL_t + AO_test_and_set_acquire(volatile AO_TS_t *addr) + { + if (AO_TS_COMPARE_AND_SWAP_ACQUIRE(addr, AO_TS_CLEAR, AO_TS_SET)) + return AO_TS_CLEAR; + else + return AO_TS_SET; + } +# define AO_HAVE_test_and_set_acquire +# endif /* AO_HAVE_compare_and_swap_acquire */ + +# if AO_AO_TS_T && defined(AO_HAVE_compare_and_swap_release) || \ + AO_CHAR_TS_T && defined(AO_HAVE_char_compare_and_swap_release) + AO_INLINE AO_TS_VAL_t + AO_test_and_set_release(volatile AO_TS_t *addr) + { + if (AO_TS_COMPARE_AND_SWAP_RELEASE(addr, AO_TS_CLEAR, AO_TS_SET)) + return AO_TS_CLEAR; + else + return AO_TS_SET; + } +# define AO_HAVE_test_and_set_release +# endif /* AO_HAVE_compare_and_swap_release */ + +# if AO_AO_TS_T && defined(AO_HAVE_compare_and_swap) || \ + AO_CHAR_TS_T && defined(AO_HAVE_char_compare_and_swap) + AO_INLINE AO_TS_VAL_t + AO_test_and_set(volatile AO_TS_t *addr) + { + if (AO_TS_COMPARE_AND_SWAP(addr, AO_TS_CLEAR, AO_TS_SET)) + return AO_TS_CLEAR; + else + return AO_TS_SET; + } +# define AO_HAVE_test_and_set +# endif /* AO_HAVE_compare_and_swap */ + +# if defined(AO_HAVE_test_and_set) && defined(AO_HAVE_nop_full) \ + && !defined(AO_HAVE_test_and_set_acquire) + AO_INLINE AO_TS_VAL_t + AO_test_and_set_acquire(volatile AO_TS_t *addr) + { + AO_TS_VAL_t result = AO_test_and_set(addr); + AO_nop_full(); + return result; + } +# define AO_HAVE_test_and_set_acquire +# endif + +#endif /* No prior test and set */ + +/* Nop */ +#if !defined(AO_HAVE_nop) + AO_INLINE void AO_nop(void) {} +# define AO_HAVE_nop +#endif + +#if defined(AO_HAVE_test_and_set_full) && !defined(AO_HAVE_nop_full) + AO_INLINE void + AO_nop_full() + { + AO_TS_t dummy = AO_TS_INITIALIZER; + AO_test_and_set_full(&dummy); + } +# define AO_HAVE_nop_full +#endif + +#if defined(AO_HAVE_nop_acquire) +# error AO_nop_acquire is useless: dont define. +#endif +#if defined(AO_HAVE_nop_release) +# error AO_nop_release is useless: dont define. +#endif + +#if defined(AO_HAVE_nop_full) && !defined(AO_HAVE_nop_read) +# define AO_nop_read() AO_nop_full() +# define AO_HAVE_nop_read +#endif + +#if defined(AO_HAVE_nop_full) && !defined(AO_HAVE_nop_write) +# define AO_nop_write() AO_nop_full() +# define AO_HAVE_nop_write +#endif + +/* Load */ +#if defined(AO_HAVE_load_full) && !defined(AO_HAVE_load_acquire) +# define AO_load_acquire(addr) AO_load_full(addr) +# define AO_HAVE_load_acquire +#endif + +#if defined(AO_HAVE_load_acquire) && !defined(AO_HAVE_load) +# define AO_load(addr) AO_load_acquire(addr) +# define AO_HAVE_load +#endif + +#if defined(AO_HAVE_load_full) && !defined(AO_HAVE_load_read) +# define AO_load_read(addr) AO_load_full(addr) +# define AO_HAVE_load_read +#endif + +#if !defined(AO_HAVE_load_acquire_read) && defined(AO_HAVE_load_acquire) +# define AO_load_acquire_read(addr) AO_load_acquire(addr) +# define AO_HAVE_load_acquire_read +#endif + +#if defined(AO_HAVE_load) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_load_acquire) + AO_INLINE AO_t + AO_load_acquire(volatile AO_t *addr) + { + AO_t result = AO_load(addr); + /* Acquire barrier would be useless, since the load could be delayed */ + /* beyond it. */ + AO_nop_full(); + return result; + } +# define AO_HAVE_load_acquire +#endif + +#if defined(AO_HAVE_load) && defined(AO_HAVE_nop_read) && \ + !defined(AO_HAVE_load_read) + AO_INLINE AO_t + AO_load_read(volatile AO_t *addr) + { + AO_t result = AO_load(addr); + /* Acquire barrier would be useless, since the load could be delayed */ + /* beyond it. */ + AO_nop_read(); + return result; + } +# define AO_HAVE_load_read +#endif + +#if defined(AO_HAVE_load_acquire) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_load_full) +# define AO_load_full(addr) (AO_nop_full(), AO_load_acquire(addr)) +# define AO_HAVE_load_full +#endif + +#if !defined(AO_HAVE_load_acquire_read) && defined(AO_HAVE_load_read) +# define AO_load_acquire_read(addr) AO_load_read(addr) +# define AO_HAVE_load_acquire_read +#endif + +#if defined(AO_HAVE_load_acquire_read) && !defined(AO_HAVE_load) +# define AO_load(addr) AO_load_acquire_read(addr) +# define AO_HAVE_load +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_load_acquire_read) +# define AO_load_dd_acquire_read(addr) AO_load_acquire_read(addr) +# define AO_HAVE_load_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_load) +# define AO_load_dd_acquire_read(addr) AO_load(addr) +# define AO_HAVE_load_dd_acquire_read +# endif +#endif + + +/* Store */ + +#if defined(AO_HAVE_store_full) && !defined(AO_HAVE_store_release) +# define AO_store_release(addr,val) AO_store_full(addr,val) +# define AO_HAVE_store_release +#endif + +#if defined(AO_HAVE_store_release) && !defined(AO_HAVE_store) +# define AO_store(addr, val) AO_store_release(addr,val) +# define AO_HAVE_store +#endif + +#if defined(AO_HAVE_store_full) && !defined(AO_HAVE_store_write) +# define AO_store_write(addr,val) AO_store_full(addr,val) +# define AO_HAVE_store_write +#endif + +#if defined(AO_HAVE_store_release) && !defined(AO_HAVE_store_release_write) +# define AO_store_release_write(addr, val) AO_store_release(addr,val) +# define AO_HAVE_store_release_write +#endif + +#if defined(AO_HAVE_store_write) && !defined(AO_HAVE_store) +# define AO_store(addr, val) AO_store_write(addr,val) +# define AO_HAVE_store +#endif + +#if defined(AO_HAVE_store) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_store_release) +# define AO_store_release(addr,val) (AO_nop_full(), AO_store(addr,val)) +# define AO_HAVE_store_release +#endif + +#if defined(AO_HAVE_nop_write) && defined(AO_HAVE_store) && \ + !defined(AO_HAVE_store_write) +# define AO_store_write(addr, val) (AO_nop_write(), AO_store(addr,val)) +# define AO_HAVE_store_write +#endif + +#if defined(AO_HAVE_store_write) && !defined(AO_HAVE_store_release_write) +# define AO_store_release_write(addr, val) AO_store_write(addr,val) +# define AO_HAVE_store_release_write +#endif + +#if defined(AO_HAVE_store_release) && defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_store_full) +# define AO_store_full(addr, val) (AO_store_release(addr, val), AO_nop_full()) +# define AO_HAVE_store_full +#endif + + +/* Fetch_and_add */ +/* We first try to implement fetch_and_add variants in terms */ +/* of the corresponding compare_and_swap variants to minimize */ +/* adding barriers. */ +#if defined(AO_HAVE_compare_and_swap_full) && \ + !defined(AO_HAVE_fetch_and_add_full) + AO_INLINE AO_t + AO_fetch_and_add_full(volatile AO_t *addr, AO_t incr) + { + AO_t old; + do + { + old = *addr; + } + while (!AO_compare_and_swap_full(addr, old, old+incr)); + return old; + } +# define AO_HAVE_fetch_and_add_full +#endif + +#if defined(AO_HAVE_compare_and_swap_acquire) && \ + !defined(AO_HAVE_fetch_and_add_acquire) + AO_INLINE AO_t + AO_fetch_and_add_acquire(volatile AO_t *addr, AO_t incr) + { + AO_t old; + do + { + old = *addr; + } + while (!AO_compare_and_swap_acquire(addr, old, old+incr)); + return old; + } +# define AO_HAVE_fetch_and_add_acquire +#endif + +#if defined(AO_HAVE_compare_and_swap_release) && \ + !defined(AO_HAVE_fetch_and_add_release) + AO_INLINE AO_t + AO_fetch_and_add_release(volatile AO_t *addr, AO_t incr) + { + AO_t old; + do + { + old = *addr; + } + while (!AO_compare_and_swap_release(addr, old, old+incr)); + return old; + } +# define AO_HAVE_fetch_and_add_release +#endif + +#if defined(AO_HAVE_compare_and_swap) && \ + !defined(AO_HAVE_fetch_and_add) + AO_INLINE AO_t + AO_fetch_and_add(volatile AO_t *addr, AO_t incr) + { + AO_t old; + do + { + old = *addr; + } + while (!AO_compare_and_swap(addr, old, old+incr)); + return old; + } +# define AO_HAVE_fetch_and_add +#endif + +#if defined(AO_HAVE_fetch_and_add_full) +# if !defined(AO_HAVE_fetch_and_add_release) +# define AO_fetch_and_add_release(addr, val) \ + AO_fetch_and_add_full(addr, val) +# define AO_HAVE_fetch_and_add_release +# endif +# if !defined(AO_HAVE_fetch_and_add_acquire) +# define AO_fetch_and_add_acquire(addr, val) \ + AO_fetch_and_add_full(addr, val) +# define AO_HAVE_fetch_and_add_acquire +# endif +# if !defined(AO_HAVE_fetch_and_add_write) +# define AO_fetch_and_add_write(addr, val) \ + AO_fetch_and_add_full(addr, val) +# define AO_HAVE_fetch_and_add_write +# endif +# if !defined(AO_HAVE_fetch_and_add_read) +# define AO_fetch_and_add_read(addr, val) \ + AO_fetch_and_add_full(addr, val) +# define AO_HAVE_fetch_and_add_read +# endif +#endif /* AO_HAVE_fetch_and_add_full */ + +#if !defined(AO_HAVE_fetch_and_add) && \ + defined(AO_HAVE_fetch_and_add_release) +# define AO_fetch_and_add(addr, val) \ + AO_fetch_and_add_release(addr, val) +# define AO_HAVE_fetch_and_add +#endif +#if !defined(AO_HAVE_fetch_and_add) && \ + defined(AO_HAVE_fetch_and_add_acquire) +# define AO_fetch_and_add(addr, val) \ + AO_fetch_and_add_acquire(addr, val) +# define AO_HAVE_fetch_and_add +#endif +#if !defined(AO_HAVE_fetch_and_add) && \ + defined(AO_HAVE_fetch_and_add_write) +# define AO_fetch_and_add(addr, val) \ + AO_fetch_and_add_write(addr, val) +# define AO_HAVE_fetch_and_add +#endif +#if !defined(AO_HAVE_fetch_and_add) && \ + defined(AO_HAVE_fetch_and_add_read) +# define AO_fetch_and_add(addr, val) \ + AO_fetch_and_add_read(addr, val) +# define AO_HAVE_fetch_and_add +#endif + +#if defined(AO_HAVE_fetch_and_add_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_fetch_and_add_full) +# define AO_fetch_and_add_full(addr, val) \ + (AO_nop_full(), AO_fetch_and_add_acquire(addr, val)) +# define AO_HAVE_fetch_and_add_full +#endif + +#if !defined(AO_HAVE_fetch_and_add_release_write) && \ + defined(AO_HAVE_fetch_and_add_write) +# define AO_fetch_and_add_release_write(addr, val) \ + AO_fetch_and_add_write(addr, val) +# define AO_HAVE_fetch_and_add_release_write +#endif +#if !defined(AO_HAVE_fetch_and_add_release_write) && \ + defined(AO_HAVE_fetch_and_add_release) +# define AO_fetch_and_add_release_write(addr, val) \ + AO_fetch_and_add_release(addr, val) +# define AO_HAVE_fetch_and_add_release_write +#endif +#if !defined(AO_HAVE_fetch_and_add_acquire_read) && \ + defined(AO_HAVE_fetch_and_add_read) +# define AO_fetch_and_add_acquire_read(addr, val) \ + AO_fetch_and_add_read(addr, val) +# define AO_HAVE_fetch_and_add_acquire_read +#endif +#if !defined(AO_HAVE_fetch_and_add_acquire_read) && \ + defined(AO_HAVE_fetch_and_add_acquire) +# define AO_fetch_and_add_acquire_read(addr, val) \ + AO_fetch_and_add_acquire(addr, val) +# define AO_HAVE_fetch_and_add_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_fetch_and_add_acquire_read) +# define AO_fetch_and_add_dd_acquire_read(addr, val) \ + AO_fetch_and_add_acquire_read(addr, val) +# define AO_HAVE_fetch_and_add_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_fetch_and_add) +# define AO_fetch_and_add_dd_acquire_read(addr, val) \ + AO_fetch_and_add(addr, val) +# define AO_HAVE_fetch_and_add_dd_acquire_read +# endif +#endif + +/* Fetch_and_add1 */ + +#if defined(AO_HAVE_fetch_and_add_full) &&\ + !defined(AO_HAVE_fetch_and_add1_full) +# define AO_fetch_and_add1_full(addr) AO_fetch_and_add_full(addr,1) +# define AO_HAVE_fetch_and_add1_full +#endif +#if defined(AO_HAVE_fetch_and_add_release) &&\ + !defined(AO_HAVE_fetch_and_add1_release) +# define AO_fetch_and_add1_release(addr) AO_fetch_and_add_release(addr,1) +# define AO_HAVE_fetch_and_add1_release +#endif +#if defined(AO_HAVE_fetch_and_add_acquire) &&\ + !defined(AO_HAVE_fetch_and_add1_acquire) +# define AO_fetch_and_add1_acquire(addr) AO_fetch_and_add_acquire(addr,1) +# define AO_HAVE_fetch_and_add1_acquire +#endif +#if defined(AO_HAVE_fetch_and_add_write) &&\ + !defined(AO_HAVE_fetch_and_add1_write) +# define AO_fetch_and_add1_write(addr) AO_fetch_and_add_write(addr,1) +# define AO_HAVE_fetch_and_add1_write +#endif +#if defined(AO_HAVE_fetch_and_add_read) &&\ + !defined(AO_HAVE_fetch_and_add1_read) +# define AO_fetch_and_add1_read(addr) AO_fetch_and_add_read(addr,1) +# define AO_HAVE_fetch_and_add1_read +#endif +#if defined(AO_HAVE_fetch_and_add_release_write) &&\ + !defined(AO_HAVE_fetch_and_add1_release_write) +# define AO_fetch_and_add1_release_write(addr) \ + AO_fetch_and_add_release_write(addr,1) +# define AO_HAVE_fetch_and_add1_release_write +#endif +#if defined(AO_HAVE_fetch_and_add_acquire_read) &&\ + !defined(AO_HAVE_fetch_and_add1_acquire_read) +# define AO_fetch_and_add1_acquire_read(addr) \ + AO_fetch_and_add_acquire_read(addr,1) +# define AO_HAVE_fetch_and_add1_acquire_read +#endif +#if defined(AO_HAVE_fetch_and_add) &&\ + !defined(AO_HAVE_fetch_and_add1) +# define AO_fetch_and_add1(addr) \ + AO_fetch_and_add(addr,1) +# define AO_HAVE_fetch_and_add1 +#endif + +#if defined(AO_HAVE_fetch_and_add1_full) +# if !defined(AO_HAVE_fetch_and_add1_release) +# define AO_fetch_and_add1_release(addr) \ + AO_fetch_and_add1_full(addr) +# define AO_HAVE_fetch_and_add1_release +# endif +# if !defined(AO_HAVE_fetch_and_add1_acquire) +# define AO_fetch_and_add1_acquire(addr) \ + AO_fetch_and_add1_full(addr) +# define AO_HAVE_fetch_and_add1_acquire +# endif +# if !defined(AO_HAVE_fetch_and_add1_write) +# define AO_fetch_and_add1_write(addr) \ + AO_fetch_and_add1_full(addr) +# define AO_HAVE_fetch_and_add1_write +# endif +# if !defined(AO_HAVE_fetch_and_add1_read) +# define AO_fetch_and_add1_read(addr) \ + AO_fetch_and_add1_full(addr) +# define AO_HAVE_fetch_and_add1_read +# endif +#endif /* AO_HAVE_fetch_and_add1_full */ + +#if !defined(AO_HAVE_fetch_and_add1) && \ + defined(AO_HAVE_fetch_and_add1_release) +# define AO_fetch_and_add1(addr) \ + AO_fetch_and_add1_release(addr) +# define AO_HAVE_fetch_and_add1 +#endif +#if !defined(AO_HAVE_fetch_and_add1) && \ + defined(AO_HAVE_fetch_and_add1_acquire) +# define AO_fetch_and_add1(addr) \ + AO_fetch_and_add1_acquire(addr) +# define AO_HAVE_fetch_and_add1 +#endif +#if !defined(AO_HAVE_fetch_and_add1) && \ + defined(AO_HAVE_fetch_and_add1_write) +# define AO_fetch_and_add1(addr) \ + AO_fetch_and_add1_write(addr) +# define AO_HAVE_fetch_and_add1 +#endif +#if !defined(AO_HAVE_fetch_and_add1) && \ + defined(AO_HAVE_fetch_and_add1_read) +# define AO_fetch_and_add1(addr) \ + AO_fetch_and_add1_read(addr) +# define AO_HAVE_fetch_and_add1 +#endif + +#if defined(AO_HAVE_fetch_and_add1_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_fetch_and_add1_full) +# define AO_fetch_and_add1_full(addr) \ + (AO_nop_full(), AO_fetch_and_add1_acquire(addr)) +# define AO_HAVE_fetch_and_add1_full +#endif + +#if !defined(AO_HAVE_fetch_and_add1_release_write) && \ + defined(AO_HAVE_fetch_and_add1_write) +# define AO_fetch_and_add1_release_write(addr) \ + AO_fetch_and_add1_write(addr) +# define AO_HAVE_fetch_and_add1_release_write +#endif +#if !defined(AO_HAVE_fetch_and_add1_release_write) && \ + defined(AO_HAVE_fetch_and_add1_release) +# define AO_fetch_and_add1_release_write(addr) \ + AO_fetch_and_add1_release(addr) +# define AO_HAVE_fetch_and_add1_release_write +#endif +#if !defined(AO_HAVE_fetch_and_add1_acquire_read) && \ + defined(AO_HAVE_fetch_and_add1_read) +# define AO_fetch_and_add1_acquire_read(addr) \ + AO_fetch_and_add1_read(addr) +# define AO_HAVE_fetch_and_add1_acquire_read +#endif +#if !defined(AO_HAVE_fetch_and_add1_acquire_read) && \ + defined(AO_HAVE_fetch_and_add1_acquire) +# define AO_fetch_and_add1_acquire_read(addr) \ + AO_fetch_and_add1_acquire(addr) +# define AO_HAVE_fetch_and_add1_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_fetch_and_add1_acquire_read) +# define AO_fetch_and_add1_dd_acquire_read(addr) \ + AO_fetch_and_add1_acquire_read(addr) +# define AO_HAVE_fetch_and_add1_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_fetch_and_add1) +# define AO_fetch_and_add1_dd_acquire_read(addr) AO_fetch_and_add1(addr) +# define AO_HAVE_fetch_and_add1_dd_acquire_read +# endif +#endif + +/* Fetch_and_sub1 */ + +#if defined(AO_HAVE_fetch_and_add_full) &&\ + !defined(AO_HAVE_fetch_and_sub1_full) +# define AO_fetch_and_sub1_full(addr) AO_fetch_and_add_full(addr,(AO_t)(-1)) +# define AO_HAVE_fetch_and_sub1_full +#endif +#if defined(AO_HAVE_fetch_and_add_release) &&\ + !defined(AO_HAVE_fetch_and_sub1_release) +# define AO_fetch_and_sub1_release(addr) \ + AO_fetch_and_add_release(addr,(AO_t)(-1)) +# define AO_HAVE_fetch_and_sub1_release +#endif +#if defined(AO_HAVE_fetch_and_add_acquire) &&\ + !defined(AO_HAVE_fetch_and_sub1_acquire) +# define AO_fetch_and_sub1_acquire(addr) \ + AO_fetch_and_add_acquire(addr,(AO_t)(-1)) +# define AO_HAVE_fetch_and_sub1_acquire +#endif +#if defined(AO_HAVE_fetch_and_add_write) &&\ + !defined(AO_HAVE_fetch_and_sub1_write) +# define AO_fetch_and_sub1_write(addr) \ + AO_fetch_and_add_write(addr,(AO_t)(-1)) +# define AO_HAVE_fetch_and_sub1_write +#endif +#if defined(AO_HAVE_fetch_and_add_read) &&\ + !defined(AO_HAVE_fetch_and_sub1_read) +# define AO_fetch_and_sub1_read(addr) \ + AO_fetch_and_add_read(addr,(AO_t)(-1)) +# define AO_HAVE_fetch_and_sub1_read +#endif +#if defined(AO_HAVE_fetch_and_add_release_write) &&\ + !defined(AO_HAVE_fetch_and_sub1_release_write) +# define AO_fetch_and_sub1_release_write(addr) \ + AO_fetch_and_add_release_write(addr,(AO_t)(-1)) +# define AO_HAVE_fetch_and_sub1_release_write +#endif +#if defined(AO_HAVE_fetch_and_add_acquire_read) &&\ + !defined(AO_HAVE_fetch_and_sub1_acquire_read) +# define AO_fetch_and_sub1_acquire_read(addr) \ + AO_fetch_and_add_acquire_read(addr,(AO_t)(-1)) +# define AO_HAVE_fetch_and_sub1_acquire_read +#endif +#if defined(AO_HAVE_fetch_and_add) &&\ + !defined(AO_HAVE_fetch_and_sub1) +# define AO_fetch_and_sub1(addr) \ + AO_fetch_and_add(addr,(AO_t)(-1)) +# define AO_HAVE_fetch_and_sub1 +#endif + +#if defined(AO_HAVE_fetch_and_sub1_full) +# if !defined(AO_HAVE_fetch_and_sub1_release) +# define AO_fetch_and_sub1_release(addr) \ + AO_fetch_and_sub1_full(addr) +# define AO_HAVE_fetch_and_sub1_release +# endif +# if !defined(AO_HAVE_fetch_and_sub1_acquire) +# define AO_fetch_and_sub1_acquire(addr) \ + AO_fetch_and_sub1_full(addr) +# define AO_HAVE_fetch_and_sub1_acquire +# endif +# if !defined(AO_HAVE_fetch_and_sub1_write) +# define AO_fetch_and_sub1_write(addr) \ + AO_fetch_and_sub1_full(addr) +# define AO_HAVE_fetch_and_sub1_write +# endif +# if !defined(AO_HAVE_fetch_and_sub1_read) +# define AO_fetch_and_sub1_read(addr) \ + AO_fetch_and_sub1_full(addr) +# define AO_HAVE_fetch_and_sub1_read +# endif +#endif /* AO_HAVE_fetch_and_sub1_full */ + +#if !defined(AO_HAVE_fetch_and_sub1) && \ + defined(AO_HAVE_fetch_and_sub1_release) +# define AO_fetch_and_sub1(addr) \ + AO_fetch_and_sub1_release(addr) +# define AO_HAVE_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_fetch_and_sub1) && \ + defined(AO_HAVE_fetch_and_sub1_acquire) +# define AO_fetch_and_sub1(addr) \ + AO_fetch_and_sub1_acquire(addr) +# define AO_HAVE_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_fetch_and_sub1) && \ + defined(AO_HAVE_fetch_and_sub1_write) +# define AO_fetch_and_sub1(addr) \ + AO_fetch_and_sub1_write(addr) +# define AO_HAVE_fetch_and_sub1 +#endif +#if !defined(AO_HAVE_fetch_and_sub1) && \ + defined(AO_HAVE_fetch_and_sub1_read) +# define AO_fetch_and_sub1(addr) \ + AO_fetch_and_sub1_read(addr) +# define AO_HAVE_fetch_and_sub1 +#endif + +#if defined(AO_HAVE_fetch_and_sub1_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_fetch_and_sub1_full) +# define AO_fetch_and_sub1_full(addr) \ + (AO_nop_full(), AO_fetch_and_sub1_acquire(addr)) +# define AO_HAVE_fetch_and_sub1_full +#endif + +#if !defined(AO_HAVE_fetch_and_sub1_release_write) && \ + defined(AO_HAVE_fetch_and_sub1_write) +# define AO_fetch_and_sub1_release_write(addr) \ + AO_fetch_and_sub1_write(addr) +# define AO_HAVE_fetch_and_sub1_release_write +#endif +#if !defined(AO_HAVE_fetch_and_sub1_release_write) && \ + defined(AO_HAVE_fetch_and_sub1_release) +# define AO_fetch_and_sub1_release_write(addr) \ + AO_fetch_and_sub1_release(addr) +# define AO_HAVE_fetch_and_sub1_release_write +#endif +#if !defined(AO_HAVE_fetch_and_sub1_acquire_read) && \ + defined(AO_HAVE_fetch_and_sub1_read) +# define AO_fetch_and_sub1_acquire_read(addr) \ + AO_fetch_and_sub1_read(addr) +# define AO_HAVE_fetch_and_sub1_acquire_read +#endif +#if !defined(AO_HAVE_fetch_and_sub1_acquire_read) && \ + defined(AO_HAVE_fetch_and_sub1_acquire) +# define AO_fetch_and_sub1_acquire_read(addr) \ + AO_fetch_and_sub1_acquire(addr) +# define AO_HAVE_fetch_and_sub1_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_fetch_and_sub1_acquire_read) +# define AO_fetch_and_sub1_dd_acquire_read(addr) \ + AO_fetch_and_sub1_acquire_read(addr) +# define AO_HAVE_fetch_and_sub1_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_fetch_and_sub1) +# define AO_fetch_and_sub1_dd_acquire_read(addr) AO_fetch_and_sub1(addr) +# define AO_HAVE_fetch_and_sub1_dd_acquire_read +# endif +#endif + +/* Atomic or */ +#if defined(AO_HAVE_compare_and_swap_full) && \ + !defined(AO_HAVE_or_full) + AO_INLINE void + AO_or_full(volatile AO_t *addr, AO_t incr) + { + AO_t old; + do + { + old = *addr; + } + while (!AO_compare_and_swap_full(addr, old, (old | incr))); + } +# define AO_HAVE_or_full +#endif + +#if defined(AO_HAVE_or_full) +# if !defined(AO_HAVE_or_release) +# define AO_or_release(addr, val) \ + AO_or_full(addr, val) +# define AO_HAVE_or_release +# endif +# if !defined(AO_HAVE_or_acquire) +# define AO_or_acquire(addr, val) \ + AO_or_full(addr, val) +# define AO_HAVE_or_acquire +# endif +# if !defined(AO_HAVE_or_write) +# define AO_or_write(addr, val) \ + AO_or_full(addr, val) +# define AO_HAVE_or_write +# endif +# if !defined(AO_HAVE_or_read) +# define AO_or_read(addr, val) \ + AO_or_full(addr, val) +# define AO_HAVE_or_read +# endif +#endif /* AO_HAVE_or_full */ + +#if !defined(AO_HAVE_or) && \ + defined(AO_HAVE_or_release) +# define AO_or(addr, val) \ + AO_or_release(addr, val) +# define AO_HAVE_or +#endif +#if !defined(AO_HAVE_or) && \ + defined(AO_HAVE_or_acquire) +# define AO_or(addr, val) \ + AO_or_acquire(addr, val) +# define AO_HAVE_or +#endif +#if !defined(AO_HAVE_or) && \ + defined(AO_HAVE_or_write) +# define AO_or(addr, val) \ + AO_or_write(addr, val) +# define AO_HAVE_or +#endif +#if !defined(AO_HAVE_or) && \ + defined(AO_HAVE_or_read) +# define AO_or(addr, val) \ + AO_or_read(addr, val) +# define AO_HAVE_or +#endif + +#if defined(AO_HAVE_or_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_or_full) +# define AO_or_full(addr, val) \ + (AO_nop_full(), AO_or_acquire(addr, val)) +#endif + +#if !defined(AO_HAVE_or_release_write) && \ + defined(AO_HAVE_or_write) +# define AO_or_release_write(addr, val) \ + AO_or_write(addr, val) +# define AO_HAVE_or_release_write +#endif +#if !defined(AO_HAVE_or_release_write) && \ + defined(AO_HAVE_or_release) +# define AO_or_release_write(addr, val) \ + AO_or_release(addr, val) +# define AO_HAVE_or_release_write +#endif +#if !defined(AO_HAVE_or_acquire_read) && \ + defined(AO_HAVE_or_read) +# define AO_or_acquire_read(addr, val) \ + AO_or_read(addr, val) +# define AO_HAVE_or_acquire_read +#endif +#if !defined(AO_HAVE_or_acquire_read) && \ + defined(AO_HAVE_or_acquire) +# define AO_or_acquire_read(addr, val) \ + AO_or_acquire(addr, val) +# define AO_HAVE_or_acquire_read +#endif + +/* dd_aquire_read is meaningless. */ + +/* Test_and_set */ + +#if defined(AO_HAVE_test_and_set_full) +# if !defined(AO_HAVE_test_and_set_release) +# define AO_test_and_set_release(addr) \ + AO_test_and_set_full(addr) +# define AO_HAVE_test_and_set_release +# endif +# if !defined(AO_HAVE_test_and_set_acquire) +# define AO_test_and_set_acquire(addr) \ + AO_test_and_set_full(addr) +# define AO_HAVE_test_and_set_acquire +# endif +# if !defined(AO_HAVE_test_and_set_write) +# define AO_test_and_set_write(addr) \ + AO_test_and_set_full(addr) +# define AO_HAVE_test_and_set_write +# endif +# if !defined(AO_HAVE_test_and_set_read) +# define AO_test_and_set_read(addr) \ + AO_test_and_set_full(addr) +# define AO_HAVE_test_and_set_read +# endif +#endif /* AO_HAVE_test_and_set_full */ + +#if !defined(AO_HAVE_test_and_set) && \ + defined(AO_HAVE_test_and_set_release) +# define AO_test_and_set(addr) \ + AO_test_and_set_release(addr) +# define AO_HAVE_test_and_set +#endif +#if !defined(AO_HAVE_test_and_set) && \ + defined(AO_HAVE_test_and_set_acquire) +# define AO_test_and_set(addr) \ + AO_test_and_set_acquire(addr) +# define AO_HAVE_test_and_set +#endif +#if !defined(AO_HAVE_test_and_set) && \ + defined(AO_HAVE_test_and_set_write) +# define AO_test_and_set(addr) \ + AO_test_and_set_write(addr) +# define AO_HAVE_test_and_set +#endif +#if !defined(AO_HAVE_test_and_set) && \ + defined(AO_HAVE_test_and_set_read) +# define AO_test_and_set(addr) \ + AO_test_and_set_read(addr) +# define AO_HAVE_test_and_set +#endif + +#if defined(AO_HAVE_test_and_set_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_test_and_set_full) +# define AO_test_and_set_full(addr) \ + (AO_nop_full(), AO_test_and_set_acquire(addr)) +# define AO_HAVE_test_and_set_full +#endif + +#if !defined(AO_HAVE_test_and_set_release_write) && \ + defined(AO_HAVE_test_and_set_write) +# define AO_test_and_set_release_write(addr) \ + AO_test_and_set_write(addr) +# define AO_HAVE_test_and_set_release_write +#endif +#if !defined(AO_HAVE_test_and_set_release_write) && \ + defined(AO_HAVE_test_and_set_release) +# define AO_test_and_set_release_write(addr) \ + AO_test_and_set_release(addr) +# define AO_HAVE_test_and_set_release_write +#endif +#if !defined(AO_HAVE_test_and_set_acquire_read) && \ + defined(AO_HAVE_test_and_set_read) +# define AO_test_and_set_acquire_read(addr) \ + AO_test_and_set_read(addr) +# define AO_HAVE_test_and_set_acquire_read +#endif +#if !defined(AO_HAVE_test_and_set_acquire_read) && \ + defined(AO_HAVE_test_and_set_acquire) +# define AO_test_and_set_acquire_read(addr) \ + AO_test_and_set_acquire(addr) +# define AO_HAVE_test_and_set_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_test_and_set_acquire_read) +# define AO_test_and_set_dd_acquire_read(addr) \ + AO_test_and_set_acquire_read(addr) +# define AO_HAVE_test_and_set_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_test_and_set) +# define AO_test_and_set_dd_acquire_read(addr) AO_test_and_set(addr) +# define AO_HAVE_test_and_set_dd_acquire_read +# endif +#endif + +/* Compare_and_swap */ +#if defined(AO_HAVE_compare_and_swap) && defined(AO_HAVE_nop_full)\ + && !defined(AO_HAVE_compare_and_swap_acquire) + AO_INLINE int + AO_compare_and_swap_acquire(volatile AO_t *addr, AO_t old, AO_t new_val) + { + int result = AO_compare_and_swap(addr, old, new_val); + AO_nop_full(); + return result; + } +# define AO_HAVE_compare_and_swap_acquire +#endif +#if defined(AO_HAVE_compare_and_swap) && defined(AO_HAVE_nop_full)\ + && !defined(AO_HAVE_compare_and_swap_release) +# define AO_compare_and_swap_release(addr, old, new_val) \ + (AO_nop_full(), AO_compare_and_swap(addr, old, new_val)) +# define AO_HAVE_compare_and_swap_release +#endif +#if defined(AO_HAVE_compare_and_swap_full) +# if !defined(AO_HAVE_compare_and_swap_release) +# define AO_compare_and_swap_release(addr, old, new_val) \ + AO_compare_and_swap_full(addr, old, new_val) +# define AO_HAVE_compare_and_swap_release +# endif +# if !defined(AO_HAVE_compare_and_swap_acquire) +# define AO_compare_and_swap_acquire(addr, old, new_val) \ + AO_compare_and_swap_full(addr, old, new_val) +# define AO_HAVE_compare_and_swap_acquire +# endif +# if !defined(AO_HAVE_compare_and_swap_write) +# define AO_compare_and_swap_write(addr, old, new_val) \ + AO_compare_and_swap_full(addr, old, new_val) +# define AO_HAVE_compare_and_swap_write +# endif +# if !defined(AO_HAVE_compare_and_swap_read) +# define AO_compare_and_swap_read(addr, old, new_val) \ + AO_compare_and_swap_full(addr, old, new_val) +# define AO_HAVE_compare_and_swap_read +# endif +#endif /* AO_HAVE_compare_and_swap_full */ + +#if !defined(AO_HAVE_compare_and_swap) && \ + defined(AO_HAVE_compare_and_swap_release) +# define AO_compare_and_swap(addr, old, new_val) \ + AO_compare_and_swap_release(addr, old, new_val) +# define AO_HAVE_compare_and_swap +#endif +#if !defined(AO_HAVE_compare_and_swap) && \ + defined(AO_HAVE_compare_and_swap_acquire) +# define AO_compare_and_swap(addr, old, new_val) \ + AO_compare_and_swap_acquire(addr, old, new_val) +# define AO_HAVE_compare_and_swap +#endif +#if !defined(AO_HAVE_compare_and_swap) && \ + defined(AO_HAVE_compare_and_swap_write) +# define AO_compare_and_swap(addr, old, new_val) \ + AO_compare_and_swap_write(addr, old, new_val) +# define AO_HAVE_compare_and_swap +#endif +#if !defined(AO_HAVE_compare_and_swap) && \ + defined(AO_HAVE_compare_and_swap_read) +# define AO_compare_and_swap(addr, old, new_val) \ + AO_compare_and_swap_read(addr, old, new_val) +# define AO_HAVE_compare_and_swap +#endif + +#if defined(AO_HAVE_compare_and_swap_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_compare_and_swap_full) +# define AO_compare_and_swap_full(addr, old, new_val) \ + (AO_nop_full(), AO_compare_and_swap_acquire(addr, old, new_val)) +# define AO_HAVE_compare_and_swap_full +#endif + +#if !defined(AO_HAVE_compare_and_swap_release_write) && \ + defined(AO_HAVE_compare_and_swap_write) +# define AO_compare_and_swap_release_write(addr, old, new_val) \ + AO_compare_and_swap_write(addr, old, new_val) +# define AO_HAVE_compare_and_swap_release_write +#endif +#if !defined(AO_HAVE_compare_and_swap_release_write) && \ + defined(AO_HAVE_compare_and_swap_release) +# define AO_compare_and_swap_release_write(addr, old, new_val) \ + AO_compare_and_swap_release(addr, old, new_val) +# define AO_HAVE_compare_and_swap_release_write +#endif +#if !defined(AO_HAVE_compare_and_swap_acquire_read) && \ + defined(AO_HAVE_compare_and_swap_read) +# define AO_compare_and_swap_acquire_read(addr, old, new_val) \ + AO_compare_and_swap_read(addr, old, new_val) +# define AO_HAVE_compare_and_swap_acquire_read +#endif +#if !defined(AO_HAVE_compare_and_swap_acquire_read) && \ + defined(AO_HAVE_compare_and_swap_acquire) +# define AO_compare_and_swap_acquire_read(addr, old, new_val) \ + AO_compare_and_swap_acquire(addr, old, new_val) +# define AO_HAVE_compare_and_swap_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_compare_and_swap_acquire_read) +# define AO_compare_and_swap_dd_acquire_read(addr, old, new_val) \ + AO_compare_and_swap_acquire_read(addr, old, new_val) +# define AO_HAVE_compare_and_swap_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_compare_and_swap) +# define AO_compare_and_swap_dd_acquire_read(addr, old, new_val) \ + AO_compare_and_swap(addr, old, new_val) +# define AO_HAVE_compare_and_swap_dd_acquire_read +# endif +#endif + +#include "generalize-small.h" + +/* Compare_double_and_swap_double */ +#if defined(AO_HAVE_compare_double_and_swap_double) && defined(AO_HAVE_nop_full)\ + && !defined(AO_HAVE_compare_double_and_swap_double_acquire) + AO_INLINE int + AO_compare_double_and_swap_double_acquire(volatile AO_double_t *addr, + AO_t o1, AO_t o2, + AO_t n1, AO_t n2) + { + int result = AO_compare_double_and_swap_double(addr, o1, o2, n1, n2); + AO_nop_full(); + return result; + } +# define AO_HAVE_compare_double_and_swap_double_acquire +#endif +#if defined(AO_HAVE_compare_double_and_swap_double) \ + && defined(AO_HAVE_nop_full)\ + && !defined(AO_HAVE_compare_double_and_swap_double_release) +# define AO_compare_double_and_swap_double_release(addr, o1, o2, n1, n2) \ + (AO_nop_full(), AO_compare_double_and_swap_double(addr, o1, o2, n1, n2)) +# define AO_HAVE_compare_double_and_swap_double_release +#endif +#if defined(AO_HAVE_compare_double_and_swap_double_full) +# if !defined(AO_HAVE_compare_double_and_swap_double_release) +# define AO_compare_double_and_swap_double_release(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_full(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double_release +# endif +# if !defined(AO_HAVE_compare_double_and_swap_double_acquire) +# define AO_compare_double_and_swap_double_acquire(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_full(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double_acquire +# endif +# if !defined(AO_HAVE_compare_double_and_swap_double_write) +# define AO_compare_double_and_swap_double_write(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_full(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double_write +# endif +# if !defined(AO_HAVE_compare_double_and_swap_double_read) +# define AO_compare_double_and_swap_double_read(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_full(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double_read +# endif +#endif /* AO_HAVE_compare_double_and_swap_double_full */ + +#if !defined(AO_HAVE_compare_double_and_swap_double) && \ + defined(AO_HAVE_compare_double_and_swap_double_release) +# define AO_compare_double_and_swap_double(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_release(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double +#endif +#if !defined(AO_HAVE_compare_double_and_swap_double) && \ + defined(AO_HAVE_compare_double_and_swap_double_acquire) +# define AO_compare_double_and_swap_double(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_acquire(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double +#endif +#if !defined(AO_HAVE_compare_double_and_swap_double) && \ + defined(AO_HAVE_compare_double_and_swap_double_write) +# define AO_compare_double_and_swap_double(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_write(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double +#endif +#if !defined(AO_HAVE_compare_double_and_swap_double) && \ + defined(AO_HAVE_compare_double_and_swap_double_read) +# define AO_compare_double_and_swap_double(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_read(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double +#endif + +#if defined(AO_HAVE_compare_double_and_swap_double_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_compare_double_and_swap_double_full) +# define AO_compare_double_and_swap_double_full(addr, o1, o2, n1, n2) \ + (AO_nop_full(), AO_compare_double_and_swap_double_acquire(addr, o1, o2, n1, n2)) +# define AO_HAVE_compare_double_and_swap_double_full +#endif + +#if !defined(AO_HAVE_compare_double_and_swap_double_release_write) && \ + defined(AO_HAVE_compare_double_and_swap_double_write) +# define AO_compare_double_and_swap_double_release_write(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_write(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double_release_write +#endif +#if !defined(AO_HAVE_compare_double_and_swap_double_release_write) && \ + defined(AO_HAVE_compare_double_and_swap_double_release) +# define AO_compare_double_and_swap_double_release_write(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_release(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double_release_write +#endif +#if !defined(AO_HAVE_compare_double_and_swap_double_acquire_read) && \ + defined(AO_HAVE_compare_double_and_swap_double_read) +# define AO_compare_double_and_swap_double_acquire_read(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_read(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double_acquire_read +#endif +#if !defined(AO_HAVE_compare_double_and_swap_double_acquire_read) && \ + defined(AO_HAVE_compare_double_and_swap_double_acquire) +# define AO_compare_double_and_swap_double_acquire_read(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_acquire(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_compare_double_and_swap_double_acquire_read) +# define AO_compare_double_and_swap_double_dd_acquire_read(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double_acquire_read(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_compare_double_and_swap_double) +# define AO_compare_double_and_swap_double_dd_acquire_read(addr, o1, o2, n1, n2) \ + AO_compare_double_and_swap_double(addr, o1, o2, n1, n2) +# define AO_HAVE_compare_double_and_swap_double_dd_acquire_read +# endif +#endif + +/* Compare_and_swap_double */ +#if defined(AO_HAVE_compare_and_swap_double) && defined(AO_HAVE_nop_full)\ + && !defined(AO_HAVE_compare_and_swap_double_acquire) + AO_INLINE int + AO_compare_and_swap_double_acquire(volatile AO_double_t *addr, + AO_t o1, AO_t o2, + AO_t n1, AO_t n2) + { + int result = AO_compare_and_swap_double(addr, o1, n1, n2); + AO_nop_full(); + return result; + } +# define AO_HAVE_compare_and_swap_double_acquire +#endif +#if defined(AO_HAVE_compare_and_swap_double) \ + && defined(AO_HAVE_nop_full)\ + && !defined(AO_HAVE_compare_and_swap_double_release) +# define AO_compare_and_swap_double_release(addr, o1, n1, n2) \ + (AO_nop_full(), AO_compare_and_swap_double(addr, o1, n1, n2)) +# define AO_HAVE_compare_and_swap_double_release +#endif +#if defined(AO_HAVE_compare_and_swap_double_full) +# if !defined(AO_HAVE_compare_and_swap_double_release) +# define AO_compare_and_swap_double_release(addr, o1, n1, n2) \ + AO_compare_and_swap_double_full(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double_release +# endif +# if !defined(AO_HAVE_compare_and_swap_double_acquire) +# define AO_compare_and_swap_double_acquire(addr, o1, n1, n2) \ + AO_compare_and_swap_double_full(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double_acquire +# endif +# if !defined(AO_HAVE_compare_and_swap_double_write) +# define AO_compare_and_swap_double_write(addr, o1, n1, n2) \ + AO_compare_and_swap_double_full(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double_write +# endif +# if !defined(AO_HAVE_compare_and_swap_double_read) +# define AO_compare_and_swap_double_read(addr, o1, n1, n2) \ + AO_compare_and_swap_double_full(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double_read +# endif +#endif /* AO_HAVE_compare_and_swap_double_full */ + +#if !defined(AO_HAVE_compare_and_swap_double) && \ + defined(AO_HAVE_compare_and_swap_double_release) +# define AO_compare_and_swap_double(addr, o1, n1, n2) \ + AO_compare_and_swap_double_release(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double +#endif +#if !defined(AO_HAVE_compare_and_swap_double) && \ + defined(AO_HAVE_compare_and_swap_double_acquire) +# define AO_compare_and_swap_double(addr, o1, n1, n2) \ + AO_compare_and_swap_double_acquire(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double +#endif +#if !defined(AO_HAVE_compare_and_swap_double) && \ + defined(AO_HAVE_compare_and_swap_double_write) +# define AO_compare_and_swap_double(addr, o1, n1, n2) \ + AO_compare_and_swap_double_write(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double +#endif +#if !defined(AO_HAVE_compare_and_swap_double) && \ + defined(AO_HAVE_compare_and_swap_double_read) +# define AO_compare_and_swap_double(addr, o1, n1, n2) \ + AO_compare_and_swap_double_read(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double +#endif + +#if defined(AO_HAVE_compare_and_swap_double_acquire) &&\ + defined(AO_HAVE_nop_full) && \ + !defined(AO_HAVE_compare_and_swap_double_full) +# define AO_compare_and_swap_double_full(addr, o1, n1, n2) \ + (AO_nop_full(), AO_compare_and_swap_double_acquire(addr, o1, n1, n2)) +# define AO_HAVE_compare_and_swap_double_full +#endif + +#if !defined(AO_HAVE_compare_and_swap_double_release_write) && \ + defined(AO_HAVE_compare_and_swap_double_write) +# define AO_compare_and_swap_double_release_write(addr, o1, n1, n2) \ + AO_compare_and_swap_double_write(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double_release_write +#endif +#if !defined(AO_HAVE_compare_and_swap_double_release_write) && \ + defined(AO_HAVE_compare_and_swap_double_release) +# define AO_compare_and_swap_double_release_write(addr, o1, n1, n2) \ + AO_compare_and_swap_double_release(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double_release_write +#endif +#if !defined(AO_HAVE_compare_and_swap_double_acquire_read) && \ + defined(AO_HAVE_compare_and_swap_double_read) +# define AO_compare_and_swap_double_acquire_read(addr, o1, n1, n2) \ + AO_compare_and_swap_double_read(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double_acquire_read +#endif +#if !defined(AO_HAVE_compare_and_swap_double_acquire_read) && \ + defined(AO_HAVE_compare_and_swap_double_acquire) +# define AO_compare_and_swap_double_acquire_read(addr, o1, n1, n2) \ + AO_compare_and_swap_double_acquire(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double_acquire_read +#endif + +#ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_compare_and_swap_double_acquire_read) +# define AO_compare_and_swap_double_dd_acquire_read(addr, o1, n1, n2) \ + AO_compare_and_swap_double_acquire_read(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double_dd_acquire_read +# endif +#else +# if defined(AO_HAVE_compare_and_swap_double) +# define AO_compare_and_swap_double_dd_acquire_read(addr, o1, n1, n2) \ + AO_compare_and_swap_double(addr, o1, n1, n2) +# define AO_HAVE_compare_and_swap_double_dd_acquire_read +# endif +#endif diff --git a/src/atomic_ops/sysdeps/Makefile.am b/src/atomic_ops/sysdeps/Makefile.am new file mode 100644 index 0000000..5234381 --- /dev/null +++ b/src/atomic_ops/sysdeps/Makefile.am @@ -0,0 +1,45 @@ +#General sysdep utility headers, followed by the arch-specific ones +nobase_sysdep_HEADERS= generic_pthread.h \ + atomic_load_store.h \ + aligned_atomic_load_store.h \ + acquire_release_volatile.h \ + char_acquire_release_volatile.h \ + char_atomic_load_store.h \ + short_acquire_release_volatile.h \ + short_aligned_atomic_load_store.h \ + short_atomic_load_store.h \ + int_acquire_release_volatile.h \ + int_aligned_atomic_load_store.h \ + int_atomic_load_store.h \ + all_acquire_release_volatile.h \ + all_aligned_atomic_load_store.h \ + all_atomic_load_store.h \ + ordered_except_wr.h \ + ordered.h \ + ao_t_is_int.h \ + test_and_set_t_is_ao_t.h \ + test_and_set_t_is_char.h \ + emul_cas.h \ + standard_ao_double_t.h \ + README \ + \ + gcc/alpha.h gcc/arm.h gcc/x86.h \ + gcc/hppa.h gcc/ia64.h \ + gcc/powerpc.h gcc/sparc.h \ + gcc/hppa.h gcc/m68k.h gcc/s390.h \ + gcc/ia64.h gcc/x86_64.h gcc/cris.h \ + \ + icc/ia64.h \ + \ + msftc/x86.h \ + \ + hpc/ia64.h hpc/hppa.h \ + \ + sunc/sparc.h \ + \ + ibmc/powerpc.h + +sysdepdir= ${includedir}/atomic_ops/sysdeps + +# A few architectures require special .S files +EXTRA_DIST = sunc/sparc.S diff --git a/src/atomic_ops/sysdeps/Makefile.in b/src/atomic_ops/sysdeps/Makefile.in new file mode 100644 index 0000000..91d0789 --- /dev/null +++ b/src/atomic_ops/sysdeps/Makefile.in @@ -0,0 +1,419 @@ +# Makefile.in generated by automake 1.9.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/atomic_ops/sysdeps +DIST_COMMON = README $(nobase_sysdep_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/src/config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(sysdepdir)" +nobase_sysdepHEADERS_INSTALL = $(install_sh_DATA) +HEADERS = $(nobase_sysdep_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +NEED_ASM_FALSE = @NEED_ASM_FALSE@ +NEED_ASM_TRUE = @NEED_ASM_TRUE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PICFLAG = @PICFLAG@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ + +#General sysdep utility headers, followed by the arch-specific ones +nobase_sysdep_HEADERS = generic_pthread.h \ + atomic_load_store.h \ + aligned_atomic_load_store.h \ + acquire_release_volatile.h \ + char_acquire_release_volatile.h \ + char_atomic_load_store.h \ + short_acquire_release_volatile.h \ + short_aligned_atomic_load_store.h \ + short_atomic_load_store.h \ + int_acquire_release_volatile.h \ + int_aligned_atomic_load_store.h \ + int_atomic_load_store.h \ + all_acquire_release_volatile.h \ + all_aligned_atomic_load_store.h \ + all_atomic_load_store.h \ + ordered_except_wr.h \ + ordered.h \ + ao_t_is_int.h \ + test_and_set_t_is_ao_t.h \ + test_and_set_t_is_char.h \ + emul_cas.h \ + standard_ao_double_t.h \ + README \ + \ + gcc/alpha.h gcc/arm.h gcc/x86.h \ + gcc/hppa.h gcc/ia64.h \ + gcc/powerpc.h gcc/sparc.h \ + gcc/hppa.h gcc/m68k.h gcc/s390.h \ + gcc/ia64.h gcc/x86_64.h gcc/cris.h \ + \ + icc/ia64.h \ + \ + msftc/x86.h \ + \ + hpc/ia64.h hpc/hppa.h \ + \ + sunc/sparc.h \ + \ + ibmc/powerpc.h + +sysdepdir = ${includedir}/atomic_ops/sysdeps + +# A few architectures require special .S files +EXTRA_DIST = sunc/sparc.S +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/atomic_ops/sysdeps/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/atomic_ops/sysdeps/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +uninstall-info-am: +install-nobase_sysdepHEADERS: $(nobase_sysdep_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(sysdepdir)" || $(mkdir_p) "$(DESTDIR)$(sysdepdir)" + @$(am__vpath_adj_setup) \ + list='$(nobase_sysdep_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + $(am__vpath_adj) \ + echo " $(nobase_sysdepHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(sysdepdir)/$$f'"; \ + $(nobase_sysdepHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(sysdepdir)/$$f"; \ + done + +uninstall-nobase_sysdepHEADERS: + @$(NORMAL_UNINSTALL) + @$(am__vpath_adj_setup) \ + list='$(nobase_sysdep_HEADERS)'; for p in $$list; do \ + $(am__vpath_adj) \ + echo " rm -f '$(DESTDIR)$(sysdepdir)/$$f'"; \ + rm -f "$(DESTDIR)$(sysdepdir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(mkdir_p) $(distdir)/gcc $(distdir)/hpc $(distdir)/ibmc $(distdir)/icc $(distdir)/msftc $(distdir)/sunc + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(sysdepdir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-nobase_sysdepHEADERS + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-nobase_sysdepHEADERS + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + ctags distclean distclean-generic distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-man \ + install-nobase_sysdepHEADERS install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags uninstall uninstall-am uninstall-info-am \ + uninstall-nobase_sysdepHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/atomic_ops/sysdeps/README b/src/atomic_ops/sysdeps/README new file mode 100644 index 0000000..605699f --- /dev/null +++ b/src/atomic_ops/sysdeps/README @@ -0,0 +1,7 @@ +There are two kinds of entities in this directory: + +- Subdirectories corresponding to specific compilers (or compiler/OS combinations). + Each of these includes one or more architecture-specific headers. + +- More generic header files corresponding to a particular ordering and/or + atomicity property that might be shared by multiple hardware platforms. diff --git a/src/atomic_ops/sysdeps/acquire_release_volatile.h b/src/atomic_ops/sysdeps/acquire_release_volatile.h new file mode 100644 index 0000000..1a387d3 --- /dev/null +++ b/src/atomic_ops/sysdeps/acquire_release_volatile.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003 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. + */ + +/* + * This file adds definitions appropriate for environments in which an AO_t + * volatile load has acquire semantics, and an AO_t volatile store has release + * semantics. This is arguably supposed to be true with the standard Itanium + * software conventions. + */ + +/* + * Empirically gcc/ia64 does some reordering of ordinary operations around volatiles + * even when we think it shouldn't. Gcc 3.3 and earlier could reorder a volatile store + * with another store. As of March 2005, gcc pre-4 reused previously computed + * common subexpressions across a volatile load. + * Hence we now add compiler barriers for gcc. + */ +#if !defined(AO_GCC_BARRIER) +# if defined(__GNUC__) +# define AO_GCC_BARRIER() AO_compiler_barrier() +# else +# define AO_GCC_BARRIER() +# endif +#endif + +AO_INLINE AO_t +AO_load_acquire(volatile AO_t *p) +{ + AO_t result = *p; + /* A normal volatile load generates an ld.acq */ + AO_GCC_BARRIER(); + return result; +} +#define AO_HAVE_load_acquire + +AO_INLINE void +AO_store_release(volatile AO_t *p, AO_t val) +{ + AO_GCC_BARRIER(); + /* A normal volatile store generates an st.rel */ + *p = val; +} +#define AO_HAVE_store_release + + diff --git a/src/atomic_ops/sysdeps/aligned_atomic_load_store.h b/src/atomic_ops/sysdeps/aligned_atomic_load_store.h new file mode 100644 index 0000000..e69c0dd --- /dev/null +++ b/src/atomic_ops/sysdeps/aligned_atomic_load_store.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2003 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. + */ + +/* + * Definitions for architecturs on which loads and stores of AO_t are + * atomic fo all legal alignments. + */ + +AO_INLINE AO_t +AO_load(volatile AO_t *addr) +{ + assert(((unsigned long)addr & (sizeof(AO_t) - 1)) == 0); + /* Cast away the volatile for architectures where */ + /* volatile adds barrier semantics. */ + return *(AO_t *)addr; +} + +#define AO_HAVE_load + +AO_INLINE void +AO_store(volatile AO_t *addr, AO_t new_val) +{ + assert(((unsigned long)addr & (sizeof(AO_t) - 1)) == 0); + (*(AO_t *)addr) = new_val; +} + +#define AO_HAVE_store + + diff --git a/src/atomic_ops/sysdeps/all_acquire_release_volatile.h b/src/atomic_ops/sysdeps/all_acquire_release_volatile.h new file mode 100644 index 0000000..6787387 --- /dev/null +++ b/src/atomic_ops/sysdeps/all_acquire_release_volatile.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2004 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. + */ + +/* + * Describes architectures on which volatile AO_t, unsigned char, unsigned + * short, and unsigned int loads and stores have acquire/release semantics for + * all normally legal alignments. + */ +#include "acquire_release_volatile.h" +#include "char_acquire_release_volatile.h" +#include "short_acquire_release_volatile.h" +#include "int_acquire_release_volatile.h" diff --git a/src/atomic_ops/sysdeps/all_aligned_atomic_load_store.h b/src/atomic_ops/sysdeps/all_aligned_atomic_load_store.h new file mode 100644 index 0000000..b9f7247 --- /dev/null +++ b/src/atomic_ops/sysdeps/all_aligned_atomic_load_store.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2004 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. + */ + +/* + * Describes architectures on which AO_t, unsigned char, unsigned short, + * and unsigned int loads and strores are atomic for all normally legal alignments. + */ +#include "aligned_atomic_load_store.h" +#include "char_atomic_load_store.h" +#include "short_aligned_atomic_load_store.h" +#include "int_aligned_atomic_load_store.h" diff --git a/src/atomic_ops/sysdeps/all_atomic_load_store.h b/src/atomic_ops/sysdeps/all_atomic_load_store.h new file mode 100644 index 0000000..d0ebe08 --- /dev/null +++ b/src/atomic_ops/sysdeps/all_atomic_load_store.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2004 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. + */ + +/* + * Describes architectures on which AO_t, unsigned char, unsigned short, + * and unsigned int loads and strores are atomic for all normally legal + * alignments. + */ +#include "atomic_load_store.h" +#include "char_atomic_load_store.h" +#include "short_atomic_load_store.h" +#include "int_atomic_load_store.h" diff --git a/src/atomic_ops/sysdeps/ao_t_is_int.h b/src/atomic_ops/sysdeps/ao_t_is_int.h new file mode 100644 index 0000000..18156c8 --- /dev/null +++ b/src/atomic_ops/sysdeps/ao_t_is_int.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2003-2004 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. + */ + +/* + * Inclusion of this file signifies that AO_t is in fact int. Hence + * any AO_... operations can also server as AO_int_... operations. + * We currently define only the more important ones here, and allow for + * the normal generalization process to define the others. + * We should probably add others in the future. + */ + +#if defined(AO_HAVE_compare_and_swap_full) && \ + !defined(AO_HAVE_int_compare_and_swap_full) +# define AO_int_compare_and_swap_full(addr, old, new_val) \ + AO_compare_and_swap_full((volatile AO_t *)addr, \ + (AO_t) old, (AO_t)new_val) +# define AO_HAVE_int_compare_and_swap_full +# endif + +#if defined(AO_HAVE_compare_and_swap_acquire) && \ + !defined(AO_HAVE_int_compare_and_swap_acquire) +# define AO_int_compare_and_swap_acquire(addr, old, new_val) \ + AO_compare_and_swap_acquire((volatile AO_t *)addr, \ + (AO_t) old, (AO_t)new_val) +# define AO_HAVE_int_compare_and_swap_acquire +# endif + +#if defined(AO_HAVE_compare_and_swap_release) && \ + !defined(AO_HAVE_int_compare_and_swap_release) +# define AO_int_compare_and_swap_release(addr, old, new_val) \ + AO_compare_and_swap_release((volatile AO_t *)addr, \ + (AO_t) old, (AO_t)new_val) +# define AO_HAVE_int_compare_and_swap_release +# endif + +#if defined(AO_HAVE_compare_and_swap_write) && \ + !defined(AO_HAVE_int_compare_and_swap_write) +# define AO_int_compare_and_swap_write(addr, old, new_val) \ + AO_compare_and_swap_write((volatile AO_t *)addr, \ + (AO_t) old, (AO_t)new_val) +# define AO_HAVE_int_compare_and_swap_write +# endif + +#if defined(AO_HAVE_compare_and_swap_read) && \ + !defined(AO_HAVE_int_compare_and_swap_read) +# define AO_int_compare_and_swap_read(addr, old, new_val) \ + AO_compare_and_swap_read((volatile AO_t *)addr, \ + (AO_t) old, (AO_t)new_val) +# define AO_HAVE_int_compare_and_swap_read +# endif + +#if defined(AO_HAVE_compare_and_swap) && \ + !defined(AO_HAVE_int_compare_and_swap) +# define AO_int_compare_and_swap(addr, old, new_val) \ + AO_compare_and_swap((volatile AO_t *)addr, \ + (AO_t) old, (AO_t)new_val) +# define AO_HAVE_int_compare_and_swap +# endif + +#if defined(AO_HAVE_load_acquire) && \ + !defined(AO_HAVE_int_load_acquire) +# define AO_int_load_acquire(addr) (int)AO_load_acquire((volatile AO_t *)addr) +# define AO_HAVE_int_load_acquire +# endif + +#if defined(AO_HAVE_store_release) && \ + !defined(AO_HAVE_int_store_release) +# define AO_int_store_release(addr, val) \ + AO_store_release((volatile AO_t *)addr, (AO_t)val) +# define AO_HAVE_int_store_release +# endif + +#if defined(AO_HAVE_fetch_and_add_full) && \ + !defined(AO_HAVE_int_fetch_and_add_full) +# define AO_int_fetch_and_add_full(addr, incr) \ + (int)AO_fetch_and_add_full((volatile AO_t *)addr, (AO_t)incr) +# define AO_HAVE_int_fetch_and_add_full +# endif + +#if defined(AO_HAVE_fetch_and_add1_acquire) && \ + !defined(AO_HAVE_int_fetch_and_add1_acquire) +# define AO_int_fetch_and_add1_acquire(addr) \ + (int)AO_fetch_and_add1_acquire((volatile AO_t *)addr) +# define AO_HAVE_int_fetch_and_add1_acquire +# endif + +#if defined(AO_HAVE_fetch_and_add1_release) && \ + !defined(AO_HAVE_int_fetch_and_add1_release) +# define AO_int_fetch_and_add1_release(addr) \ + (int)AO_fetch_and_add1_release((volatile AO_t *)addr) +# define AO_HAVE_int_fetch_and_add1_release +# endif + +#if defined(AO_HAVE_fetch_and_sub1_acquire) && \ + !defined(AO_HAVE_int_fetch_and_sub1_acquire) +# define AO_int_fetch_and_sub1_acquire(addr) \ + (int)AO_fetch_and_sub1_acquire((volatile AO_t *)addr) +# define AO_HAVE_int_fetch_and_sub1_acquire +# endif + +#if defined(AO_HAVE_fetch_and_sub1_release) && \ + !defined(AO_HAVE_int_fetch_and_sub1_release) +# define AO_int_fetch_and_sub1_release(addr) \ + (int)AO_fetch_and_sub1_release((volatile AO_t *)addr) +# define AO_HAVE_int_fetch_and_sub1_release +# endif + diff --git a/src/atomic_ops/sysdeps/atomic_load_store.h b/src/atomic_ops/sysdeps/atomic_load_store.h new file mode 100644 index 0000000..68c5179 --- /dev/null +++ b/src/atomic_ops/sysdeps/atomic_load_store.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2003 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. + */ + +/* + * Definitions for architecturs on which loads and stores of AO_t are + * atomic fo all legal alignments. + */ + +AO_INLINE AO_t +AO_load(volatile AO_t *addr) +{ + /* Cast away the volatile for architectures like IA64 where */ + /* volatile adds barrier semantics. */ + return (*(AO_t *)addr); +} + +#define AO_HAVE_load + +AO_INLINE void +AO_store(volatile AO_t *addr, AO_t new_val) +{ + (*(AO_t *)addr) = new_val; +} + +#define AO_HAVE_store + + diff --git a/src/atomic_ops/sysdeps/char_acquire_release_volatile.h b/src/atomic_ops/sysdeps/char_acquire_release_volatile.h new file mode 100644 index 0000000..37aa021 --- /dev/null +++ b/src/atomic_ops/sysdeps/char_acquire_release_volatile.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003-2004 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. + */ + +/* + * This file adds definitions appropriate for environments in which an unsigned char + * volatile load has acquire semantics, and an unsigned char volatile store has release + * semantics. This is true with the standard Itanium ABI. + */ +#if !defined(AO_GCC_BARRIER) +# if defined(__GNUC__) +# define AO_GCC_BARRIER() AO_compiler_barrier() +# else +# define AO_GCC_BARRIER() +# endif +#endif + +AO_INLINE unsigned char +AO_char_load_acquire(volatile unsigned char *p) +{ + unsigned char result = *p; + /* A normal volatile load generates an ld.acq */ + AO_GCC_BARRIER(); + return result; +} +#define AO_HAVE_char_load_acquire + +AO_INLINE void +AO_char_store_release(volatile unsigned char *p, unsigned char val) +{ + AO_GCC_BARRIER(); + /* A normal volatile store generates an st.rel */ + *p = val; +} +#define AO_HAVE_char_store_release + + diff --git a/src/atomic_ops/sysdeps/char_atomic_load_store.h b/src/atomic_ops/sysdeps/char_atomic_load_store.h new file mode 100644 index 0000000..6eb0978 --- /dev/null +++ b/src/atomic_ops/sysdeps/char_atomic_load_store.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * 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. + */ + +/* + * Definitions for architecturs on which loads and stores of unsigned char are + * atomic for all legal alignments. + */ + +AO_INLINE unsigned char +AO_char_load(volatile unsigned char *addr) +{ + /* Cast away the volatile for architectures like IA64 where */ + /* volatile adds barrier semantics. */ + return (*(unsigned char *)addr); +} + +#define AO_HAVE_char_load + +AO_INLINE void +AO_char_store(volatile unsigned char *addr, unsigned char new_val) +{ + (*(unsigned char *)addr) = new_val; +} + +#define AO_HAVE_char_store + + diff --git a/src/atomic_ops/sysdeps/emul_cas.h b/src/atomic_ops/sysdeps/emul_cas.h new file mode 100644 index 0000000..4187f9f --- /dev/null +++ b/src/atomic_ops/sysdeps/emul_cas.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * 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. + */ + +/* + * Ensure, if at all possible, that AO_compare_and_swap_full() is + * available. The emulation should be brute-force signal-safe, even + * though it actually blocks. + * Including this file will generate an error if AO_compare_and_swap_full() + * cannot be made available. + * This will be included from platform-specific atomic_ops files + * id appropriate, and if AO_FORCE_CAS is defined. It should not be + * included directly, especially since it affects the implementation + * of other atomic update primitives. + * The implementation assumes that only AO_store_XXX and AO_test_and_set_XXX + * variants are defined, and that AO_test_and_set_XXX is not used to + * operate on compare_and_swap locations. + */ + +#if !defined(ATOMIC_OPS_H) +# error This file should not be included directly. +#endif + +#ifndef AO_HAVE_double_t +# include "standard_ao_double_t.h" +#endif + +int AO_compare_and_swap_emulation(volatile AO_t *addr, AO_t old, + AO_t new_val); + +int AO_compare_double_and_swap_double_emulation(volatile AO_double_t *addr, + AO_t old_val1, AO_t old_val2, + AO_t new_val1, AO_t new_val2); + +void AO_store_full_emulation(volatile AO_t *addr, AO_t val); + +#define AO_compare_and_swap_full(addr, old, newval) \ + AO_compare_and_swap_emulation(addr, old, newval) +#define AO_HAVE_compare_and_swap_full + +#ifndef AO_HAVE_compare_double_and_swap_double +# define AO_compare_double_and_swap_double_full(addr, old1, old2, \ + newval1, newval2) \ + AO_compare_double_and_swap_double_emulation(addr, old1, old2, \ + newval1, newval2) +# define AO_HAVE_compare_double_and_swap_double_full +#endif + +#undef AO_store +#undef AO_HAVE_store +#undef AO_store_write +#undef AO_HAVE_store_write +#undef AO_store_release +#undef AO_HAVE_store_release +#undef AO_store_full +#undef AO_HAVE_store_full +#define AO_store_full(addr, val) AO_store_full_emulation(addr, val) +#define AO_HAVE_store_full diff --git a/src/atomic_ops/sysdeps/gcc/alpha.h b/src/atomic_ops/sysdeps/gcc/alpha.h new file mode 100644 index 0000000..90c060c --- /dev/null +++ b/src/atomic_ops/sysdeps/gcc/alpha.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. + * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. + * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved. + * + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + */ + +#include "../atomic_load_store.h" + +#include "../test_and_set_t_is_ao_t.h" + +#define AO_NO_DD_ORDERING + /* Data dependence does not imply read ordering. */ + +AO_INLINE void +AO_nop_full() +{ + __asm__ __volatile__("mb" : : : "memory"); +} + +#define AO_HAVE_nop_full + +AO_INLINE void +AO_nop_write() +{ + __asm__ __volatile__("wmb" : : : "memory"); +} + +#define AO_HAVE_nop_write + +/* mb should be used for AO_nop_read(). That's the default. */ + +/* We believe that ldq_l ... stq_c does not imply any memory barrier. */ +/* We should add an explicit fetch_and_add definition. */ +AO_INLINE int +AO_compare_and_swap(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ + unsigned long was_equal; + unsigned long temp; + + __asm__ __volatile__( + "1: ldq_l %0,%1\n" + " cmpeq %0,%4,%2\n" + " mov %3,%0\n" + " beq %2,2f\n" + " stq_c %0,%1\n" + " beq %0,1b\n" + "2:\n" + :"=&r" (temp), "=m" (*addr), "=&r" (was_equal) + : "r" (new_val), "Ir" (old) + :"memory"); + return was_equal; +} + +#define AO_HAVE_compare_and_swap + + diff --git a/src/atomic_ops/sysdeps/gcc/arm.h b/src/atomic_ops/sysdeps/gcc/arm.h new file mode 100644 index 0000000..e10ffa0 --- /dev/null +++ b/src/atomic_ops/sysdeps/gcc/arm.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. + * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. + * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved. + * + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + */ + +/* FIXME. Very incomplete. No support for 64 bits. */ + +#include "../all_atomic_load_store.h" + +#include "../test_and_set_t_is_ao_t.h" /* Probably suboptimal */ + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t *addr) { + int oldval; + int temp = 1; /* locked value */ + + __asm__ __volatile__ ( + " l %0,0(%2)\n" + "0: cs %0,%1,0(%2)\n" + " jl 0b" + : "=&d" (ret) + : "d" (1), "a" (addr) + : "cc", "memory"); + return oldval; +} + +#define AO_HAVE_test_and_set_full + + + diff --git a/src/atomic_ops/sysdeps/gcc/cris.h b/src/atomic_ops/sysdeps/gcc/cris.h new file mode 100644 index 0000000..3864905 --- /dev/null +++ b/src/atomic_ops/sysdeps/gcc/cris.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2004 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. + * + * Most of this code originally comes from Hans-Peter Nilsson. It is included + * here with his permission. + * + * This version has not been tested. It was coped here from a GC + * patch so that we wouldn't lose the code in the upgrade to gc7. + */ + +#include "../all_atomic_load_store.h" + +#include "../ordered.h" /* There are no multiprocessor implementations. */ + +#include "../test_and_set_t_is_ao_t.h" + +/* + * The architecture apparently supports an "f" flag which is + * set on preemption. This essentially gives us load-locked, + * store-conditional primitives, though I'm not quite sure how + * this would work on a hypothetical multiprocessor. -HB + * + * For details, see + * http://developer.axis.com/doc/hardware/etrax100lx/prog_man/ + * 1_architectural_description.pdf + * + * Presumably many other primitives (notably CAS, including the double- + * width versions) could be implemented in this manner, if someone got + * around to it. + */ + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t *addr) { + /* Ripped from linuxthreads/sysdeps/cris/pt-machine.h */ + register unsigned long int ret; + + /* Note the use of a dummy output of *addr to expose the write. The + memory barrier is to stop *other* writes being moved past this code. */ + __asm__ __volatile__("clearf\n" + "0:\n\t" + "movu.b [%2],%0\n\t" + "ax\n\t" + "move.b %3,[%2]\n\t" + "bwf 0b\n\t" + "clearf" + : "=&r" (ret), "=m" (*addr) + : "r" (addr), "r" ((int) 1), "m" (*addr) + : "memory"); + return ret; +} + +#define AO_HAVE_test_and_set_full + diff --git a/src/atomic_ops/sysdeps/gcc/hppa.h b/src/atomic_ops/sysdeps/gcc/hppa.h new file mode 100644 index 0000000..3349a38 --- /dev/null +++ b/src/atomic_ops/sysdeps/gcc/hppa.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2003 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. + * + * Modified by Carlos O'Donell <carlos@baldric.uwo.ca>, 2003 + * - Added self-aligning lock. + * + */ + +#include "../all_atomic_load_store.h" + +/* Some architecture set descriptions include special "ordered" memory */ +/* operations. As far as we can tell, no existing processors actually */ +/* require those. Nor does it appear likely that future processors */ +/* will. */ +#include "../ordered.h" + +/* GCC will not guarantee the alignment we need, use four lock words */ +/* and select the correctly aligned datum. See the glibc 2.3.2 */ +/* linuxthread port for the original implementation. */ +struct AO_pa_clearable_loc { + int data[4]; +}; + +#undef AO_TS_INITIALIZER +#define AO_TS_t struct AO_pa_clearable_loc +#define AO_TS_INITIALIZER {1,1,1,1} +/* Switch meaning of set and clear, since we only have an atomic clear */ +/* instruction. */ +typedef enum {AO_PA_TS_set = 0, AO_PA_TS_clear = 1} AO_PA_TS_val; +#define AO_TS_VAL_t AO_PA_TS_val +#define AO_TS_CLEAR AO_PA_TS_clear +#define AO_TS_SET AO_PA_TS_set + +/* The hppa only has one atomic read and modify memory operation, */ +/* load and clear, so hppa spinlocks must use zero to signify that */ +/* someone is holding the lock. The address used for the ldcw */ +/* semaphore must be 16-byte aligned. */ + +#define __ldcw(a) ({ \ + volatile unsigned int __ret; \ + __asm__ __volatile__("ldcw 0(%2),%0" \ + : "=r" (__ret), "=m" (*(a)) : "r" (a)); \ + __ret; \ +}) + +/* Because malloc only guarantees 8-byte alignment for malloc'd data, */ +/* and GCC only guarantees 8-byte alignment for stack locals, we can't */ +/* be assured of 16-byte alignment for atomic lock data even if we */ +/* specify "__attribute ((aligned(16)))" in the type declaration. So, */ +/* we use a struct containing an array of four ints for the atomic lock */ +/* type and dynamically select the 16-byte aligned int from the array */ +/* for the semaphore. */ +#define __PA_LDCW_ALIGNMENT 16 +#define __ldcw_align(a) ({ \ + unsigned long __ret = (unsigned long) a; \ + __ret += __PA_LDCW_ALIGNMENT - 1; \ + __ret &= ~(__PA_LDCW_ALIGNMENT - 1); \ + (volatile unsigned int *) __ret; \ +}) + +/* Works on PA 1.1 and PA 2.0 systems */ +AO_INLINE AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t * addr) +{ + volatile unsigned int *a = __ldcw_align (addr); + return __ldcw (a); +} + +AO_INLINE void +AO_pa_clear(volatile AO_TS_t * addr) +{ + volatile unsigned int *a = __ldcw_align (addr); + AO_compiler_barrier(); + *a = 1; +} +#define AO_CLEAR(addr) AO_pa_clear(addr) + +#define AO_HAVE_test_and_set_full + diff --git a/src/atomic_ops/sysdeps/gcc/ia64.h b/src/atomic_ops/sysdeps/gcc/ia64.h new file mode 100644 index 0000000..522eaee --- /dev/null +++ b/src/atomic_ops/sysdeps/gcc/ia64.h @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2003 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. + */ + +#include "../all_atomic_load_store.h" + +#include "../acquire_release_volatile.h" + +#include "../test_and_set_t_is_char.h" + +#ifdef _ILP32 + /* 32-bit HP/UX code. */ + /* This requires pointer "swizzling". Pointers need to be expanded */ + /* to 64 bits using the addp4 instruction before use. This makes it */ + /* hard to share code, but we try anyway. */ +# define AO_LEN "4" + /* We assume that addr always appears in argument position 1 in asm */ + /* code. If it is clobbered due to swizzling, we also need it in */ + /* second position. Any later arguments are referenced symbolically, */ + /* so that we don't have to worry about their position. This requires*/ + /* gcc 3.1, but you shouldn't be using anything older than that on */ + /* IA64 anyway. */ + /* The AO_MASK macro is a workaround for the fact that HP/UX gcc */ + /* appears to otherwise store 64-bit pointers in ar.ccv, i.e. it */ + /* doesn't appear to clear high bits in a pointer value we pass into */ + /* assembly code, even if it is supposedly of type AO_t. */ +# define AO_IN_ADDR "1"(addr) +# define AO_OUT_ADDR , "=r"(addr) +# define AO_SWIZZLE "addp4 %1=0,%1;;\n" +# define AO_MASK(ptr) __asm__("zxt4 %1=%1": "=r"(ptr) : "0"(ptr)); +#else +# define AO_LEN "8" +# define AO_IN_ADDR "r"(addr) +# define AO_OUT_ADDR +# define AO_SWIZZLE +# define AO_MASK(ptr) +#endif + +AO_INLINE void +AO_nop_full() +{ + __asm__ __volatile__("mf" : : : "memory"); +} +#define AO_HAVE_nop_full + +AO_INLINE AO_t +AO_fetch_and_add1_acquire (volatile AO_t *addr) +{ + AO_t result; + + __asm__ __volatile__ (AO_SWIZZLE + "fetchadd" AO_LEN ".acq %0=[%1],1": + "=r" (result) AO_OUT_ADDR: AO_IN_ADDR :"memory"); + return result; +} +#define AO_HAVE_fetch_and_add1_acquire + +AO_INLINE AO_t +AO_fetch_and_add1_release (volatile AO_t *addr) +{ + AO_t result; + + __asm__ __volatile__ (AO_SWIZZLE + "fetchadd" AO_LEN ".rel %0=[%1],1": + "=r" (result) AO_OUT_ADDR: AO_IN_ADDR :"memory"); + return result; +} + +#define AO_HAVE_fetch_and_add1_release + +AO_INLINE AO_t +AO_fetch_and_sub1_acquire (volatile AO_t *addr) +{ + AO_t result; + + __asm__ __volatile__ (AO_SWIZZLE + "fetchadd" AO_LEN ".acq %0=[%1],-1": + "=r" (result) AO_OUT_ADDR: AO_IN_ADDR :"memory"); + return result; +} + +#define AO_HAVE_fetch_and_sub1_acquire + +AO_INLINE AO_t +AO_fetch_and_sub1_release (volatile AO_t *addr) +{ + AO_t result; + + __asm__ __volatile__ (AO_SWIZZLE + "fetchadd" AO_LEN ".rel %0=[%1],-1": + "=r" (result) AO_OUT_ADDR: AO_IN_ADDR :"memory"); + return result; +} + +#define AO_HAVE_fetch_and_sub1_release + +#ifndef _ILP32 + +AO_INLINE unsigned int +AO_int_fetch_and_add1_acquire (volatile unsigned int *addr) +{ + unsigned int result; + + __asm__ __volatile__ ("fetchadd4.acq %0=[%1],1": + "=r" (result): AO_IN_ADDR :"memory"); + return result; +} +#define AO_HAVE_int_fetch_and_add1_acquire + +AO_INLINE unsigned int +AO_int_fetch_and_add1_release (volatile unsigned int *addr) +{ + unsigned int result; + + __asm__ __volatile__ ("fetchadd4.rel %0=[%1],1": + "=r" (result): AO_IN_ADDR :"memory"); + return result; +} + +#define AO_HAVE_int_fetch_and_add1_release + +AO_INLINE unsigned int +AO_int_fetch_and_sub1_acquire (volatile unsigned int *addr) +{ + unsigned int result; + + __asm__ __volatile__ ("fetchadd4.acq %0=[%1],-1": + "=r" (result): AO_IN_ADDR :"memory"); + return result; +} + +#define AO_HAVE_int_fetch_and_sub1_acquire + +AO_INLINE unsigned int +AO_int_fetch_and_sub1_release (volatile unsigned int *addr) +{ + unsigned int result; + + __asm__ __volatile__ ("fetchadd4.rel %0=[%1],-1": + "=r" (result): AO_IN_ADDR :"memory"); + return result; +} + +#define AO_HAVE_int_fetch_and_sub1_release + +#endif /* !_ILP32 */ + +AO_INLINE int +AO_compare_and_swap_acquire(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ + AO_t oldval; + AO_MASK(old); + __asm__ __volatile__(AO_SWIZZLE + "mov ar.ccv=%[old] ;; cmpxchg" AO_LEN + ".acq %0=[%1],%[new_val],ar.ccv" + : "=r"(oldval) AO_OUT_ADDR + : AO_IN_ADDR, [new_val]"r"(new_val), [old]"r"(old) + : "memory"); + return (oldval == old); +} + +#define AO_HAVE_compare_and_swap_acquire + +AO_INLINE int +AO_compare_and_swap_release(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ + AO_t oldval; + AO_MASK(old); + __asm__ __volatile__(AO_SWIZZLE + "mov ar.ccv=%[old] ;; cmpxchg" AO_LEN + ".rel %0=[%1],%[new_val],ar.ccv" + : "=r"(oldval) AO_OUT_ADDR + : AO_IN_ADDR, [new_val]"r"(new_val), [old]"r"(old) + : "memory"); + return (oldval == old); +} + +#define AO_HAVE_compare_and_swap_release + +AO_INLINE int +AO_char_compare_and_swap_acquire(volatile unsigned char *addr, + unsigned char old, unsigned char new_val) +{ + unsigned char oldval; + __asm__ __volatile__(AO_SWIZZLE + "mov ar.ccv=%[old] ;; cmpxchg1.acq %0=[%1],%[new_val],ar.ccv" + : "=r"(oldval) AO_OUT_ADDR + : AO_IN_ADDR, [new_val]"r"(new_val), [old]"r"((AO_t)old) + : "memory"); + return (oldval == old); +} + +#define AO_HAVE_char_compare_and_swap_acquire + +AO_INLINE int +AO_char_compare_and_swap_release(volatile unsigned char *addr, + unsigned char old, unsigned char new_val) +{ + unsigned char oldval; + __asm__ __volatile__(AO_SWIZZLE + "mov ar.ccv=%[old] ;; cmpxchg1.rel %0=[%1],%[new_val],ar.ccv" + : "=r"(oldval) AO_OUT_ADDR + : AO_IN_ADDR, [new_val]"r"(new_val), [old]"r"((AO_t)old) + : "memory"); + return (oldval == old); +} + +#define AO_HAVE_char_compare_and_swap_release + +AO_INLINE int +AO_short_compare_and_swap_acquire(volatile unsigned short *addr, + unsigned short old, unsigned short new_val) +{ + unsigned short oldval; + __asm__ __volatile__(AO_SWIZZLE + "mov ar.ccv=%[old] ;; cmpxchg2.acq %0=[%1],%[new_val],ar.ccv" + : "=r"(oldval) AO_OUT_ADDR + : AO_IN_ADDR, [new_val]"r"(new_val), [old]"r"((AO_t)old) + : "memory"); + return (oldval == old); +} + +#define AO_HAVE_short_compare_and_swap_acquire + +AO_INLINE int +AO_short_compare_and_swap_release(volatile unsigned short *addr, + unsigned short old, unsigned short new_val) +{ + unsigned short oldval; + __asm__ __volatile__(AO_SWIZZLE + "mov ar.ccv=%[old] ;; cmpxchg2.rel %0=[%1],%[new_val],ar.ccv" + : "=r"(oldval) AO_OUT_ADDR + : AO_IN_ADDR, [new_val]"r"(new_val), [old]"r"((AO_t)old) + : "memory"); + return (oldval == old); +} + +#define AO_HAVE_short_compare_and_swap_release + +#ifndef _ILP32 + +AO_INLINE int +AO_int_compare_and_swap_acquire(volatile unsigned int *addr, + unsigned int old, unsigned int new_val) +{ + unsigned int oldval; + __asm__ __volatile__("mov ar.ccv=%3 ;; cmpxchg4.acq %0=[%1],%2,ar.ccv" + : "=r"(oldval) + : AO_IN_ADDR, "r"(new_val), "r"((AO_t)old) : "memory"); + return (oldval == old); +} + +#define AO_HAVE_int_compare_and_swap_acquire + +AO_INLINE int +AO_int_compare_and_swap_release(volatile unsigned int *addr, + unsigned int old, unsigned int new_val) +{ + unsigned int oldval; + __asm__ __volatile__("mov ar.ccv=%3 ;; cmpxchg4.rel %0=[%1],%2,ar.ccv" + : "=r"(oldval) + : AO_IN_ADDR, "r"(new_val), "r"((AO_t)old) : "memory"); + return (oldval == old); +} + +#define AO_HAVE_int_compare_and_swap_release + +#endif /* !_ILP32 */ + +/* FIXME: Add compare_and_swap_double as soon as there is widely */ +/* available hardware that implements it. */ + +/* FIXME: Add compare_double_and_swap_double for the _ILP32 case. */ + +#ifdef _ILP32 +# include "../ao_t_is_int.h" +#endif diff --git a/src/atomic_ops/sysdeps/gcc/m68k.h b/src/atomic_ops/sysdeps/gcc/m68k.h new file mode 100644 index 0000000..9e7f70a --- /dev/null +++ b/src/atomic_ops/sysdeps/gcc/m68k.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. + * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. + * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved. + * + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + */ + +/* FIXME. Very incomplete. */ +#include "../all_aligned_atomic_load_store.h" + +/* Are there any m68k multiprocessors still around? */ +/* AFAIK, Alliants were sequentially consistent. */ +#include "../ordered.h" + +#include "../test_and_set_t_is_ao_t.h" + +/* Contributed by Tony Mantler or new. Should be changed to MIT license? */ +AO_INLINE AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t *addr) { + int oldval; + + /* The return value is semi-phony. */ + /* 'tas' sets bit 7 while the return */ + /* value pretends bit 0 was set */ + __asm__ __volatile__( + "tas %1@; sne %0; negb %0" + : "=d" (oldval) + : "a" (addr) : "memory"); + return oldval; +} + +#define AO_HAVE_test_and_set_full + + + diff --git a/src/atomic_ops/sysdeps/gcc/powerpc.h b/src/atomic_ops/sysdeps/gcc/powerpc.h new file mode 100644 index 0000000..5f33e71 --- /dev/null +++ b/src/atomic_ops/sysdeps/gcc/powerpc.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. + * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. + * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P. + * + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + */ + +/* FIXME. Incomplete. No support for 64 bits. */ +/* Memory model documented at http://www-106.ibm.com/developerworks/ */ +/* eserver/articles/archguide.html and (clearer) */ +/* http://www-106.ibm.com/developerworks/eserver/articles/powerpc.html. */ +/* There appears to be no implicit ordering between any kind of */ +/* independent memory references. */ +/* Architecture enforces some ordering based on control dependence. */ +/* I don't know if that could help. */ +/* Data-dependent loads are always ordered. */ +/* Based on the above references, eieio is intended for use on */ +/* uncached memory, which we don't support. It does not order loads */ +/* from cached memory. */ +/* Thanks to Maged Michael, Doug Lea, and Roger Hoover for helping to */ +/* track some of this down and correcting my misunderstandings. -HB */ + +#include "../all_aligned_atomic_load_store.h" + +#include "../test_and_set_t_is_ao_t.h" + /* There seems to be no byte equivalent of lwarx, so this */ + /* may really be what we want, at least in the 32-bit case. */ + +AO_INLINE void +AO_nop_full() +{ + __asm__ __volatile__("sync" : : : "memory"); +} + +#define AO_HAVE_nop_full + +/* lwsync apparently works for everything but a StoreLoad barrier. */ +AO_INLINE void +AO_lwsync() +{ + __asm__ __volatile__("lwsync" : : : "memory"); +} + +#define AO_nop_write() AO_lwsync() +#define AO_HAVE_nop_write + +#define AO_nop_read() AO_lwsync() +#define AO_HAVE_nop_read + +/* We explicitly specify load_acquire, since it is important, and can */ +/* be implemented relatively cheaply. It could be implemented */ +/* with an ordinary load followed by a lwsync. But the general wisdom */ +/* seems to be that a data dependent branch followed by an isync is */ +/* cheaper. And the documentation is fairly explicit that this also */ +/* has acquire semantics. */ +AO_INLINE AO_t +AO_load_acquire(volatile AO_t *addr) +{ + int cr; + AO_t result; + + /* FIXME: We should get gcc to allocate one of the condition */ + /* registers. I always got "impossible constraint" when I */ + /* tried the "y" constraint. */ + __asm__ __volatile__ ( + "lwz %0,%1\n" + "cmpw cr7,%0,%0\n" + "bne- cr7,1f\n" + "1: isync\n" + : "=r" (result) + : "m"(*addr) : "memory", "cc"); + return result; +} + +#define AO_HAVE_load_acquire + +/* We explicitly specify store_release, since it relies */ +/* on the fact that lwsync is also a LoadStore barrier. */ +AO_INLINE void +AO_store_release(volatile AO_t *addr, AO_t value) +{ + AO_lwsync(); + *addr = value; +} + +#define AO_HAVE_load_acquire + +/* This is similar to the code in the garbage collector. Deleting */ +/* this and having it synthesized from compare_and_swap would probably */ +/* only cost us a load immediate instruction. */ +AO_INLINE AO_TS_VAL_t +AO_test_and_set(volatile AO_TS_t *addr) { + int oldval; + int temp = 1; /* locked value */ + + __asm__ __volatile__( + "1:lwarx %0,0,%1\n" /* load and reserve */ + "cmpwi %0, 0\n" /* if load is */ + "bne 2f\n" /* non-zero, return already set */ + "stwcx. %2,0,%1\n" /* else store conditional */ + "bne- 1b\n" /* retry if lost reservation */ + "2:\n" /* oldval is zero if we set */ + : "=&r"(oldval) + : "r"(addr), "r"(temp) + : "memory", "cc"); + + return oldval; +} + +#define AO_have_test_and_set + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_acquire(volatile AO_TS_t *addr) { + AO_TS_VAL_t result = AO_test_and_set(addr); + AO_lwsync(); + return result; +} + +#define AO_HAVE_test_and_set_acquire + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_release(volatile AO_TS_t *addr) { + AO_lwsync(); + return AO_test_and_set(addr); +} + +#define AO_HAVE_test_and_set_release + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t *addr) { + AO_TS_VAL_t result; + AO_lwsync(); + result = AO_test_and_set(addr); + AO_lwsync(); + return result; +} + +#define AO_HAVE_test_and_set_full + +AO_INLINE int +AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val) { + AO_t oldval; + int result = 0; + + __asm__ __volatile__( + "1:lwarx %0,0,%2\n" /* load and reserve */ + "cmpw %0, %4\n" /* if load is not equal to */ + "bne 2f\n" /* old, fail */ + "stwcx. %3,0,%2\n" /* else store conditional */ + "bne- 1b\n" /* retry if lost reservation */ + "li %1,1\n" /* result = 1; */ + "2:\n" + : "=&r"(oldval), "=&r"(result) + : "r"(addr), "r"(new_val), "r"(old), "1"(result) + : "memory", "cc"); + + return result; +} + +#define AO_HAVE_compare_and_swap + +AO_INLINE int +AO_compare_and_swap_acquire(volatile AO_t *addr, AO_t old, AO_t new_val) { + int result = AO_compare_and_swap(addr, old, new_val); + AO_lwsync(); + return result; +} + +#define AO_HAVE_compare_and_swap_acquire + +AO_INLINE int +AO_compare_and_swap_release(volatile AO_t *addr, AO_t old, AO_t new_val) { + AO_lwsync(); + return AO_compare_and_swap(addr, old, new_val); +} + +#define AO_HAVE_compare_and_swap_release + +AO_INLINE int +AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) { + AO_t result; + AO_lwsync(); + result = AO_compare_and_swap(addr, old, new_val); + AO_lwsync(); + return result; +} + +#define AO_HAVE_compare_and_swap_full + +/* FIXME: We should also implement fetch_and_add and or primitives */ +/* directly. */ diff --git a/src/atomic_ops/sysdeps/gcc/s390.h b/src/atomic_ops/sysdeps/gcc/s390.h new file mode 100644 index 0000000..7cb9986 --- /dev/null +++ b/src/atomic_ops/sysdeps/gcc/s390.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. + * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. + * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved. + * + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + */ + +/* FIXME: untested. */ +/* The relevant documentation appears to be at */ +/* http://publibz.boulder.ibm.com/epubs/pdf/dz9zr003.pdf */ +/* around page 5-96. Apparently: */ +/* - Memory references in general are atomic only for a single */ +/* byte. But it appears that the most common load/store */ +/* instructions also guarantee atomicity for aligned */ +/* operands of standard types. WE FOOLISHLY ASSUME that */ +/* compilers only generate those. If that turns out to be */ +/* wrong, we need inline assembly code for AO_load and */ +/* AO_store. */ +/* - A store followed by a load is unordered since the store */ +/* may be delayed. Otherwise everything is ordered. */ +/* - There is a hardware compare-and-swap (CS) instruction. */ + +#include "ordered_except_wr.h" +#include "all_aligned_atomic_load_store.h" + +#include "../test_and_set_t_is_ao_t.h" +/* FIXME: Is there a way to do byte-sized test-and-set? */ + +/* FIXME: AO_nop_full should probably be implemented directly. */ +/* It appears that certain BCR instructions have that effect. */ +/* Presumably they're cheaper than CS? */ + +AO_INLINE AO_t AO_compare_and_swap_full(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ + int retval; + __asm__ __volatile__ ( +# ifndef __s390x__ + " cs %1,%2,0(%3)\n" +# else + " csg %1,%2,0(%3)\n" +# endif + " ipm %0\n" + " srl %0,28\n" + : "=&d" (retval), "+d" (old) + : "d" (new_val), "a" (addr) + : "cc", "memory"); + return retval == 0; +} + +#define AO_HAVE_compare_and_swap_full + +/* FIXME: Add double-wide compare-and-swap for 32-bit executables. */ diff --git a/src/atomic_ops/sysdeps/gcc/sparc.h b/src/atomic_ops/sysdeps/gcc/sparc.h new file mode 100644 index 0000000..4850855 --- /dev/null +++ b/src/atomic_ops/sysdeps/gcc/sparc.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. + * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. + * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved. + * + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + */ + +/* FIXME. Very incomplete. No support for sparc64. */ +/* Non-ancient SPARCs provide compare-and-swap (casa). */ +/* We should make that available. */ + +#include "../all_atomic_load_store.h" + +/* Real SPARC code uses TSO: */ +#include "../ordered_except_wr.h" + +/* Test_and_set location is just a byte. */ +#include "../test_and_set_t_is_char.h" + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t *addr) { + int oldval; + + __asm__ __volatile__("ldstub %1,%0" + : "=r"(oldval), "=m"(*addr) + : "m"(*addr) : "memory"); + return oldval; +} + +#define AO_HAVE_test_and_set_full + +/* FIXME: This needs to be extended for SPARC v8 and v9. */ +/* SPARC V8 also has swap. V9 has CAS. */ +/* There are barriers like membar #LoadStore. */ +/* CASA (32-bit) and CASXA(64-bit) instructions were */ +/* added in V9. */ diff --git a/src/atomic_ops/sysdeps/gcc/x86.h b/src/atomic_ops/sysdeps/gcc/x86.h new file mode 100644 index 0000000..19d2274 --- /dev/null +++ b/src/atomic_ops/sysdeps/gcc/x86.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. + * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. + * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved. + * + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + * Some of the machine specific code was borrowed from our GC distribution. + */ + +/* The following really assume we have a 486 or better. Unfortunately */ +/* gcc doesn't define a suitable feature test macro based on command */ +/* line options. */ +/* We should perhaps test dynamically. */ + +#include "../all_aligned_atomic_load_store.h" + +/* Real X86 implementations, except for some old WinChips, appear */ +/* to enforce ordering between memory operations, EXCEPT that a later */ +/* read can pass earlier writes, presumably due to the visible */ +/* presence of store buffers. */ +/* We ignore both the WinChips, and the fact that the official specs */ +/* seem to be much weaker (and arguably too weak to be usable). */ + +#include "../ordered_except_wr.h" + +#include "../test_and_set_t_is_char.h" + +#include "../standard_ao_double_t.h" + +#if defined(AO_USE_PENTIUM4_INSTRS) +AO_INLINE void +AO_nop_full() +{ + __asm__ __volatile__("mfence" : : : "memory"); +} + +#define AO_HAVE_nop_full + +#else + +/* We could use the cpuid instruction. But that seems to be slower */ +/* than the default implementation based on test_and_set_full. Thus */ +/* we omit that bit of misinformation here. */ + +#endif + +/* As far as we can tell, the lfence and sfence instructions are not */ +/* currently needed or useful for cached memory accesses. */ + +/* Really only works for 486 and later */ +AO_INLINE AO_t +AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) +{ + AO_t result; + + __asm__ __volatile__ ("lock; xaddl %0, %1" : + "=r" (result), "=m" (*p) : "0" (incr), "m" (*p) + : "memory"); + return result; +} + +#define AO_HAVE_fetch_and_add_full + +AO_INLINE unsigned char +AO_char_fetch_and_add_full (volatile unsigned char *p, unsigned char incr) +{ + unsigned char result; + + __asm__ __volatile__ ("lock; xaddb %0, %1" : + "=r" (result), "=m" (*p) : "0" (incr), "m" (*p) + : "memory"); + return result; +} + +#define AO_HAVE_char_fetch_and_add_full + +AO_INLINE unsigned short +AO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr) +{ + unsigned short result; + + __asm__ __volatile__ ("lock; xaddw %0, %1" : + "=r" (result), "=m" (*p) : "0" (incr), "m" (*p) + : "memory"); + return result; +} + +#define AO_HAVE_short_fetch_and_add_full + +/* Really only works for 486 and later */ +AO_INLINE void +AO_or_full (volatile AO_t *p, AO_t incr) +{ + __asm__ __volatile__ ("lock; orl %1, %0" : + "=m" (*p) : "r" (incr), "m" (*p) : "memory"); +} + +#define AO_HAVE_or_full + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t *addr) +{ + unsigned char oldval; + /* Note: the "xchg" instruction does not need a "lock" prefix */ + __asm__ __volatile__("xchgb %0, %1" + : "=r"(oldval), "=m"(*addr) + : "0"(0xff), "m"(*addr) : "memory"); + return (AO_TS_VAL_t)oldval; +} + +#define AO_HAVE_test_and_set_full + +/* Returns nonzero if the comparison succeeded. */ +AO_INLINE int +AO_compare_and_swap_full(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ + char result; + __asm__ __volatile__("lock; cmpxchgl %3, %0; setz %1" + : "=m"(*addr), "=q"(result) + : "m"(*addr), "r" (new_val), "a"(old) : "memory"); + return (int) result; +} + +#define AO_HAVE_compare_and_swap_full + +/* Returns nonzero if the comparison succeeded. */ +/* Really requires at least a Pentium. */ +AO_INLINE int +AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, + AO_t old_val1, AO_t old_val2, + AO_t new_val1, AO_t new_val2) +{ + char result; + __asm__ __volatile__("lock; cmpxchg8b %0; setz %1" + : "=m"(*addr), "=q"(result) + : "m"(*addr), "d" (old_val1), "a" (old_val2), + "c" (new_val1), "b" (new_val2) : "memory"); + return (int) result; +} + +#define AO_HAVE_double_compare_and_swap_full + +#include "../ao_t_is_int.h" diff --git a/src/atomic_ops/sysdeps/gcc/x86_64.h b/src/atomic_ops/sysdeps/gcc/x86_64.h new file mode 100644 index 0000000..356476f --- /dev/null +++ b/src/atomic_ops/sysdeps/gcc/x86_64.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. + * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. + * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved. + * + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + * Some of the machine specific code was borrowed from our GC distribution. + */ + +/* The following really assume we have a 486 or better. Unfortunately */ +/* gcc doesn't define a suitable feature test macro based on command */ +/* line options. */ +/* We should perhaps test dynamically. */ + +#include "../all_aligned_atomic_load_store.h" + +/* Real X86 implementations, except for some old WinChips, appear */ +/* to enforce ordering between memory operations, EXCEPT that a later */ +/* read can pass earlier writes, presumably due to the visible */ +/* presence of store buffers. */ +/* We ignore both the WinChips, and the fact that the official specs */ +/* seem to be much weaker (and arguably too weak to be usable). */ + +#include "../ordered_except_wr.h" + +#include "../test_and_set_t_is_char.h" + +#if defined(AO_USE_PENTIUM4_INSTRS) +AO_INLINE void +AO_nop_full() +{ + __asm__ __volatile__("mfence" : : : "memory"); +} + +#define AO_HAVE_nop_full + +#else + +/* We could use the cpuid instruction. But that seems to be slower */ +/* than the default implementation based on test_and_set_full. Thus */ +/* we omit that bit of misinformation here. */ + +#endif + +/* As far as we can tell, the lfence and sfence instructions are not */ +/* currently needed or useful for cached memory accesses. */ + +/* Really only works for 486 and later */ +AO_INLINE AO_t +AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) +{ + AO_t result; + + __asm__ __volatile__ ("lock; xaddq %0, %1" : + "=r" (result), "=m" (*p) : "0" (incr), "m" (*p) + : "memory"); + return result; +} + +#define AO_HAVE_fetch_and_add_full + +AO_INLINE unsigned char +AO_char_fetch_and_add_full (volatile unsigned char *p, unsigned char incr) +{ + unsigned char result; + + __asm__ __volatile__ ("lock; xaddb %0, %1" : + "=r" (result), "=m" (*p) : "0" (incr), "m" (*p) + : "memory"); + return result; +} + +#define AO_HAVE_char_fetch_and_add_full + +AO_INLINE unsigned short +AO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr) +{ + unsigned short result; + + __asm__ __volatile__ ("lock; xaddw %0, %1" : + "=r" (result), "=m" (*p) : "0" (incr), "m" (*p) + : "memory"); + return result; +} + +#define AO_HAVE_short_fetch_and_add_full + +AO_INLINE unsigned short +AO_int_fetch_and_add_full (volatile unsigned int *p, unsigned int incr) +{ + unsigned int result; + + __asm__ __volatile__ ("lock; xaddl %0, %1" : + "=r" (result), "=m" (*p) : "0" (incr), "m" (*p) + : "memory"); + return result; +} + +#define AO_HAVE_int_fetch_and_add_full + +/* Really only works for 486 and later */ +AO_INLINE void +AO_or_full (volatile AO_t *p, AO_t incr) +{ + __asm__ __volatile__ ("lock; orq %1, %0" : + "=m" (*p) : "r" (incr), "m" (*p) : "memory"); +} + +#define AO_HAVE_or_full + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t *addr) +{ + unsigned char oldval; + /* Note: the "xchg" instruction does not need a "lock" prefix */ + __asm__ __volatile__("xchgb %0, %1" + : "=r"(oldval), "=m"(*addr) + : "0"(0xff), "m"(*addr) : "memory"); + return (AO_TS_VAL_t)oldval; +} + +#define AO_HAVE_test_and_set_full + +/* Returns nonzero if the comparison succeeded. */ +AO_INLINE int +AO_compare_and_swap_full(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ + char result; + __asm__ __volatile__("lock; cmpxchgq %3, %0; setz %1" + : "=m"(*addr), "=q"(result) + : "m"(*addr), "r" (new_val), "a"(old) : "memory"); + return (int) result; +} + +#define AO_HAVE_compare_and_swap_full + +/* FIXME: The Intel version has a 16byte CAS instruction. */ diff --git a/src/atomic_ops/sysdeps/generic_pthread.h b/src/atomic_ops/sysdeps/generic_pthread.h new file mode 100644 index 0000000..8d17c0a --- /dev/null +++ b/src/atomic_ops/sysdeps/generic_pthread.h @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * 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. + */ + +/* The following is useful primarily for debugging and documentation. */ +/* We define various atomic operations by acquiring a global pthread */ +/* lock. The resulting implementation will perform poorly, but should */ +/* be correct unless it is used from signal handlers. */ +/* We assume that all pthread operations act like full memory barriers. */ +/* (We believe that is the intent of the specification.) */ + +#include <pthread.h> + +#include "test_and_set_t_is_ao_t.h" + /* This is not necessarily compatible with the native */ + /* implementation. But those can't be safely mixed anyway. */ + +/* We define only the full barrier variants, and count on the */ +/* generalization section below to fill in the rest. */ +extern pthread_mutex_t AO_pt_lock; + +AO_INLINE void +AO_nop_full() +{ + pthread_mutex_lock(&AO_pt_lock); + pthread_mutex_unlock(&AO_pt_lock); +} + +#define AO_HAVE_nop_full + +AO_INLINE AO_t +AO_load_full(volatile AO_t *addr) +{ + AO_t result; + pthread_mutex_lock(&AO_pt_lock); + result = *addr; + pthread_mutex_unlock(&AO_pt_lock); + return result; +} + +#define AO_HAVE_load_full + +AO_INLINE void +AO_store_full(volatile AO_t *addr, AO_t val) +{ + pthread_mutex_lock(&AO_pt_lock); + *addr = val; + pthread_mutex_unlock(&AO_pt_lock); +} + +#define AO_HAVE_store_full + +AO_INLINE unsigned char +AO_char_load_full(volatile unsigned char *addr) +{ + unsigned char result; + pthread_mutex_lock(&AO_pt_lock); + result = *addr; + pthread_mutex_unlock(&AO_pt_lock); + return result; +} + +#define AO_HAVE_char_load_full + +AO_INLINE void +AO_char_store_full(volatile unsigned char *addr, unsigned char val) +{ + pthread_mutex_lock(&AO_pt_lock); + *addr = val; + pthread_mutex_unlock(&AO_pt_lock); +} + +#define AO_HAVE_char_store_full + +AO_INLINE unsigned short +AO_short_load_full(volatile unsigned short *addr) +{ + unsigned short result; + pthread_mutex_lock(&AO_pt_lock); + result = *addr; + pthread_mutex_unlock(&AO_pt_lock); + return result; +} + +#define AO_HAVE_short_load_full + +AO_INLINE void +AO_short_store_full(volatile unsigned short *addr, unsigned short val) +{ + pthread_mutex_lock(&AO_pt_lock); + *addr = val; + pthread_mutex_unlock(&AO_pt_lock); +} + +#define AO_HAVE_short_store_full + +AO_INLINE unsigned int +AO_int_load_full(volatile unsigned int *addr) +{ + unsigned int result; + pthread_mutex_lock(&AO_pt_lock); + result = *addr; + pthread_mutex_unlock(&AO_pt_lock); + return result; +} + +#define AO_HAVE_int_load_full + +AO_INLINE void +AO_int_store_full(volatile unsigned int *addr, unsigned int val) +{ + pthread_mutex_lock(&AO_pt_lock); + *addr = val; + pthread_mutex_unlock(&AO_pt_lock); +} + +#define AO_HAVE_int_store_full + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t *addr) +{ + AO_TS_VAL_t result; + pthread_mutex_lock(&AO_pt_lock); + result = (AO_TS_VAL_t)(*addr); + *addr = AO_TS_SET; + pthread_mutex_unlock(&AO_pt_lock); + assert(result == AO_TS_SET || result == AO_TS_CLEAR); + return result; +} + +#define AO_HAVE_test_and_set_full + +AO_INLINE AO_t +AO_fetch_and_add_full(volatile AO_t *p, AO_t incr) +{ + AO_t tmp; + + pthread_mutex_lock(&AO_pt_lock); + tmp = *p; + *p = tmp + incr; + pthread_mutex_unlock(&AO_pt_lock); + return tmp; +} + +#define AO_HAVE_fetch_and_add_full + +AO_INLINE unsigned char +AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr) +{ + unsigned char tmp; + + pthread_mutex_lock(&AO_pt_lock); + tmp = *p; + *p = tmp + incr; + pthread_mutex_unlock(&AO_pt_lock); + return tmp; +} + +#define AO_HAVE_char_fetch_and_add_full + +AO_INLINE unsigned short +AO_short_fetch_and_add_full(volatile unsigned short *p, unsigned short incr) +{ + unsigned short tmp; + + pthread_mutex_lock(&AO_pt_lock); + tmp = *p; + *p = tmp + incr; + pthread_mutex_unlock(&AO_pt_lock); + return tmp; +} + +#define AO_HAVE_short_fetch_and_add_full + +AO_INLINE unsigned int +AO_int_fetch_and_add_full(volatile unsigned int *p, unsigned int incr) +{ + unsigned int tmp; + + pthread_mutex_lock(&AO_pt_lock); + tmp = *p; + *p = tmp + incr; + pthread_mutex_unlock(&AO_pt_lock); + return tmp; +} + +#define AO_HAVE_int_fetch_and_add_full + +AO_INLINE void +AO_or_full(volatile AO_t *p, AO_t incr) +{ + AO_t tmp; + + pthread_mutex_lock(&AO_pt_lock); + tmp = *p; + *p = (tmp | incr); + pthread_mutex_unlock(&AO_pt_lock); +} + +#define AO_HAVE_or_full + +AO_INLINE int +AO_compare_and_swap_full(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ + pthread_mutex_lock(&AO_pt_lock); + if (*addr == old) + { + *addr = new_val; + pthread_mutex_unlock(&AO_pt_lock); + return 1; + } + else + pthread_mutex_unlock(&AO_pt_lock); + return 0; +} + +#define AO_HAVE_compare_and_swap_full + +/* Unlike real architectures, we define both double-width CAS variants. */ + +typedef struct { + AO_t AO_val1; + AO_t AO_val2; +} AO_double_t; + +#define AO_HAVE_double_t + +AO_INLINE int +AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, + AO_t old1, AO_t old2, + AO_t new1, AO_t new2) +{ + pthread_mutex_lock(&AO_pt_lock); + if (addr -> AO_val1 == old1 && addr -> AO_val2 == old2) + { + addr -> AO_val1 = new1; + addr -> AO_val2 = new2; + pthread_mutex_unlock(&AO_pt_lock); + return 1; + } + else + pthread_mutex_unlock(&AO_pt_lock); + return 0; +} + +#define AO_HAVE_compare_double_and_swap_double_full + +AO_INLINE int +AO_compare_and_swap_double_full(volatile AO_double_t *addr, + AO_t old1, + AO_t new1, AO_t new2) +{ + pthread_mutex_lock(&AO_pt_lock); + if (addr -> AO_val1 == old1) + { + addr -> AO_val1 = new1; + addr -> AO_val2 = new2; + pthread_mutex_unlock(&AO_pt_lock); + return 1; + } + else + pthread_mutex_unlock(&AO_pt_lock); + return 0; +} + +#define AO_HAVE_compare_and_swap_double_full + +/* We can't use hardware loads and stores, since they don't */ +/* interact correctly with atomic updates. */ + diff --git a/src/atomic_ops/sysdeps/hpc/hppa.h b/src/atomic_ops/sysdeps/hpc/hppa.h new file mode 100644 index 0000000..80bd94c --- /dev/null +++ b/src/atomic_ops/sysdeps/hpc/hppa.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2003 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. + * + * Derived from the corresponsing header file for gcc. + * + */ + +#include "../atomic_load_store.h" + +/* Some architecture set descriptions include special "ordered" memory */ +/* operations. As far as we can tell, no existing processors actually */ +/* require those. Nor does it appear likely that future processors */ +/* will. */ +/* FIXME: */ +/* The PA emulator on Itanium may obey weaker restrictions. */ +/* There should be a mode in which we don't assume sequential */ +/* consistency here. */ +#include "../ordered.h" + +#include <machine/inline.h> + +/* GCC will not guarantee the alignment we need, use four lock words */ +/* and select the correctly aligned datum. See the glibc 2.3.2 */ +/* linuxthread port for the original implementation. */ +struct AO_pa_clearable_loc { + int data[4]; +}; + +#undef AO_TS_INITIALIZER +#define AO_TS_t struct AO_pa_clearable_loc +#define AO_TS_INITIALIZER {1,1,1,1} +/* Switch meaning of set and clear, since we only have an atomic clear */ +/* instruction. */ +typedef enum {AO_PA_TS_set = 0, AO_PA_TS_clear = 1} AO_PA_TS_val; +#define AO_TS_VAL_t AO_PA_TS_val +#define AO_TS_CLEAR AO_PA_TS_clear +#define AO_TS_SET AO_PA_TS_set + +/* The hppa only has one atomic read and modify memory operation, */ +/* load and clear, so hppa spinlocks must use zero to signify that */ +/* someone is holding the lock. The address used for the ldcw */ +/* semaphore must be 16-byte aligned. */ + +#define __ldcw(a, ret) \ + _LDCWX(0 /* index */, 0 /* s */, a /* base */, ret); + +/* Because malloc only guarantees 8-byte alignment for malloc'd data, */ +/* and GCC only guarantees 8-byte alignment for stack locals, we can't */ +/* be assured of 16-byte alignment for atomic lock data even if we */ +/* specify "__attribute ((aligned(16)))" in the type declaration. So, */ +/* we use a struct containing an array of four ints for the atomic lock */ +/* type and dynamically select the 16-byte aligned int from the array */ +/* for the semaphore. */ +#define __PA_LDCW_ALIGNMENT 16 + +#define __ldcw_align(a, ret) { \ + ret = (unsigned long) a; \ + ret += __PA_LDCW_ALIGNMENT - 1; \ + ret &= ~(__PA_LDCW_ALIGNMENT - 1); \ +} + +/* Works on PA 1.1 and PA 2.0 systems */ +AO_INLINE AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t * addr) +{ + register unsigned int ret; + register unsigned long a; + __ldcw_align (addr, a); + __ldcw (a, ret); + return ret; +} + +AO_INLINE void +AO_pa_clear(volatile AO_TS_t * addr) +{ + unsigned long a; + __ldcw_align (addr,a); + AO_compiler_barrier(); + *(volatile unsigned int *)a = 1; +} +#define AO_CLEAR(addr) AO_pa_clear(addr) + +#define AO_HAVE_test_and_set_full + diff --git a/src/atomic_ops/sysdeps/hpc/ia64.h b/src/atomic_ops/sysdeps/hpc/ia64.h new file mode 100644 index 0000000..72552d5 --- /dev/null +++ b/src/atomic_ops/sysdeps/hpc/ia64.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2003 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. + */ + +/* + * This file specifies Itanimum primitives for use with the HP compiler + * unde HP/UX. We use intrinsics instead of the inline assembly code in the + * gcc file. + */ + +#include "../atomic_load_store.h" + +#include "../acquire_release_volatile.h" + +#include "../test_and_set_t_is_char.h" + +#include <machine/sys/inline.h> + +#ifdef __LP64__ +# define AO_T_FASIZE _FASZ_D +# define AO_T_SIZE _SZ_D +#else +# define AO_T_FASIZE _FASZ_W +# define AO_T_SIZE _SZ_W +#endif + +AO_INLINE void +AO_nop_full() +{ + _Asm_mf(); +} +#define AO_HAVE_nop_full + +AO_INLINE AO_t +AO_fetch_and_add1_acquire (volatile AO_t *p) +{ + return _Asm_fetchadd(AO_T_FASIZE, _SEM_ACQ, p, 1, + _LDHINT_NONE, _DOWN_MEM_FENCE); +} +#define AO_HAVE_fetch_and_add1_acquire + +AO_INLINE AO_t +AO_fetch_and_add1_release (volatile AO_t *p) +{ + return _Asm_fetchadd(AO_T_FASIZE, _SEM_REL, p, 1, + _LDHINT_NONE, _UP_MEM_FENCE); +} + +#define AO_HAVE_fetch_and_add1_release + +AO_INLINE AO_t +AO_fetch_and_sub1_acquire (volatile AO_t *p) +{ + return _Asm_fetchadd(AO_T_FASIZE, _SEM_ACQ, p, -1, + _LDHINT_NONE, _DOWN_MEM_FENCE); +} + +#define AO_HAVE_fetch_and_sub1_acquire + +AO_INLINE AO_t +AO_fetch_and_sub1_release (volatile AO_t *p) +{ + return _Asm_fetchadd(AO_T_FASIZE, _SEM_REL, p, -1, + _LDHINT_NONE, _UP_MEM_FENCE); +} + +#define AO_HAVE_fetch_and_sub1_release + +AO_INLINE int +AO_compare_and_swap_acquire(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ + AO_t oldval; + + _Asm_mov_to_ar(_AREG_CCV, old, _DOWN_MEM_FENCE); + oldval = _Asm_cmpxchg(AO_T_SIZE, _SEM_ACQ, addr, + new_val, _LDHINT_NONE, _DOWN_MEM_FENCE); + return (oldval == old); +} + +#define AO_HAVE_compare_and_swap_acquire + +AO_INLINE int +AO_compare_and_swap_release(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ + AO_t oldval; + _Asm_mov_to_ar(_AREG_CCV, old, _UP_MEM_FENCE); + oldval = _Asm_cmpxchg(AO_T_SIZE, _SEM_REL, addr, + new_val, _LDHINT_NONE, _UP_MEM_FENCE); + /* Hopefully the compiler knows not to reorder the above two? */ + return (oldval == old); +} + +#define AO_HAVE_compare_and_swap_release + +AO_INLINE int +AO_char_compare_and_swap_acquire(volatile unsigned char *addr, + unsigned char old, unsigned char new_val) +{ + unsigned char oldval; + + _Asm_mov_to_ar(_AREG_CCV, old, _DOWN_MEM_FENCE); + oldval = _Asm_cmpxchg(_SZ_B, _SEM_ACQ, addr, + new_val, _LDHINT_NONE, _DOWN_MEM_FENCE); + return (oldval == old); +} + +#define AO_HAVE_char_compare_and_swap_acquire + +AO_INLINE int +AO_char_compare_and_swap_release(volatile unsigned char *addr, + unsigned char old, unsigned char new_val) +{ + insigned char oldval; + _Asm_mov_to_ar(_AREG_CCV, old, _UP_MEM_FENCE); + oldval = _Asm_cmpxchg(_SZ_B, _SEM_REL, addr, + new_val, _LDHINT_NONE, _UP_MEM_FENCE); + /* Hopefully the compiler knows not to reorder the above two? */ + return (oldval == old); +} + +#define AO_HAVE_char_compare_and_swap_release + +AO_INLINE int +AO_short_compare_and_swap_acquire(volatile unsigned short *addr, + unsigned short old, unsigned short new_val) +{ + unsigned short oldval; + + _Asm_mov_to_ar(_AREG_CCV, old, _DOWN_MEM_FENCE); + oldval = _Asm_cmpxchg(_SZ_B, _SEM_ACQ, addr, + new_val, _LDHINT_NONE, _DOWN_MEM_FENCE); + return (oldval == old); +} + +#define AO_HAVE_short_compare_and_swap_acquire + +AO_INLINE int +AO_short_compare_and_swap_release(volatile unsigned short *addr, + unsigned short old, unsigned short new_val) +{ + insigned short oldval; + _Asm_mov_to_ar(_AREG_CCV, old, _UP_MEM_FENCE); + oldval = _Asm_cmpxchg(_SZ_B, _SEM_REL, addr, + new_val, _LDHINT_NONE, _UP_MEM_FENCE); + /* Hopefully the compiler knows not to reorder the above two? */ + return (oldval == old); +} + +#define AO_HAVE_short_compare_and_swap_release + +#ifndef __LP64__ +# include "ao_t_is_int.h" +#endif + diff --git a/src/atomic_ops/sysdeps/ibmc/powerpc.h b/src/atomic_ops/sysdeps/ibmc/powerpc.h new file mode 100644 index 0000000..d1f9c50 --- /dev/null +++ b/src/atomic_ops/sysdeps/ibmc/powerpc.h @@ -0,0 +1,126 @@ +/* FIXME. This is only a placeholder for the AIX compiler. */ +/* It doesn't work. Please send a patch. */ +/* Memory model documented at http://www-106.ibm.com/developerworks/ */ +/* eserver/articles/archguide.html and (clearer) */ +/* http://www-106.ibm.com/developerworks/eserver/articles/powerpc.html. */ +/* There appears to be no implicit ordering between any kind of */ +/* independent memory references. */ +/* Architecture enforces some ordering based on control dependence. */ +/* I don't know if that could help. */ +/* Data-dependent loads are always ordered. */ +/* Based on the above references, eieio is intended for use on */ +/* uncached memory, which we don't support. It does not order loads */ +/* from cached memory. */ +/* Thanks to Maged Michael, Doug Lea, and Roger Hoover for helping to */ +/* track some of this down and correcting my misunderstandings. -HB */ + +#include "../all_aligned_atomic_load_store.h" + +void AO_sync(void); +#pragma mc_func AO_sync { "7c0004ac" } + +void AO_lwsync(void); +#pragma mc_func AO_lwsync { "7c2004ac" } + +#define AO_nop_write() AO_lwsync() +#define AO_HAVE_nop_write + +#define AO_nop_read() AO_lwsync() +#define AO_HAVE_nop_read + +/* We explicitly specify load_acquire and store_release, since these */ +/* rely on the fact that lwsync is also a LoadStore barrier. */ +AO_INLINE AO_t +AO_load_acquire(volatile AO_t *addr) +{ + AO_t result = *addr; + AO_lwsync(); + return result; +} + +#define AO_HAVE_load_acquire + +AO_INLINE void +AO_store_release(volatile AO_t *addr, AO_t value) +{ + AO_lwsync(); + *addr = value; +} + +#define AO_HAVE_load_acquire + +/* This is similar to the code in the garbage collector. Deleting */ +/* this and having it synthesized from compare_and_swap would probably */ +/* only cost us a load immediate instruction. */ +AO_INLINE AO_TS_VAL_t +AO_test_and_set(volatile AO_TS_t *addr) { +# error Implement me +} + +#define AO_have_test_and_set + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_acquire(volatile AO_TS_t *addr) { + AO_TS_VAL_t result = AO_test_and_set(addr); + AO_lwsync(); + return result; +} + +#define AO_HAVE_test_and_set_acquire + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_release(volatile AO_TS_t *addr) { + AO_lwsync(); + return AO_test_and_set(addr); +} + +#define AO_HAVE_test_and_set_release + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t *addr) { + AO_TS_VAL_t result; + AO_lwsync(); + result = AO_test_and_set(addr); + AO_lwsync(); + return result; +} + +#define AO_HAVE_test_and_set_full + +AO_INLINE AO_t +AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val) { +# error Implement me +} + +#define AO_HAVE_compare_and_swap + +AO_INLINE AO_t +AO_compare_and_swap_acquire(volatile AO_t *addr, AO_t old, AO_t new_val) { + AO_t result = AO_compare_and_swap(addr, old, new_val); + AO_lwsync(); + return result; +} + +#define AO_HAVE_compare_and_swap_acquire + +AO_INLINE AO_t +AO_compare_and_swap_release(volatile AO_t *addr, AO_t old, AO_t new_val) { + AO_lwsync(); + return AO_compare_and_swap(addr, old, new_val); +} + +#define AO_HAVE_compare_and_swap_release + +AO_INLINE AO_t +AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) { + AO_t result; + AO_lwsync(); + result = AO_compare_and_swap(addr, old, new_val); + AO_lwsync(); + return result; +} + +#define AO_HAVE_compare_and_swap_full + +/* FIXME: We should also implement fetch_and_add and or primitives */ +/* directly. */ diff --git a/src/atomic_ops/sysdeps/icc/ia64.h b/src/atomic_ops/sysdeps/icc/ia64.h new file mode 100644 index 0000000..358ddda --- /dev/null +++ b/src/atomic_ops/sysdeps/icc/ia64.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * 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. + */ + +/* + * This file specifies Itanimum primitives for use with the Intel (ecc) + * compiler. We use intrinsics instead of the inline assembly code in the + * gcc file. + */ + +#include "../all_atomic_load_store.h" + +#include "../test_and_set_t_is_char.h" + +#include <ia64intrin.h> + +/* The acquire release semantics of volatile can be turned off. And volatile */ +/* operations in icc9 don't imply ordering with respect to other nonvolatile */ +/* operations. */ + +#define AO_INTEL_PTR_t void * + +AO_INLINE AO_t +AO_load_acquire(volatile AO_t *p) +{ + return (AO_t)(__ld8_acq((AO_INTEL_PTR_t)p)); +} +#define AO_HAVE_load_acquire + +AO_INLINE void +AO_store_release(volatile AO_t *p, AO_t val) +{ + __st8_rel((AO_INTEL_PTR_t)p, (__int64)val); +} +#define AO_HAVE_store_release + +AO_INLINE unsigned char +AO_char_load_acquire(volatile unsigned char *p) +{ + /* A normal volatile load generates an ld.acq */ + return (__ld1_acq((AO_INTEL_PTR_t)p)); +} +#define AO_HAVE_char_load_acquire + +AO_INLINE void +AO_char_store_release(volatile unsigned char *p, unsigned char val) +{ + __st1_rel((AO_INTEL_PTR_t)p, val); +} +#define AO_HAVE_char_store_release + +AO_INLINE unsigned short +AO_short_load_acquire(volatile unsigned short *p) +{ + /* A normal volatile load generates an ld.acq */ + return (__ld2_acq((AO_INTEL_PTR_t)p)); +} +#define AO_HAVE_short_load_acquire + +AO_INLINE void +AO_short_store_release(volatile unsigned short *p, unsigned short val) +{ + __st2_rel((AO_INTEL_PTR_t)p, val); +} +#define AO_HAVE_short_store_release + +AO_INLINE unsigned int +AO_int_load_acquire(volatile unsigned int *p) +{ + /* A normal volatile load generates an ld.acq */ + return (__ld4_acq((AO_INTEL_PTR_t)p)); +} +#define AO_HAVE_int_load_acquire + +AO_INLINE void +AO_int_store_release(volatile unsigned int *p, unsigned int val) +{ + __st4_rel((AO_INTEL_PTR_t)p, val); +} +#define AO_HAVE_int_store_release + +AO_INLINE void +AO_nop_full() +{ + __mf(); +} +#define AO_HAVE_nop_full + +AO_INLINE AO_t +AO_fetch_and_add1_acquire (volatile AO_t *p) +{ + return __fetchadd8_acq((unsigned __int64 *)p, 1); +} +#define AO_HAVE_fetch_and_add1_acquire + +AO_INLINE AO_t +AO_fetch_and_add1_release (volatile AO_t *p) +{ + return __fetchadd8_rel((unsigned __int64 *)p, 1); +} + +#define AO_HAVE_fetch_and_add1_release + +AO_INLINE AO_t +AO_fetch_and_sub1_acquire (volatile AO_t *p) +{ + return __fetchadd8_acq((unsigned __int64 *)p, -1); +} + +#define AO_HAVE_fetch_and_sub1_acquire + +AO_INLINE AO_t +AO_fetch_and_sub1_release (volatile AO_t *p) +{ + return __fetchadd8_rel((unsigned __int64 *)p, -1); +} + +#define AO_HAVE_fetch_and_sub1_release + +AO_INLINE int +AO_compare_and_swap_acquire(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ + AO_t oldval; + oldval = _InterlockedCompareExchange64_acq(addr, new_val, old); + return (oldval == old); +} + +#define AO_HAVE_compare_and_swap_acquire + +AO_INLINE int +AO_compare_and_swap_release(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ + AO_t oldval; + oldval = _InterlockedCompareExchange64_rel(addr, new_val, old); + return (oldval == old); +} + +#define AO_HAVE_compare_and_swap_release + +AO_INLINE int +AO_char_compare_and_swap_acquire(volatile unsigned char *addr, + unsigned char old, unsigned char new_val) +{ + unsigned char oldval; + oldval = _InterlockedCompareExchange8_acq(addr, new_val, old); + return (oldval == old); +} + +#define AO_HAVE_char_compare_and_swap_acquire + +AO_INLINE int +AO_char_compare_and_swap_release(volatile unsigned char *addr, + unsigned char old, unsigned char new_val) +{ + unsigned char oldval; + oldval = _InterlockedCompareExchange8_rel(addr, new_val, old); + return (oldval == old); +} + +#define AO_HAVE_char_compare_and_swap_release + +AO_INLINE int +AO_short_compare_and_swap_acquire(volatile unsigned short *addr, + unsigned short old, unsigned short new_val) +{ + unsigned short oldval; + oldval = _InterlockedCompareExchange16_acq(addr, new_val, old); + return (oldval == old); +} + +#define AO_HAVE_short_compare_and_swap_acquire + +AO_INLINE int +AO_short_compare_and_swap_release(volatile unsigned short *addr, + unsigned short old, unsigned short new_val) +{ + unsigned short oldval; + oldval = _InterlockedCompareExchange16_rel(addr, new_val, old); + return (oldval == old); +} + +#define AO_HAVE_short_compare_and_swap_release + +AO_INLINE int +AO_int_compare_and_swap_acquire(volatile unsigned int *addr, + unsigned int old, unsigned int new_val) +{ + unsigned int oldval; + oldval = _InterlockedCompareExchange_acq(addr, new_val, old); + return (oldval == old); +} + +#define AO_HAVE_int_compare_and_swap_acquire + +AO_INLINE int +AO_int_compare_and_swap_release(volatile unsigned int *addr, + unsigned int old, unsigned int new_val) +{ + unsigned int oldval; + oldval = _InterlockedCompareExchange_rel(addr, new_val, old); + return (oldval == old); +} + +#define AO_HAVE_int_compare_and_swap_release + diff --git a/src/atomic_ops/sysdeps/int_acquire_release_volatile.h b/src/atomic_ops/sysdeps/int_acquire_release_volatile.h new file mode 100644 index 0000000..e0a6ed0 --- /dev/null +++ b/src/atomic_ops/sysdeps/int_acquire_release_volatile.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003-2004 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. + */ + +/* + * This file adds definitions appropriate for environments in which an unsigned + * int volatile load has acquire semantics, and an unsigned short volatile + * store has release semantics. This is true with the standard Itanium ABI. + */ +#if !defined(AO_GCC_BARRIER) +# if defined(__GNUC__) +# define AO_GCC_BARRIER() AO_compiler_barrier() +# else +# define AO_GCC_BARRIER() +# endif +#endif + +AO_INLINE unsigned int +AO_int_load_acquire(volatile unsigned int *p) +{ + unsigned int result = *p; + /* A normal volatile load generates an ld.acq */ + AO_GCC_BARRIER(); + return result; +} +#define AO_HAVE_int_load_acquire + +AO_INLINE void +AO_int_store_release(volatile unsigned int *p, unsigned int val) +{ + AO_GCC_BARRIER(); + /* A normal volatile store generates an st.rel */ + *p = val; +} +#define AO_HAVE_int_store_release + + diff --git a/src/atomic_ops/sysdeps/int_aligned_atomic_load_store.h b/src/atomic_ops/sysdeps/int_aligned_atomic_load_store.h new file mode 100644 index 0000000..fa59656 --- /dev/null +++ b/src/atomic_ops/sysdeps/int_aligned_atomic_load_store.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004 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. + */ + +/* + * Definitions for architecturs on which loads and stores of unsigned int are + * atomic fo all legal alignments. + */ + +AO_INLINE unsigned int +AO_int_load(volatile unsigned int *addr) +{ + assert(((unsigned long)addr & (sizeof(unsigned int) - 1)) == 0); + /* Cast away the volatile for architectures like IA64 where */ + /* volatile adds barrier semantics. */ + return (*(unsigned int *)addr); +} + +#define AO_HAVE_int_load + +AO_INLINE void +AO_int_store(volatile unsigned int *addr, unsigned int new_val) +{ + assert(((unsigned long)addr & (sizeof(unsigned int) - 1)) == 0); + (*(unsigned int *)addr) = new_val; +} + +#define AO_HAVE_int_store + + diff --git a/src/atomic_ops/sysdeps/int_atomic_load_store.h b/src/atomic_ops/sysdeps/int_atomic_load_store.h new file mode 100644 index 0000000..b2a4813 --- /dev/null +++ b/src/atomic_ops/sysdeps/int_atomic_load_store.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * 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. + */ + +/* + * Definitions for architecturs on which loads and stores of unsigned int are + * atomic for all legal alignments. + */ + +AO_INLINE unsigned int +AO_int_load(volatile unsigned int *addr) +{ + /* Cast away the volatile for architectures like IA64 where */ + /* volatile adds barrier semantics. */ + return (*(unsigned int *)addr); +} + +#define AO_HAVE_int_load + +AO_INLINE void +AO_int_store(volatile unsigned int *addr, unsigned int new_val) +{ + (*(unsigned int *)addr) = new_val; +} + +#define AO_HAVE_int_store + + diff --git a/src/atomic_ops/sysdeps/msftc/x86.h b/src/atomic_ops/sysdeps/msftc/x86.h new file mode 100644 index 0000000..eac112c --- /dev/null +++ b/src/atomic_ops/sysdeps/msftc/x86.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2003 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. + */ + +/* The following really assume we have a 486 or better. */ +/* If ASSUME_WINDOWS98 is defined, we assume Windows 98 or newer. */ + +#include "../aligned_atomic_load_store.h" + +/* Real X86 implementations, except for some old WinChips, appear */ +/* to enforce ordering between memory operations, EXCEPT that a later */ +/* read can pass earlier writes, presumably due to the visible */ +/* presence of store buffers. */ +/* We ignore both the WinChips, and the fact that the official specs */ +/* seem to be much weaker (and arguably too weak to be usable). */ + +#include "../ordered_except_wr.h" + +#include "../test_and_set_t_is_ao_t.h" + /* We should use byte-sized test-and-set locations, as with */ + /* gcc. But I couldn't find the appropriate compiler */ + /* intrinsic. - HB */ + +#include <windows.h> + +/* As far as we can tell, the lfence and sfence instructions are not */ +/* currently needed or useful for cached memory accesses. */ + +AO_INLINE AO_t +AO_fetch_and_add1_full (volatile AO_t *p) +{ + return InterlockedIncrement((LONG volatile *)p) - 1; +} + +#define AO_HAVE_fetch_and_add1_full + +AO_INLINE AO_t +AO_fetch_and_sub1_full (volatile AO_t *p) +{ + return InterlockedDecrement((LONG volatile *)p) + 1; +} + +#define AO_HAVE_fetch_and_sub1_full + +AO_INLINE AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t *addr) +{ + return (AO_TS_VAL_t) InterlockedExchange((LONG volatile *)addr, + (LONG)AO_TS_SET); +} + +#define AO_HAVE_test_and_set_full + +#ifdef AO_ASSUME_WINDOWS98 +/* Returns nonzero if the comparison succeeded. */ +AO_INLINE int +AO_compare_and_swap_full(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ +# if 0 + /* Use the pointer variant, since that should always have the right size. */ + /* This seems to fail with VC++ 6 on Win2000 because the routine isn't */ + /* actually there. */ + return InterlockedCompareExchangePointer((PVOID volatile *)addr, + (PVOID)new_val, (PVOID) old) + == (PVOID)old; +# endif + /* FIXME - This is nearly useless on win64. */ + /* Use InterlockedCompareExchange64 for win64? */ + return InterlockedCompareExchange((DWORD volatile *)addr, + (DWORD)new_val, (DWORD) old) + == (DWORD)old; +} + +#define AO_HAVE_compare_and_swap_full +#endif /* ASSUME_WINDOWS98 */ diff --git a/src/atomic_ops/sysdeps/ordered.h b/src/atomic_ops/sysdeps/ordered.h new file mode 100644 index 0000000..2bcd8d8 --- /dev/null +++ b/src/atomic_ops/sysdeps/ordered.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2003 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. + */ + +/* + * These are common definitions for architectures that provide processor + * ordered memory operations. + */ + +#include "ordered_except_wr.h" + +AO_INLINE void +AO_nop_full() +{ + AO_compiler_barrier(); +} + +#define AO_HAVE_nop_full + + diff --git a/src/atomic_ops/sysdeps/ordered_except_wr.h b/src/atomic_ops/sysdeps/ordered_except_wr.h new file mode 100644 index 0000000..b984f0d --- /dev/null +++ b/src/atomic_ops/sysdeps/ordered_except_wr.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * 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. + */ + +/* + * These are common definitions for architectures that provide processor + * ordered memory operations except that a later read may pass an + * earlier write. Real x86 implementations seem to be in this category, + * except apparently for some IDT WinChips, which we ignore. + */ + +AO_INLINE void +AO_nop_write() +{ + AO_compiler_barrier(); + /* sfence according to Intel docs. Pentium 3 and up. */ + /* Unnecessary for cached accesses? */ +} + +#define AO_HAVE_NOP_WRITE + +AO_INLINE void +AO_nop_read() +{ + AO_compiler_barrier(); +} + +#define AO_HAVE_NOP_READ + +#ifdef AO_HAVE_load + +AO_INLINE AO_t +AO_load_read(volatile AO_t *addr) +{ + AO_t result = AO_load(addr); + AO_compiler_barrier(); + return result; +} +#define AO_HAVE_load_read + +#define AO_load_acquire(addr) AO_load_read(addr) +#define AO_HAVE_load_acquire + +#endif /* AO_HAVE_load */ + +#ifdef AO_HAVE_char_load + +AO_INLINE AO_t +AO_char_load_read(volatile unsigned char *addr) +{ + AO_t result = AO_char_load(addr); + AO_compiler_barrier(); + return result; +} +#define AO_HAVE_char_load_read + +#define AO_char_load_acquire(addr) AO_char_load_read(addr) +#define AO_HAVE_char_load_acquire + +#endif /* AO_HAVE_char_load */ + +#ifdef AO_HAVE_short_load + +AO_INLINE AO_t +AO_short_load_read(volatile unsigned short *addr) +{ + AO_t result = AO_short_load(addr); + AO_compiler_barrier(); + return result; +} +#define AO_HAVE_short_load_read + +#define AO_short_load_acquire(addr) AO_short_load_read(addr) +#define AO_HAVE_short_load_acquire + +#endif /* AO_HAVE_short_load */ + +#ifdef AO_HAVE_int_load + +AO_INLINE AO_t +AO_int_load_read(volatile unsigned int *addr) +{ + AO_t result = AO_int_load(addr); + AO_compiler_barrier(); + return result; +} +#define AO_HAVE_int_load_read + +#define AO_int_load_acquire(addr) AO_int_load_read(addr) +#define AO_HAVE_int_load_acquire + +#endif /* AO_HAVE_int_load */ + +#if defined(AO_HAVE_store) + +AO_INLINE void +AO_store_write(volatile AO_t *addr, AO_t val) +{ + AO_compiler_barrier(); + AO_store(addr, val); +} +# define AO_HAVE_store_write + +# define AO_store_release(addr, val) AO_store_write(addr, val) +# define AO_HAVE_store_release + +#endif /* AO_HAVE_store */ + +#if defined(AO_HAVE_char_store) + +AO_INLINE void +AO_char_store_write(volatile unsigned char *addr, unsigned char val) +{ + AO_compiler_barrier(); + AO_char_store(addr, val); +} +# define AO_HAVE_char_store_write + +# define AO_char_store_release(addr, val) AO_char_store_write(addr, val) +# define AO_HAVE_char_store_release + +#endif /* AO_HAVE_char_store */ + +#if defined(AO_HAVE_short_store) + +AO_INLINE void +AO_short_store_write(volatile unsigned short *addr, unsigned short val) +{ + AO_compiler_barrier(); + AO_short_store(addr, val); +} +# define AO_HAVE_short_store_write + +# define AO_short_store_release(addr, val) AO_short_store_write(addr, val) +# define AO_HAVE_short_store_release + +#endif /* AO_HAVE_short_store */ + +#if defined(AO_HAVE_int_store) + +AO_INLINE void +AO_int_store_write(volatile unsigned int *addr, unsigned int val) +{ + AO_compiler_barrier(); + AO_int_store(addr, val); +} +# define AO_HAVE_int_store_write + +# define AO_int_store_release(addr, val) AO_int_store_write(addr, val) +# define AO_HAVE_int_store_release + +#endif /* AO_HAVE_int_store */ + diff --git a/src/atomic_ops/sysdeps/short_acquire_release_volatile.h b/src/atomic_ops/sysdeps/short_acquire_release_volatile.h new file mode 100644 index 0000000..035ada7 --- /dev/null +++ b/src/atomic_ops/sysdeps/short_acquire_release_volatile.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003-2004 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. + */ + +/* + * This file adds definitions appropriate for environments in which an unsigned short + * volatile load has acquire semantics, and an unsigned short volatile store has release + * semantics. This is true with the standard Itanium ABI. + */ +#if !defined(AO_GCC_BARRIER) +# if defined(__GNUC__) +# define AO_GCC_BARRIER() AO_compiler_barrier() +# else +# define AO_GCC_BARRIER() +# endif +#endif + +AO_INLINE unsigned short +AO_short_load_acquire(volatile unsigned short *p) +{ + unsigned short result = *p; + /* A normal volatile load generates an ld.acq */ + AO_GCC_BARRIER(); + return result; +} +#define AO_HAVE_short_load_acquire + +AO_INLINE void +AO_short_store_release(volatile unsigned short *p, unsigned short val) +{ + AO_GCC_BARRIER(); + /* A normal volatile store generates an st.rel */ + *p = val; +} +#define AO_HAVE_short_store_release + + diff --git a/src/atomic_ops/sysdeps/short_aligned_atomic_load_store.h b/src/atomic_ops/sysdeps/short_aligned_atomic_load_store.h new file mode 100644 index 0000000..54ed757 --- /dev/null +++ b/src/atomic_ops/sysdeps/short_aligned_atomic_load_store.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004 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. + */ + +/* + * Definitions for architecturs on which loads and stores of unsigned short are + * atomic fo all legal alignments. + */ + +AO_INLINE unsigned short +AO_short_load(volatile unsigned short *addr) +{ + assert(((unsigned long)addr & (sizeof(unsigned short) - 1)) == 0); + /* Cast away the volatile for architectures like IA64 where */ + /* volatile adds barrier semantics. */ + return (*(unsigned short *)addr); +} + +#define AO_HAVE_short_load + +AO_INLINE void +AO_short_store(volatile unsigned short *addr, unsigned short new_val) +{ + assert(((unsigned long)addr & (sizeof(unsigned short) - 1)) == 0); + (*(unsigned short *)addr) = new_val; +} + +#define AO_HAVE_short_store + + diff --git a/src/atomic_ops/sysdeps/short_atomic_load_store.h b/src/atomic_ops/sysdeps/short_atomic_load_store.h new file mode 100644 index 0000000..f1b5281 --- /dev/null +++ b/src/atomic_ops/sysdeps/short_atomic_load_store.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * 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. + */ + +/* + * Definitions for architecturs on which loads and stores of unsigned short are + * atomic for all legal alignments. + */ + +AO_INLINE unsigned short +AO_short_load(volatile unsigned short *addr) +{ + /* Cast away the volatile for architectures like IA64 where */ + /* volatile adds barrier semantics. */ + return (*(unsigned short *)addr); +} + +#define AO_HAVE_short_load + +AO_INLINE void +AO_short_store(volatile unsigned short *addr, unsigned short new_val) +{ + (*(unsigned short *)addr) = new_val; +} + +#define AO_HAVE_short_store + + diff --git a/src/atomic_ops/sysdeps/standard_ao_double_t.h b/src/atomic_ops/sysdeps/standard_ao_double_t.h new file mode 100644 index 0000000..1d08fc7 --- /dev/null +++ b/src/atomic_ops/sysdeps/standard_ao_double_t.h @@ -0,0 +1,8 @@ +typedef union { + unsigned long long AO_whole; + struct {AO_t AO_v1; AO_t AO_v2;} AO_parts; +} AO_double_t; +#define AO_HAVE_double_t +#define AO_val1 AO_parts.AO_v1 +#define AO_val2 AO_parts.AO_v2 + diff --git a/src/atomic_ops/sysdeps/sunc/sparc.S b/src/atomic_ops/sysdeps/sunc/sparc.S new file mode 100644 index 0000000..81f0ef0 --- /dev/null +++ b/src/atomic_ops/sysdeps/sunc/sparc.S @@ -0,0 +1,5 @@ + .seg "text" + .globl AO_test_and_set_full +AO_test_and_set_full: + retl + ldstub [%o0],%o0 diff --git a/src/atomic_ops/sysdeps/sunc/sparc.h b/src/atomic_ops/sysdeps/sunc/sparc.h new file mode 100644 index 0000000..3578722 --- /dev/null +++ b/src/atomic_ops/sysdeps/sunc/sparc.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2004 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. + */ + +#include "../all_atomic_load_store.h" + +/* Real SPARC code uses TSO: */ +#include "../ordered_except_wr.h" + +/* Test_and_set location is just a byte. */ +#include "../test_and_set_t_is_char.h" + +extern AO_TS_VAL_t +AO_test_and_set_full(volatile AO_TS_t *addr); +/* Implemented in separate .S file, for now. */ + +#define AO_HAVE_test_and_set_full + +/* FIXME: Like the gcc version, this needs to be extended for V8 */ +/* and V9. */ diff --git a/src/atomic_ops/sysdeps/test_and_set_t_is_ao_t.h b/src/atomic_ops/sysdeps/test_and_set_t_is_ao_t.h new file mode 100644 index 0000000..663bccf --- /dev/null +++ b/src/atomic_ops/sysdeps/test_and_set_t_is_ao_t.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004 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. + */ + +/* + * These are common definitions for architectures on which test_and_set + * operates on pointer-sized quantities, the "clear" value contains + * all zeroes, and the "set" value contains all ones. + * This can be used if test_and_set is synthesized from compare_and_swap. + */ +typedef enum {AO_TS_clear = 0, AO_TS_set = 1} AO_TS_val; +#define AO_TS_VAL_t AO_TS_val +#define AO_TS_CLEAR AO_TS_clear +#define AO_TS_SET AO_TS_set + +#define AO_TS_t AO_t + +#define AO_AO_TS_T 1 diff --git a/src/atomic_ops/sysdeps/test_and_set_t_is_char.h b/src/atomic_ops/sysdeps/test_and_set_t_is_char.h new file mode 100644 index 0000000..bde0f21 --- /dev/null +++ b/src/atomic_ops/sysdeps/test_and_set_t_is_char.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2004 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. + */ + +/* + * These are common definitions for architectures on which test_and_set + * operates on byte sized quantities, the "clear" value contains + * all zeroes, and the "set" value contains all ones. + */ + +#define AO_TS_t unsigned char +typedef enum {AO_BYTE_TS_clear = 0, AO_BYTE_TS_set = 0xff} AO_BYTE_TS_val; +#define AO_TS_VAL_t AO_BYTE_TS_val +#define AO_TS_CLEAR AO_BYTE_TS_clear +#define AO_TS_SET AO_BYTE_TS_set + +#define AO_CHAR_TS_T 1 + + + diff --git a/src/atomic_ops_malloc.c b/src/atomic_ops_malloc.c new file mode 100644 index 0000000..dff4908 --- /dev/null +++ b/src/atomic_ops_malloc.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2005 Hewlett-Packard Development Company, L.P. + * Original Author: Hans Boehm + * + * 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 doc/COPYING for more details. + */ + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +#define AO_REQUIRE_CAS +#include "atomic_ops_stack.h" +#include <string.h> /* for ffs, which is assumed reentrant. */ +#include <stdlib.h> +#ifdef AO_TRACE_MALLOC +# include <stdio.h> +# include <pthread.h> +#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; +static volatile char *initial_heap_lim = AO_initial_heap + AO_INITIAL_HEAP_SIZE; + +#if defined(HAVE_MMAP) + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/mman.h> + +static volatile AO_t mmap_enabled = 0; + +void +AO_malloc_enable_mmap(void) +{ + AO_store(&mmap_enabled, 1); +} + +static char *get_mmaped(size_t sz) +{ + char * result; + + assert(!(sz & (CHUNK_SIZE - 1))); + if (!mmap_enabled) return 0; +# if defined(MAP_ANONYMOUS) + result = mmap(0, sz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); +# elif defined(MAP_ANON) + result = mmap(0, sz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); +# else + { + int zero_fd = open("/dev/zero", O_RDONLY); + result = mmap(0, sz, PROT_READ | PROT_WRITE, + MAP_PRIVATE, zero_fd, 0); + 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) +{ +} + +static char *get_mmaped(size_t sz) +{ + return 0; +} + +static char * +AO_malloc_large(size_t sz) +{ + return 0; +} + +static void +AO_free_large(char * p) +{ + abort(); /* Programmer error. Not really async-signal-safe, but ... */ +} + +#endif /* No MMAP */ + +static char * +get_chunk(void) +{ + char *initial_ptr; + char *my_chunk_ptr; + char * my_lim; + +retry: + 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. */ + AO_compare_and_swap_acquire(&initial_heap_ptr, (AO_t)initial_ptr, + (AO_t)my_chunk_ptr); + } + my_lim = my_chunk_ptr + CHUNK_SIZE; + if (my_lim <= initial_heap_lim) + { + if (!AO_compare_and_swap(&initial_heap_ptr, (AO_t)my_chunk_ptr, + (AO_t)my_lim)) + goto retry; + 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]; + +/* Chunk free list, linked through first word in chunks. */ +/* All entries of size CHUNK_SIZE. */ +AO_stack_t AO_chunk_free_list; + +/* Break up the chunk, and add it to the object free list for */ +/* the given size. Sz must be a power of two. */ +/* We have exclusive access to chunk. */ +static void +add_chunk_as(void * chunk, size_t sz, unsigned log_sz) +{ + char *first = (char *)chunk + ALIGNMENT - sizeof(AO_t); + char *limit = (char *)chunk + CHUNK_SIZE - sz; + char *next, *p; + + for (p = first; p <= limit; p = next) { + next = p + sz; + AO_stack_push(AO_free_list+log_sz, (AO_t *)p); + } +} + +static 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. */ +int msb(size_t s) +{ + int result = 0; + if ((s & 0xff) != s) { + /* The following shift often generates warnings on 32-bit arch's */ + /* That's OK, because it will never be executed there. */ + if (sizeof(size_t) > 4 && (s >> 32) != 0) + { + s >>= 32; + 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; + size_t adj_sz = sz + sizeof(AO_t); + int log_sz; + if (sz > CHUNK_SIZE) + return AO_malloc_large(sz); + log_sz = msb(adj_sz-1); + result = AO_stack_pop(AO_free_list+log_sz); + while (0 == result) { + void * chunk = get_chunk(); + if (0 == chunk) return 0; + adj_sz = 1 << log_sz; + add_chunk_as(chunk, adj_sz, 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 = *(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 new file mode 100644 index 0000000..c55d27c --- /dev/null +++ b/src/atomic_ops_malloc.h @@ -0,0 +1,44 @@ +/* + * 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 README.malloc file for detailed usage rules. */ + +#ifndef AO_ATOMIC_H +#define AO_ATOMIC_H + +#include <stdlib.h> /* For size_t */ + +#include "atomic_ops_stack.h" + +#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 mmpa to grow the heap. No-op on some platforms. */ +void AO_malloc_enable_mmap(void); + +#endif /* !AO_ATOMIC_H */ diff --git a/src/atomic_ops_stack.c b/src/atomic_ops_stack.c new file mode 100644 index 0000000..c3df101 --- /dev/null +++ b/src/atomic_ops_stack.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2005 Hewlett-Packard Development Company, L.P. + * Original Author: Hans Boehm + * + * 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 doc/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" + +#if defined(_MSC_VER) \ + || defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) + /* AO_pause not defined elsewhere */ + /* FIXME: At least AO_spin should be factored out. */ +#include <windows.h> + +AO_t dummy; + +/* Spin for 2**n units. */ +static void AO_spin(int n) +{ + int i; + AO_T j = AO_load(&dummy); + + for (i = 0; i < (2 << n); ++i) + { + j *= 5; + j -= 4; + } + AO_store(&dummy, j); +} + +void AO_pause(int n) +{ + if (n < 12) + AO_spin(n); + else + { + DWORD msecs; + + /* Short async-signal-safe sleep. */ + msecs = (n > 18? 100 : (1 << (n - 12))); + Sleep(msecs); + } +} + +#else + +/* AO_pause is available elsewhere */ + +extern void AO_pause(int); + +#endif + +#ifdef AO_USE_ALMOST_LOCK_FREE + +/* LIFO linked lists based on compare-and-swap. We need to avoid */ +/* the case of a node deleton 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) +{ + int i; + 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 + 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_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. + * ince 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 >= 0 && 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 (first != AO_load(list)) { + AO_store_release(a->AO_stack_bl+i, 0); + goto retry; + } + first_ptr = AO_REAL_NEXT_PTR(first); + next = AO_load(first_ptr); + if (!AO_compare_and_swap_release(list, first, next)) { + 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_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 interveining "pop"s and "push"es.*/ + /* Inthat case we still see a change inthe version number. */ +} + +AO_t *AO_stack_pop_acquire(AO_stack_t *list) +{ + AO_t *cptr; + 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_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 new file mode 100644 index 0000000..f0c789b --- /dev/null +++ b/src/atomic_ops_stack.h @@ -0,0 +1,188 @@ +/* + * 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 lecation 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} + +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 {0} + +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/src/atomic_ops_sysdeps.S b/src/atomic_ops_sysdeps.S new file mode 100644 index 0000000..f586f23 --- /dev/null +++ b/src/atomic_ops_sysdeps.S @@ -0,0 +1,9 @@ +/* + * Include the appropriate system-dependent assembly file, if any. + * This is used only if the platform supports neither inline assembly + * code, nor appropriate compiler intrinsics. + */ + +#if !defined(__GNUC__) && (defined(sparc) || defined(__sparc)) +# include "atomic_ops/sysdeps/sunc/sparc.S" +#endif diff --git a/src/config.h.in b/src/config.h.in new file mode 100644 index 0000000..5b61fbd --- /dev/null +++ b/src/config.h.in @@ -0,0 +1,58 @@ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `getpagesize' function. */ +#undef HAVE_GETPAGESIZE + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION |
