~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/skiboot/core/lock.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2013-2014 IBM Corp.
 
2
 *
 
3
 * Licensed under the Apache License, Version 2.0 (the "License");
 
4
 * you may not use this file except in compliance with the License.
 
5
 * You may obtain a copy of the License at
 
6
 *
 
7
 *      http://www.apache.org/licenses/LICENSE-2.0
 
8
 *
 
9
 * Unless required by applicable law or agreed to in writing, software
 
10
 * distributed under the License is distributed on an "AS IS" BASIS,
 
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 
12
 * implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
#include <skiboot.h>
 
18
#include <lock.h>
 
19
#include <assert.h>
 
20
#include <processor.h>
 
21
#include <cpu.h>
 
22
#include <console.h>
 
23
 
 
24
/* Set to bust locks. Note, this is initialized to true because our
 
25
 * lock debugging code is not going to work until we have the per
 
26
 * CPU data initialized
 
27
 */
 
28
bool bust_locks = true;
 
29
 
 
30
#ifdef DEBUG_LOCKS
 
31
 
 
32
static void lock_error(struct lock *l, const char *reason, uint16_t err)
 
33
{
 
34
        bust_locks = true;
 
35
 
 
36
        fprintf(stderr, "LOCK ERROR: %s @%p (state: 0x%016lx)\n",
 
37
                reason, l, l->lock_val);
 
38
        op_display(OP_FATAL, OP_MOD_LOCK, err);
 
39
 
 
40
        abort();
 
41
}
 
42
 
 
43
static void lock_check(struct lock *l)
 
44
{
 
45
        if ((l->lock_val & 1) && (l->lock_val >> 32) == this_cpu()->pir)
 
46
                lock_error(l, "Invalid recursive lock", 0);
 
47
}
 
48
 
 
49
static void unlock_check(struct lock *l)
 
50
{
 
51
        if (!(l->lock_val & 1))
 
52
                lock_error(l, "Unlocking unlocked lock", 1);
 
53
 
 
54
        if ((l->lock_val >> 32) != this_cpu()->pir)
 
55
                lock_error(l, "Unlocked non-owned lock", 2);
 
56
 
 
57
        if (l->in_con_path && this_cpu()->con_suspend == 0)
 
58
                lock_error(l, "Unlock con lock with console not suspended", 3);
 
59
 
 
60
        if (this_cpu()->lock_depth == 0)
 
61
                lock_error(l, "Releasing lock with 0 depth", 4);
 
62
}
 
63
 
 
64
#else
 
65
static inline void lock_check(struct lock *l) { };
 
66
static inline void unlock_check(struct lock *l) { };
 
67
#endif /* DEBUG_LOCKS */
 
68
 
 
69
bool lock_held_by_me(struct lock *l)
 
70
{
 
71
        uint64_t pir64 = this_cpu()->pir;
 
72
 
 
73
        return l->lock_val == ((pir64 << 32) | 1);
 
74
}
 
75
 
 
76
bool try_lock(struct lock *l)
 
77
{
 
78
        if (__try_lock(l)) {
 
79
                if (l->in_con_path)
 
80
                        this_cpu()->con_suspend++;
 
81
                this_cpu()->lock_depth++;
 
82
                return true;
 
83
        }
 
84
        return false;
 
85
}
 
86
 
 
87
void lock(struct lock *l)
 
88
{
 
89
        if (bust_locks)
 
90
                return;
 
91
 
 
92
        lock_check(l);
 
93
        for (;;) {
 
94
                if (try_lock(l))
 
95
                        break;
 
96
                cpu_relax();
 
97
        }
 
98
}
 
99
 
 
100
void unlock(struct lock *l)
 
101
{
 
102
        struct cpu_thread *cpu = this_cpu();
 
103
 
 
104
        if (bust_locks)
 
105
                return;
 
106
 
 
107
        unlock_check(l);
 
108
 
 
109
        lwsync();
 
110
        this_cpu()->lock_depth--;
 
111
        l->lock_val = 0;
 
112
 
 
113
        if (l->in_con_path) {
 
114
                cpu->con_suspend--;
 
115
                if (cpu->con_suspend == 0 && cpu->con_need_flush)
 
116
                        flush_console();
 
117
        }
 
118
}
 
119
 
 
120
bool lock_recursive(struct lock *l)
 
121
{
 
122
        if (bust_locks)
 
123
                return false;
 
124
 
 
125
        if (lock_held_by_me(l))
 
126
                return false;
 
127
 
 
128
        lock(l);
 
129
        return true;
 
130
}
 
131
 
 
132
void init_locks(void)
 
133
{
 
134
        bust_locks = false;
 
135
}