Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
script3r
GitHub Repository: script3r/os161
Path: blob/master/kern/thread/spl.c
2093 views
1
/*
2
* Copyright (c) 2009
3
* The President and Fellows of Harvard College.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. Neither the name of the University nor the names of its contributors
14
* may be used to endorse or promote products derived from this software
15
* without specific prior written permission.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
/* Make sure to build out-of-line versions of spl inline functions */
31
#define SPL_INLINE /* empty */
32
33
#include <types.h>
34
#include <lib.h>
35
#include <cpu.h>
36
#include <spl.h>
37
#include <thread.h>
38
#include <current.h>
39
40
/*
41
* Machine-independent interrupt handling functions.
42
*
43
* Traditionally, all this code is machine-dependent.
44
*
45
* However.
46
*
47
* Since on OS/161 we don't support interrupt levels on any platform,
48
* all we require under this logic is cpu_irqoff() and cpu_irqon()
49
* that explicitly turn interrupts off and on.
50
*
51
* If we had multiple interrupt levels, the number of levels would in
52
* general be different on different platforms (depending on hardware
53
* requirements and hardware capabilities) so things would get more
54
* complicated -- but nearly all of this code could remain MI.
55
*/
56
57
58
/*
59
* Raise and lower the interrupt priority level.
60
*
61
* Each spinlock acquisition can raise and lower the priority level
62
* independently. The spl calls also raise and lower the priority
63
* level independently of the spinlocks. This is necessary because in
64
* general spinlock acquisitions and releases don't nest perfectly,
65
* and don't necessarily nest with respect to spl calls either.
66
*
67
* For example:
68
*
69
* struct spinlock red, blue;
70
* int s;
71
*
72
* spinlock_acquire(&red);
73
* s = splhigh();
74
* spinlock_acquire(&blue);
75
* splx(s);
76
* spinlock_release(&red);
77
* spinlock_release(&blue);
78
*
79
* In order to make this work we need to count the number of times
80
* IPL_HIGH (or, if we had multiple interrupt priority levels, each
81
* level independently) has been raised. Interrupts go off on the
82
* first raise, and go on again only on the last lower.
83
*
84
* curthread->t_iplhigh_count is used to track this.
85
*/
86
void
87
splraise(int oldspl, int newspl)
88
{
89
struct thread *cur = curthread;
90
91
/* only one priority level, only one valid args configuration */
92
KASSERT(oldspl == IPL_NONE);
93
KASSERT(newspl == IPL_HIGH);
94
95
if (!CURCPU_EXISTS()) {
96
/* before curcpu initialization; interrupts are off anyway */
97
return;
98
}
99
100
if (cur->t_iplhigh_count == 0) {
101
cpu_irqoff();
102
}
103
cur->t_iplhigh_count++;
104
}
105
106
void
107
spllower(int oldspl, int newspl)
108
{
109
struct thread *cur = curthread;
110
111
/* only one priority level, only one valid args configuration */
112
KASSERT(oldspl == IPL_HIGH);
113
KASSERT(newspl == IPL_NONE);
114
115
if (!CURCPU_EXISTS()) {
116
/* before curcpu initialization; interrupts are off anyway */
117
return;
118
}
119
120
cur->t_iplhigh_count--;
121
if (cur->t_iplhigh_count == 0) {
122
cpu_irqon();
123
}
124
}
125
126
127
/*
128
* Disable or enable interrupts and adjust curspl setting. Return old
129
* spl level.
130
*/
131
int
132
splx(int spl)
133
{
134
struct thread *cur = curthread;
135
int ret;
136
137
if (cur->t_curspl < spl) {
138
/* turning interrupts off */
139
splraise(cur->t_curspl, spl);
140
ret = cur->t_curspl;
141
cur->t_curspl = spl;
142
}
143
else if (cur->t_curspl > spl) {
144
/* turning interrupts on */
145
ret = cur->t_curspl;
146
cur->t_curspl = spl;
147
spllower(ret, spl);
148
}
149
else {
150
/* do nothing */
151
ret = spl;
152
}
153
154
return ret;
155
}
156
157