commit 5ca7441102daf5ab906359f8f45e3d74979b470a
parent 7e304f12d94a6d4ea5cc5518f2e093508cb746f4
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Sat, 16 Mar 2024 09:39:54 +0900
implement save_context
Diffstat:
| M | ex3/main.c | | | 74 | +++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- | 
| M | ex3/proc.s | | | 18 | +----------------- | 
2 files changed, 52 insertions(+), 40 deletions(-)
diff --git a/ex3/main.c b/ex3/main.c
@@ -1,3 +1,5 @@
+#define NULL 0L // TODO: Should fail when dereferenced.
+
 void init(void);
 int puts(char *);
 void printh(void *);
@@ -9,11 +11,6 @@ void wfi(void);
 void *memcpy(void *s1, void *s2, long n);
 void setreg(void);
 
-extern char proc0_start, proc0_size;
-extern char proc1_start, proc1_size;
-extern char msg0;
-extern char msg1;
-
 // A proc represents a process in execution.
 typedef struct proc {
 	// Id is the unique identifier of the process.
@@ -24,6 +21,14 @@ typedef struct proc {
 	struct proc *next;
 } proc;
 
+proc *save_context(unsigned int pid, void *r[16]);
+
+extern char proc0_start, proc0_size;
+extern char proc1_start, proc1_size;
+extern char msg0;
+extern char msg1;
+
+
 // A proc_tab is the queue of waiting processes.
 typedef struct proc_tab {
 	// Head is the head of the queue.
@@ -32,7 +37,7 @@ typedef struct proc_tab {
 	proc *tail;
 } proc_tab;
 
-proc_tab *ptab;
+proc_tab ptab;
 
 int
 main(void) {
@@ -42,24 +47,61 @@ main(void) {
 	memcpy((void *)0x20000000, &proc0_start, (long) &proc0_size);
 	memcpy((void *)0x20000100, &proc1_start, (long) &proc1_size);
 
+	ptab.head = &p0;
+	ptab.tail = &p1;
+
+	p0.id = 0;
 	p0.r[13] = (void *) 0x20000100; // sp
 	p0.r[14] = (void *) main; // lr
 	p0.r[15] = (void *) 0x20000000; // pc
+	p0.next = &p1;
 
+	p1.id = 1;
 	p1.r[13] = (void *) 0x20000200; // sp
 	p1.r[14] = (void *) main; // lr
 	p1.r[15] = (void *) 0x20000100; // pc
+	p1.next = NULL;
 
 	for (;;) {
 		setreg();
 		wfi();
+		void *r[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+		proc *p = save_context(0, r);
+		if (p == NULL) {
+			puts("process 0 not found");
+			continue;
+		}
+		for (int i = 0; i < 16; i++) {
+			printh(p0.r[i]);
+			puts("");
+		}
+		puts("");
 	}
 	return 0;
 }
 
-void
-save_context(proc *p)
-{}
+// Save_context saves registers r to the proc struct specified by pid.
+// It returns the address of matching process, or NULL if no such process is found.
+proc *
+save_context(unsigned int pid, void *r[16])
+{
+	proc *p;
+	int i;
+
+	for (p = ptab.head; p; p = p->next) {
+		if (p->id == pid) {
+			break;
+		}
+	}
+	if (!p) {
+		return NULL;
+	}
+
+	for (i = 0; i < 16; i++) {
+		p->r[i] = r[i];
+	}
+	return p;
+}
 
 void
 restore_context(proc *p)
@@ -80,16 +122,3 @@ void
 isr_svcall(void) {
 	puts("svcall");
 }
-/*
-void
-isr_alarm(void) {
-	int *sp = get_sp();
-	for (int i = 0; i < 12; i += 1) {
-		printh(sp+i);
-		printh((void *)*(sp+i));
-		puts("");
-	}
-	scheduler();
-	set_alarm(1000 * 1000);
-}
-*/
-\ No newline at end of file
diff --git a/ex3/proc.s b/ex3/proc.s
@@ -55,21 +55,6 @@ print_sr:
 	.global isr_alarm
 isr_alarm:
 	push {r4, r5, r6, lr}
-	bl get_sp
-	mov r4, r0
-	mov r5, sp
-	add r5, #16
-	mov r6, r5
-	add r6, #32 // 8 words
-isr_alarm_loop:
-	ldr r0, [r5, #0]
-	bl printh
-	mov r0, #'\n'
-	bl putbyte
-	add r5, r5, #4
-	cmp r5, r6
-	blt isr_alarm_loop
-	bl scheduler
 	ldr r0, =(1000 * 1000)
 	bl set_alarm
-	pop {r4, r5, r6, pc}
-\ No newline at end of file
+	pop {r4, r5, r6, pc}