LCOV - code coverage report
Current view: top level - include - lock.h (source / functions) Hit Total Coverage
Test: coverage3.info Lines: 34 37 91.9 %
Date: 2014-04-22 Functions: 9 10 90.0 %
Branches: 19 32 59.4 %

           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 "asm/types.h"
      10                 :            : #include "asm/atomic.h"
      11                 :            : #include "syscall.h"
      12                 :            : #include "bug.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                 :       1465 :         return atomic_read(&f->raw);
      25                 :            : }
      26                 :            : 
      27                 :            : /* Set futex @f value to @v */
      28                 :            : static inline void futex_set(futex_t *f, u32 v)
      29                 :            : {
      30                 :            :         atomic_set(&f->raw, (int)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 = (u32)atomic_read(&(__f)->raw);     \
      43                 :            :                         if ((tmp & FUTEX_ABORT_FLAG) ||             \
      44                 :            :                             (tmp __cond (__v)))                 \
      45                 :            :                                 break;                          \
      46                 :            :                         ret = sys_futex((u32 *)&(__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                 :       2805 : static inline void futex_set_and_wake(futex_t *f, u32 v)
      54                 :            : {
      55                 :       2805 :         atomic_set(&f->raw, (int)v);
      56         [ -  + ]:       2805 :         BUG_ON(sys_futex((u32 *)&f->raw.counter, FUTEX_WAKE, INT_MAX, NULL, NULL, 0) < 0);
      57                 :       2805 : }
      58                 :            : 
      59                 :            : /* Mark futex @f as wait abort needed and wake up all waiters */
      60                 :            : 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                 :            : }
      65                 :            : 
      66                 :            : /* Decrement futex @f value and wake up all waiters */
      67                 :        925 : static inline void futex_dec_and_wake(futex_t *f)
      68                 :            : {
      69                 :        925 :         atomic_dec(&f->raw);
      70         [ -  + ]:        925 :         BUG_ON(sys_futex((u32 *)&f->raw.counter, FUTEX_WAKE, INT_MAX, NULL, NULL, 0) < 0);
      71                 :        925 : }
      72                 :            : 
      73                 :            : /* Increment futex @f value and wake up all waiters */
      74                 :          8 : static inline void futex_inc_and_wake(futex_t *f)
      75                 :            : {
      76                 :          8 :         atomic_inc(&f->raw);
      77         [ -  + ]:          8 :         BUG_ON(sys_futex((u32 *)&f->raw.counter, FUTEX_WAKE, INT_MAX, NULL, NULL, 0) < 0);
      78                 :          8 : }
      79                 :            : 
      80                 :            : /* Plain increment futex @f value */
      81                 :        182 : static inline void futex_inc(futex_t *f) { atomic_inc(&f->raw); }
      82                 :            : 
      83                 :            : /* Plain decrement futex @f value */
      84                 :         62 : static inline void futex_dec(futex_t *f) { atomic_dec(&f->raw); }
      85                 :            : 
      86                 :            : /* Wait until futex @f value become @v */
      87                 :         76 : static inline void futex_wait_until(futex_t *f, u32 v)
      88 [ +  + ][ +  - ]:         55 : { futex_wait_if_cond(f, v, ==); }
      89                 :            : 
      90                 :            : /* Wait while futex @f value is greater than @v */
      91                 :       4480 : static inline void futex_wait_while_gt(futex_t *f, u32 v)
      92 [ +  + ][ +  - ]:       6124 : { futex_wait_if_cond(f, v, <=); }
      93                 :            : 
      94                 :            : /* Wait while futex @f value is less than @v */
      95                 :         14 : static inline void futex_wait_while_lt(futex_t *f, u32 v)
      96 [ +  + ][ +  - ]:         13 : { futex_wait_if_cond(f, v, >=); }
      97                 :            : 
      98                 :            : /* Wait while futex @f value is equal to @v */
      99                 :          0 : static inline void futex_wait_while_eq(futex_t *f, u32 v)
     100 [ #  # ][ #  # ]:          0 : { futex_wait_if_cond(f, v, !=); }
     101                 :            : 
     102                 :            : /* Wait while futex @f value is @v */
     103                 :       1477 : static inline void futex_wait_while(futex_t *f, u32 v)
     104                 :            : {
     105         [ +  + ]:       3861 :         while ((u32)atomic_read(&f->raw) == v) {
     106                 :        907 :                 int ret = sys_futex((u32 *)&f->raw.counter, FUTEX_WAIT, v, NULL, NULL, 0);
     107         [ +  - ]:       2384 :                 BUG_ON(ret < 0 && ret != -EWOULDBLOCK);
     108                 :            :         }
     109                 :       1477 : }
     110                 :            : 
     111                 :            : typedef struct {
     112                 :            :         atomic_t        raw;
     113                 :            : } mutex_t;
     114                 :            : 
     115                 :            : static inline void mutex_init(mutex_t *m)
     116                 :            : {
     117                 :            :         u32 c = 0;
     118                 :            :         atomic_set(&m->raw, (int)c);
     119                 :            : }
     120                 :            : 
     121                 :         57 : static inline void mutex_lock(mutex_t *m)
     122                 :            : {
     123                 :            :         u32 c;
     124                 :            :         int ret;
     125                 :            : 
     126         [ +  + ]:        117 :         while ((c = (u32)atomic_inc_return(&m->raw)) != 1) {
     127                 :          3 :                 ret = sys_futex((u32 *)&m->raw.counter, FUTEX_WAIT, c, NULL, NULL, 0);
     128         [ +  - ]:         60 :                 BUG_ON(ret < 0 && ret != -EWOULDBLOCK);
     129                 :            :         }
     130                 :         57 : }
     131                 :            : 
     132                 :         50 : static inline void mutex_unlock(mutex_t *m)
     133                 :            : {
     134                 :            :         u32 c = 0;
     135                 :            :         atomic_set(&m->raw, (int)c);
     136         [ -  + ]:         50 :         BUG_ON(sys_futex((u32 *)&m->raw.counter, FUTEX_WAKE, 1, NULL, NULL, 0) < 0);
     137                 :         50 : }
     138                 :            : 
     139                 :            : #endif /* __CR_LOCK_H__ */

Generated by: LCOV version 1.9