Separate persistence tests from the extended filesys tests.
[pintos.git] / src / devices / intq.c
blob028dca4272aee56836c64a68974e8cd4bf4ef5a4
1 #include "devices/intq.h"
2 #include <debug.h>
3 #include "threads/thread.h"
5 static int next (int pos);
6 static void wait (struct intq *q, struct thread **waiter);
7 static void signal (struct intq *q, struct thread **waiter);
9 /* Initializes interrupt queue Q. */
10 void
11 intq_init (struct intq *q)
13 lock_init (&q->lock);
14 q->not_full = q->not_empty = NULL;
15 q->head = q->tail = 0;
18 /* Returns true if Q is empty, false otherwise. */
19 bool
20 intq_empty (const struct intq *q)
22 ASSERT (intr_get_level () == INTR_OFF);
23 return q->head == q->tail;
26 /* Returns true if Q is full, false otherwise. */
27 bool
28 intq_full (const struct intq *q)
30 ASSERT (intr_get_level () == INTR_OFF);
31 return next (q->head) == q->tail;
34 /* Removes a byte from Q and returns it.
35 Q must not be empty if called from an interrupt handler.
36 Otherwise, if Q is empty, first sleeps until a byte is
37 added. */
38 uint8_t
39 intq_getc (struct intq *q)
41 uint8_t byte;
43 ASSERT (intr_get_level () == INTR_OFF);
44 while (intq_empty (q))
46 ASSERT (!intr_context ());
47 lock_acquire (&q->lock);
48 wait (q, &q->not_empty);
49 lock_release (&q->lock);
52 byte = q->buf[q->tail];
53 q->tail = next (q->tail);
54 signal (q, &q->not_full);
55 return byte;
58 /* Adds BYTE to the end of Q.
59 Q must not be full if called from an interrupt handler.
60 Otherwise, if Q is full, first sleeps until a byte is
61 removed. */
62 void
63 intq_putc (struct intq *q, uint8_t byte)
65 ASSERT (intr_get_level () == INTR_OFF);
66 while (intq_full (q))
68 ASSERT (!intr_context ());
69 lock_acquire (&q->lock);
70 wait (q, &q->not_full);
71 lock_release (&q->lock);
74 q->buf[q->head] = byte;
75 q->head = next (q->head);
76 signal (q, &q->not_empty);
79 /* Returns the position after POS within an intq. */
80 static int
81 next (int pos)
83 return (pos + 1) % INTQ_BUFSIZE;
86 /* WAITER must be the address of Q's not_empty or not_full
87 member. Waits until the given condition is true. */
88 static void
89 wait (struct intq *q UNUSED, struct thread **waiter)
91 ASSERT (!intr_context ());
92 ASSERT (intr_get_level () == INTR_OFF);
93 ASSERT ((waiter == &q->not_empty && intq_empty (q))
94 || (waiter == &q->not_full && intq_full (q)));
96 *waiter = thread_current ();
97 thread_block ();
100 /* WAITER must be the address of Q's not_empty or not_full
101 member, and the associated condition must be true. If a
102 thread is waiting for the condition, wakes it up and resets
103 the waiting thread. */
104 static void
105 signal (struct intq *q UNUSED, struct thread **waiter)
107 ASSERT (intr_get_level () == INTR_OFF);
108 ASSERT ((waiter == &q->not_empty && !intq_empty (q))
109 || (waiter == &q->not_full && !intq_full (q)));
111 if (*waiter != NULL)
113 thread_unblock (*waiter);
114 *waiter = NULL;