From b323bc875a248c68df1b5608e3475848cdcb5569 Mon Sep 17 00:00:00 2001
From: h2-addad <hamza2.addad@live.uwe.ac.uk>
Date: Sun, 16 Jul 2023 00:33:30 +0000
Subject: [PATCH] Update

---
 src/devices/intq.c | 114 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)
 create mode 100644 src/devices/intq.c

diff --git a/src/devices/intq.c b/src/devices/intq.c
new file mode 100644
index 0000000..40b23ae
--- /dev/null
+++ b/src/devices/intq.c
@@ -0,0 +1,114 @@
+#include "devices/intq.h"
+#include <debug.h>
+#include "threads/thread.h"
+
+static int next (int pos);
+static void wait (struct intq *q, struct thread **waiter);
+static void signal (struct intq *q, struct thread **waiter);
+
+/* Initializes interrupt queue Q. */
+void
+intq_init (struct intq *q) 
+{
+  lock_init (&q->lock);
+  q->not_full = q->not_empty = NULL;
+  q->head = q->tail = 0;
+}
+
+/* Returns true if Q is empty, false otherwise. */
+bool
+intq_empty (const struct intq *q) 
+{
+  ASSERT (intr_get_level () == INTR_OFF);
+  return q->head == q->tail;
+}
+
+/* Returns true if Q is full, false otherwise. */
+bool
+intq_full (const struct intq *q) 
+{
+  ASSERT (intr_get_level () == INTR_OFF);
+  return next (q->head) == q->tail;
+}
+
+/* Removes a byte from Q and returns it.
+   If Q is empty, sleeps until a byte is added.
+   When called from an interrupt handler, Q must not be empty. */
+uint8_t
+intq_getc (struct intq *q) 
+{
+  uint8_t byte;
+  
+  ASSERT (intr_get_level () == INTR_OFF);
+  while (intq_empty (q)) 
+    {
+      ASSERT (!intr_context ());
+      lock_acquire (&q->lock);
+      wait (q, &q->not_empty);
+      lock_release (&q->lock);
+    }
+  
+  byte = q->buf[q->tail];
+  q->tail = next (q->tail);
+  signal (q, &q->not_full);
+  return byte;
+}
+
+/* Adds BYTE to the end of Q.
+   If Q is full, sleeps until a byte is removed.
+   When called from an interrupt handler, Q must not be full. */
+void
+intq_putc (struct intq *q, uint8_t byte) 
+{
+  ASSERT (intr_get_level () == INTR_OFF);
+  while (intq_full (q))
+    {
+      ASSERT (!intr_context ());
+      lock_acquire (&q->lock);
+      wait (q, &q->not_full);
+      lock_release (&q->lock);
+    }
+
+  q->buf[q->head] = byte;
+  q->head = next (q->head);
+  signal (q, &q->not_empty);
+}
+
+/* Returns the position after POS within an intq. */
+static int
+next (int pos) 
+{
+  return (pos + 1) % INTQ_BUFSIZE;
+}
+
+/* WAITER must be the address of Q's not_empty or not_full
+   member.  Waits until the given condition is true. */
+static void
+wait (struct intq *q UNUSED, struct thread **waiter) 
+{
+  ASSERT (!intr_context ());
+  ASSERT (intr_get_level () == INTR_OFF);
+  ASSERT ((waiter == &q->not_empty && intq_empty (q))
+          || (waiter == &q->not_full && intq_full (q)));
+
+  *waiter = thread_current ();
+  thread_block ();
+}
+
+/* WAITER must be the address of Q's not_empty or not_full
+   member, and the associated condition must be true.  If a
+   thread is waiting for the condition, wakes it up and resets
+   the waiting thread. */
+static void
+signal (struct intq *q UNUSED, struct thread **waiter) 
+{
+  ASSERT (intr_get_level () == INTR_OFF);
+  ASSERT ((waiter == &q->not_empty && !intq_empty (q))
+          || (waiter == &q->not_full && !intq_full (q)));
+
+  if (*waiter != NULL) 
+    {
+      thread_unblock (*waiter);
+      *waiter = NULL;
+    }
+}
-- 
GitLab