changeset 506:5cb01f04b0eb

cp: handle task exits Introduced a new SVC that will terminate the current task. If a task returns from its "main" function, it will implicitly use this new SVC. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Sat, 23 Apr 2011 17:29:58 -0400
parents b1c6346f553c
children 354fc5b6cbd9
files cp/include/interrupt.h cp/include/sched.h cp/nucleus/sched.c cp/nucleus/svc.c
diffstat 4 files changed, 54 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/cp/include/interrupt.h	Sat Apr 23 14:16:31 2011 -0400
+++ b/cp/include/interrupt.h	Sat Apr 23 17:29:58 2011 -0400
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2007-2010  Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ * (C) Copyright 2007-2011  Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  *
  * This file is released under the GPLv2.  See the COPYING file for more
  * details.
@@ -89,7 +89,8 @@
  */
 #define SVC_SCHEDULE		0
 #define SVC_SCHEDULE_BLOCKED	1
-#define NR_SVC			2
+#define SVC_SCHEDULE_EXIT	2
+#define NR_SVC			3
 extern u64 svc_table[NR_SVC];
 
 /* Interrupt handlers */
--- a/cp/include/sched.h	Sat Apr 23 14:16:31 2011 -0400
+++ b/cp/include/sched.h	Sat Apr 23 17:29:58 2011 -0400
@@ -21,6 +21,7 @@
 #define TASK_RUNNING		0
 #define TASK_SLEEPING		1
 #define TASK_LOCKED		2
+#define TASK_ZOMBIE		3
 
 #define STACK_FRAME_SIZE	160
 
@@ -115,6 +116,8 @@
 
 	int state;			/* state */
 
+	void *stack;			/* the stack */
+
 	char name[TASK_NAME_LEN+1];	/* task name */
 
 	/* lock dependency tracking */
@@ -143,6 +146,7 @@
 		       int newstate);	/* scheduler helper - use with caution */
 extern void __schedule_svc(void);
 extern void __schedule_blocked_svc(void);
+extern void __schedule_exit_svc(void);
 
 extern void make_runnable(struct task *task);
 
@@ -212,4 +216,23 @@
 	);
 }
 
+/**
+ * exit - schedule with the intent to terminate the current task
+ */
+static inline void exit(void)
+{
+	/*
+	 * if we are not interruptable, we shouldn't call any functions that
+	 * may sleep - schedule() is guaranteed to sleep :)
+	 */
+	BUG_ON(!interruptable());
+
+	asm volatile(
+		"	svc	%0\n"
+	: /* output */
+	: /* input */
+	  "i" (SVC_SCHEDULE_EXIT)
+	);
+}
+
 #endif
--- a/cp/nucleus/sched.c	Sat Apr 23 14:16:31 2011 -0400
+++ b/cp/nucleus/sched.c	Sat Apr 23 17:29:58 2011 -0400
@@ -32,15 +32,9 @@
 	if (f)
 		(*f)(data);
 
-	/*
-	 * Done, now, it's time to cleanup
-	 *
-	 * FIXME:
-	 *  - delete from processes list
-	 *  - free stack page
-	 *  - free struct
-	 *  - schedule
-	 */
+	exit();
+
+	/* unreachable */
 	BUG();
 }
 
@@ -68,6 +62,8 @@
 
 	task->state = TASK_SLEEPING;
 
+	task->stack = stack;
+
 	task->nr_locks = 0;
 }
 
@@ -224,8 +220,6 @@
 	 * Add back on the queue
 	 */
 	prev->state = newstate;
-	if (newstate != TASK_LOCKED)
-		list_add_tail(&prev->run_queue, &runnable);
 
 	/*
 	 * If the previous task didn't use it's full slice, force idle_task
@@ -234,6 +228,19 @@
 	if (prev->slice_end_time >= (ticks + SCHED_TICKS_PER_SLICE))
 		force_idle = prev->slice_end_time;
 
+	switch(newstate) {
+		case TASK_ZOMBIE:
+			list_del(&prev->proc_list);
+			free_pages(prev->stack, 0);
+			free(prev);
+			break;
+		case TASK_LOCKED:
+			break;
+		default:
+			list_add_tail(&prev->run_queue, &runnable);
+			break;
+	}
+
 go:
 	/*
 	 * Run the rest of the scheduler that selects the next task and
@@ -258,6 +265,14 @@
 	__schedule(SVC_INT_OLD_PSW, TASK_LOCKED);
 }
 
+/**
+ * __schedule_blocked__svc - wrapper for the supervisor-service call handler
+ */
+void __schedule_exit_svc(void)
+{
+	__schedule(SVC_INT_OLD_PSW, TASK_ZOMBIE);
+}
+
 /*
  * Initialize the schduler, and all associated structures
  */
--- a/cp/nucleus/svc.c	Sat Apr 23 14:16:31 2011 -0400
+++ b/cp/nucleus/svc.c	Sat Apr 23 17:29:58 2011 -0400
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2007-2010  Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ * (C) Copyright 2007-2011  Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  *
  * This file is released under the GPLv2.  See the COPYING file for more
  * details.
@@ -11,5 +11,6 @@
 u64 svc_table[NR_SVC] = {
 	(u64) __schedule_svc,
 	(u64) __schedule_blocked_svc,
+	(u64) __schedule_exit_svc,
 };