LCOV - code coverage report
Current view: top level - crtools/include - lock.h (source / functions) Hit Total Coverage
Test: crtools.info Lines: 32 36 88.9 %
Date: 2012-12-28 Functions: 7 8 87.5 %
Branches: 13 22 59.1 %

           Branch data     Line data    Source code
       1                 :            : #ifndef __CR_LOCK_H__
       2                 :            : #define __CR_LOCK_H__
       3                 :            : 
       4                 :            : #include <linux/futex.h>
       5                 :            : #include <sys/time.h>
       6                 :            : #include <limits.h>
       7                 :            : #include <errno.h>
       8                 :            : 
       9                 :            : #include "types.h"
      10                 :            : #include "atomic.h"
      11                 :            : #include "syscall.h"
      12                 :            : #include "util.h"
      13                 :            : 
      14                 :            : typedef struct {
      15                 :            :         atomic_t raw;
      16                 :            : } futex_t;
      17                 :            : 
      18                 :            : #define FUTEX_ABORT_FLAG        (0x80000000)
      19                 :            : #define FUTEX_ABORT_RAW         (-1U)
      20                 :            : 
      21                 :            : /* Get current futex @f value */
      22                 :            : static inline u32 futex_get(futex_t *f)
      23                 :            : {
      24                 :       1024 :         return atomic_get(&f->raw);
      25                 :            : }
      26                 :            : 
      27                 :            : /* Set futex @f value to @v */
      28                 :            : static inline void futex_set(futex_t *f, u32 v)
      29                 :            : {
      30                 :       7364 :         atomic_set(&f->raw, v);
      31                 :            : }
      32                 :            : 
      33                 :            : #define futex_init(f)   futex_set(f, 0)
      34                 :            : 
      35                 :            : /* Wait on futex @__f value @__v become in condition @__c */
      36                 :            : #define futex_wait_if_cond(__f, __v, __cond)                    \
      37                 :            :         do {                                                    \
      38                 :            :                 int ret;                                        \
      39                 :            :                 u32 tmp;                                        \
      40                 :            :                                                                 \
      41                 :            :                 while (1) {                                     \
      42                 :            :                         tmp = atomic_get(&(__f)->raw);                   \
      43                 :            :                         if ((tmp & FUTEX_ABORT_FLAG) ||             \
      44                 :            :                             (tmp __cond (__v)))                 \
      45                 :            :                                 break;                          \
      46                 :            :                         ret = sys_futex(&(__f)->raw.counter, FUTEX_WAIT,\
      47                 :            :                                         tmp, NULL, NULL, 0);    \
      48                 :            :                         BUG_ON(ret < 0 && ret != -EWOULDBLOCK);      \
      49                 :            :                 }                                               \
      50                 :            :         } while (0)
      51                 :            : 
      52                 :            : /* Set futex @f to @v and wake up all waiters */
      53                 :       1225 : static inline void futex_set_and_wake(futex_t *f, u32 v)
      54                 :            : {
      55                 :       1225 :         atomic_set(&f->raw, v);
      56         [ -  + ]:       1225 :         BUG_ON(sys_futex(&f->raw.counter, FUTEX_WAKE, INT_MAX, NULL, NULL, 0) < 0);
      57                 :       1225 : }
      58                 :            : 
      59                 :            : /* Mark futex @f as wait abort needed and wake up all waiters */
      60                 :          0 : static inline void futex_abort_and_wake(futex_t *f)
      61                 :            : {
      62                 :            :         BUILD_BUG_ON(!(FUTEX_ABORT_RAW & FUTEX_ABORT_FLAG));
      63                 :          0 :         futex_set_and_wake(f, FUTEX_ABORT_RAW);
      64                 :          0 : }
      65                 :            : 
      66                 :            : /* Decrement futex @f value and wake up all waiters */
      67                 :        722 : static inline void futex_dec_and_wake(futex_t *f)
      68                 :            : {
      69                 :        722 :         atomic_dec(&f->raw);
      70         [ -  + ]:        722 :         BUG_ON(sys_futex(&f->raw.counter, FUTEX_WAKE, INT_MAX, NULL, NULL, 0) < 0);
      71                 :        722 : }
      72                 :            : 
      73                 :            : /* Plain increment futex @f value */
      74                 :         76 : static inline void futex_inc(futex_t *f) { atomic_inc(&f->raw); }
      75                 :            : 
      76                 :            : /* Plain decrement futex @f value */
      77                 :         38 : static inline void futex_dec(futex_t *f) { atomic_dec(&f->raw); }
      78                 :            : 
      79                 :            : /* Wait until futex @f value become @v */
      80                 :        215 : static inline void futex_wait_until(futex_t *f, u32 v)
      81 [ +  + ][ +  - ]:        526 : { futex_wait_if_cond(f, v, ==); }
      82                 :            : 
      83                 :            : /* Wait while futex @f value is greater than @v */
      84                 :        498 : static inline void futex_wait_while_gt(futex_t *f, u32 v)
      85 [ +  + ][ +  - ]:       1267 : { futex_wait_if_cond(f, v, <=); }
      86                 :            : 
      87                 :            : /* Wait while futex @f value is @v */
      88                 :       1256 : static inline void futex_wait_while(futex_t *f, u32 v)
      89                 :            : {
      90         [ +  + ]:       3311 :         while (atomic_get(&f->raw) == v) {
      91                 :        799 :                 int ret = sys_futex(&f->raw.counter, FUTEX_WAIT, v, NULL, NULL, 0);
      92         [ +  - ]:       2055 :                 BUG_ON(ret < 0 && ret != -EWOULDBLOCK);
      93                 :            :         }
      94                 :       1256 : }
      95                 :            : 
      96                 :            : typedef struct {
      97                 :            :         atomic_t        raw;
      98                 :            : } mutex_t;
      99                 :            : 
     100                 :            : static void inline mutex_init(mutex_t *m)
     101                 :            : {
     102                 :       1059 :         u32 c = 0;
     103                 :       1059 :         atomic_set(&m->raw, c);
     104                 :            : }
     105                 :            : 
     106                 :         33 : static void inline mutex_lock(mutex_t *m)
     107                 :            : {
     108                 :            :         u32 c;
     109                 :            :         int ret;
     110                 :            : 
     111         [ -  + ]:         66 :         while ((c = atomic_inc(&m->raw))) {
     112                 :          0 :                 ret = sys_futex(&m->raw.counter, FUTEX_WAIT, c + 1, NULL, NULL, 0);
     113         [ #  # ]:         33 :                 BUG_ON(ret < 0 && ret != -EWOULDBLOCK);
     114                 :            :         }
     115                 :         33 : }
     116                 :            : 
     117                 :         33 : static void inline mutex_unlock(mutex_t *m)
     118                 :            : {
     119                 :         33 :         u32 c = 0;
     120                 :         33 :         atomic_set(&m->raw, c);
     121         [ -  + ]:         33 :         BUG_ON(sys_futex(&m->raw.counter, FUTEX_WAKE, 1, NULL, NULL, 0) < 0);
     122                 :         33 : }
     123                 :            : 
     124                 :            : #endif /* __CR_LOCK_H__ */

Generated by: LCOV version 1.9