1 #include "devices/intq.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, naming it NAME (for debugging
12 intq_init (struct intq *q, const char *name)
14 lock_init (&q->lock, name);
15 q->not_full = q->not_empty = NULL;
16 q->head = q->tail = 0;
19 /* Returns true if Q is empty, false otherwise. */
21 intq_empty (const struct intq *q)
23 ASSERT (intr_get_level () == INTR_OFF);
24 return q->head == q->tail;
27 /* Returns true if Q is full, false otherwise. */
29 intq_full (const struct intq *q)
31 ASSERT (intr_get_level () == INTR_OFF);
32 return next (q->head) == q->tail;
35 /* Removes a byte from Q and returns it.
36 Q must not be empty if called from an interrupt handler.
37 Otherwise, if Q is empty, first sleeps until a byte is
40 intq_getc (struct intq *q)
44 ASSERT (intr_get_level () == INTR_OFF);
45 while (intq_empty (q))
47 ASSERT (!intr_context ());
48 lock_acquire (&q->lock);
49 wait (q, &q->not_empty);
50 lock_release (&q->lock);
53 byte = q->buf[q->tail];
54 q->tail = next (q->tail);
55 signal (q, &q->not_full);
59 /* Adds BYTE to the end of Q.
60 Q must not be full if called from an interrupt handler.
61 Otherwise, if Q is full, first sleeps until a byte is
64 intq_putc (struct intq *q, uint8_t byte)
66 ASSERT (intr_get_level () == INTR_OFF);
69 ASSERT (!intr_context ());
70 lock_acquire (&q->lock);
71 wait (q, &q->not_full);
72 lock_release (&q->lock);
75 q->buf[q->head] = byte;
76 q->head = next (q->head);
77 signal (q, &q->not_empty);
80 /* Returns the position after POS within an intq. */
84 return (pos + 1) % INTQ_BUFSIZE;
87 /* WAITER must be the address of Q's not_empty or not_full
88 member. Waits until the given condition is true. */
90 wait (struct intq *q, struct thread **waiter)
92 ASSERT (!intr_context ());
93 ASSERT (intr_get_level () == INTR_OFF);
94 ASSERT ((waiter == &q->not_empty && intq_empty (q))
95 || (waiter == &q->not_full && intq_full (q)));
97 *waiter = thread_current ();
101 /* WAITER must be the address of Q's not_empty or not_full
102 member, and the associated condition must be true. If a
103 thread is waiting for the condition, wakes it up and resets
104 the waiting thread. */
106 signal (struct intq *q, struct thread **waiter)
108 ASSERT (intr_get_level () == INTR_OFF);
109 ASSERT ((waiter == &q->not_empty && !intq_empty (q))
110 || (waiter == &q->not_full && !intq_full (q)));
114 thread_unblock (*waiter);