Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/include/xen/spinlock.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef __SPINLOCK_H__
2
#define __SPINLOCK_H__
3
4
#include <asm/system.h>
5
#include <asm/spinlock.h>
6
#include <asm/types.h>
7
#include <xen/percpu.h>
8
9
#ifndef NDEBUG
10
struct lock_debug {
11
    s16 irq_safe; /* +1: IRQ-safe; 0: not IRQ-safe; -1: don't know yet */
12
};
13
1.52k
#define _LOCK_DEBUG { -1 }
14
void spin_debug_enable(void);
15
void spin_debug_disable(void);
16
#else
17
struct lock_debug { };
18
#define _LOCK_DEBUG { }
19
#define spin_debug_enable() ((void)0)
20
#define spin_debug_disable() ((void)0)
21
#endif
22
23
#ifdef CONFIG_LOCK_PROFILE
24
25
#include <public/sysctl.h>
26
27
/*
28
    lock profiling on:
29
30
    Global locks which should be subject to profiling must be declared via
31
    DEFINE_SPINLOCK.
32
33
    For locks in structures further measures are necessary:
34
    - the structure definition must include a profile_head with exactly this
35
      name:
36
37
      struct lock_profile_qhead   profile_head;
38
39
    - the single locks which are subject to profiling have to be initialized
40
      via
41
42
      spin_lock_init_prof(ptr, lock);
43
44
      with ptr being the main structure pointer and lock the spinlock field
45
46
    - each structure has to be added to profiling with
47
48
      lock_profile_register_struct(type, ptr, idx, print);
49
50
      with:
51
        type:  something like LOCKPROF_TYPE_PERDOM
52
        ptr:   pointer to the structure
53
        idx:   index of that structure, e.g. domid
54
        print: descriptive string like "domain"
55
56
    - removing of a structure is done via
57
58
      lock_profile_deregister_struct(type, ptr);
59
*/
60
61
struct spinlock;
62
63
struct lock_profile {
64
    struct lock_profile *next;       /* forward link */
65
    char                *name;       /* lock name */
66
    struct spinlock     *lock;       /* the lock itself */
67
    u64                 lock_cnt;    /* # of complete locking ops */
68
    u64                 block_cnt;   /* # of complete wait for lock */
69
    s64                 time_hold;   /* cumulated lock time */
70
    s64                 time_block;  /* cumulated wait time */
71
    s64                 time_locked; /* system time of last locking */
72
};
73
74
struct lock_profile_qhead {
75
    struct lock_profile_qhead *head_q; /* next head of this type */
76
    struct lock_profile       *elem_q; /* first element in q */
77
    int32_t                   idx;     /* index for printout */
78
};
79
80
#define _LOCK_PROFILE(name) { 0, #name, &name, 0, 0, 0, 0, 0 }
81
#define _LOCK_PROFILE_PTR(name)                                               \
82
    static struct lock_profile * const __lock_profile_##name                  \
83
    __used_section(".lockprofile.data") =                                     \
84
    &__lock_profile_data_##name
85
#define _SPIN_LOCK_UNLOCKED(x) { { 0 }, SPINLOCK_NO_CPU, 0, _LOCK_DEBUG, x }
86
#define SPIN_LOCK_UNLOCKED _SPIN_LOCK_UNLOCKED(NULL)
87
#define DEFINE_SPINLOCK(l)                                                    \
88
    spinlock_t l = _SPIN_LOCK_UNLOCKED(NULL);                                 \
89
    static struct lock_profile __lock_profile_data_##l = _LOCK_PROFILE(l);    \
90
    _LOCK_PROFILE_PTR(l)
91
92
#define spin_lock_init_prof(s, l)                                             \
93
    do {                                                                      \
94
        struct lock_profile *prof;                                            \
95
        prof = xzalloc(struct lock_profile);                                  \
96
        if (!prof) break;                                                     \
97
        prof->name = #l;                                                      \
98
        prof->lock = &(s)->l;                                                 \
99
        (s)->l = (spinlock_t)_SPIN_LOCK_UNLOCKED(prof);                       \
100
        prof->next = (s)->profile_head.elem_q;                                \
101
        (s)->profile_head.elem_q = prof;                                      \
102
    } while(0)
103
104
void _lock_profile_register_struct(
105
    int32_t, struct lock_profile_qhead *, int32_t, char *);
106
void _lock_profile_deregister_struct(int32_t, struct lock_profile_qhead *);
107
108
#define lock_profile_register_struct(type, ptr, idx, print)                   \
109
    _lock_profile_register_struct(type, &((ptr)->profile_head), idx, print)
110
#define lock_profile_deregister_struct(type, ptr)                             \
111
    _lock_profile_deregister_struct(type, &((ptr)->profile_head))
112
113
extern int spinlock_profile_control(struct xen_sysctl_lockprof_op *pc);
114
extern void spinlock_profile_printall(unsigned char key);
115
extern void spinlock_profile_reset(unsigned char key);
116
117
#else
118
119
struct lock_profile_qhead { };
120
121
1.52k
#define SPIN_LOCK_UNLOCKED { { 0 }, SPINLOCK_NO_CPU, 0, _LOCK_DEBUG }
122
36
#define DEFINE_SPINLOCK(l) spinlock_t l = SPIN_LOCK_UNLOCKED
123
124
11
#define spin_lock_init_prof(s, l) spin_lock_init(&((s)->l))
125
#define lock_profile_register_struct(type, ptr, idx, print)
126
#define lock_profile_deregister_struct(type, ptr)
127
128
#endif
129
130
typedef union {
131
    u32 head_tail;
132
    struct {
133
        u16 head;
134
        u16 tail;
135
    };
136
} spinlock_tickets_t;
137
138
48.7M
#define SPINLOCK_TICKET_INC { .head_tail = 0x10000, }
139
140
typedef struct spinlock {
141
    spinlock_tickets_t tickets;
142
    u16 recurse_cpu:12;
143
5.63M
#define SPINLOCK_NO_CPU 0xfffu
144
    u16 recurse_cnt:4;
145
#define SPINLOCK_MAX_RECURSE 0xfu
146
    struct lock_debug debug;
147
#ifdef CONFIG_LOCK_PROFILE
148
    struct lock_profile *profile;
149
#endif
150
} spinlock_t;
151
152
153
1.23k
#define spin_lock_init(l) (*(l) = (spinlock_t)SPIN_LOCK_UNLOCKED)
154
155
void _spin_lock(spinlock_t *lock);
156
void _spin_lock_cb(spinlock_t *lock, void (*cond)(void *), void *data);
157
void _spin_lock_irq(spinlock_t *lock);
158
unsigned long _spin_lock_irqsave(spinlock_t *lock);
159
160
void _spin_unlock(spinlock_t *lock);
161
void _spin_unlock_irq(spinlock_t *lock);
162
void _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
163
164
int _spin_is_locked(spinlock_t *lock);
165
int _spin_trylock(spinlock_t *lock);
166
void _spin_barrier(spinlock_t *lock);
167
168
int _spin_trylock_recursive(spinlock_t *lock);
169
void _spin_lock_recursive(spinlock_t *lock);
170
void _spin_unlock_recursive(spinlock_t *lock);
171
172
40.4M
#define spin_lock(l)                  _spin_lock(l)
173
10
#define spin_lock_cb(l, c, d)         _spin_lock_cb(l, c, d)
174
13.7M
#define spin_lock_irq(l)              _spin_lock_irq(l)
175
#define spin_lock_irqsave(l, f)                                 \
176
734k
    ({                                                          \
177
734k
        BUILD_BUG_ON(sizeof(f) != sizeof(unsigned long));       \
178
734k
        ((f) = _spin_lock_irqsave(l));                          \
179
734k
    })
180
181
40.6M
#define spin_unlock(l)                _spin_unlock(l)
182
13.7M
#define spin_unlock_irq(l)            _spin_unlock_irq(l)
183
734k
#define spin_unlock_irqrestore(l, f)  _spin_unlock_irqrestore(l, f)
184
185
65.8k
#define spin_is_locked(l)             _spin_is_locked(l)
186
8.80k
#define spin_trylock(l)               _spin_trylock(l)
187
188
0
#define spin_trylock_irqsave(lock, flags)       \
189
0
({                                              \
190
0
    local_irq_save(flags);                      \
191
0
    spin_trylock(lock) ?                        \
192
0
    1 : ({ local_irq_restore(flags); 0; });     \
193
0
})
194
195
7
#define spin_lock_kick(l)             arch_lock_signal_wmb()
196
197
/* Ensure a lock is quiescent between two critical operations. */
198
0
#define spin_barrier(l)               _spin_barrier(l)
199
200
/*
201
 * spin_[un]lock_recursive(): Use these forms when the lock can (safely!) be
202
 * reentered recursively on the same CPU. All critical regions that may form
203
 * part of a recursively-nested set must be protected by these forms. If there
204
 * are any critical regions that cannot form part of such a set, they can use
205
 * standard spin_[un]lock().
206
 */
207
11
#define spin_trylock_recursive(l)     _spin_trylock_recursive(l)
208
36.7k
#define spin_lock_recursive(l)        _spin_lock_recursive(l)
209
36.7k
#define spin_unlock_recursive(l)      _spin_unlock_recursive(l)
210
211
#endif /* __SPINLOCK_H__ */