dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dotgnu-pnet-commits] [SCM] DotGNU Portable.NET engine, compilers and to


From: Klaus Treichel
Subject: [dotgnu-pnet-commits] [SCM] DotGNU Portable.NET engine, compilers and tools (pnet) branch, master, updated. d6b8eb60db08ccc275e66fd8f3506f347ba6e000
Date: Thu, 10 Sep 2009 13:20:40 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "DotGNU Portable.NET engine, compilers and tools (pnet)".

The branch, master has been updated
       via  d6b8eb60db08ccc275e66fd8f3506f347ba6e000 (commit)
      from  f786df20e8e25a80b936eb4211e98268197ec3d6 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit/pnet.git/commit/?id=d6b8eb60db08ccc275e66fd8f3506f347ba6e000

commit d6b8eb60db08ccc275e66fd8f3506f347ba6e000
Author: Klaus Treichel <address@hidden>
Date:   Thu Sep 10 15:20:19 2009 +0200

    Change internal organization of the interlocked functions and add
    some more for addition, substraction logical and and or.

diff --git a/ChangeLog b/ChangeLog
index e06fb31..825ec6c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2009-09-10  Klaus Treichel  <address@hidden>
+
+       Change internal organization of the interlocked functions.
+
+       * support/interlocked.h: Add documentation notes for the implemented
+       functions.
+
+       * support/interlocked_any.h (ILInterlockedAdd): Add generic function
+       for an atomic addition of two 32 bit integers.
+       (ILInterlockedAnd): Add generic function for an atomic bitwise and of
+       two 32 bit integers.
+       (ILInterlockedSub): Add convinience macro for subtraction of two
+       32 bit integers using ILInterlockedAdd.
+       (ILInterlockedOr): Add generic function for an atomic bitwise or of
+       two 32 bit integers.
+       (ILInterlockedIncrement): Change to a macro using ILInterlockedAdd.
+       (ILInterlockedDecrement): Change to a macro using ILInterlockedSub.
+
+       * support/interlocked_x86.h (ILInterlockedIncrement): Change to more
+       general function ILInterlockedAdd with an additional increment value
+       argument.
+       (ILInterlockedAnd): Add x86 version for an atomic bitwise and of two
+       32 bit integers.
+       (ILInterlockedOr): Add x86 version for an atomic bitwise or of two
+       32 bit integers.
+
 2009-09-08  Klaus Treichel  <address@hidden>
 
        * engine/cvm.c: Add support for restoring the interpreter state after
diff --git a/support/interlocked.h b/support/interlocked.h
index cd201e4..b199dae 100644
--- a/support/interlocked.h
+++ b/support/interlocked.h
@@ -1,7 +1,7 @@
 /*
  * interlocked.h - Implementation of interlocked functions.
  *
- * Copyright (C) 2002  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2002, 2009  Southern Storm Software, Pty Ltd.
  *
  * Authors: Thong Nguyen (address@hidden)
  *
@@ -24,15 +24,99 @@
 #define _INTERLOCKED_H_
 
 #ifndef IL_INLINE
-       #ifdef __GNUC__
-               #define IL_INLINE       __inline__
-       #elif defined(_MSC_VER)
-               #define IL_INLINE       __forceinline
-       #else
-               #define IL_INLINE
+       #ifdef __GNUC__
+               #define IL_INLINE       __inline__
+       #elif defined(_MSC_VER)
+               #define IL_INLINE       __forceinline
+       #else
+               #define IL_INLINE
        #endif
 #endif
 
+/*
+ * NOTE: The identifier after define: has to be defined if an arch specific
+ * version of this function is available.
+ *
+ * Implemented functions:
+ *
+ * Flush cache and set a memory barrier.
+ * define: IL_HAVE_INTERLOCKED_MEMORYBARRIER
+ *
+ * void ILInterlockedMemoryBarrier(void)
+ *
+ * Exchange integers.
+ * Returns the original value at *dest.
+ * define: IL_HAVE_INTERLOCKED_EXCHANGE
+ *
+ * ILInt32 ILInterlockedExchange(ILInt32 *dest, ILInt32 value)
+ *
+ * Exchange pointers.
+ * Returns the original value at *dest 
+ * define: IL_HAVE_INTERLOCKED_EXCHANGEPOINTERS
+ *
+ * void *ILInterlockedExchangePointers(void **dest, void *value)
+ *
+ * Compare and exchange two 32bit integers.
+ * Returns the original value at *dest 
+ * define: IL_HAVE_INTERLOCKED_COMPAREANDEXCHANGE
+ *
+ * ILInt32 ILInterlockedCompareAndExchange(ILInt32 *dest, ILInt32 value,
+ *                                                                             
   ILInt32 comparand)
+ *
+ * Compare and exchange two pointers.
+ * Returns the original value at *dest 
+ * define: IL_HAVE_INTERLOCKED_COMPAREANDEXCHANGEPOINTERS
+ * 
+ * void *ILInterlockedCompareAndExchangePointers(void **dest, void *value,
+ *                                                                             
                 void *comparand)
+ *
+ * Add the 32 bit values *dest and value and store the result at *dest.
+ * Returns the result od the addition (new value at *dest)
+ * define: IL_HAVE_INTERLOCKED_ADD
+ *
+ * ILInt32 ILInterlockedAdd(ILInt32 *dest, ILInt32 value)
+ *
+ * Substract the 32 bit values *dest and value and store the result at *dest.
+ * Returns the result od the subtraction (new value at *dest)
+ * define: IL_HAVE_INTERLOCKED_SUB
+ *
+ * ILInt32 ILInterlockedSub(ILInt32 *dest, ILInt32 value)
+ *
+ * NOTE: If not defined by the arch specific definition it is a implemented
+ * by a macro that is using ILInterlockedAdd with value negated.
+ * (See interlocked_any.h)
+ *
+ * Increment a 32bit integer.
+ * Returns the value of the incremented integer.
+ * define: IL_HAVE_INTERLOCKED_INCREMENT
+ *
+ * ILInt32 ILInterlockedIncrement(ILInt32 *dest)
+ *
+ * NOTE: If not defined by the arch specific definition it is a implemented
+ * by a macro that is using ILInterlockedAdd with a value of 1.
+ * (See interlocked_any.h)
+ *
+ * Decrement a 32bit integer.
+ * Returns the value of the decremented integer.
+ * define: IL_HAVE_INTERLOCKED_DECREMENT
+ *
+ * ILInt32 ILInterlockedDecrement(ILInt32 *dest)
+ *
+ * NOTE: If not defined by the arch specific definition it is a implemented
+ * by a macro that is using ILInterlockedSub with a value of 1.
+ * (See interlocked_any.h)
+ *
+ * Bitwise AND of *dest and value and the result is stored at *dest
+ * define: IL_HAVE_INTERLOCKED_AND
+ *
+ * void ILInterlockedAnd(volatile ILUInt32 *dest, ILUInt32 value)
+ *
+ * Bitwise OR of *dest and value and the result is stored at *dest
+ * define: IL_HAVE_INTERLOCKED_OR
+ *
+ * void ILInterlockedAnd(volatile ILUInt32 *dest, ILUInt32 value)
+ */
+
 /* TODO: implement native interlocked functions for other processors */
 
 #include "interlocked_x86.h"
diff --git a/support/interlocked_any.h b/support/interlocked_any.h
index 15de2c4..a5a8808 100644
--- a/support/interlocked_any.h
+++ b/support/interlocked_any.h
@@ -1,7 +1,7 @@
 /*
  * interlocked_any.h - Generic implementation of interlocked functions
  *
- * Copyright (C) 2002  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2002, 2009  Southern Storm Software, Pty Ltd.
  *
  * Authors: Thong Nguyen (address@hidden)
  *
@@ -20,128 +20,183 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#if !defined(IL_HAVE_INTERLOCK)
-
-#define IL_HAVE_INTERLOCK 1
-
-/*
-* Flush cache and set a memory barrier.
-*/
-static IL_INLINE void ILInterlockedMemoryBarrier()
-{
-       ILThreadAtomicStart();
-       ILThreadAtomicEnd();
-}
-
+#if !defined(IL_HAVE_INTERLOCKED_MEMORYBARRIER)
 /*
- * Compare and exchange two 32bit integers.
+ * Flush cache and set a memory barrier.
  */
-static IL_INLINE ILInt32 ILInterlockedCompareAndExchange(ILInt32 *destination, 
ILInt32 value,
-                                                                               
                                        ILInt32 comparand)
+static IL_INLINE void ILInterlockedMemoryBarrier()
 {
-       ILInt32 retval;
-       
        ILThreadAtomicStart();
-       
-       retval = *destination;
-       
-       if (retval == comparand)
-       {
-               *destination = value;
-       }
-       
        ILThreadAtomicEnd();
-       
-       return retval;
 }
+#endif /* !defined(IL_HAVE_INTERLOCKED_MEMORYBARRIER) */
 
+#if !defined(IL_HAVE_INTERLOCKED_EXCHANGE)
 /*
- * Increment a 32bit integer.
+ * Exchange integers.
  */
-static IL_INLINE ILInt32 ILInterlockedIncrement(ILInt32 *destination)
+static IL_INLINE ILInt32 ILInterlockedExchange(volatile ILInt32 *dest,
+                                                                               
           ILInt32 value)
 {
-       int retval;
+       ILInt32 retval;
 
        ILThreadAtomicStart();
 
-       retval = ++(*destination);
+       retval = *dest;
+       *dest = value;
 
        ILThreadAtomicEnd();
 
-       return retval;  
+       return retval;
 }
+#endif /* !defined(IL_HAVE_INTERLOCKED_EXCHANGE) */
 
+#if !defined(IL_HAVE_INTERLOCKED_EXCHANGEPOINTERS)
 /*
- * Decrement a 32bit integer.
+ * Exchange pointers.
  */
-static IL_INLINE ILInt32 ILInterlockedDecrement(ILInt32 *destination)
+static IL_INLINE void *ILInterlockedExchangePointers(void * volatile *dest,
+                                                                               
                         void *value)
 {
-       int retval;
-
+       void *retval;
+               
        ILThreadAtomicStart();
-
-       retval = --(*destination);
-
+       
+       retval = *dest;
+       *dest = value;
+       
        ILThreadAtomicEnd();
-
+       
        return retval;
 }
+#endif /* !defined(IL_HAVE_INTERLOCKED_EXCHANGEPOINTERS) */
 
+#if !defined(IL_HAVE_INTERLOCKED_COMPAREANDEXCHANGE)
 /*
- * Exchange integers.
+ * Compare and exchange two 32bit integers.
  */
-static IL_INLINE ILInt32 ILInterlockedExchange(ILInt32 *destination, ILInt32 
value)
+static IL_INLINE ILInt32 ILInterlockedCompareAndExchange(volatile ILInt32 
*dest,
+                                                                               
                                 ILInt32 value,
+                                                                               
                                 ILInt32 comparand)
 {
-       int retval;
-
+       ILInt32 retval;
+       
        ILThreadAtomicStart();
-
-       retval = *destination;
-       *destination = value;
-
+       
+       retval = *dest;
+       
+       if (retval == comparand)
+       {
+               *dest = value;
+       }
+       
        ILThreadAtomicEnd();
-
+       
        return retval;
 }
+#endif /* !defined(IL_HAVE_INTERLOCKED_COMPAREANDEXCHANGE) */
 
+#if !defined(IL_HAVE_INTERLOCKED_COMPAREANDEXCHANGEPOINTERS)
 /*
  * Compare and exchange two pointers.
  */
-static IL_INLINE void *ILInterlockedCompareAndExchangePointers(void 
**destination, void *value,
-                                                                               
                                                void *comparand)
+static IL_INLINE void *ILInterlockedCompareAndExchangePointers(void * volatile 
*dest,
+                                                                               
                                           void *value,
+                                                                               
                                           void *comparand)
 {
        void *retval;
                
        ILThreadAtomicStart();
        
-       retval = *destination;
+       retval = (void *)*dest;
        
        if (retval == comparand)
        {
-               *destination = value;
+               *dest = value;
        }
        
        ILThreadAtomicEnd();
        
        return retval;
 }
+#endif /* !defined(IL_HAVE_INTERLOCKED_COMPAREANDEXCHANGEPOINTERS) */
 
+#if !defined(IL_HAVE_INTERLOCKED_ADD)
 /*
- * Exchange pointers.
+ * Add the two 32bit integers *dest and value and store the result at *dest.
  */
-static IL_INLINE void *ILInterlockedExchangePointers(void **destination, void 
*value)
+static IL_INLINE ILInt32 ILInterlockedAdd(volatile ILInt32 *dest,
+                                                                               
  ILInt32 value)
 {
-       void *retval;
-               
+       ILInt32 retval;
+
        ILThreadAtomicStart();
-       
-       retval = *destination;  
-       *destination = value;
-       
+
+       retval = *dest + value;
+       *dest = retval;
+
        ILThreadAtomicEnd();
-       
-       return retval;
+
+       return retval;  
 }
+#endif /* !defined(IL_HAVE_INTERLOCKED_ADD) */
 
+#if !defined(IL_HAVE_INTERLOCKED_SUB)
+/*
+ * Subtract value from *dest and store the result at *dest.
+ */
+#define ILInterlockedSub(dest, value)  ILInterlockedAdd((dest), -(value))
+#if defined(IL_HAVE_INTERLOCKED_ADD)
+#define IL_HAVE_INTERLOCKED_SUB 1
+#endif
+#endif /* !defined(IL_HAVE_INTERLOCKED_SUB) */
+
+#if !defined(IL_HAVE_INTERLOCKED_INCREMENT)
+/*
+ * Increment a 32bit integer.
+ */
+#define ILInterlockedIncrement(dest) ILInterlockedAdd((dest), 1)
+#if defined(IL_HAVE_INTERLOCKED_ADD)
+#define IL_HAVE_INTERLOCKED_INCREMENT 1
 #endif
+#endif /* !defined(IL_HAVE_INTERLOCKED_INCREMENT) */
 
+#if !defined(IL_HAVE_INTERLOCKED_DECREMENT)
+/*
+ * Decrement a 32bit integer.
+ */
+#define ILInterlockedDecrement(dest)   ILInterlockedSub((dest), 1)
+#if defined(IL_HAVE_INTERLOCKED_SUB)
+#define IL_HAVE_INTERLOCKED_DECREMENT 1
+#endif
+#endif /* !defined(IL_HAVE_INTERLOCKED_DECREMENT) */
+
+#if !defined(IL_HAVE_INTERLOCKED_AND)
+/*
+ * Atomic bitwise AND of unsigned 32 bit values
+ */
+static IL_INLINE void ILInterlockedAnd(volatile ILUInt32 *dest,
+                                                                          
ILUInt32 value)
+{
+       ILThreadAtomicStart();
+
+       *dest &= value;
+
+       ILThreadAtomicEnd();
+}
+#endif /* !defined(IL_HAVE_INTERLOCKED_AND) */
+
+#if !defined(IL_HAVE_INTERLOCKED_OR)
+/*
+ * Atomic bitwise OR of unsigned 32 bit values
+ */
+static IL_INLINE void ILInterlockedOr(volatile ILUInt32 *dest,
+                                                                         
ILUInt32 value)
+{
+       ILThreadAtomicStart();
+
+       *dest |= value;
+
+       ILThreadAtomicEnd();
+}
+#endif /* !defined(IL_HAVE_INTERLOCKED_OR) */
diff --git a/support/interlocked_x86.h b/support/interlocked_x86.h
index af9231c..40171d7 100644
--- a/support/interlocked_x86.h
+++ b/support/interlocked_x86.h
@@ -2,7 +2,7 @@
  * interlocked_x86.h - Implementation of interlocked functions for
  * intel processors.
  *
- * Copyright (C) 2002  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2002, 2009  Southern Storm Software, Pty Ltd.
  *
  * Authors: Thong Nguyen (address@hidden)
  *
@@ -21,93 +21,108 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#if !defined(IL_HAVE_INTERLOCK) \
-       && ((defined(__i386) || defined(__i386__) || defined(__x86_64__)) \
-       && defined(__GNUC__))
+#if (defined(__i386) || defined(__i386__) || defined(__x86_64__))
 
-#define IL_HAVE_INTERLOCK 1
+#if defined(__GNUC__)
 
 /*
- * Compare and exchange two 32bit integers.
+ * Flush cache and set a memory barrier.
  */
-
-static IL_INLINE ILInt32 ILInterlockedCompareAndExchange(ILInt32 *destination, 
ILInt32 value,
-                                                                               
ILInt32 comparand)
+static IL_INLINE void ILInterlockedMemoryBarrier()
 {
-       ILInt32 retval;
-
+#if defined(__SSE2__) || defined(__sse2__)
        __asm__ __volatile__
        (
-               "lock;"
-               "cmpxchgl %2, %0"
-               : "=m" (*destination), "=a" (retval)
-               : "r" (value), "m" (*destination), "a" (comparand)
+               "mfence"
+               :::
+               "memory"
        );
-
-       return retval;
+#else
+       __asm__ __volatile__
+       (
+               "lock; addl $0,0(%%esp)"
+               :::
+               "memory"
+       );
+#endif
 }
+#define IL_HAVE_INTERLOCKED_MEMORYBARRIER 1
 
 /*
- * Increment a 32bit integer.
+ * Exchange two 32 bit integers.
  */
-static IL_INLINE ILInt32 ILInterlockedIncrement(ILInt32 *destination)
+static IL_INLINE ILInt32 ILInterlockedExchange(volatile ILInt32 *dest,
+                                                                               
           ILInt32 value)
 {
        ILInt32 retval;
 
        __asm__ __volatile__ 
        (
+               "1:;"
                "lock;"
-               "xaddl %0, %1"
-               : "=r" (retval), "=m" (*destination)
-               : "0" (1), "m" (*destination)
+               "cmpxchgl %2, %0;"
+               "jne 1b"
+               : "=m" (*dest), "=a" (retval)
+               : "r" (value), "m" (*dest), "a" (*dest)
        );
 
-       return retval + 1;
+       return retval;
 }
+#define IL_HAVE_INTERLOCKED_EXCHANGE 1
 
 /*
- * Decrement a 32bit integer.
+ * Exchange pointers.
  */
-static IL_INLINE ILInt32 ILInterlockedDecrement(ILInt32 *destination)
+static IL_INLINE void *ILInterlockedExchangePointers(void * volatile *dest,
+                                                                               
                         void *value)
 {
-       ILInt32 retval;
+       void *retval;
 
        __asm__ __volatile__ 
        (
+               "1:;"
                "lock;"
-               "xaddl %0, %1"
-               : "=r" (retval), "=m" (*destination)
-               : "0" (-1), "m" (*destination)
+#if defined(__x86_64__)
+               "cmpxchgq %2, %0;"
+#else
+               "cmpxchgl %2, %0;"
+#endif
+               "jne 1b"
+               : "=m" (*dest), "=a" (retval)
+               : "r" (value), "m" (*dest), "a" (*dest)
        );
 
-       return retval - 1;
+       return retval;
 }
+#define IL_HAVE_INTERLOCKED_EXCHANGEPOINTERS 1
 
 /*
- * Exchange integers.
+ * Compare and exchange two 32bit integers.
  */
-static IL_INLINE ILInt32 ILInterlockedExchange(ILInt32 *destination, ILInt32 
value)
+static IL_INLINE ILInt32 ILInterlockedCompareAndExchange(volatile ILInt32 
*dest,
+                                                                               
                                 ILInt32 value,
+                                                                               
                                 ILInt32 comparand)
 {
        ILInt32 retval;
 
-       __asm__ __volatile__ 
+       __asm__ __volatile__
        (
-               "1:;"
                "lock;"
-               "cmpxchgl %2, %0;"
-               "jne 1b"
-               : "=m" (*destination), "=a" (retval)
-               : "r" (value), "m" (*destination), "a" (*destination)
+               "cmpxchgl %2, %0"
+               : "=m" (*dest), "=a" (retval)
+               : "r" (value), "m" (*dest), "a" (comparand)
        );
 
        return retval;
 }
+#define IL_HAVE_INTERLOCKED_COMPAREANDEXCHANGE 1
 
 /*
  * Compare and exchange two pointers.
  */
-static IL_INLINE void *ILInterlockedCompareAndExchangePointers(void 
**destination, void *value,
-                                                                               
          void *comparand)
+static IL_INLINE void *ILInterlockedCompareAndExchangePointers(void * volatile 
*dest,
+                                                                               
                                           void *value,
+                                                                               
                                           void *comparand)
 {
        void *retval;
 
@@ -119,57 +134,64 @@ static IL_INLINE void 
*ILInterlockedCompareAndExchangePointers(void **destinatio
 #else
                "cmpxchgl %2, %0;"
 #endif
-               : "=m" (*destination), "=a" (retval)
-               : "r" (value), "m" (*destination), "a" (comparand)
+               : "=m" (*dest), "=a" (retval)
+               : "r" (value), "m" (*dest), "a" (comparand)
        );
 
        return retval;
 }
+#define IL_HAVE_INTERLOCKED_COMPAREANDEXCHANGEPOINTERS 1
 
 /*
- * Exchange pointers.
+ * Add two 32 bit integer values.
  */
-static IL_INLINE void *ILInterlockedExchangePointers(void **destination, void 
*value)
+static IL_INLINE ILInt32 ILInterlockedAdd(volatile ILInt32 *dest,
+                                                                               
 ILInt32 value)
 {
-       void *retval;
+       ILInt32 retval;
 
        __asm__ __volatile__ 
        (
-               "1:;"
                "lock;"
-#if defined(__x86_64__)
-               "cmpxchgq %2, %0;"
-#else
-               "cmpxchgl %2, %0;"
-#endif
-               "jne 1b"
-               : "=m" (*destination), "=a" (retval)
-               : "r" (value), "m" (*destination), "a" (*destination)
+               "xaddl %0, %1"
+               : "=r" (retval), "=m" (*dest)
+               : "0" (value), "m" (*dest) : "memory"
        );
 
-       return retval;
+       return retval + value;
 }
+#define IL_HAVE_INTERLOCKED_ADD 1
 
 /*
- * Flush cache and set a memory barrier.
+ * 32bit bitwise AND
  */
-static IL_INLINE void ILInterlockedMemoryBarrier()
+static IL_INLINE void ILInterlockedAnd(volatile ILUInt32 *dest, ILUInt32 value)
 {
-#if defined(__SSE2__) || defined(__sse2__)
-       __asm__ __volatile__
+       __asm__ __volatile__ 
        (
-               "mfence"
-               :::
-               "memory"
-       );
-#else
-       __asm__ __volatile__
+               "lock;"
+               "andl %1, %0"
+               : "=m" (*dest)
+               : "r" (value), "m" (*dest)
+               : "memory");
+}
+#define IL_HAVE_INTERLOCKED_AND 1
+
+/*
+ * 32bit bitwise OR
+ */
+static IL_INLINE void ILInterlockedOr(volatile ILUInt32 *dest, ILUInt32 value)
+{
+       __asm__ __volatile__ 
        (
-               "lock; addl $0,0(%%esp)"
-               :::
-               "memory"
-       );
-#endif
+               "lock;"
+               "orl %1, %0"
+               : "=m" (*dest)
+               : "r" (value), "m" (*dest)
+               : "memory");
 }
+#define IL_HAVE_INTERLOCKED_OR 1
 
-#endif
+#endif /* defined(__GNUC__) */
+
+#endif /* (defined(__i386) || defined(__i386__) || defined(__x86_64__)) */

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                 |   26 ++++++
 support/interlocked.h     |   98 ++++++++++++++++++++++--
 support/interlocked_any.h |  185 +++++++++++++++++++++++++++++----------------
 support/interlocked_x86.h |  164 +++++++++++++++++++++++-----------------
 4 files changed, 330 insertions(+), 143 deletions(-)


hooks/post-receive
-- 
DotGNU Portable.NET engine, compilers and tools (pnet)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]