Advertisement
Guest User

Untitled

a guest
Oct 9th, 2015
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.26 KB | None | 0 0
  1. /* This file is derived from source code for the Nachos
  2. instructional operating system. The Nachos copyright notice
  3. is reproduced in full below. */
  4.  
  5. /* Copyright (c) 1992-1996 The Regents of the University of California.
  6. All rights reserved.
  7.  
  8. Permission to use, copy, modify, and distribute this software
  9. and its documentation for any purpose, without fee, and
  10. without written agreement is hereby granted, provided that the
  11. above copyright notice and the following two paragraphs appear
  12. in all copies of this software.
  13.  
  14. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO
  15. ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
  16. CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE
  17. AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA
  18. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  19.  
  20. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
  21. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  22. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
  24. BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  25. PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
  26. MODIFICATIONS.
  27. */
  28.  
  29. #include "threads/synch.h"
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include "threads/interrupt.h"
  33. #include "threads/thread.h"
  34.  
  35. /** Below are implementations the group added **/
  36. //Returns true if the lock has
  37. static bool
  38. lock_less_func (const struct list_elem *a_, const struct list_elem *b_,
  39. void *aux UNUSED)
  40. {
  41. struct semaphore *semaA = &(list_entry(a_, struct lock, lock_elem)->semaphore);
  42. struct semaphore *semaB = &(list_entry(b_, struct lock, lock_elem)->semaphore);
  43. const struct thread *a = list_entry(list_begin(&semaA->waiters), struct thread, elem);
  44. const struct thread *b = list_entry(list_begin(&semaB->waiters), struct thread, elem);
  45. return a->priority >= b->priority;
  46. }
  47. /* Initializes semaphore SEMA to VALUE. A semaphore is a
  48. nonnegative integer along with two atomic operators for
  49. manipulating it:
  50.  
  51. - down or "P": wait for the value to become positive, then
  52. decrement it.
  53.  
  54. - up or "V": increment the value (and wake up one waiting
  55. thread, if any). */
  56. void
  57. sema_init (struct semaphore *sema, unsigned value)
  58. {
  59. ASSERT (sema != NULL);
  60.  
  61. sema->value = value;
  62. list_init (&sema->waiters);
  63. }
  64.  
  65. /* Down or "P" operation on a semaphore. Waits for SEMA's value
  66. to become positive and then atomically decrements it.
  67.  
  68. This function may sleep, so it must not be called within an
  69. interrupt handler. This function may be called with
  70. interrupts disabled, but if it sleeps then the next scheduled
  71. thread will probably turn interrupts back on. */
  72. void
  73. sema_down (struct semaphore *sema)
  74. {
  75. enum intr_level old_level;
  76.  
  77. ASSERT (sema != NULL);
  78. ASSERT (!intr_context ());
  79.  
  80. old_level = intr_disable ();
  81. while (sema->value == 0)
  82. {
  83. list_insert_ordered(&sema->waiters, &thread_current()->elem, priority_less_func, NULL);
  84. thread_current()->list_of_elem = &sema->waiters;
  85. thread_block ();
  86. }
  87. sema->value--;
  88. intr_set_level (old_level);
  89. }
  90.  
  91. /* Down or "P" operation on a semaphore, but only if the
  92. semaphore is not already 0. Returns true if the semaphore is
  93. decremented, false otherwise.
  94.  
  95. This function may be called from an interrupt handler. */
  96. bool
  97. sema_try_down (struct semaphore *sema)
  98. {
  99. enum intr_level old_level;
  100. bool success;
  101.  
  102. ASSERT (sema != NULL);
  103.  
  104. old_level = intr_disable ();
  105. if (sema->value > 0)
  106. {
  107. sema->value--;
  108. success = true;
  109. }
  110. else
  111. success = false;
  112. intr_set_level (old_level);
  113.  
  114. return success;
  115. }
  116.  
  117. /* Up or "V" operation on a semaphore. Increments SEMA's value
  118. and wakes up one thread of those waiting for SEMA, if any.
  119.  
  120. This function may be called from an interrupt handler. */
  121. void
  122. sema_up (struct semaphore *sema)
  123. {
  124. enum intr_level old_level;
  125.  
  126. ASSERT (sema != NULL);
  127.  
  128. old_level = intr_disable ();
  129. struct thread *t = NULL;
  130. if (!list_empty (&sema->waiters)){
  131. t = list_entry (list_pop_front (&sema->waiters),
  132. struct thread, elem);
  133. thread_unblock (t);
  134. }
  135.  
  136. sema->value++;
  137. intr_set_level (old_level);
  138. if(t!=NULL && t->priority > thread_current()->priority){
  139. thread_yield();
  140. }
  141.  
  142. }
  143.  
  144. static void sema_test_helper (void *sema_);
  145.  
  146. /* Self-test for semaphores that makes control "ping-pong"
  147. between a pair of threads. Insert calls to printf() to see
  148. what's going on. */
  149. void
  150. sema_self_test (void)
  151. {
  152. struct semaphore sema[2];
  153. int i;
  154.  
  155. printf ("Testing semaphores...");
  156. sema_init (&sema[0], 0);
  157. sema_init (&sema[1], 0);
  158. thread_create ("sema-test", PRI_DEFAULT, sema_test_helper, &sema);
  159. for (i = 0; i < 10; i++)
  160. {
  161. sema_up (&sema[0]);
  162. sema_down (&sema[1]);
  163. }
  164. printf ("done.\n");
  165. }
  166.  
  167. /* Thread function used by sema_self_test(). */
  168. static void
  169. sema_test_helper (void *sema_)
  170. {
  171. struct semaphore *sema = sema_;
  172. int i;
  173.  
  174. for (i = 0; i < 10; i++)
  175. {
  176. sema_down (&sema[0]);
  177. sema_up (&sema[1]);
  178. }
  179. }
  180. /* Initializes LOCK. A lock can be held by at most a single
  181. thread at any given time. Our locks are not "recursive", that
  182. is, it is an error for the thread currently holding a lock to
  183. try to acquire that lock.
  184.  
  185. A lock is a specialization of a semaphore with an initial
  186. value of 1. The difference between a lock and such a
  187. semaphore is twofold. First, a semaphore can have a value
  188. greater than 1, but a lock can only be owned by a single
  189. thread at a time. Second, a semaphore does not have an owner,
  190. meaning that one thread can "down" the semaphore and then
  191. another one "up" it, but with a lock the same thread must both
  192. acquire and release it. When these restrictions prove
  193. onerous, it's a good sign that a semaphore should be used,
  194. instead of a lock. */
  195. void
  196. lock_init (struct lock *lock)
  197. {
  198. ASSERT (lock != NULL);
  199.  
  200. lock->holder = NULL;
  201. sema_init (&lock->semaphore, 1);
  202. }
  203.  
  204. /* Acquires LOCK, sleeping until it becomes available if
  205. necessary. The lock must not already be held by the current
  206. thread.
  207.  
  208. This function may sleep, so it must not be called within an
  209. interrupt handler. This function may be called with
  210. interrupts disabled, but interrupts will be turned back on if
  211. we need to sleep. */
  212. void
  213. lock_acquire (struct lock *lock)
  214. {
  215. ASSERT (lock != NULL);
  216. ASSERT (!intr_context ());
  217. ASSERT (!lock_held_by_current_thread (lock));
  218. enum intr_level old_level;
  219. old_level = intr_disable ();
  220.  
  221. struct thread *curr = thread_current();
  222. //Check if the current lock is taken
  223.  
  224. if(sema_try_down(&lock->semaphore)){
  225. lock->holder = curr;
  226. } else{
  227. /**Since the lock was taken, we must donate this thread's priority to the lock holder
  228. lock holder == someone else **/
  229. struct lock *next_lock = lock;
  230. struct thread *next_thread = lock->holder;
  231. while(next_thread!=NULL){
  232. next_thread->priority = curr->priority;
  233. if(next_thread->status==THREAD_BLOCKED){
  234. remove_list_elem(next_thread->list_of_elem, &(next_thread->elem));
  235. list_insert_ordered(next_thread->list_of_elem, &(next_thread->elem),
  236. priority_less_func, NULL);
  237. }
  238.  
  239. next_lock = next_thread->blocking_lock;
  240. if(next_lock==NULL){
  241. break;
  242. }
  243. next_thread = next_lock->holder;
  244. }
  245. struct list_elem *lock_elem_ = &lock->lock_elem;
  246. remove_list_elem(&lock->holder->lock_list, lock_elem_);
  247. list_push_front(&lock->holder->lock_list, lock_elem_);
  248. curr->blocking_lock = lock;
  249.  
  250. sema_down(&lock->semaphore);
  251. lock->holder = curr;
  252. curr->blocking_lock = NULL;// THIS MIGHT NEED TO BE IN LOCK RELEASE
  253.  
  254. /*We want to order our lock list so that the lock with the highest waiting priority is at the
  255. front of the lock list**/
  256. }
  257. list_push_back(&curr->lock_list, &lock->lock_elem);
  258. intr_set_level(old_level);
  259. }
  260.  
  261. /* Tries to acquires LOCK and returns true if successful or false
  262. on failure. The lock must not already be held by the current
  263. thread.
  264.  
  265. This function will not sleep, so it may be called within an
  266. interrupt handler. */
  267. bool
  268. lock_try_acquire (struct lock *lock)
  269. {
  270. bool success;
  271.  
  272. ASSERT (lock != NULL);
  273. ASSERT (!lock_held_by_current_thread (lock));
  274.  
  275. success = sema_try_down (&lock->semaphore);
  276. if (success)
  277. lock->holder = thread_current ();
  278. return success;
  279. }
  280.  
  281. /* Releases LOCK, which must be owned by the current thread.
  282.  
  283. An interrupt handler cannot acquire a lock, so it does not
  284. make sense to try to release a lock within an interrupt
  285. handler. */
  286. void
  287. lock_release (struct lock *lock)
  288. {
  289. ASSERT (lock != NULL);
  290. ASSERT (lock_held_by_current_thread (lock));
  291.  
  292. enum intr_level old_level;
  293. old_level = intr_disable ();
  294.  
  295. struct semaphore *sema = &lock->semaphore;
  296. struct thread *cur = thread_current();
  297. struct list_elem *lock_elem_ = &lock->lock_elem;
  298.  
  299. remove_list_elem(&cur->lock_list, lock_elem_);
  300. lock->holder = NULL;
  301. struct thread *t = NULL;
  302.  
  303. /**If lock list is not empty, then get the top priority from the list of waiters in the first
  304. lock in lock_list.**/
  305. if (!list_empty(&cur->lock_list)){
  306. struct semaphore *lock_sema = &(list_entry(list_begin(&cur->lock_list),
  307. struct lock, lock_elem)->semaphore);
  308. if (!list_empty(&lock_sema->waiters)){
  309. t = list_entry(list_begin(&lock_sema->waiters), struct thread, elem);
  310. if(cur->old_priority < t->priority){
  311. cur->priority = t->priority;
  312. }
  313. }
  314. else{
  315. cur->priority = cur->old_priority;
  316. }
  317. }
  318. else{
  319. cur->priority = cur->old_priority;
  320. }
  321.  
  322. sema_up (sema);
  323. /**If one of the waiters for the lock has a higher priority than the currently running thread,
  324. the thread should yield **/
  325. if (t != NULL && cur->priority < t->priority){
  326. thread_yield();
  327. }
  328. intr_set_level(old_level);
  329. }
  330.  
  331. /* Returns true if the current thread holds LOCK, false
  332. otherwise. (Note that testing whether some other thread holds
  333. a lock would be racy.) */
  334. bool
  335. lock_held_by_current_thread (const struct lock *lock)
  336. {
  337. ASSERT (lock != NULL);
  338.  
  339. return lock->holder == thread_current ();
  340. }
  341. /* One semaphore in a list. */
  342. struct semaphore_elem
  343. {
  344. struct list_elem elem; /* List element. */
  345. struct semaphore semaphore; /* This semaphore. */
  346. };
  347.  
  348. /* Initializes condition variable COND. A condition variable
  349. allows one piece of code to signal a condition and cooperating
  350. code to receive the signal and act upon it. */
  351. void
  352. cond_init (struct condition *cond)
  353. {
  354. ASSERT (cond != NULL);
  355.  
  356. list_init (&cond->waiters);
  357. }
  358.  
  359. static bool
  360. cond_less_func (const struct list_elem *a_, const struct list_elem *b_,
  361. void *aux UNUSED)
  362. {
  363. struct semaphore *semaA = &list_entry (a_, struct semaphore_elem, elem)->semaphore;
  364. struct semaphore *semaB = &list_entry (b_, struct semaphore_elem, elem)->semaphore;
  365. const struct thread *a = list_entry(list_begin(&semaA->waiters), struct thread, elem);
  366. const struct thread *b = list_entry(list_begin(&semaB->waiters), struct thread, elem);
  367. printf("%d, %d, %d\n", thread_current()->priority, b->priority, thread_current()->priority > b->priority );
  368. return thread_current()->priority > b->priority;
  369. }
  370.  
  371. /* Atomically releases LOCK and waits for COND to be signaled by
  372. some other piece of code. After COND is signaled, LOCK is
  373. reacquired before returning. LOCK must be held before calling
  374. this function.
  375.  
  376. The monitor implemented by this function is "Mesa" style, not
  377. "Hoare" style, that is, sending and receiving a signal are not
  378. an atomic operation. Thus, typically the caller must recheck
  379. the condition after the wait completes and, if necessary, wait
  380. again.
  381.  
  382. A given condition variable is associated with only a single
  383. lock, but one lock may be associated with any number of
  384. condition variables. That is, there is a one-to-many mapping
  385. from locks to condition variables.
  386.  
  387. This function may sleep, so it must not be called within an
  388. interrupt handler. This function may be called with
  389. interrupts disabled, but interrupts will be turned back on if
  390. we need to sleep. */
  391. void
  392. cond_wait (struct condition *cond, struct lock *lock)
  393. {
  394. struct semaphore_elem waiter;
  395.  
  396. ASSERT (cond != NULL);
  397. ASSERT (lock != NULL);
  398. ASSERT (!intr_context ());
  399. ASSERT (lock_held_by_current_thread (lock));
  400.  
  401. sema_init (&waiter.semaphore, 0);
  402. //list_push_back (&cond->waiters, &waiter.elem);
  403. list_insert_ordered(&cond->waiters, &waiter.elem, cond_less_func, NULL);
  404. struct semaphore *s = &list_entry (list_begin(&cond->waiters), struct semaphore_elem, elem)->semaphore;
  405. struct thread *a = list_entry(list_begin(&s->waiters), struct thread, elem);
  406. lock_release (lock);
  407. sema_down (&waiter.semaphore);
  408. lock_acquire (lock);
  409. }
  410.  
  411. /* If any threads are waiting on COND (protected by LOCK), then
  412. this function signals one of them to wake up from its wait.
  413. LOCK must be held before calling this function.
  414.  
  415. An interrupt handler cannot acquire a lock, so it does not
  416. make sense to try to signal a condition variable within an
  417. interrupt handler. */
  418. void
  419. cond_signal (struct condition *cond, struct lock *lock UNUSED)
  420. {
  421. ASSERT (cond != NULL);
  422. ASSERT (lock != NULL);
  423. ASSERT (!intr_context ());
  424. ASSERT (lock_held_by_current_thread (lock));
  425.  
  426.  
  427. if (!list_empty (&cond->waiters)){
  428. struct semaphore *s = &list_entry (list_pop_front(&cond->waiters), struct semaphore_elem, elem)->semaphore;
  429. struct thread *a = list_entry(list_begin(&s->waiters), struct thread, elem);
  430. sema_up(s);
  431. }
  432. }
  433.  
  434. /* Wakes up all threads, if any, waiting on COND (protected by
  435. LOCK). LOCK must be held before calling this function.
  436.  
  437. An interrupt handler cannot acquire a lock, so it does not
  438. make sense to try to signal a condition variable within an
  439. interrupt handler. */
  440. void
  441. cond_broadcast (struct condition *cond, struct lock *lock)
  442. {
  443. ASSERT (cond != NULL);
  444. ASSERT (lock != NULL);
  445.  
  446. while (!list_empty (&cond->waiters))
  447. cond_signal (cond, lock);
  448. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement