Initial Contribution
diff --git a/libcutils/atomic-android-arm.S b/libcutils/atomic-android-arm.S
new file mode 100644
index 0000000..2a4c34f
--- /dev/null
+++ b/libcutils/atomic-android-arm.S
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * NOTE: these atomic operations are SMP safe on all architectures, 
+ * except swap(), see below.
+ */
+
+	.text
+	.align
+	
+    .global android_atomic_write
+
+	.global android_atomic_inc
+	.global android_atomic_dec
+    
+	.global android_atomic_add
+	.global android_atomic_and
+	.global android_atomic_or
+    
+    .global android_atomic_swap
+	
+	.global android_atomic_cmpxchg
+
+/*
+ * ----------------------------------------------------------------------------
+ * int __kernel_cmpxchg(int oldval, int newval, int *ptr)
+ * clobbered: r3, ip, flags
+ * return 0 if a swap was made, non-zero otherwise.
+ */ 
+
+   .equ     kernel_cmpxchg, 0xFFFF0FC0
+   .equ     kernel_atomic_base, 0xFFFF0FFF
+
+/*
+ * ----------------------------------------------------------------------------
+ * android_atomic_write
+ * input: r0=value, r1=address
+ * output: void
+ */
+ 
+android_atomic_write:
+    stmdb   sp!, {r4, lr}
+    mov     r2, r1
+    mov     r1, r0
+1: @ android_atomic_write
+    ldr     r0, [r2]
+    mov     r3, #kernel_atomic_base
+    add     lr, pc, #4
+    add     pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
+    bcc     1b
+    ldmia   sp!, {r4, lr}
+    bx      lr
+
+/*
+ * ----------------------------------------------------------------------------
+ * android_atomic_inc
+ * input: r0 = address
+ * output: r0 = old value
+ */
+ 
+android_atomic_inc:
+    stmdb   sp!, {r4, lr}
+    mov     r2, r0
+1: @ android_atomic_inc
+    ldr     r0, [r2]
+    mov     r3, #kernel_atomic_base
+    add     lr, pc, #4
+    add     r1, r0, #1
+    add     pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
+    bcc     1b
+    sub     r0, r1, #1
+    ldmia   sp!, {r4, lr}
+    bx      lr
+  
+/*
+ * ----------------------------------------------------------------------------
+ * android_atomic_dec
+ * input: r0=address
+ * output: r0 = old value
+ */
+ 
+android_atomic_dec:
+    stmdb   sp!, {r4, lr}
+    mov     r2, r0
+1: @ android_atomic_dec
+    ldr     r0, [r2]
+    mov     r3, #kernel_atomic_base
+    add     lr, pc, #4
+    sub     r1, r0, #1
+    add     pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
+    bcc     1b
+    add     r0, r1, #1
+    ldmia   sp!, {r4, lr}
+    bx      lr
+    
+/*
+ * ----------------------------------------------------------------------------
+ * android_atomic_add
+ * input: r0=value, r1=address
+ * output: r0 = old value
+ */
+
+android_atomic_add:
+    stmdb   sp!, {r4, lr}
+    mov     r2, r1
+    mov     r4, r0
+1: @ android_atomic_add
+    ldr     r0, [r2]
+    mov     r3, #kernel_atomic_base
+    add     lr, pc, #4
+    add     r1, r0, r4
+    add     pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
+    bcc     1b
+    sub     r0, r1, r4
+    ldmia   sp!, {r4, lr}
+    bx      lr
+    
+    
+/*
+ * ----------------------------------------------------------------------------
+ * android_atomic_and
+ * input: r0=value, r1=address
+ * output: r0 = old value
+ */
+
+android_atomic_and:
+    stmdb   sp!, {r4, r5, lr}   
+    mov     r2, r1              /* r2 = address */
+    mov     r4, r0              /* r4 = the value */
+1: @ android_atomic_and
+    ldr     r0, [r2]            /* r0 = address[0] */
+    mov     r3, #kernel_atomic_base
+    add     lr, pc, #8
+    mov     r5, r0              /* r5 = save address[0] */
+    and     r1, r0, r4          /* r1 = new value */
+    add     pc, r3, #(kernel_cmpxchg - kernel_atomic_base)  /* call cmpxchg() */
+    bcc     1b
+    mov     r0, r5
+    ldmia   sp!, {r4, r5, lr}
+    bx      lr
+    
+/*
+ * ----------------------------------------------------------------------------
+ * android_atomic_or
+ * input: r0=value, r1=address
+ * output: r0 = old value
+ */
+
+android_atomic_or:
+    stmdb   sp!, {r4, r5, lr}   
+    mov     r2, r1              /* r2 = address */
+    mov     r4, r0              /* r4 = the value */
+1: @ android_atomic_or
+    ldr     r0, [r2]            /* r0 = address[0] */
+    mov     r3, #kernel_atomic_base
+    add     lr, pc, #8
+    mov     r5, r0              /* r5 = save address[0] */
+    orr     r1, r0, r4          /* r1 = new value */
+    add     pc, r3, #(kernel_cmpxchg - kernel_atomic_base)  /* call cmpxchg() */
+    bcc     1b
+    mov     r0, r5
+    ldmia   sp!, {r4, r5, lr}
+    bx      lr
+
+/*
+ * ----------------------------------------------------------------------------
+ * android_atomic_swap
+ * input: r0=value, r1=address
+ * output: r0 = old value
+ */
+
+/* FIXME: this is not safe on SMP systems 
+ * a general way to do it is to use kernel_cmpxchg */
+
+android_atomic_swap:
+    swp     r0, r0, [r1]
+    bx      lr
+
+/*
+ * ----------------------------------------------------------------------------
+ * android_atomic_cmpxchg
+ * input: r0=oldvalue, r1=newvalue, r2=address
+ * output: r0 = 0 (xchg done) or non-zero (xchg not done)
+ */
+
+android_atomic_cmpxchg:
+    stmdb   sp!, {r4, lr}
+    mov     r4, r0          /* r4 = save oldvalue */
+1: @ android_atomic_cmpxchg
+    mov     r3, #kernel_atomic_base
+    add     lr, pc, #4
+    mov     r0, r4          /* r0 = oldvalue */
+    add     pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
+    bcs     2f              /* swap was made. we're good, return. */
+    ldr     r3, [r2]        /* swap not made, see if it's because *ptr!=oldvalue */
+    cmp     r3, r4
+    beq     1b
+2: @ android_atomic_cmpxchg
+    ldmia   sp!, {r4, lr}
+    bx      lr
+
+/*
+ * ----------------------------------------------------------------------------
+ * android_atomic_cmpxchg_64
+ * input: r0-r1=oldvalue, r2-r3=newvalue, arg4 (on stack)=address
+ * output: r0 = 0 (xchg done) or non-zero (xchg not done)
+ */
+/* TODO: NEED IMPLEMENTATION FOR THIS ARCHITECTURE */