Separated Architecture independent thread controll into the root of the tree
authorJohn Hodge <[email protected]>
Fri, 25 Sep 2009 00:25:29 +0000 (08:25 +0800)
committerJohn Hodge <[email protected]>
Fri, 25 Sep 2009 00:25:29 +0000 (08:25 +0800)
20 files changed:
Kernel/Makefile
Kernel/arch/x86/errors.c
Kernel/arch/x86/include/arch.h
Kernel/arch/x86/include/proc.h
Kernel/arch/x86/main.c
Kernel/arch/x86/mm_virt.c
Kernel/arch/x86/proc.c
Kernel/arch/x86/start.asm
Kernel/binary.c
Kernel/debug.c
Kernel/drv/ata_x86.c
Kernel/drv/vterm.c
Kernel/heap.c
Kernel/include/common.h
Kernel/include/threads.h [new file with mode: 0644]
Kernel/messages.c
Kernel/syscalls.c
Kernel/threads.c [new file with mode: 0644]
Kernel/vfs/acls.c
Usermode/Applications/CLIShell_src/main.c

index de3c071..68b84b8 100644 (file)
@@ -18,7 +18,7 @@ ASFLAGS               += -D ARCH=\"$(ARCH)\"
 LDFLAGS                += -T arch/$(ARCHDIR)/link.ld
 
 OBJ = $(addprefix arch/$(ARCHDIR)/,$(A_OBJ))
-OBJ += heap.o messages.o debug.o modules.o lib.o syscalls.o system.o
+OBJ += heap.o messages.o debug.o modules.o lib.o syscalls.o system.o threads.o
 OBJ += binary.o bin/elf.o
 OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/dir.o vfs/io.o vfs/mount.o vfs/memfile.o vfs/nodecache.o
 OBJ += vfs/fs/root.o vfs/fs/devfs.o vfs/fs/fat.o
index a8d89ac..2c3582c 100644 (file)
@@ -7,7 +7,7 @@
 
 // === IMPORTS ===
 extern void    MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs);
-extern void Proc_DumpThreads();
+extern void Threads_Dump();
 
 // === CODE ===
 /**
@@ -46,7 +46,7 @@ void ErrorHandler(tRegs *Regs)
        Warning(" CR3: 0x%08x", cr);
        
        // Dump running threads
-       Proc_DumpThreads();
+       Threads_Dump();
        
        for(;;) __asm__ __volatile__ ("hlt");
 }
index 9c16b18..0611c6c 100644 (file)
@@ -42,6 +42,7 @@
 #define LOCK(lockptr)  do {int v=1;\
        while(v)__asm__ __volatile__("lock xchgl %%eax, (%%edi)":"=a"(v):"a"(1),"D"(lockptr));}while(0)
 #define        RELEASE(lockptr)        __asm__ __volatile__("lock andl $0, (%%edi)"::"D"(lockptr));
+#define        HALT()  __asm__ __volatile__ ("hlt")
 
 // === TYPES ===
 typedef unsigned int   Uint;   // Unsigned machine native integer
@@ -109,6 +110,18 @@ typedef struct {
        Uint8   BaseHi;
 } __attribute__ ((packed)) tGDT;
 
+typedef struct {
+       #if USE_PAE
+       Uint    PDPT[4];
+       #else
+       Uint    CR3;
+       #endif
+} tMemoryState;
+
+typedef struct {
+       Uint    EIP, ESP, EBP;
+} tTaskState;
+
 // --- Interface Flags & Macros
 #define CLONE_VM       0x10
 
index 6e559be..6619ec0 100644 (file)
@@ -5,52 +5,12 @@
 #ifndef _PROC_H
 #define _PROC_H
 
+#include <threads.h>
+
 // === CONSTANTS ===
 #define GETMSG_IGNORE  ((void*)-1)
 
 // === TYPES ===
-typedef struct sMessage {
-       struct sMessage *Next;
-       Uint    Source;
-       Uint    Length;
-       Uint8   Data[];
-} tMsg;        // sizeof = 12+
-
-typedef struct sThread {
-       struct sThread  *Next;
-        int    IsLocked;
-        int    Status; //!< Thread Status
-       
-       Uint    TID;    //!< Thread ID
-       Uint    TGID;   //!< Thread Group (Process)
-       Uint    UID, GID;       //!< User and Group
-       char    *ThreadName;    //!< Name of thread
-       
-       Uint    ESP, EBP, EIP;  //!< State on switch
-       #if USE_PAE
-       Uint64  PML4[3];        //!< Address Space
-       #else
-       Uint    CR3;    //!< Memory Space
-       #endif
-       
-       Uint    KernelStack;    //!< Thread's Kernel Stack
-       
-       tMsg    *Messages;      //!< Message Queue
-       tMsg    *LastMessage;   //!< Last Message (speeds up insertion)
-       
-        int    Quantum, Remaining;     //!< Quantum Size and remaining timesteps
-        int    NumTickets;     //!< Priority - Chance of gaining CPU
-       
-       Uint    Config[NUM_CFG_ENTRIES];        //!< Per-process configuration
-} tThread;     // sizeof = 68
-
-enum {
-       THREAD_STAT_NULL,
-       THREAD_STAT_ACTIVE,
-       THREAD_STAT_SLEEPING,
-       THREAD_STAT_WAITING,
-       THREAD_STAT_DEAD
-};
 
 typedef struct sTSS {
        Uint32  Link;
@@ -67,17 +27,8 @@ typedef struct sTSS {
        Uint16  Resvd, IOPB;    // IO Permissions Bitmap
 } tTSS;
 
-// === GLOBALS ===
-extern tThread *gCurrentThread;
-
 // === FUNCTIONS ===
 extern void    Proc_Start();
 extern int     Proc_Clone(Uint *Err, Uint Flags);
-extern void Proc_Exit();
-extern void Proc_Yield();
-extern void Proc_Sleep();
-extern void Proc_SetTickets(int Num);
-extern tThread *Proc_GetThread(Uint TID);
-extern void    Thread_Wake(tThread *Thread);
 
 #endif
index 710923d..304c3dd 100644 (file)
@@ -17,10 +17,10 @@ extern void Desctab_Install();
 extern void    MM_PreinitVirtual();
 extern void    MM_Install(tMBoot_Info *MBoot);
 extern void MM_InstallVirtual();
-extern void    Proc_Start();
+extern void    Threads_Init();
 extern Uint    Proc_Clone(Uint *Err, Uint Flags);
-extern void    Proc_Sleep();
-extern void    Proc_Exit();
+extern void    Threads_Sleep();
+extern void    Threads_Exit();
 
 // === GLOBALS ===
 
@@ -41,7 +41,7 @@ int kmain(Uint MbMagic, tMBoot_Info *MbInfo)
        
        Log("Starting Multitasking...");
        // Start Multitasking
-       Proc_Start();
+       Threads_Init();
        
        Log("Starting VFS...");
        // Load Virtual Filesystem
@@ -71,6 +71,6 @@ int kmain(Uint MbMagic, tMBoot_Info *MbInfo)
        System_Init( (char*)(MbInfo->CommandLine + KERNEL_BASE) );
        
        // Sleep forever (sleeping beauty)
-       for(;;) Proc_Sleep();
+       for(;;) Threads_Sleep();
        return 0;
 }
index a022da2..2e726cc 100644 (file)
@@ -381,7 +381,7 @@ Uint MM_ClearUser()
 Uint MM_Clone()
 {
        Uint    i, j;
-       Uint    kStackBase = gCurrentThread->KernelStack - KERNEL_STACK_SIZE;
+       Uint    kStackBase = Proc_GetCurThread()->KernelStack - KERNEL_STACK_SIZE;
        void    *tmp;
        
        //ENTER("");
@@ -621,7 +621,7 @@ Uint MM_MapTemp(tPAddr PAddr)
                        return TEMP_MAP_ADDR + (i << 12);
                }
                RELEASE( &gilTempMappings );
-               Proc_Yield();
+               Threads_Yield();
        }
 }
 
index 0f9f449..31eb055 100644 (file)
@@ -12,9 +12,6 @@
 
 // === CONSTANTS ===
 #define        SWITCH_MAGIC    0xFFFACE55      // There is no code in this area
-#define        DEFAULT_QUANTUM 10
-#define        DEFAULT_TICKETS 5
-#define MAX_TICKETS            10
 #define TIMER_DIVISOR  11931   //~100Hz
 
 // === IMPORTS ===
@@ -22,59 +19,30 @@ extern tGDT gGDT[];
 extern Uint    GetEIP();       // start.asm
 extern Uint32  gaInitPageDir[1024];    // start.asm
 extern void    Kernel_Stack_Top;
+extern volatile int    giThreadListLock;
+extern int     giNumCPUs;
+extern int     giNextTID;
+extern int     giTotalTickets;
+extern int     giNumActiveThreads;
+extern tThread *gActiveThreads;
+extern tThread *gSleepingThreads;
+extern tThread *gDeleteThreads;
 
 // === PROTOTYPES ===
-void   Proc_Start();
+void   ArchThreads_Init();
+tThread        *Proc_GetCurThread();
 void   Proc_ChangeStack();
  int   Proc_Clone(Uint *Err, Uint Flags);
-void   Proc_Exit();
-void   Proc_Yield();
-void   Proc_Sleep();
-static tThread *Proc_int_GetPrevThread(tThread **List, tThread *Thread);
 void   Proc_Scheduler();
-Sint64 now();
-Uint   rand();
 
 // === GLOBALS ===
-// -- Core Thread --
-tThread        gThreadZero = {
-       NULL, 0,        // Next, Lock
-       THREAD_STAT_ACTIVE,     // Status
-       0, 0,   // TID, TGID
-       0, 0,   // UID, GID
-       "ThreadZero",   // Name
-       0, 0, 0,        // ESP, EBP, EIP (Set on switch)
-       #if USE_PAE
-       {0,0,0},        // PML4 Entries
-       #else
-       (Uint)&gaInitPageDir-KERNEL_BASE,       // CR3
-       #endif
-       (Uint)&Kernel_Stack_Top,        // Kernel Stack (Unused as it is PL0)
-       NULL, NULL,     // Messages, Last Message
-       DEFAULT_QUANTUM, DEFAULT_QUANTUM,       // Quantum, Remaining
-       DEFAULT_TICKETS,
-       {0}     // Default config to zero
-       };
-// -- Processes --
-// --- Locks ---
-volatile int   giThreadListLock = 0;   ///\note NEVER use a heap function while locked
 // --- Current State ---
 #if USE_MP
 tThread        **gCurrentThread = NULL;
-# define CUR_THREAD    gCurrentThread[0]
 #else
 tThread        *gCurrentThread = NULL;
-# define CUR_THREAD    gCurrentThread
 #endif
-volatile int   giNumActiveThreads = 0;
-volatile int   giTotalTickets = 0;
-volatile Uint  giNextTID = 1;
-// --- Thread Lists ---
-tThread        *gActiveThreads = NULL;         // Currently Running Threads
-tThread        *gSleepingThreads = NULL;       // Sleeping Threads
-tThread        *gDeleteThreads = NULL;         // Threads to delete
 // --- Multiprocessing ---
- int   giNumCPUs = 1;
 #if USE_MP
 tMPInfo        *gMPTable = NULL;
 #endif
@@ -88,13 +56,12 @@ tTSS        gTSS0 = {0};
 
 // === CODE ===
 /**
- * \fn void Proc_Start()
+ * \fn void ArchThreads_Init()
  * \brief Starts the process scheduler
  */
-void Proc_Start()
+void ArchThreads_Init()
 {
        Uint    pos = 0;
-       
        #if USE_MP
        // -- Initialise Multiprocessing
        // Find MP Floating Table
@@ -161,33 +128,29 @@ void Proc_Start()
        outb(0x40, TIMER_DIVISOR&0xFF); // Low Byte of Divisor
        outb(0x40, (TIMER_DIVISOR>>8)&0xFF);    // High Byte
        
-       // Create Initial Task
-       gActiveThreads = &gThreadZero;
-       gCurrentThread = &gThreadZero;
-       giTotalTickets = gThreadZero.NumTickets;
-       giNumActiveThreads = 1;
-       
        // Create Per-Process Data Block
        MM_Allocate(MM_PPD_CFG);
        
        // Change Stacks
        Proc_ChangeStack();
        
-       #if 1
-       // Create Idle Task
-       if(Proc_Clone(0, 0) == 0)
-       {
-               gCurrentThread->ThreadName = "Idle Thread";
-               Proc_SetTickets(0);     // Never called randomly
-               gCurrentThread->Quantum = 1;    // 1 slice quantum
-               for(;;) __asm__ __volatile__ ("hlt");   // Just yeilds
-       }
-       #endif
-       
        // Start Interrupts (and hence scheduler)
        __asm__ __volatile__("sti");
 }
 
+/**
+ * \fn tThread *Proc_GetCurThread()
+ * \brief Gets the current thread
+ */
+tThread *Proc_GetCurThread()
+{
+       #if USE_MP
+       return NULL;
+       #else
+       return gCurrentThread;
+       #endif
+}
+
 /**
  * \fn void Proc_ChangeStack()
  * \brief Swaps the current stack for a new one (in the proper stack reigon)
@@ -263,7 +226,7 @@ int Proc_Clone(Uint *Err, Uint Flags)
        // Initialise Memory Space (New Addr space or kernel stack)
        if(Flags & CLONE_VM) {
                newThread->TGID = newThread->TID;
-               newThread->CR3 = MM_Clone();
+               newThread->MemState.CR3 = MM_Clone();
        } else {
                Uint    tmpEbp, oldEsp = esp;
 
@@ -297,6 +260,7 @@ int Proc_Clone(Uint *Err, Uint Flags)
        newThread->Next = NULL;
        newThread->IsLocked = 0;
        newThread->TID = giNextTID++;
+       newThread->PTID = gCurrentThread->TID;
 
        // Clear message list (messages are not inherited)
        newThread->Messages = NULL;
@@ -306,8 +270,8 @@ int Proc_Clone(Uint *Err, Uint Flags)
        newThread->Remaining = newThread->Quantum;
        
        // Save core machine state
-       newThread->ESP = esp;
-       newThread->EBP = ebp;
+       newThread->SavedState.ESP = esp;
+       newThread->SavedState.EBP = ebp;
        eip = GetEIP();
        if(eip == SWITCH_MAGIC) {
                outb(0x20, 0x20);       // ACK Timer and return as child
@@ -315,9 +279,7 @@ int Proc_Clone(Uint *Err, Uint Flags)
        }
        
        // Set EIP as parent
-       newThread->EIP = eip;
-       
-       //Log(" Proc_Clone: giTimestamp = %i.%07i", (Uint)giTimestamp, (Uint)giPartMiliseconds/214);
+       newThread->SavedState.EIP = eip;
        
        // Lock list and add to active
        LOCK( &giThreadListLock );
@@ -330,18 +292,58 @@ int Proc_Clone(Uint *Err, Uint Flags)
        return newThread->TID;
 }
 
+#if 0
 /**
- * \fn void Proc_SetThreadName()
- * \brief Sets the thread's name
+ * \fn void Proc_SetSignalHandler(int Num, void *Handler)
+ * \brief Sets the signal handler for a signal
  */
-void Proc_SetThreadName(char *NewName)
+void Proc_SetSignalHandler(int Num, void *Handler)
 {
-       if( (Uint)CUR_THREAD->ThreadName > 0xC0400000 )
-               free( CUR_THREAD->ThreadName );
-       CUR_THREAD->ThreadName = malloc(strlen(NewName)+1);
-       strcpy(CUR_THREAD->ThreadName, NewName);
+       if(Num < 0 || Num >= NSIG)      return;
+       
+       gCurrentThread->SignalHandlers[Num] = Handler;
+}
+
+/**
+ * \fn void Proc_SendSignal(int TID, int Num)
+ */
+void Proc_SendSignal(int TID, int Num)
+{
+       tThread *thread = Proc_GetThread(TID);
+       void    *handler;
+       
+       if(!thread)     return ;
+       
+       handler = thread->SignalHandlers[Num];
+       
+       // Panic?
+       if(handler == SIG_ERR) {
+               Proc_Kill(TID);
+               return ;
+       }
+       // Dump Core?
+       if(handler == -2) {
+               Proc_Kill(TID);
+               return ;
+       }
+       // Ignore?
+       if(handler == -2)       return;
+       
+       // Check the type and handle if the thread is already in a signal
+       if(thread->CurSignal != 0) {
+               if(Num < _SIGTYPE_FATAL)
+                       Proc_Kill(TID);
+               } else {
+                       while(thread->CurSignal != 0)
+                               Proc_Yield();
+               }
+       }
+       
+       //TODO: 
 }
 
+#endif
+
 /**
  * \fn Uint Proc_MakeUserStack()
  * \brief Creates a new user stack
@@ -434,153 +436,6 @@ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **
        for(;;);
 }
 
-/**
- * \fn void Proc_Exit()
- * \brief Kill the current process
- */
-void Proc_Exit()
-{
-       tThread *thread;
-       tMsg    *msg;
-       
-       ///\note Double lock is needed due to overlap of locks
-       
-       // Lock thread (stop us recieving messages)
-       LOCK( &gCurrentThread->IsLocked );
-       
-       // Lock thread list
-       LOCK( &giThreadListLock );
-       
-       // Get previous thread on list
-       thread = Proc_int_GetPrevThread( &gActiveThreads, gCurrentThread );
-       if(!thread) {
-               Warning("Proc_Exit - Current thread is not on the active queue");
-               return;
-       }
-       
-       // Clear Message Queue
-       while( gCurrentThread->Messages )
-       {
-               msg = gCurrentThread->Messages->Next;
-               free( gCurrentThread->Messages );
-               gCurrentThread->Messages = msg;
-       }
-       
-       gCurrentThread->Remaining = 0;  // Clear Remaining Quantum
-       gCurrentThread->Quantum = 0;    // Clear Quantum to indicate dead thread
-       thread->Next = gCurrentThread->Next;    // Remove from active
-       
-       // Add to delete queue
-       if(gDeleteThreads) {
-               gCurrentThread->Next = gDeleteThreads;
-               gDeleteThreads = gCurrentThread;
-       } else {
-               gCurrentThread->Next = NULL;
-               gDeleteThreads = gCurrentThread;
-       }
-       
-       giNumActiveThreads --;
-       giTotalTickets -= gCurrentThread->NumTickets;
-       
-       // Mark thread as sleeping
-       gCurrentThread->Status = THREAD_STAT_DEAD;
-       
-       // Release spinlocks
-       RELEASE( &gCurrentThread->IsLocked );   // Released first so that it IS released
-       RELEASE( &giThreadListLock );
-       __asm__ __volatile__ ("hlt");
-}
-
-/**
- * \fn void Proc_Yield()
- * \brief Yield remainder of timeslice
- */
-void Proc_Yield()
-{
-       gCurrentThread->Quantum = 0;
-       __asm__ __volatile__ ("hlt");
-}
-
-/**
- * \fn void Proc_Sleep()
- * \brief Take the current process off the run queue
- */
-void Proc_Sleep()
-{
-       tThread *thread;
-       
-       //Log("Proc_Sleep: %i going to sleep", gCurrentThread->TID);
-       
-       // Acquire Spinlock
-       LOCK( &giThreadListLock );
-       
-       // Get thread before current thread
-       thread = Proc_int_GetPrevThread( &gActiveThreads, gCurrentThread );
-       if(!thread) {
-               Warning("Proc_Sleep - Current thread is not on the active queue");
-               return;
-       }
-       
-       // Don't sleep if there is a message waiting
-       if( gCurrentThread->Messages ) {
-               RELEASE( &giThreadListLock );
-               return;
-       }
-       
-       // Unset remaining timeslices (force a task switch on timer fire)
-       gCurrentThread->Remaining = 0;
-       
-       // Remove from active list
-       thread->Next = gCurrentThread->Next;
-       
-       // Add to Sleeping List (at the top)
-       gCurrentThread->Next = gSleepingThreads;
-       gSleepingThreads = gCurrentThread;
-       
-       // Reduce the active count & ticket count
-       giNumActiveThreads --;
-       giTotalTickets -= gCurrentThread->NumTickets;
-       
-       // Mark thread as sleeping
-       gCurrentThread->Status = THREAD_STAT_SLEEPING;
-       
-       // Release Spinlock
-       RELEASE( &giThreadListLock );
-       
-       __asm__ __volatile__ ("hlt");
-}
-
-/**
- * \fn void Thread_Wake( tThread *Thread )
- * \brief Wakes a sleeping/waiting thread up
- */
-void Thread_Wake(tThread *Thread)
-{
-       tThread *prev;
-       switch(Thread->Status)
-       {
-       case THREAD_STAT_ACTIVE:        break;
-       case THREAD_STAT_SLEEPING:
-               LOCK( &giThreadListLock );
-               prev = Proc_int_GetPrevThread(&gSleepingThreads, Thread);
-               prev->Next = Thread->Next;      // Remove from sleeping queue
-               Thread->Next = gActiveThreads;  // Add to active queue
-               gActiveThreads = Thread;
-               Thread->Status = THREAD_STAT_ACTIVE;
-               RELEASE( &giThreadListLock );
-               break;
-       case THREAD_STAT_WAITING:
-               Warning("Thread_Wake - Waiting threads are not currently supported");
-               break;
-       case THREAD_STAT_DEAD:
-               Warning("Thread_Wake - Attempt to wake dead thread (%i)", Thread->TID);
-               break;
-       default:
-               Warning("Thread_Wake - Unknown process status (%i)\n", Thread->Status);
-               break;
-       }
-}
-
 /**
  * \fn int Proc_Demote(Uint *Err, int Dest, tRegs *Regs)
  * \brief Demotes a process to a lower permission level
@@ -613,99 +468,6 @@ int Proc_Demote(Uint *Err, int Dest, tRegs *Regs)
        return 0;
 }
 
-/**
- * \fn void Proc_SetTickets(int Num)
- * \brief Sets the 'priority' of a task
- */
-void Proc_SetTickets(int Num)
-{
-       if(Num < 0)     return;
-       if(Num > MAX_TICKETS)   Num = MAX_TICKETS;
-       
-       LOCK( &giThreadListLock );
-       giTotalTickets -= gCurrentThread->NumTickets;
-       gCurrentThread->NumTickets = Num;
-       giTotalTickets += Num;
-       //LOG("giTotalTickets = %i", giTotalTickets);
-       RELEASE( &giThreadListLock );
-}
-
-/**
- * \fn tThread *Proc_GetThread(Uint TID)
- * \brief Gets a thread given its TID
- */
-tThread *Proc_GetThread(Uint TID)
-{
-       tThread *thread;
-       
-       // Search Active List
-       for(thread = gActiveThreads;
-               thread;
-               thread = thread->Next)
-       {
-               if(thread->TID == TID)
-                       return thread;
-       }
-       
-       // Search Sleeping List
-       for(thread = gSleepingThreads;
-               thread;
-               thread = thread->Next)
-       {
-               if(thread->TID == TID)
-                       return thread;
-       }
-       
-       return NULL;
-}
-
-/**
- * \fn static tThread *Proc_int_GetPrevThread(tThread *List, tThread *Thread)
- * \brief Gets the previous entry in a thead linked list
- */
-static tThread *Proc_int_GetPrevThread(tThread **List, tThread *Thread)
-{
-       tThread *ret;
-       // First Entry
-       if(*List == Thread) {
-               return (tThread*)List;
-       } else {
-               for(ret = *List;
-                       ret->Next && ret->Next != Thread;
-                       ret = ret->Next
-                       );
-               // Error if the thread is not on the list
-               if(!ret->Next || ret->Next != Thread) {
-                       return NULL;
-               }
-       }
-       return ret;
-}
-
-/**
- * \fn void Proc_DumpThreads()
- * \brief Dums a list of currently running threads
- */
-void Proc_DumpThreads()
-{
-       tThread *thread;
-       
-       Log("Active Threads:");
-       for(thread=gActiveThreads;thread;thread=thread->Next)
-       {
-               Log(" %i (%i) - %s", thread->TID, thread->TGID, thread->ThreadName);
-               Log("  %i Tickets, Quantum %i", thread->NumTickets, thread->Quantum);
-               Log("  CR3 0x%x, KStack 0x%x", thread->CR3, thread->KernelStack);
-       }
-       Log("Sleeping Threads:");
-       for(thread=gSleepingThreads;thread;thread=thread->Next)
-       {
-               Log(" %i (%i) - %s", thread->TID, thread->TGID, thread->ThreadName);
-               Log("  %i Tickets, Quantum %i", thread->NumTickets, thread->Quantum);
-               Log("  CR3 0x%x, KStack 0x%x", thread->CR3, thread->KernelStack);
-       }
-}
-
 /**
  * \fn void Proc_Scheduler(int CPU)
  * \brief Swap current thread and clears dead threads
@@ -749,9 +511,9 @@ void Proc_Scheduler(int CPU)
        if(eip == SWITCH_MAGIC) return; // Check if a switch happened
        
        // Save machine state
-       gCurrentThread->ESP = esp;
-       gCurrentThread->EBP = ebp;
-       gCurrentThread->EIP = eip;
+       gCurrentThread->SavedState.ESP = esp;
+       gCurrentThread->SavedState.EBP = ebp;
+       gCurrentThread->SavedState.EIP = eip;
        
        // Special case: 1 thread
        if(giNumActiveThreads == 1)
@@ -792,31 +554,13 @@ void Proc_Scheduler(int CPU)
 performSwitch:
        // Set address space
        //MM_SetCR3( gCurrentThread->CR3 );
-       __asm__ __volatile__ ("mov %0, %%cr3"::"a"(gCurrentThread->CR3));
+       __asm__ __volatile__ ("mov %0, %%cr3"::"a"(gCurrentThread->MemState.CR3));
        // Switch threads
        __asm__ __volatile__ (
                "mov %1, %%esp\n\t"
                "mov %2, %%ebp\n\t"
                "jmp *%3" : :
-               "a"(SWITCH_MAGIC), "b"(gCurrentThread->ESP),
-               "d"(gCurrentThread->EBP), "c"(gCurrentThread->EIP));
+               "a"(SWITCH_MAGIC), "b"(gCurrentThread->SavedState.ESP),
+               "d"(gCurrentThread->SavedState.EBP), "c"(gCurrentThread->SavedState.EIP));
        for(;;);        // Shouldn't reach here
 }
-
-// --- Process Structure Access Functions ---
-int Proc_GetPID()
-{
-       return gCurrentThread->TGID;
-}
-int Proc_GetTID()
-{
-       return gCurrentThread->TID;
-}
-int Proc_GetUID()
-{
-       return gCurrentThread->UID;
-}
-int Proc_GetGID()
-{
-       return gCurrentThread->GID;
-}
index e1cc70a..3da5075 100644 (file)
@@ -58,7 +58,7 @@ _GetEIP:
        ret\r
 \r
 [extern _Proc_Clone]\r
-[extern _Proc_Exit]\r
+[extern _Threads_Exit]\r
 [global _SpawnTask]\r
 _SpawnTask:\r
        ; Call Proc_Clone with Flags=0\r
@@ -77,7 +77,7 @@ _SpawnTask:
        ; Child\r
        push edx        ; Argument\r
        call ebx        ; Function\r
-       call _Proc_Exit ; Kill Thread\r
+       call _Threads_Exit      ; Kill Thread\r
        \r
 .parent:\r
        ret\r
index 46d086c..ae8207b 100644 (file)
@@ -34,9 +34,9 @@ typedef struct sKernelBin {
 \r
 // === IMPORTS ===\r
 extern int     Proc_Clone(Uint *Err, Uint Flags);\r
-extern void    Proc_SetThreadName(char *Name);\r
+extern void    Threads_SetName(char *Name);\r
 extern Uint    MM_ClearUser();\r
-extern void    Proc_Exit();\r
+extern void    Threads_Exit();\r
 extern void    Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize);\r
 extern tKernelSymbol   gKernelSymbols[];\r
 extern void            gKernelSymbolsEnd;\r
@@ -146,7 +146,7 @@ int Proc_Execve(char *File, char **ArgV, char **EnvP)
        strcpy(savedFile, File);\r
        \r
        // --- Set Process Name\r
-       Proc_SetThreadName(File);\r
+       Threads_SetName(File);\r
        \r
        // --- Clear User Address space\r
        MM_ClearUser();\r
@@ -157,7 +157,7 @@ int Proc_Execve(char *File, char **ArgV, char **EnvP)
        if(bases[0] == 0)\r
        {\r
                Warning("Proc_Execve - Unable to load '%s'", File);\r
-               Proc_Exit();\r
+               Threads_Exit();\r
                for(;;);\r
        }\r
        \r
index 8df3609..bd3b407 100644 (file)
@@ -9,7 +9,7 @@
 #define E9(ch) __asm__ __volatile__ ("outb %%al, $0xe9"::"a"(((Uint8)ch)))
 
 // === IMPORTS ===
-extern void Proc_DumpThreads();
+extern void Threads_Dump();
 
 // === GLOBALS ===
  int   gDebug_Level = 0;
@@ -183,7 +183,7 @@ void Panic(char *Fmt, ...)
        va_end(args);
        E9('\n');
        
-       Proc_DumpThreads();
+       Threads_Dump();
        
        __asm__ __volatile__ ("xchg %bx, %bx");
        __asm__ __volatile__ ("cli;\n\thlt");
index a4c5306..837085b 100644 (file)
@@ -793,7 +793,7 @@ int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
        ATA_int_BusMasterWriteByte( cont << 3, 9 );     // Read and start
        
        // Wait for transfer to complete
-       while( gaATA_IRQs[cont] == 0 )  Proc_Yield();
+       while( gaATA_IRQs[cont] == 0 )  Threads_Yield();
        
        // Complete Transfer
        ATA_int_BusMasterWriteByte( cont << 3, 0 );     // Write and stop
index 2cdd84f..e5abc73 100644 (file)
@@ -242,10 +242,9 @@ Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        case VT_MODE_TEXT8:
                while(pos < Length)
                {
-                       while(term->InputRead == term->InputWrite)      Proc_Yield();
+                       while(term->InputRead == term->InputWrite)      Threads_Yield();
                        while(term->InputRead != term->InputWrite)
                        {
-                               LOG("WriteUTF8(%p, 0x%x)", Buffer+pos, term->InputBuffer[term->InputRead]);
                                pos += WriteUTF8(Buffer+pos, term->InputBuffer[term->InputRead]);
                                term->InputRead ++;
                                term->InputRead %= MAX_INPUT_CHARS;
@@ -256,7 +255,7 @@ Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        case VT_MODE_TEXT32:
                while(pos < Length)
                {
-                       while(term->InputRead == term->InputWrite)      Proc_Yield();
+                       while(term->InputRead == term->InputWrite)      Threads_Yield();
                        while(term->InputRead != term->InputWrite)
                        {
                                ((Uint32*)Buffer)[pos] = term->InputBuffer[term->InputRead];
index 90b7256..6823918 100644 (file)
@@ -359,6 +359,23 @@ void *realloc(void *__ptr, size_t __size)
        return NULL;
 }
 
+/**
+ * \fn int IsHeap(void *Ptr)
+ * \brief Checks if an address is a heap address
+ */
+int IsHeap(void *Ptr)
+{
+       tHeapHead       *head;
+       if((Uint)Ptr < (Uint)gHeapStart)        return 0;
+       if((Uint)Ptr > (Uint)gHeapEnd)  return 0;
+       
+       head = (void*)( (Uint)Ptr - sizeof(tHeapHead) );
+       if(head->Magic != MAGIC_USED && head->Magic != MAGIC_FREE)
+               return 0;
+       
+       return 1;
+}
+
 #if WARNINGS
 void Heap_Dump()
 {
index 827d8ff..4fb0952 100644 (file)
@@ -87,10 +87,12 @@ extern int  strpos8(char *str, Uint32 search);
 extern void    itoa(char *buf, Uint num, int base, int minLength, char pad);
 extern int     ReadUTF8(Uint8 *str, Uint32 *Val);
 extern int     WriteUTF8(Uint8 *str, Uint32 Val);
+extern Uint    rand();
 // --- Heap ---
 extern void *malloc(size_t size);
 extern void    *realloc(void *ptr, size_t size);
 extern void free(void *Ptr);
+extern int     IsHeap(void *Ptr);
 // --- Modules ---
 extern int     Module_LoadMem(void *Buffer, Uint Length, char *ArgStr);
 extern int     Module_LoadFile(char *Path, char *ArgStr);
@@ -99,11 +101,12 @@ extern Sint64      timestamp(int sec, int mins, int hrs, int day, int month, int year
 extern Sint64  now();
 // --- Threads ---
 extern  int    Proc_Spawn(char *Path);
-extern void    Proc_Exit();
-extern void    Proc_Yield();
-extern int     Proc_GetCfg(int Index);
-extern int     Proc_GetUID();
-extern int     Proc_GetGID();
+extern void    Threads_Exit();
+extern void    Threads_Yield();
+extern void    Threads_Sleep();
+extern int     Threads_GetCfg(int Index);
+extern int     Threads_GetUID();
+extern int     Threads_GetGID();
 extern int     SpawnTask(tThreadFunction Function, void *Arg);
 
 #include <binary_ext.h>
diff --git a/Kernel/include/threads.h b/Kernel/include/threads.h
new file mode 100644 (file)
index 0000000..644d033
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ */
+#ifndef _THREADS_H_
+#define _THREADS_H_
+
+#include <arch.h>
+#include <signal.h>
+
+typedef struct sMessage
+{
+       struct sMessage *Next;
+       Uint    Source;
+       Uint    Length;
+       Uint8   Data[];
+} tMsg;        // sizeof = 12+
+
+typedef struct sThread
+{
+       struct sThread  *Next;  //!< Next thread in list
+        int    IsLocked;       //!< Thread's spinlock
+        int    Status;         //!< Thread Status
+        int    RetStatus;      //!< Return Status
+       
+       Uint    TID;    //!< Thread ID
+       Uint    TGID;   //!< Thread Group (Process)
+       Uint    PTID;   //!< Parent Thread ID
+       Uint    UID, GID;       //!< User and Group
+       char    *ThreadName;    //!< Name of thread
+       
+       tVAddr  KernelStack;    //!< Kernel Stack Base
+       
+       //! Memory Manager State
+       tMemoryState    MemState;
+       
+       //! State on task switch
+       tTaskState      SavedState;
+       
+        int    CurSignal;      //!< Signal currently being handled (0 for none)
+       tVAddr  SignalHandlers[NSIG];   //!< Signal Handler List
+       tTaskState      SignalState;    //!< Saved state for signal handler
+       
+       tMsg    *Messages;      //!< Message Queue
+       tMsg    *LastMessage;   //!< Last Message (speeds up insertion)
+       
+        int    Quantum, Remaining;     //!< Quantum Size and remaining timesteps
+        int    NumTickets;     //!< Priority - Chance of gaining CPU
+       
+       Uint    Config[NUM_CFG_ENTRIES];        //!< Per-process configuration
+} tThread;
+
+
+enum {
+       THREAD_STAT_NULL,
+       THREAD_STAT_ACTIVE,
+       THREAD_STAT_SLEEPING,
+       THREAD_STAT_WAITING,
+       THREAD_STAT_ZOMBIE,
+       THREAD_STAT_DEAD
+};
+
+// === FUNCTIONS ===
+extern tThread *Proc_GetCurThread();
+extern tThread *Threads_GetThread(Uint TID);
+extern void    Threads_Wake(tThread *Thread);
+
+#endif
index 31ae8f3..93cf6ca 100644 (file)
@@ -26,7 +26,7 @@ int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data)
        }
        
        // Get thread
-       thread = Proc_GetThread( Dest );
+       thread = Threads_GetThread( Dest );
        
        // Error check
        if(!thread) {   return -1;      }
@@ -40,7 +40,7 @@ int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data)
        // Create message
        msg = malloc( sizeof(tMsg)+Length );
        msg->Next = NULL;
-       msg->Source = gCurrentThread->TID;
+       msg->Source = Proc_GetCurThread()->TID;
        msg->Length = Length;
        memcpy(msg->Data, Data, Length);
        
@@ -55,7 +55,7 @@ int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data)
        
        RELEASE(&thread->IsLocked);
        
-       Thread_Wake( thread );
+       Threads_Wake( thread );
        
        return 0;
 }
@@ -68,35 +68,36 @@ int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer)
 {
         int    ret;
        void *tmp;
+       tThread *cur = Proc_GetCurThread();
        
        // Check if queue has any items
-       if(!gCurrentThread->Messages) {
+       if(!cur->Messages) {
                return 0;
        }
 
-       LOCK( &gCurrentThread->IsLocked );
+       LOCK( &cur->IsLocked );
        
        if(Source)
-               *Source = gCurrentThread->Messages->Source;
+               *Source = cur->Messages->Source;
        
        // Get message length
        if( !Buffer ) {
-               ret = gCurrentThread->Messages->Length;
-               RELEASE( &gCurrentThread->IsLocked );
+               ret = cur->Messages->Length;
+               RELEASE( &cur->IsLocked );
                return ret;
        }
        
        // Get message
        if(Buffer != GETMSG_IGNORE)
-               memcpy(Buffer, gCurrentThread->Messages->Data, gCurrentThread->Messages->Length);
-       ret = gCurrentThread->Messages->Length;
+               memcpy(Buffer, cur->Messages->Data, cur->Messages->Length);
+       ret = cur->Messages->Length;
        
        // Remove from list
-       tmp = gCurrentThread->Messages->Next;
-       free(gCurrentThread->Messages);
-       gCurrentThread->Messages = tmp;
+       tmp = cur->Messages->Next;
+       free(cur->Messages);
+       cur->Messages = tmp;
        
-       RELEASE( &gCurrentThread->IsLocked );
+       RELEASE( &cur->IsLocked );
        
        return ret;
 }
index 8e02c5d..47200c6 100644 (file)
 
 // === IMPORTS ===
 extern int     Proc_Clone(Uint *Err, Uint Flags);
+extern int     Threads_WaitTID(int TID, int *status);
 extern Uint    Proc_SendMessage(Uint *Err, Uint Dest, Uint Length, void *Data);
 extern int     Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer);
 extern int     Proc_Execve(char *File, char **ArgV, char **EnvP);
 extern Uint    Binary_Load(char *file, Uint *entryPoint);
 extern int     VFS_FInfo(int FD, void *Dest, int MaxACLs);
+extern int     Threads_SetName(char *NewName);
+extern int     Threads_GetPID();
+extern int     Threads_GetTID();
+extern int     Threads_GetUID();
+extern int     Threads_GetGID();
 
 // === CODE ===
 void SyscallHandler(tSyscallRegs *Regs)
@@ -31,13 +37,13 @@ void SyscallHandler(tSyscallRegs *Regs)
        switch(Regs->Num)
        {
        // -- Exit the current thread
-       case SYS_EXIT:  Proc_Exit();    break;
+       case SYS_EXIT:  Threads_Exit(); break;
        
        // -- Put the current thread to sleep
-       case SYS_SLEEP: Proc_Sleep();   Log(" SyscallHandler: %i is alive", gCurrentThread->TID);       break;
+       case SYS_SLEEP: Threads_Sleep();        break;
        
        // -- Yield current timeslice
-       case SYS_YIELD: Proc_Yield();   break;
+       case SYS_YIELD: Threads_Yield();        break;
        
        // -- Clone the current thread
        case SYS_CLONE:
@@ -54,6 +60,11 @@ void SyscallHandler(tSyscallRegs *Regs)
                ret = -1;
                break;
        
+       // -- Wait for a thread
+       case SYS_WAITTID:
+               ret = Threads_WaitTID(Regs->Arg1, (void*)Regs->Arg2);
+               break;
+       
        case SYS_GETPHYS:
                ret = MM_GetPhysAddr(Regs->Arg1);
                break;
@@ -65,11 +76,11 @@ void SyscallHandler(tSyscallRegs *Regs)
        case SYS_UNMAP:         MM_Deallocate(Regs->Arg1);      break;
        
        // -- Get Thread/Process IDs
-       case SYS_GETTID:        ret = gCurrentThread->TID;      break;
-       case SYS_GETPID:        ret = gCurrentThread->TGID;     break;
+       case SYS_GETTID:        ret = Threads_GetTID(); break;
+       case SYS_GETPID:        ret = Threads_GetPID(); break;
        // -- Get User/Group IDs
-       case SYS_GETUID:        ret = gCurrentThread->UID;      break;
-       case SYS_GETGID:        ret = gCurrentThread->GID;      break;
+       case SYS_GETUID:        ret = Threads_GetUID(); break;
+       case SYS_GETGID:        ret = Threads_GetGID(); break;
        
        // -- Send Message
        case SYS_SENDMSG:
@@ -84,16 +95,7 @@ void SyscallHandler(tSyscallRegs *Regs)
        case SYS_SETNAME:
                // Sanity Check
                if(!Regs->Arg1) {       ret = -1;       err = -EINVAL;  break;  }
-               // Lock Process
-               LOCK( &gCurrentThread->IsLocked );
-               // Free old name
-               if(gCurrentThread->ThreadName && (Uint)gCurrentThread->ThreadName > 0xE0800000)
-                       free(gCurrentThread->ThreadName);
-               // Change name
-               gCurrentThread->ThreadName = malloc( strlen( (char*)Regs->Arg1 ) + 1 );
-               strcpy(gCurrentThread->ThreadName, (char*)Regs->Arg1);
-               // Unlock
-               RELEASE( &gCurrentThread->IsLocked );
+               Threads_SetName( (void*)Regs->Arg1 );
                break;
        
        // ---
diff --git a/Kernel/threads.c b/Kernel/threads.c
new file mode 100644 (file)
index 0000000..fb14f4d
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ * Acess2
+ * threads.c
+ * - Common Thread Control
+ */
+#include <common.h>
+#include <threads.h>
+
+// === CONSTANTS ===
+#define        DEFAULT_QUANTUM 10
+#define        DEFAULT_TICKETS 5
+#define MAX_TICKETS            10
+
+// === IMPORTS ===
+extern void    ArchThreads_Init();
+extern tThread *Proc_GetCurThread();
+extern int     Proc_Clone(Uint *Err, Uint Flags);
+
+// === PROTOTYPES ===
+void   Threads_Init();
+void   Threads_SetName(char *NewName);
+void   Threads_SetTickets(int Num);
+ int   Threads_WaitTID(int TID, int *status);
+tThread        *Threads_GetThread(Uint TID);
+tThread        *Threads_int_GetPrev(tThread **List, tThread *Thread);
+void   Threads_Exit(int TID, int Status);
+void   Threads_Kill(tThread *Thread, int Status);
+void   Threads_Yield();
+void   Threads_Sleep();
+void   Threads_Wake(tThread *Thread);
+ int   Threads_GetPID();
+ int   Threads_GetTID();
+ int   Threads_GetUID();
+ int   Threads_GetGID();
+void   Threads_Dump();
+
+// === GLOBALS ===
+// -- Core Thread --
+tThread        gThreadZero = {
+       NULL, 0,        // Next, Lock
+       THREAD_STAT_ACTIVE,     // Status
+       0,      // Exit Status
+       0, 0,   // TID, TGID
+       0, 0,   // UID, GID
+       0,      // Parent Thread ID
+       "ThreadZero",   // Name
+       
+       0,      // Kernel Stack
+       {0},    // Saved State
+       {0},    // VM State
+       
+       0, {0}, {0},    // Signal State
+       
+       NULL, NULL,     // Messages, Last Message
+       DEFAULT_QUANTUM, DEFAULT_QUANTUM,       // Quantum, Remaining
+       DEFAULT_TICKETS,
+       {0}     // Default config to zero
+       };
+// -- Processes --
+// --- Locks ---
+volatile int   giThreadListLock = 0;   ///\note NEVER use a heap function while locked
+// --- Current State ---
+volatile int   giNumActiveThreads = 0;
+volatile int   giTotalTickets = 0;
+volatile Uint  giNextTID = 1;
+// --- Thread Lists ---
+tThread        *gActiveThreads = NULL;         // Currently Running Threads
+tThread        *gSleepingThreads = NULL;       // Sleeping Threads
+tThread        *gDeleteThreads = NULL;         // Threads to delete
+ int   giNumCPUs = 1;
+
+// === CODE ===
+/**
+ * \fn void Threads_Init()
+ * \brief Initialse the thread list
+ */
+void Threads_Init()
+{
+       ArchThreads_Init();
+       
+       // Create Initial Task
+       gActiveThreads = &gThreadZero;
+       giTotalTickets = gThreadZero.NumTickets;
+       giNumActiveThreads = 1;
+       
+       #if 1
+       // Create Idle Task
+       if(Proc_Clone(0, 0) == 0)
+       {
+               tThread *cur = Proc_GetCurThread();
+               cur->ThreadName = "Idle Thread";
+               Threads_SetTickets(0);  // Never called randomly
+               cur->Quantum = 1;       // 1 slice quantum
+               for(;;) __asm__ __volatile__ ("hlt");   // Just yeilds
+       }
+       #endif
+}
+
+/**
+ * \fn void Threads_SetName(char *NewName)
+ * \brief Sets the current thread's name
+ */
+void Threads_SetName(char *NewName)
+{
+       tThread *cur = Proc_GetCurThread();
+       if( IsHeap(cur->ThreadName) )
+               free( cur->ThreadName );
+       cur->ThreadName = malloc(strlen(NewName)+1);
+       strcpy(cur->ThreadName, NewName);
+}
+
+/**
+ * \fn void Threads_SetTickets(int Num)
+ * \brief Sets the 'priority' of a task
+ */
+void Threads_SetTickets(int Num)
+{
+       tThread *cur = Proc_GetCurThread();
+       if(Num < 0)     return;
+       if(Num > MAX_TICKETS)   Num = MAX_TICKETS;
+       
+       LOCK( &giThreadListLock );
+       giTotalTickets -= cur->NumTickets;
+       cur->NumTickets = Num;
+       giTotalTickets += Num;
+       //LOG("giTotalTickets = %i", giTotalTickets);
+       RELEASE( &giThreadListLock );
+}
+
+/**
+ * \fn void Threads_WaitTID(int TID, int *status)
+ * \brief Wait for a task to change state
+ */
+int Threads_WaitTID(int TID, int *status)
+{
+       // Any Child
+       if(TID == -1) {
+               
+               return -1;
+       }
+       
+       // Any peer/child thread
+       if(TID == 0) {
+               
+               return -1;
+       }
+       
+       // TGID = abs(TID)
+       if(TID < -1) {
+               return -1;
+       }
+       
+       // Specific Thread
+       if(TID > 0) {
+               tThread *t = Threads_GetThread(TID);
+                int    initStatus = t->Status;
+                int    ret;
+               while(t->Status == initStatus)  Threads_Yield();
+               ret = t->RetStatus;
+               switch(t->Status)
+               {
+               case THREAD_STAT_ZOMBIE:
+                       t->Status = THREAD_STAT_DEAD;
+                       *status = 0;
+                       break;
+               default:
+                       *status = -1;
+                       break;
+               }
+               return ret;
+       }
+       
+       return -1;
+}
+
+/**
+ * \fn tThread *Threads_GetThread(Uint TID)
+ * \brief Gets a thread given its TID
+ */
+tThread *Threads_GetThread(Uint TID)
+{
+       tThread *thread;
+       
+       // Search Active List
+       for(thread = gActiveThreads;
+               thread;
+               thread = thread->Next)
+       {
+               if(thread->TID == TID)
+                       return thread;
+       }
+       
+       // Search Sleeping List
+       for(thread = gSleepingThreads;
+               thread;
+               thread = thread->Next)
+       {
+               if(thread->TID == TID)
+                       return thread;
+       }
+       
+       return NULL;
+}
+
+/**
+ * \fn tThread *Threads_int_GetPrev(tThread *List, tThread *Thread)
+ * \brief Gets the previous entry in a thead linked list
+ */
+tThread *Threads_int_GetPrev(tThread **List, tThread *Thread)
+{
+       tThread *ret;
+       // First Entry
+       if(*List == Thread) {
+               return (tThread*)List;
+       } else {
+               for(ret = *List;
+                       ret->Next && ret->Next != Thread;
+                       ret = ret->Next
+                       );
+               // Error if the thread is not on the list
+               if(!ret->Next || ret->Next != Thread) {
+                       return NULL;
+               }
+       }
+       return ret;
+}
+
+/**
+ * \fn void Threads_Exit(int TID, int Status)
+ * \brief Exit the current process
+ */
+void Threads_Exit(int TID, int Status)
+{
+       Threads_Kill( Proc_GetCurThread(), (Uint)Status & 0xFF );
+}
+
+/**
+ * \fn void Threads_Kill(tThread *Thread, int Status)
+ * \brief Kill a thread
+ * \param TID  Thread ID (0 for current)
+ */
+void Threads_Kill(tThread *Thread, int Status)
+{
+       tThread *prev;
+       tMsg    *msg;
+       
+       // Kill all children
+       #if 0
+       {
+               tThread *child;
+               for(child = gActiveThreads;
+                       child;
+                       child = child->Next)
+               {
+                       if(child->PTID == gCurrentThread->TID)
+                               Threads_Kill(child, -1);
+               }
+       }
+       #endif
+       
+       ///\note Double lock is needed due to overlap of locks
+       
+       // Lock thread (stop us recieving messages)
+       LOCK( &Thread->IsLocked );
+       
+       // Lock thread list
+       LOCK( &giThreadListLock );
+       
+       // Get previous thread on list
+       prev = Threads_int_GetPrev( &gActiveThreads, Thread );
+       if(!prev) {
+               Warning("Proc_Exit - Current thread is not on the active queue");
+               return;
+       }
+       
+       // Clear Message Queue
+       while( Thread->Messages )
+       {
+               msg = Thread->Messages->Next;
+               free( Thread->Messages );
+               Thread->Messages = msg;
+       }
+       
+       Thread->Remaining = 0;  // Clear Remaining Quantum
+       Thread->Quantum = 0;    // Clear Quantum to indicate dead thread
+       prev->Next = Thread->Next;      // Remove from active
+       
+       giNumActiveThreads --;
+       giTotalTickets -= Thread->NumTickets;
+       
+       // Mark thread as a zombie
+       Thread->RetStatus = Status;
+       
+       // Don't Zombie if we are being killed as part of a tree
+       if(Status == -1)
+       {
+               Thread->Status = THREAD_STAT_DEAD;
+               // Add to delete queue
+               if(gDeleteThreads) {
+                       Thread->Next = gDeleteThreads;
+                       gDeleteThreads = Thread;
+               } else {
+                       Thread->Next = NULL;
+                       gDeleteThreads = Thread;
+               }
+       } else {
+               Thread->Status = THREAD_STAT_ZOMBIE;
+       }
+       
+       // Release spinlocks
+       RELEASE( &Thread->IsLocked );   // Released first so that it IS released
+       RELEASE( &giThreadListLock );
+       if(Status != -1)        HALT();
+}
+
+/**
+ * \fn void Threads_Yield()
+ * \brief Yield remainder of timeslice
+ */
+void Threads_Yield()
+{
+       Proc_GetCurThread()->Quantum = 0;
+       HALT();
+}
+
+/**
+ * \fn void Threads_Sleep()
+ * \brief Take the current process off the run queue
+ */
+void Threads_Sleep()
+{
+       tThread *cur = Proc_GetCurThread();
+       tThread *thread;
+       
+       //Log("Proc_Sleep: %i going to sleep", gCurrentThread->TID);
+       
+       // Acquire Spinlock
+       LOCK( &giThreadListLock );
+       
+       // Get thread before current thread
+       thread = Threads_int_GetPrev( &gActiveThreads, cur );
+       if(!thread) {
+               Warning("Proc_Sleep - Current thread is not on the active queue");
+               return;
+       }
+       
+       // Don't sleep if there is a message waiting
+       if( cur->Messages ) {
+               RELEASE( &giThreadListLock );
+               return;
+       }
+       
+       // Unset remaining timeslices (force a task switch on timer fire)
+       cur->Remaining = 0;
+       
+       // Remove from active list
+       thread->Next = cur->Next;
+       
+       // Add to Sleeping List (at the top)
+       cur->Next = gSleepingThreads;
+       gSleepingThreads = cur;
+       
+       // Reduce the active count & ticket count
+       giNumActiveThreads --;
+       giTotalTickets -= cur->NumTickets;
+       
+       // Mark thread as sleeping
+       cur->Status = THREAD_STAT_SLEEPING;
+       
+       // Release Spinlock
+       RELEASE( &giThreadListLock );
+       
+       HALT();
+}
+
+
+/**
+ * \fn void Threads_Wake( tThread *Thread )
+ * \brief Wakes a sleeping/waiting thread up
+ */
+void Threads_Wake(tThread *Thread)
+{
+       tThread *prev;
+       switch(Thread->Status)
+       {
+       case THREAD_STAT_ACTIVE:        break;
+       case THREAD_STAT_SLEEPING:
+               LOCK( &giThreadListLock );
+               prev = Threads_int_GetPrev(&gSleepingThreads, Thread);
+               prev->Next = Thread->Next;      // Remove from sleeping queue
+               Thread->Next = gActiveThreads;  // Add to active queue
+               gActiveThreads = Thread;
+               Thread->Status = THREAD_STAT_ACTIVE;
+               RELEASE( &giThreadListLock );
+               break;
+       case THREAD_STAT_WAITING:
+               Warning("Thread_Wake - Waiting threads are not currently supported");
+               break;
+       case THREAD_STAT_DEAD:
+               Warning("Thread_Wake - Attempt to wake dead thread (%i)", Thread->TID);
+               break;
+       default:
+               Warning("Thread_Wake - Unknown process status (%i)\n", Thread->Status);
+               break;
+       }
+}
+
+// --- Process Structure Access Functions ---
+int Threads_GetPID()
+{
+       return Proc_GetCurThread()->TGID;
+}
+int Threads_GetTID()
+{
+       return Proc_GetCurThread()->TID;
+}
+int Threads_GetUID()
+{
+       return Proc_GetCurThread()->UID;
+}
+int Threads_GetGID()
+{
+       return Proc_GetCurThread()->GID;
+}
+
+/**
+ * \fn void Threads_Dump()
+ * \brief Dums a list of currently running threads
+ */
+void Threads_Dump()
+{
+       tThread *thread;
+       
+       Log("Active Threads:");
+       for(thread=gActiveThreads;thread;thread=thread->Next)
+       {
+               Log(" %i (%i) - %s", thread->TID, thread->TGID, thread->ThreadName);
+               Log("  %i Tickets, Quantum %i", thread->NumTickets, thread->Quantum);
+               Log("  KStack 0x%x", thread->KernelStack);
+       }
+       Log("Sleeping Threads:");
+       for(thread=gSleepingThreads;thread;thread=thread->Next)
+       {
+               Log(" %i (%i) - %s", thread->TID, thread->TGID, thread->ThreadName);
+               Log("  %i Tickets, Quantum %i", thread->NumTickets, thread->Quantum);
+               Log("  KStack 0x%x", thread->KernelStack);
+       }
+}
index 52c802c..5a112de 100644 (file)
@@ -19,8 +19,8 @@ tVFS_ACL      gVFS_ACL_EveryoneRO = { {0,-1}, {0,VFS_PERM_READ} };
 int VFS_CheckACL(tVFS_Node *Node, Uint Permissions)
 {
         int    i;
-        int    uid = Proc_GetUID();
-        int    gid = Proc_GetGID();
+        int    uid = Threads_GetUID();
+        int    gid = Threads_GetGID();
        
        // Root can do anything
        if(uid == 0)    return 1;
index f753788..d605baa 100644 (file)
@@ -97,35 +97,35 @@ int main(int argc, char *argv[], char *envp[])
                                cBUILTINS[length].fcn(iArgCount-1, &saArgs[1]);\r
                                break;\r
                        }\r
-               }
-               // Calling a file\r
-               if(length == BUILTIN_COUNT)\r
-               {\r
-                       GeneratePath(saArgs[1], gsCurrentDirectory, gsTmpBuffer);\r
-                       // Use length in place of fp\r
-                       length = open(gsTmpBuffer, 0);\r
-                       // Check file existence\r
-                       if(length == -1) {\r
-                               Print("Unknown Command: `");Print(saArgs[1]);Print("'\n");      // Error Message\r
-                               continue;\r
-                       }\r
-                       // Check if the file is a directory\r
-                       finfo( length, &info );
-                       close( length );\r
-                       if(info.flags & FILEFLAG_DIRECTORY) {\r
-                               Print("`");Print(saArgs[1]);    // Error Message\r
-                               Print("' is a directory.\n");\r
-                               continue;\r
-                       }\r
-                       pid = clone(CLONE_VM, 0);\r
-                       if(pid == 0)    execve(gsTmpBuffer, &saArgs[1], NULL);\r
-                       if(pid <= 0) {\r
-                               Print("Unablt to create process: `");Print(gsTmpBuffer);Print("'\n");   // Error Message
-                               //SysDebug("pid = %i\n", pid);\r
-                       }\r
-                       else {\r
-                               //waitpid(pid, K_WAITPID_DIE);\r
-                       }\r
+               }\r
+               \r
+               if(length != BUILTIN_COUNT)     continue;\r
+               
+               // - Calling a file\r
+               GeneratePath(saArgs[1], gsCurrentDirectory, gsTmpBuffer);\r
+               // Use length in place of fp\r
+               length = open(gsTmpBuffer, 0);\r
+               // Check file existence\r
+               if(length == -1) {\r
+                       Print("Unknown Command: `");Print(saArgs[1]);Print("'\n");      // Error Message\r
+                       continue;\r
+               }\r
+               // Check if the file is a directory\r
+               finfo( length, &info );
+               close( length );\r
+               if(info.flags & FILEFLAG_DIRECTORY) {\r
+                       Print("`");Print(saArgs[1]);    // Error Message\r
+                       Print("' is a directory.\n");\r
+                       continue;\r
+               }\r
+               pid = clone(CLONE_VM, 0);\r
+               if(pid == 0)    execve(gsTmpBuffer, &saArgs[1], NULL);\r
+               if(pid <= 0) {\r
+                       Print("Unablt to create process: `");Print(gsTmpBuffer);Print("'\n");   // Error Message
+                       //SysDebug("pid = %i\n", pid);\r
+               }\r
+               else {\r
+                       //waitpid(pid, K_WAITPID_DIE);\r
                }\r
        }\r
 }\r

UCC git Repository :: git.ucc.asn.au