Statistics
| Branch: | Tag: | Revision:

root / xseg / xtypes / xlock.h @ 67e10529

History | View | Annotate | Download (4.1 kB)

1
/*
2
 * Copyright 2012 GRNET S.A. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or
5
 * without modification, are permitted provided that the following
6
 * conditions are met:
7
 *
8
 *   1. Redistributions of source code must retain the above
9
 *      copyright notice, this list of conditions and the following
10
 *      disclaimer.
11
 *   2. Redistributions in binary form must reproduce the above
12
 *      copyright notice, this list of conditions and the following
13
 *      disclaimer in the documentation and/or other materials
14
 *      provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
 * POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * The views and conclusions contained in the software and
30
 * documentation are those of the authors and should not be
31
 * interpreted as representing official policies, either expressed
32
 * or implied, of GRNET S.A.
33
 */
34

    
35
#ifndef _XLOCK_H
36
#define _XLOCK_H
37

    
38
#include <sys/util.h>
39

    
40
#define MFENCE() __sync_synchronize()
41
#define BARRIER() __asm__ __volatile__ ("" ::: "memory")
42
#define __pause() __asm__ __volatile__ ("pause\n");
43
#undef __pause
44
#define __pause()
45

    
46
#define Noone ((unsigned long)-1)
47

    
48
#define XLOCK_SANITY_CHECKS
49
#define XLOCK_CONGESTION_NOTIFY
50

    
51
#ifdef XLOCK_SANITY_CHECKS
52
#define MAX_VALID_OWNER 65536 /* we are not gonna have more ports than that */
53
#endif /* XLOCK_SANITY_CHECKS */
54

    
55
#ifdef XLOCK_CONGESTION_NOTIFY
56
#define MIN_SHIFT 20
57
#define MAX_SHIFT ((sizeof(unsigned long) * 8) -1)
58
#endif /* XLOCK_CONGESTION_NOTIFY */
59

    
60
struct xlock {
61
        unsigned long owner;
62
};
63
//} __attribute__ ((aligned (16))); /* support up to 128bit longs */
64

    
65
static inline unsigned long xlock_acquire(struct xlock *lock, unsigned long who)
66
{
67
        unsigned long owner;
68
#ifdef XLOCK_CONGESTION_NOTIFY
69
        unsigned long times = 1;
70
        unsigned long shift = MIN_SHIFT;
71
#endif /* XLOCK_CONGESTION_NOTIFY */
72

    
73
        for (;;) {
74
                for (; (owner = *(volatile unsigned long *)(&lock->owner) != Noone);){
75
#ifdef XLOCK_SANITY_CHECKS
76
                        if (owner > MAX_VALID_OWNER){
77
                                XSEGLOG("xlock %lx corrupted. Lock owner %lu",
78
                                                (unsigned long) lock, owner);
79
                                XSEGLOG("Resetting xlock %lx to Noone", 
80
                                                (unsigned long) lock);
81
                                lock->owner = Noone;
82
                        }
83
#endif /* XLOCK_SANITY_CHECKS */
84
#ifdef XLOCK_CONGESTION_NOTIFY
85
                        if (!(times & ((1<<shift) -1))){
86
                                XSEGLOG("xlock %lx spinned for %llu times"
87
                                        "\n\t who: %lu, owner: %lu",
88
                                        (unsigned long) lock, times,
89
                                        who, owner);
90
                                if (shift < MAX_SHIFT)
91
                                        shift++;
92
//                                xseg_printtrace();
93
                        }
94
                        times++;
95
#endif /* XLOCK_CONGESTION_NOTIFY */
96
                        __pause();
97
                }
98

    
99
                if (__sync_bool_compare_and_swap(&lock->owner, Noone, who))
100
                        break;
101
        }
102
#ifdef XLOCK_SANITY_CHECKS
103
        if (lock->owner > MAX_VALID_OWNER){
104
                XSEGLOG("xlock %lx locked with INVALID lock owner %lu",
105
                                (unsigned long) lock, lock->owner);
106
        }
107
#endif /* XLOCK_SANITY_CHECKS */
108

    
109
        return who;
110
}
111

    
112
static inline unsigned long xlock_try_lock(struct xlock *lock, unsigned long who)
113
{
114
        unsigned long owner;
115
        owner = *(volatile unsigned long *)(&lock->owner);
116
        if (owner == Noone)
117
                return __sync_bool_compare_and_swap(&lock->owner, Noone, who);
118
        return 0;
119
}
120

    
121
static inline void xlock_release(struct xlock *lock)
122
{
123
        BARRIER();
124
        /*
125
#ifdef XLOCK_SANITY_CHECKS
126
        if (lock->owner > MAX_VALID_OWNER){
127
                XSEGLOG("xlock %lx releasing lock with INVALID lock owner %lu",
128
                                (unsigned long) lock, lock->owner);
129
        }
130
#endif 
131
        */
132
        /* XLOCK_SANITY_CHECKS */
133
        lock->owner = Noone;
134
}
135

    
136
static inline unsigned long xlock_get_owner(struct xlock *lock)
137
{
138
        return *(volatile unsigned long *)(&lock->owner);
139
}
140

    
141
#endif