I have been working this issue for several days and have narrowed it down to what I think the problem is, but I'm at a loss to completely explain it. I was wondering if it is a compiler bug or setting, but I would get consistent results which I am not. On the other hand, it feels like timing from a task switch at a "particularly vulnerable" state (is there such a thing) in a return statement.
Here is what I am seeing: The message says that Resume is being called with PID 0, the null process.
My backtrace in gdb shows the following:
Code: Select all
(gdb) backtrace
#0 0x001002cb in hang ()
#1 0x001039d5 in Panic (message=0x105035 "Bad Resume() pid", file=0x105023 "src/proc.Resume.c", line=11) at src/cmn.Panic.c:17
#2 0x00100500 in Resume (pid=0) at src/proc.Resume.c:11
#3 0x00100842 in kmain (mbi=0x2000, magic=732803074) at src/init.kmain.c:45
#4 0x001002c9 in loader ()
Code: Select all
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'D'));
Any other ideas on how I can track down this odd bug? I have seen http://wiki.osdev.org/Troubleshooting and http://wiki.osdev.org/How_Do_I_Use_A_De ... With_My_OS.
[edit: this does not happen at the same line and does not happen every execution. It does happen at a Resume(CreateProcess( )) call.]
TASK_FUNC is a simple macro:
Code: Select all
typedef void (*TaskFunc)();
#define TASK_FUNC(x) (TaskFunc)(&(x))
Code: Select all
#include "kernel.h"
uint16 CreateProcess(TaskFunc t, uint32 numParms, ...)
{
ProcessQueueEntry *newProc = Dequeue(&freeQ);
if (0 == newProc) PANIC("Ran out of process Threads to use\n");
uint32 ps = DisableInterrupts();
uint16 pid = newProc->pid;
ProcessEntry *pe = &ProcessList[pid];
uint32 flags;
uint32 *esp;
pe->state = PRC_SUSP;
pe->priority = PTY_NORM;
pe->sem = 0;
pe->msg = 0;
pe->hasMsg = 0;
pe->stack = (uint32 *)kmalloc_a(INITIAL_STACK_SIZE);
pe->stackLength = INITIAL_STACK_SIZE;
esp = (uint32 *)((uint32)pe->stack + INITIAL_STACK_SIZE - 32);
pe->ss = GetDS(); // Stack will be from the Heap (DS)
pe->cr3 = GetCR3();
flags = GetFlags();
int *a = (int *)((&numParms) + (numParms + 1));
// start building the stack for _SwitchTasks
for (; numParms > 0; numParms --) *(--esp) = *(--a);
*(--esp) = (uint32)&UserReturn; // where to go when user task returns
*(--esp) = (uint32)t; // eip on the stack for entry point
*(--esp) = (uint32)&EnableInterrupts;
*(--esp) = 0; // ebp
*(--esp) = flags;
*(--esp) = 0; // eax
*(--esp) = 0; // ebx
*(--esp) = 0; // ecx
*(--esp) = 0; // edx
*(--esp) = 0; // esi
*(--esp) = 0; // edi
*(--esp) = (uint32)pe->ss; // ds is the same as ss
*(--esp) = (uint32)pe->ss; // es is the same as ss
*(--esp) = (uint32)pe->ss; // fs is the same as ss
*(--esp) = (uint32)pe->ss; // gs is the same as ss
pe->esp = (uint32)esp;
processCount ++;
Enqueue(&waitQ, newProc);
RestoreInterrupts(ps);
return pid;
}
Code: Select all
#include "kernel.h"
void Resume(uint16 pid)
{
uint32 flags = DisableInterrupts();
if (IS_BAD_PID(pid) || ProcessList[pid].state != PRC_SUSP) {
if (IS_BAD_PID(pid)) {
kPutStr("Bad PID in Resume() call: ");
kPutDec(pid);
PANIC("Bad Resume() pid");
}
goto out;
}
ReadyProcess(pid);
out:
RestoreInterrupts(flags);
}
Code: Select all
/*!
* @file init.kmain.c
* @author Adam Clark
* @short Kernel Main initialization routine
*
* This file contains the main initialization routine for the Century
* Hobby OS Kernel. It performs the following functions:
* 1. Checks the magic number to see if it is valid
* 2. Initializes the GDT Table
*/
#include "kernel.h"
void PrintA(void);
void PrintB(void);
void PrintLetter(char);
void kmain (void *mbi, unsigned int magic)
{
mbi = mbi;
if ( magic != 0x2badb002 ) {
kCls();
kPutStr("PANIC: Invalid magic number!!");
return;
}
kCls();
UpdateStatus();
InitGDT();
InitIDT();
InitPaging();
InitProcess();
InitTimer(2000);
kPutStr("\nStarting the Operating System\n");
EnableInterrupts();
uint16 A = CreateProcess(&PrintA, 0);
uint16 B = CreateProcess(&PrintB, 0);
uint16 C = CreateProcess(TASK_FUNC(PrintLetter), 1, 'C');
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'D'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'E'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'F'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'G'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'I'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'J'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'K'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'L'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'M'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'N'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'O'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'P'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'Q'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'R'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'S'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'T'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'U'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'V'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'W'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'X'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'Y'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, 'Z'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, '1'));
Resume(CreateProcess(TASK_FUNC(PrintLetter), 1, '2'));
Resume(A);
Resume(B);
Resume(C);
while (1) {
Resume(A);
Resume(B);
// asm volatile("hlt");
}
}