Re: page fault scalability patch final : i386 tested, x86_64

Andi Kleen
2004-08-28T13:19:18Z

On Fri, 27 Aug 2004 22:39:54 -0700
Andrew Morton <akpm@osdl.org> wrote:

> Christoph Lameter <clameter@sgi.com> wrote:
> >
> > On Fri, 27 Aug 2004, Andrew Morton wrote:
> >
> > > Christoph Lameter <clameter@sgi.com> wrote:
> > > >
> > > > So I think the move to atomic for rss acceptable?
> > >
> > > Short-term, yes. Longer term (within 12 months), no - 50-bit addresses on
> > > power5 will cause it to overflow.
> >
> > I would expect the page size to rise as well. On IA64 we already have
> > 16KB-64KB pages corresponding to 256TB - 1PB. Having to manage a couple of
> > billion pages could be a significant performance impact. Better increase
> > the page size.
>
> I don't know if that's an option on the power architecture.

On x86-64 it isn't an option.

>
> And we need larger atomic types _anyway_ for page->_count. An unprivileged
> app can mmap the same page 4G times and can then munmap it once. Do it on
> purpose and it's a security hole. Due it by accident and it's a crash.
>
> > I still would also like to see atomic64_t. I think there was a patch
> > posted to linux-ia64 a couple of months back introducing atomic64_t but it
> > was rejected since it would not be supportable on other arches.
>
> atomic64_t already appears to be implemented on alpha, ia64, mips, s390 and
> sparc64.

Here's a patch to add it to x86-64:

-Andi

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

Add atomic64_t type to x86-64

diff -u linux-2.6.8-work/include/asm-x86_64/atomic.h-o linux-2.6.8-work/include/asm-x86_64/atomic.h
--- linux-2.6.8-work/include/asm-x86_64/atomic.h-o 2004-03-21 21:11:54.000000000 +0100
+++ linux-2.6.8-work/include/asm-x86_64/atomic.h 2004-08-28 15:15:46.000000000 +0200
@@ -178,6 +178,166 @@
return c;
}

+/* An 64bit atomic type */
+
+typedef struct { volatile long counter; } atomic64_t;
+
+#define ATOMIC64_INIT(i) { (i) }
+
+/**
+ * atomic64_read - read atomic64 variable
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically reads the value of @v.
+ * Doesn't imply a read memory barrier.
+ */
+#define atomic64_read(v) ((v)->counter)
+
+/**
+ * atomic64_set - set atomic64 variable
+ * @v: pointer to type atomic64_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+#define atomic64_set(v,i) (((v)->counter) = (i))
+
+/**
+ * atomic64_add - add integer to atomic64 variable
+ * @i: integer value to add
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically adds @i to @v.
+ */
+static __inline__ void atomic64_add(long i, atomic64_t *v)
+{
+ __asm__ __volatile__(
+ LOCK "addq %1,%0"
+ :"=m" (v->counter)
+ :"ir" (i), "m" (v->counter));
+}
+
+/**
+ * atomic64_sub - subtract the atomic64 variable
+ * @i: integer value to subtract
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically subtracts @i from @v.
+ */
+static __inline__ void atomic64_sub(long i, atomic64_t *v)
+{
+ __asm__ __volatile__(
+ LOCK "subq %1,%0"
+ :"=m" (v->counter)
+ :"ir" (i), "m" (v->counter));
+}
+
+/**
+ * atomic64_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__(
+ LOCK "subq %2,%0; sete %1"
+ :"=m" (v->counter), "=qm" (c)
+ :"ir" (i), "m" (v->counter) : "memory");
+ return c;
+}
+
+/**
+ * atomic64_inc - increment atomic64 variable
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically increments @v by 1.
+ */
+static __inline__ void atomic64_inc(atomic64_t *v)
+{
+ __asm__ __volatile__(
+ LOCK "incq %0"
+ :"=m" (v->counter)
+ :"m" (v->counter));
+}
+
+/**
+ * atomic64_dec - decrement atomic64 variable
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically decrements @v by 1.
+ */
+static __inline__ void atomic64_dec(atomic64_t *v)
+{
+ __asm__ __volatile__(
+ LOCK "decq %0"
+ :"=m" (v->counter)
+ :"m" (v->counter));
+}
+
+/**
+ * atomic64_dec_and_test - decrement and test
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+static __inline__ int atomic64_dec_and_test(atomic64_t *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__(
+ LOCK "decq %0; sete %1"
+ :"=m" (v->counter), "=qm" (c)
+ :"m" (v->counter) : "memory");
+ return c != 0;
+}
+
+/**
+ * atomic64_inc_and_test - increment and test
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+static __inline__ int atomic64_inc_and_test(atomic64_t *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__(
+ LOCK "incq %0; sete %1"
+ :"=m" (v->counter), "=qm" (c)
+ :"m" (v->counter) : "memory");
+ return c != 0;
+}
+
+/**
+ * atomic64_add_negative - add and test if negative
+ * @v: pointer to atomic64_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+static __inline__ long atomic64_add_negative(long i, atomic64_t *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__(
+ LOCK "addq %2,%0; sets %1"
+ :"=m" (v->counter), "=qm" (c)
+ :"ir" (i), "m" (v->counter) : "memory");
+ return c;
+}
+
/* These are x86-specific, used by some header files */
#define atomic_clear_mask(mask, addr) \
__asm__ __volatile__(LOCK "andl %0,%1" \