--- Ice-1.0.1.orig/config/Make.rules 2003-03-07 15:36:40.000000000 +0000 +++ Ice-1.0.1/config/Make.rules 2003-03-07 15:33:19.000000000 +0000 @@ -23,8 +23,17 @@ # Define OPTIMIZE as yes if you want to build with # optimization. Otherwise Ice is build with debug information. # +# SPARC_OPTS is sparc-specific, and should be blank if you are not a sparc. +# For g++, don't use '-mcpu=v9' because under some circumstances it is known +# to generate incorrect code. -#OPTIMIZE = yes +OPTIMIZE = yes +SPARC_OPTS = -pipe -mcpu=v8 -mtune=ultrasparc +# +# On sparc, define this as 'yes' or 'no' +# If not on sparc, define it as something else, like 'nonsparc' +# +USE_SPARC_ASM = yes # # The values below can be overridden by defining them as environment @@ -128,11 +137,25 @@ CXX = c++ CXXFLAGS = -ftemplate-depth-128 -fPIC -Wall +ifeq ($(USE_SPARC_ASM),yes) + CXXFLAGS = -ftemplate-depth-128 -fPIC -Wno-deprecated -fpermissive -DUSE_SPARC_ASM=1 +endif +ifeq ($(USE_SPARC_ASM),no) + CXXFLAGS = -ftemplate-depth-128 -fPIC -Wno-deprecated -fpermissive -DICE_USE_MUTEX_SHARED=1 +endif ifeq ($(OPTIMIZE),yes) - CXXFLAGS := -O2 -DNDEBUG $(CXXFLAGS) + CXXFLAGS := -O2 -DNDEBUG $(SPARC_OPTS) $(CXXFLAGS) else CXXFLAGS := -g $(CXXFLAGS) endif +ifeq ($(USE_SPARC_ASM),yes) + CFLAGS = -O3 -mcpu=v9 -mtune=v9 -pipe -DNDEBUG -fPIC -DUSE_SPARC_ASM=1 + SFLAGS = -O2 -mcpu=v9 -mtune=v9 -fpic +endif +ifeq ($(USE_SPARC_ASM),no) + CFLAGS = -O3 -mcpu=v9 -mtune=v9 -pipe -DNDEBUG -fPIC -DICE_USE_MUTEX_SHARED=1 + SFLAGS = +endif CPPFLAGS = -I$(includedir) $(STLPORT_FLAGS) ICECPPFLAGS = -I$(slicedir) @@ -144,6 +167,7 @@ LIBEXT = so BASELIBS = -lIceUtil -lpthread -luuid $(STLPORT_LIBS) + LIBS = -lIce -ldl -lbz2 $(BASELIBS) SLICE2CPP = $(bindir)/slice2cpp @@ -154,7 +178,7 @@ EVERYTHING = all depend clean install .SUFFIXES: -.SUFFIXES: .cpp .c .o +.SUFFIXES: .cpp .c .S .o .cpp.o: $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $< @@ -162,6 +186,10 @@ .c.o: $(CC) -c $(CPPFLAGS) $(CFLAGS) $< +.S.o: + $(CC) -c $(SFLAGS) $< + + %.$(LIBEXT): %.$(LIBEXT).$(VERSION) rm -f $@ ln -s $(@F).$(VERSION) $@ --- Ice-1.0.1.orig/include/IceUtil/Shared.h 2003-03-07 15:40:22.000000000 +0000 +++ Ice-1.0.1/include/IceUtil/Shared.h 2003-03-07 14:42:22.000000000 +0000 @@ -30,6 +30,51 @@ #if !defined(_WIN32) && !defined(ICE_USE_MUTEX_SHARED) +#if defined(__sparc__) && defined(USE_SPARC_ASM) && defined(__linux__) + +/* Steal assembler code from __KERNEL__ assembler stuff */ +/* Pull in the linux/sparc64 definitions for the implementation */ +extern "C" { +#include +int __atomic_exchange_and_add(atomic_t *v, int i); +} + +#define ice_atomic_t atomic_t +#define ice_atomic_set(v,i) atomic_set(v,i) +#define ice_atomic_inc(v) atomic_inc(v) +#define ice_atomic_dec_and_test(v) atomic_dec_and_test(v) +#define ice_atomic_exchange_add(i,v) (__atomic_exchange_and_add(v,i)) + + +#elif defined(__sparc__) && defined(USE_SPARC_ASM) && !defined(__linux__) + +/* If we happen to be sparc/solaris, the header file we want here would be + * , but beyond that, you are on your own. For example, + * you will end up wanting something like the following untested definitions, + * which are just the same as the linux ones. This assumes, of course, + * that David Miller's assembler code from linux will work on solaris. + */ + +struct atomic_t +{ + volatile int counter; +}; + +extern "C" { + int __atomic_add(int i, atomic_t *v); + int __atomic_sub(int i, atomic_t *v); + int __atomic_exchange_and_add(atomic_t *v, int i); +} + +#define ice_atomic_t atomic_t +#define ice_atomic_set(v, i) (((v)->counter) = i) +#define ice_atomic_inc(v) __atomic_add(1,v) +#define ice_atomic_dec_and_test(v) (__atomic_sub(1, v) == 0) +#define ice_atomic_exchange_add(i,v) (__atomic_exchange_and_add(v,i)) + + +#else /* Either we are not a sparc, or we are not sparc/linux */ + // // Linux only. Unfortunately, asm/atomic.h builds non-SMP safe code // with non-SMP kernels. This means that executables compiled with a @@ -37,7 +82,6 @@ // reference counting on SMP hosts. Therefore the relevent pieces of // atomic.h are more-or-less duplicated. // - /* * Make sure gcc doesn't try to be clever and move things around * on us. We need to use _exactly_ the address the user gave us, @@ -47,7 +91,6 @@ { volatile int counter; }; - /* * ice_atomic_set - set ice_atomic variable * @v: pointer of type ice_atomic_t @@ -116,6 +159,7 @@ return tmp + i; } +#endif /* Whether or not we are an ultrasparc/linux system */ #endif // --- Ice-1.0.1.orig/src/IceUtil/Makefile 2003-03-07 15:41:41.000000000 +0000 +++ Ice-1.0.1/src/IceUtil/Makefile 2003-03-07 13:39:52.000000000 +0000 @@ -35,6 +35,14 @@ include $(top_srcdir)/config/Make.rules +ifeq ($(USE_SPARC_ASM),yes) +ASRC = IceAtomic.c +AOBJ = IceAtomic.o +SRCS := $(SRCS) $(ASRC) +OBJS := $(OBJS) $(AOBJ) +CFLAGS := $(CFLAGS) -fomit-frame-pointer +endif + $(VERSIONED_NAME): $(OBJS) rm -f $@ $(CXX) $(SHLIB_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS) --- Ice-1.0.1.orig/src/IceUtil/IceAtomic.c 2003-03-07 16:15:18.000000000 +0000 +++ Ice-1.0.1/src/IceUtil/IceAtomic.c 2003-03-07 14:30:11.000000000 +0000 @@ -0,0 +1,110 @@ +/* ==Id: atomic.S,v 1.4 2001/11/18 00:12:56 davem Exp == + * atomic.S: These things are too big to do inline. + * + * Copyright (C) 1999 David S. Miller (davem@redhat.com) + */ + +/* Recreated as + * $Id: IceAtomic.c,v 1.4 2003/03/07 14:30:11 fmccor Exp $ + * for use with -Ice-. + * + * Build with + * gcc -shared -o libIceAtomic.so -mcpu=v9 -mtune=v9 IceAtomic.c -fomit-frame-pointer -O2 + * for standalone use, or, better perhaps, as part of libIceUtil.so by + * gcc -c -mcpu=v9 -mtune=v9 IceAtomic.c -fomit-frame-pointer -O2 + * as part of the src/IceUtil build + * +/* Narrative: + * This is the linux kernel code for atomic add, atomic subtract on sparc-v9. In fact, + * although the add/sub routines are typed -void- externally, they actually return + * the result of their operation. + * + * The exchange_and_add is like add, except that it returns the original + * value of the counter (instead of the new one), and for some reason, the + * order of its arguments is reversed. + * + * Here is how I think (all three) work. + * do { + * A. g5 <- value; + * B. g7 <- g5 [+/-] delta; + * C. if (value == g5) swap(g7, value); + * D. } while (g5 != g7); // g5 was original value, g7 is swapped from original value + * // if they are not the same, someone changed the memory + * // copy before the swap, so we start over with a new value + * E. Synchronize_memory_and_data_cache; + * F. return [value+delta | value - delta | value] depending on add/sub/exchange_add. + * + * Notice that step -C.- is an indivisible operation, so everything is good coming + * out. The entire operation can be retried of between -A.- and start of -C.- someone + * else changes the counter variable. The point is that you get a -coherent- result + * (which is to say, you don't operate on a stale counter value, and so replace it + * with something wrong for everyone). You might not be operating on the values + * at call. To do that, put global Mutex around the call itself. + * + * WARNINGS: + * Do NOT put these in a header file for inlining. You will get bus errors, + * or the results will be wrong if you don't. + * + * Do NOT use these on Sparc 2, 5, 10, 20 etc. The instructions are + * sparc-version 9. + * + * These are written for sparc(v9)-linux-gcc. I have no idea what they will do + * with Solaris or with other compilers. + * + * I do not know if these work in general; I am not a sparc architect. + * + * -- + * Ferris McCormick + * 06.iii.03 + */ + +typedef struct {volatile int counter;} atomic_t; + +int __atomic_add(int i, atomic_t* v) { + __asm__ __volatile__ ( +"1: lduw [%o1], %g5\n" +" add %g5, %o0, %g7\n" +" cas [%o1], %g5, %g7\n" +" cmp %g5, %g7\n" +" bne,pn %icc, 1b\n" +" membar #StoreLoad | #StoreStore\n" +" retl\n" +" add %g7, %o0, %o0\n" + ); + return; /* Not Reached */ +} + +int __atomic_sub(int i, atomic_t *v) { + __asm__ __volatile__ ( +"1: lduw [%o1], %g5\n" +" sub %g5, %o0, %g7\n" +" cas [%o1], %g5, %g7\n" +" cmp %g5, %g7\n" +" bne,pn %icc, 1b\n" +" membar #StoreLoad | #StoreStore\n" +" retl\n" +" sub %g7, %o0, %o0\n" + ); + return; /* Not Reached */ +} +int __atomic_exchange_and_add(atomic_t *v, int i) { +#if 0 + int t2; + t2 = v->counter; + __atomic_add(i,v); + return t2; /* Of course, this is wrong because counter might change + after the assignment to t2 but before the add */ +#else /* This is what we actually do */ + __asm__ __volatile__ ( +"1: lduw [%o0], %g5\n" +" add %g5, %o1, %g7\n" +" cas [%o0], %g5, %g7\n" +" cmp %g5, %g7\n" +" bne,pn %icc, 1b\n" +" membar #StoreLoad | #StoreStore\n" +" retl\n" +" mov %g7, %o0\n" + ); + return; /* Not Reached */ +#endif +} --- Ice-1.0.1.orig/src/icecpp/config.h 2003-02-23 21:01:17.000000000 +0000 +++ Ice-1.0.1/src/icecpp/config.h 2003-03-06 15:50:57.000000000 +0000 @@ -53,6 +53,8 @@ # define WCHAR_TYPE_SIZE 2 #elif (defined(__linux__) || defined(__FreeBSD__)) && defined(i386) # define WCHAR_TYPE_SIZE 4 +#elif (defined(__sparc__) || defined(__sparc64__) || defined(__sparc_v9__)) +# define WCHAR_TYPE_SIZE 4 #else # error "unsupported operating system or platform" #endif