Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset cd769305 in mainline


Ignore:
Timestamp:
2009-12-07T21:57:22Z (12 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
216cb85
Parents:
a47d49f
Message:

Implement userspace arm32 cas() and atomic_add() using RAS.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libc/arch/arm32/include/atomic.h

    ra47d49f rcd769305  
    3737#define LIBC_arm32_ATOMIC_H_
    3838
     39#define LIBC_ARCH_ATOMIC_H_
     40#define CAS
     41
     42#include <atomicdflt.h>
    3943#include <bool.h>
     44#include <sys/types.h>
    4045
    41 typedef struct atomic {
    42         volatile long count;
    43 } atomic_t;
    44 
    45 static inline void atomic_set(atomic_t *val, long i)
    46 {
    47         val->count = i;
    48 }
    49 
    50 static inline long atomic_get(atomic_t *val)
    51 {
    52         return val->count;
    53 }
     46extern uintptr_t *ras_page;
    5447
    5548static inline bool cas(atomic_t *val, long ov, long nv)
    5649{
    57         /* FIXME: is not atomic */
    58         if (val->count == ov) {
    59                 val->count = nv;
    60                 return true;
    61         }
    62         return false;
     50        long ret = 0;
     51
     52        /*
     53         * The following instructions between labels 1 and 2 constitute a
     54         * Restartable Atomic Seqeunce. Should the sequence be non-atomic,
     55         * the kernel will restart it.
     56         */
     57        asm volatile (
     58                "1:\n"
     59                "       adr %[ret], 1b\n"
     60                "       str %[ret], %[rp0]\n"
     61                "       adr %[ret], 2f\n"
     62                "       str %[ret], %[rp1]\n"
     63                "       ldr %[ret], %[addr]\n"
     64                "       cmp %[ret], %[ov]\n"
     65                "       streq %[nv], %[addr]\n"
     66                "2:\n"
     67                "       moveq %[ret], #1\n"
     68                "       movne %[ret], #0\n"
     69                : [ret] "+&r" (ret),
     70                  [rp0] "=m" (ras_page[0]),
     71                  [rp1] "=m" (ras_page[1]),
     72                  [addr] "+m" (val->count)
     73                : [ov] "r" (ov),
     74                  [nv] "r" (nv)
     75                : "memory"
     76        );
     77
     78        ras_page[0] = 0;
     79        asm volatile ("" ::: "memory");
     80        ras_page[1] = 0xffffffff;
     81
     82        return (bool) ret;
    6383}
    6484
     
    7292static inline long atomic_add(atomic_t *val, int i)
    7393{
    74         int ret;
    75         volatile long * mem = &(val->count);
     94        long ret = 0;
    7695
    77         /* FIXME: is not atomic, is broken */
     96        /*
     97         * The following instructions between labels 1 and 2 constitute a
     98         * Restartable Atomic Seqeunce. Should the sequence be non-atomic,
     99         * the kernel will restart it.
     100         */
    78101        asm volatile (
    79         "1:\n"
    80                 "ldr r2, [%1]\n"
    81                 "add r3, r2, %2\n"
    82                 "str r3, %0\n"
    83                 "swp r3, r3, [%1]\n"
    84                 "cmp r3, r2\n"
    85                 "bne 1b\n"
     102                "1:\n"
     103                "       adr %[ret], 1b\n"
     104                "       str %[ret], %[rp0]\n"
     105                "       adr %[ret], 2f\n"
     106                "       str %[ret], %[rp1]\n"
     107                "       ldr %[ret], %[addr]\n"
     108                "       add %[ret], %[ret], %[imm]\n"
     109                "       str %[ret], %[addr]\n"
     110                "2:\n"
     111                : [ret] "+&r" (ret),
     112                  [rp0] "=m" (ras_page[0]),
     113                  [rp1] "=m" (ras_page[1]),
     114                  [addr] "+m" (val->count)
     115                : [imm] "r" (i)
     116        );
    86117
    87                 : "=m" (ret)
    88                 : "r" (mem), "r" (i)
    89                 : "r3", "r2"
    90         );
     118        ras_page[0] = 0;
     119        asm volatile ("" ::: "memory");
     120        ras_page[1] = 0xffffffff;
    91121
    92122        return ret;
Note: See TracChangeset for help on using the changeset viewer.