/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- sem_create
- sem_destroy
- P
- V
- lock_create
- lock_destroy
- lock_acquire
- lock_release
- lock_do_i_hold
- cv_create
- cv_destroy
- cv_wait
- cv_signal
- cv_broadcast
1 /*
2 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 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 /*
31 * Synchronization primitives.
32 * The specifications of the functions are in synch.h.
33 */
34
35 #include <types.h>
36 #include <lib.h>
37 #include <spinlock.h>
38 #include <wchan.h>
39 #include <thread.h>
40 #include <current.h>
41 #include <synch.h>
42
43 ////////////////////////////////////////////////////////////
44 //
45 // Semaphore.
46
47 struct semaphore *
48 sem_create(const char *name, int initial_count)
49 {
50 struct semaphore *sem;
51
52 KASSERT(initial_count >= 0);
53
54 sem = kmalloc(sizeof(struct semaphore));
55 if (sem == NULL) {
56 return NULL;
57 }
58
59 sem->sem_name = kstrdup(name);
60 if (sem->sem_name == NULL) {
61 kfree(sem);
62 return NULL;
63 }
64
65 sem->sem_wchan = wchan_create(sem->sem_name);
66 if (sem->sem_wchan == NULL) {
67 kfree(sem->sem_name);
68 kfree(sem);
69 return NULL;
70 }
71
72 spinlock_init(&sem->sem_lock);
73 sem->sem_count = initial_count;
74
75 return sem;
76 }
77
78 void
79 sem_destroy(struct semaphore *sem)
80 {
81 KASSERT(sem != NULL);
82
83 /* wchan_cleanup will assert if anyone's waiting on it */
84 spinlock_cleanup(&sem->sem_lock);
85 wchan_destroy(sem->sem_wchan);
86 kfree(sem->sem_name);
87 kfree(sem);
88 }
89
90 void
91 P(struct semaphore *sem)
92 {
93 KASSERT(sem != NULL);
94
95 /*
96 * May not block in an interrupt handler.
97 *
98 * For robustness, always check, even if we can actually
99 * complete the P without blocking.
100 */
101 KASSERT(curthread->t_in_interrupt == false);
102
103 spinlock_acquire(&sem->sem_lock);
104 while (sem->sem_count == 0) {
105 /*
106 * Bridge to the wchan lock, so if someone else comes
107 * along in V right this instant the wakeup can't go
108 * through on the wchan until we've finished going to
109 * sleep. Note that wchan_sleep unlocks the wchan.
110 *
111 * Note that we don't maintain strict FIFO ordering of
112 * threads going through the semaphore; that is, we
113 * might "get" it on the first try even if other
114 * threads are waiting. Apparently according to some
115 * textbooks semaphores must for some reason have
116 * strict ordering. Too bad. :-)
117 *
118 * Exercise: how would you implement strict FIFO
119 * ordering?
120 */
121 wchan_lock(sem->sem_wchan);
122 spinlock_release(&sem->sem_lock);
123 wchan_sleep(sem->sem_wchan);
124
125 spinlock_acquire(&sem->sem_lock);
126 }
127 KASSERT(sem->sem_count > 0);
128 sem->sem_count--;
129 spinlock_release(&sem->sem_lock);
130 }
131
132 void
133 V(struct semaphore *sem)
134 {
135 KASSERT(sem != NULL);
136
137 spinlock_acquire(&sem->sem_lock);
138
139 sem->sem_count++;
140 KASSERT(sem->sem_count > 0);
141 wchan_wakeone(sem->sem_wchan);
142
143 spinlock_release(&sem->sem_lock);
144 }
145
146 ////////////////////////////////////////////////////////////
147 //
148 // Lock.
149
150 struct lock *
151 lock_create(const char *name)
152 {
153 struct lock *lock;
154
155 lock = kmalloc(sizeof(struct lock));
156 if (lock == NULL) {
157 return NULL;
158 }
159
160 lock->lk_name = kstrdup(name);
161 if (lock->lk_name == NULL) {
162 kfree(lock);
163 return NULL;
164 }
165
166 // add stuff here as needed
167
168 return lock;
169 }
170
171 void
172 lock_destroy(struct lock *lock)
173 {
174 KASSERT(lock != NULL);
175
176 // add stuff here as needed
177
178 kfree(lock->lk_name);
179 kfree(lock);
180 }
181
182 void
183 lock_acquire(struct lock *lock)
184 {
185 // Write this
186
187 (void)lock; // suppress warning until code gets written
188 }
189
190 void
191 lock_release(struct lock *lock)
192 {
193 // Write this
194
195 (void)lock; // suppress warning until code gets written
196 }
197
198 bool
199 lock_do_i_hold(struct lock *lock)
200 {
201 // Write this
202
203 (void)lock; // suppress warning until code gets written
204
205 return true; // dummy until code gets written
206 }
207
208 ////////////////////////////////////////////////////////////
209 //
210 // CV
211
212
213 struct cv *
214 cv_create(const char *name)
215 {
216 struct cv *cv;
217
218 cv = kmalloc(sizeof(struct cv));
219 if (cv == NULL) {
220 return NULL;
221 }
222
223 cv->cv_name = kstrdup(name);
224 if (cv->cv_name==NULL) {
225 kfree(cv);
226 return NULL;
227 }
228
229 // add stuff here as needed
230
231 return cv;
232 }
233
234 void
235 cv_destroy(struct cv *cv)
236 {
237 KASSERT(cv != NULL);
238
239 // add stuff here as needed
240
241 kfree(cv->cv_name);
242 kfree(cv);
243 }
244
245 void
246 cv_wait(struct cv *cv, struct lock *lock)
247 {
248 // Write this
249 (void)cv; // suppress warning until code gets written
250 (void)lock; // suppress warning until code gets written
251 }
252
253 void
254 cv_signal(struct cv *cv, struct lock *lock)
255 {
256 // Write this
257 (void)cv; // suppress warning until code gets written
258 (void)lock; // suppress warning until code gets written
259 }
260
261 void
262 cv_broadcast(struct cv *cv, struct lock *lock)
263 {
264 // Write this
265 (void)cv; // suppress warning until code gets written
266 (void)lock; // suppress warning until code gets written
267 }