@@ -100,13 +100,165 @@ Semaphore::V()
100100// Dummy functions -- so we can compile our later assignments
101101// Note -- without a correct implementation of Condition::Wait(),
102102// the test case in the network assignment won't work!
103- Lock::Lock (char * debugName) {}
104- Lock::~Lock () {}
105- void Lock::Acquire () {}
106- void Lock::Release () {}
107-
108- Condition::Condition (char * debugName) { }
109- Condition::~Condition () { }
110- void Condition::Wait (Lock* conditionLock) { ASSERT (FALSE ); }
111- void Condition::Signal (Lock* conditionLock) { }
112- void Condition::Broadcast (Lock* conditionLock) { }
103+ Lock::Lock (char * debugName)
104+ {
105+ name = debugName;
106+ lockStatus = FREE;
107+ lockOwner = NULL ;
108+ waitQueue = new List;
109+ }
110+
111+ Lock::~Lock ()
112+ {
113+ delete waitQueue;
114+ }
115+
116+ void Lock::Acquire ()
117+ {
118+ IntStatus oldLevel = interrupt->SetLevel (IntOff); // disable interrupts
119+ if (currentThread == lockOwner) // current thread is lock owner
120+ {
121+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
122+ return ;
123+ }
124+
125+ if (lockStatus == FREE) // lock is available
126+ {
127+ // I can have the lock
128+ lockStatus = BUSY; // make state BUSY
129+ lockOwner = currentThread; // make myself the owner
130+ }
131+ else // lock is busy
132+ {
133+ waitQueue->Append (currentThread); // Put current thread on the lock’s waitQueue
134+ currentThread->Sleep ();
135+ }
136+
137+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
138+ }
139+
140+ void Lock::Release ()
141+ {
142+ IntStatus oldLevel = interrupt->SetLevel (IntOff); // disable interrupts
143+ if (currentThread != lockOwner) // current thread is not lock owner
144+ {
145+ printf (" Lock::Release::(currentThread != lockOwner)::Current thread is not lock owner\n " );
146+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
147+ return ;
148+ }
149+
150+ if (!waitQueue->IsEmpty ()) // lock waitQueue is not empty
151+ {
152+ Thread* thread = (Thread*)waitQueue->Remove (); // remove 1 waiting thread
153+ lockOwner = thread; // make them lock owner
154+ scheduler->ReadyToRun (thread); // puts a thread at the back of the
155+ // readyQueue in the ready state
156+ }
157+ else
158+ {
159+ lockStatus = FREE; // make lock available
160+ lockOwner = NULL ; // unset ownership
161+ }
162+
163+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
164+ }
165+
166+ void Lock::Print ()
167+ {
168+ printf (" Lock waitQueue contents:\n " );
169+ waitQueue->Mapcar ((VoidFunctionPtr) ThreadPrint);
170+ }
171+
172+ Condition::Condition (char * debugName)
173+ {
174+ name = debugName;
175+ waitingLock = NULL ;
176+ waitQueue = new List;
177+ }
178+
179+ Condition::~Condition ()
180+ {
181+ delete waitQueue;
182+ }
183+
184+ void Condition::Wait (Lock* conditionLock)
185+ {
186+ // ASSERT(FALSE);
187+
188+ IntStatus oldLevel = interrupt->SetLevel (IntOff); // disable interrupts
189+ if (conditionLock == NULL )
190+ {
191+ printf (" Condition::Wait::(conditionLock == NULL)::There is no lock to be acquired\n " );
192+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
193+ return ;
194+ }
195+ if (waitingLock == NULL )
196+ {
197+ // no one waiting
198+ waitingLock = conditionLock;
199+ }
200+ if (waitingLock != conditionLock)
201+ {
202+ printf (" Condition::Wait::(waitingLock != conditionLock)::waitingLock and the lock passed in don't match\n " );
203+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
204+ return ;
205+ }
206+ // OK to wait
207+ waitQueue->Append (currentThread);// Hung: add myself to Condition Variable waitQueue
208+ conditionLock->Release ();
209+ currentThread->Sleep (); // currentThread is put on the waitQueue
210+ conditionLock->Acquire ();
211+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
212+ }
213+
214+ void Condition::Signal (Lock* conditionLock)
215+ {
216+ IntStatus oldLevel = interrupt->SetLevel (IntOff); // disable interrupts
217+ if (waitQueue->IsEmpty ()) // no thread waiting
218+ {
219+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
220+ return ;
221+ }
222+
223+ if (waitingLock != conditionLock)
224+ {
225+ printf (" Condition::Signal::(waitingLock != lock)::Incorrect lock passed in\n " );
226+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
227+ return ;
228+ }
229+
230+ // Wake up one waiting thread
231+ Thread* thread = (Thread*)waitQueue->Remove ();// Remove one thread from waitQueue
232+ scheduler->ReadyToRun (thread); // Put on readyQueue
233+
234+ if (waitQueue->IsEmpty ()) // waitQueue is empty
235+ {
236+ waitingLock = NULL ;
237+ }
238+
239+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
240+ }
241+
242+ void Condition::Broadcast (Lock* conditionLock)
243+ {
244+ IntStatus oldLevel = interrupt->SetLevel (IntOff); // disable interrupts
245+ if (conditionLock == NULL )
246+ {
247+ printf (" Condition::Broadcast::(conditionLock == NULL)::No lock passed in. Reenable interrupts and return.\n " );
248+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
249+ return ;
250+ }
251+
252+ if (conditionLock != waitingLock)
253+ {
254+ printf (" Condition::Broadcast::(conditionLock != waitingLock)::Waiting lock is not the same as the condition lock.\n " );
255+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
256+ return ;
257+ }
258+
259+ (void ) interrupt->SetLevel (oldLevel); // restore interrupts
260+ while (!waitQueue->IsEmpty ()) // waitQueue is not empty
261+ {
262+ Signal (conditionLock);
263+ }
264+ }
0 commit comments