]> wirehaze git hosting - ppos.git/commitdiff

wirehaze git hosting

tasks implementation (ongoing) main
authorphfr24 <phfr24@inf.ufpr.br>
Sat, 14 Mar 2026 18:08:31 +0000 (15:08 -0300)
committerphfr24 <phfr24@inf.ufpr.br>
Sat, 14 Mar 2026 18:08:31 +0000 (15:08 -0300)
ppos/kernel/task.c
ppos/kernel/tcb.h

index a97fee7767faed0ade71637e605b6ad350cd8596..4266c39933e9158d0e28983310cc33f813e0aa9a 100644 (file)
@@ -1,5 +1,198 @@
 // PingPongOS - PingPong Operating System
 
 // PingPongOS - PingPong Operating System
 
-void task_init()
+/* PEDRO HENRIQUE FRIEDRICH RAMOS : GRR20243133  */
+
+#include <sys/mman.h>
+#include <stlib.h>
+#include "tcb.h"
+#include "ctx.h"
+
+/* -------------------------------------------------------------------------  */
+/* Constants  --------------------------------------------------------------  */
+
+/* 8 pages = 32 KiB  */
+#define STACK_SIZE (8 * 4096)
+
+/* -------------------------------------------------------------------------  */
+/* Static variables  -------------------------------------------------------  */
+
+static struct task_t *task_current;
+static struct task_t task_kernel; /* Is task_kernel like init for ppos?  */
+
+/* -------------------------------------------------------------------------  */
+/* Internal functions  -----------------------------------------------------  */
+
+/* Allocate memory for a task's stack.
+ *
+ * The size parameter must be page aligned!  */
+static inline void *
+alloc_stack (size_t size)
 {
 {
+
+  /* Using mmap () instead of malloc () makes a little bit more sense, since
+   * when a task ends the mapping can be immediately deleted. If we use malloc,
+   * we can't know for sure if the brk will be lowered.
+   *
+   * Also, it (probably) makes the stack allocations farther apart, so it's less
+   * likely that a task can corrupt another task's stack by accident, which is
+   * possible since ppos doesn't have virtual memory nor memory protection.  */
+
+  return mmap (/* Let the kernel choose the address for the mapping.  */
+               NULL,
+
+               /* Size of the mapping (must be page-aligned).  */
+               size,
+
+               /* RW stack.  */
+               PROT_READ | PROT_WRITE,
+
+               /* Not shared between (linux) processes.
+                * Not backed by a file.  */
+               MAP_PRIVATE | MAP_ANONYMOUS,
+
+               /* No file descriptor.  */
+               -1,
+
+               /* No offset.  */
+               0);
 }
 }
+
+/* -------------------------------------------------------------------------  */
+
+/* Free allocated memory for a task's stack.  */
+static inline int
+free_stack (void *stack, size_t size)
+{
+  return munmap (stack, size);
+}
+
+/* -------------------------------------------------------------------------  */
+
+/* Get the next free task id.
+ *
+ * Stupid simple implementation, not thread safe!  */
+static int
+get_next_id (void)
+{
+  static int id = 0;
+  return ++id; /* id=0 is reserved for task_kernel  */
+}
+
+/* -------------------------------------------------------------------------  */
+/* Exported functions  -----------------------------------------------------  */
+
+void
+task_init (void)
+{
+  /* TODO  */
+}
+
+/* -------------------------------------------------------------------------  */
+
+struct task_t *
+task_create (char *name, void (*entry) (void *), void *arg)
+{
+  struct task_t *task;
+  unsigned char *stack;
+
+  if (!(task = malloc (sizeof *task)))
+    goto err_malloc_task;
+
+  if (!(stack = alloc_stack (STACK_SIZE)))
+    goto err_malloc_stack;
+
+  task->id = get_next_id ();
+  task->name = name;
+  task->status = STATUS_READY;
+
+  /* Probably not the best way to do this but with this interface and the
+   * current implementation it's the best we can do right now.
+   *
+   * We need it for task_switch ().
+   *
+   * In a multiprocessor system this doesn't hold up.  */
+
+  task->parent = task_current;
+
+  if (ctx_create (&task->context, entry, arg, stack, STACK_SIZE))
+    goto err_ctx_create;
+
+  return task;
+
+err_ctx_create:
+  free_stack (stack, STACK_SIZE);
+err_malloc_stack:
+  free (task);
+err_malloc_task:
+  return NULL;
+}
+
+/* -------------------------------------------------------------------------  */
+
+int
+task_destroy (struct task_t *task)
+{
+  if (task->status != STATUS_TERMINATED)
+    return ERROR;
+
+  if (free_stack (task->context.stack, task->context.size))
+    return ERROR; /* Probably EINVAL.  */
+
+  free (task);
+
+  return NOERROR;
+}
+
+/* -------------------------------------------------------------------------  */
+
+int
+task_switch (struct task_t *task)
+{
+  if (!task)
+    return task_switch (task_current->parent);
+
+  /* Instructions not clear...  */
+  switch (task->status)
+    {
+    case STATUS_TERMINATED: /* Switch to task_kernel or to parent?  */
+      return task_switch (task_kernel);
+
+    case STATUS_RUNNING: /* Return ERROR or switch to another task?  */
+      return ERROR;
+    }
+
+  task_current->status = STATUS_SUSPENDED;
+  task_current = task;
+  task_current->status = STATUS_RUNNING;
+
+  /* task_current and task are not the same, because if they task->status would
+   * be STATUS_RUNNING, which is handled earlier.
+   *
+   * Since that's the only error case for ctx_swap (), we're fine ...  */
+
+  return ctx_swap (&task_current->context, &task->context);
+}
+
+/* -------------------------------------------------------------------------  */
+
+int
+task_id (struct task_t *task)
+{
+  if (!task)
+    return task_id (task->current);
+
+  return task->id;
+}
+
+/* -------------------------------------------------------------------------  */
+
+char *
+task_name (struct task_t *task)
+{
+  if (!task)
+    return task_id (task->current);
+
+  return task->name;
+}
+
+/* -------------------------------------------------------------------------  */
index d93897a9285a2372ef6b9aca14f0b4ce633df9d1..230bcdfc6b3cf63556e6fb1351905a72d1836d29 100644 (file)
@@ -9,13 +9,23 @@
 
 #include "ctx.h"
 
 
 #include "ctx.h"
 
-// Task Control Block (TCB), infos sobre uma tarefa
-struct task_t
+/* TODO  */
+enum task_status
 {
 {
-    int id;                     // identificador da tarefa
-    char *name;                 // nome da tarefa
-    struct ctx_t context;       // contexto armazenado da tarefa
-                                // ...
+  STATUS_READY,
+  STATUS_RUNNING,
+  STATUS_SUSPENDED,
+  STATUS_TERMINATED
+};
+
+/* Task Control Block.  */
+struct task_t
+{/* TODO comment fields.  */
+  int id;
+  char *name;
+  enum task_status status;
+  struct task_t *parent;
+  struct ctx_t context;
 };
 
 #endif
 };
 
 #endif