Kernel - Implimenting POSIX/C Signals
authorJohn Hodge <[email protected]>
Sun, 8 Sep 2013 11:39:36 +0000 (19:39 +0800)
committerJohn Hodge <[email protected]>
Sun, 8 Sep 2013 11:39:36 +0000 (19:39 +0800)
KernelLand/Kernel/arch/x86/proc.asm
KernelLand/Kernel/include/signal.h
KernelLand/Kernel/include/threads_int.h
KernelLand/Kernel/threads.c
KernelLand/Kernel/vfs/select.c

index dcafc5f..b8c01bc 100644 (file)
@@ -373,6 +373,14 @@ User_Syscall:
        xchg bx, bx     ; MAGIC BREAKPOINT
        int 0xAC
 
+[global User_Signal_Kill]
+User_Signal_Kill:
+       xor eax, eax
+       mov bl, [esp+4]
+       mov bh, 0x02
+       int 0xAC
+       jmp $
+
 User_RestoreState:
        pop gs
        pop fs
index 3f2a9c4..b200634 100644 (file)
@@ -31,4 +31,7 @@ enum eSignals {
        NSIGNALS
 };
 
+extern void    Threads_PostSignal(int SigNum);
+extern void    Threads_SignalGroup(tPGID PGID, int SignalNum);
+
 #endif
index d770668..5706a35 100644 (file)
@@ -33,6 +33,7 @@ typedef struct sMessage
 struct sProcess
 {
        struct sProcess *Next;
+       struct sProcess *Prev;
        tPGID   PGID;
        tPID    PID;
 
index 5a41a20..50889bf 100644 (file)
@@ -31,6 +31,7 @@
 #define MIN_PRIORITY           10
 
 // === IMPORTS ===
+extern void    User_Signal_Kill(int SigNum);
 
 // === TYPE ===
 typedef struct
@@ -58,6 +59,9 @@ void  Threads_int_AddToList(tThreadList *List, tThread *Thread);
 void   Threads_Exit(int TID, int Status);
 void   Threads_Kill(tThread *Thread, int Status);
 void   Threads_Yield(void);
+#endif
+void   Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock);
+#if 0
 void   Threads_Sleep(void);
  int   Threads_Wake(tThread *Thread);
 void   Threads_AddActive(tThread *Thread);
@@ -66,7 +70,11 @@ tThread      *Threads_RemActive(void);
 void   Threads_ToggleTrace(int TID);
 void   Threads_Fault(int Num);
 void   Threads_SegFault(tVAddr Addr);
+void   Threads_PostSignalTo(tThread *Thread, int SignalNum);
+#if 0
 void   Threads_PostSignal(int SignalNum);
+void   Threads_SignalGroup(tPGID PGID, int SignalNum);
+#endif
  int   Threads_GetPendingSignal(void);
 void   Threads_SetSignalHandler(int SignalNum, void *Handler);
 void   *Threads_GetSignalHandler(int SignalNum);
@@ -84,7 +92,7 @@ void  Threads_DumpActive(void);
 
 // === GLOBALS ===
 // -- Core Thread --
-struct sProcess        gProcessZero = {
+tProcess       gProcessZero = {
        };
 // Only used for the core kernel
 tThread        gThreadZero = {
@@ -95,6 +103,7 @@ tThread      gThreadZero = {
        .Priority       = DEFAULT_PRIORITY      // Number of tickets
        };
 // -- Processes --
+tProcess       *gAllProcesses = &gProcessZero;
 // --- Locks ---
 tShortSpinlock glThreadListLock;       ///\note NEVER use a heap function while locked
 // --- Current State ---
@@ -170,6 +179,16 @@ void Threads_Delete(tThread *Thread)
        if( Thread->Process->nThreads == 0 )
        {
                tProcess        *proc = Thread->Process;
+
+               // Remove from global process list
+               // TODO: RWLock
+               if(proc->Prev)
+                       proc->Prev->Next = proc->Next;
+               else
+                       gAllProcesses = proc->Next;
+               if(proc->Next)
+                       proc->Next->Prev = proc->Prev;
+
                // VFS Cleanup
                VFS_CloseAllUserHandles();
                // Architecture cleanup
@@ -338,17 +357,17 @@ tThread *Threads_CloneTCB(Uint Flags)
                newproc->UID = oldproc->UID;
                newproc->GID = oldproc->GID;
                newproc->MaxFD = oldproc->MaxFD;
-               if( oldproc->CurrentWorkingDir )
-                       newproc->CurrentWorkingDir = strdup( oldproc->CurrentWorkingDir );
-               else
-                       newproc->CurrentWorkingDir = NULL;
-               if( oldproc->RootDir )
-                       newproc->RootDir = strdup( oldproc->RootDir );
-               else
-                       newproc->RootDir = NULL;
+               newproc->CurrentWorkingDir = oldproc->CurrentWorkingDir ? strdup( oldproc->CurrentWorkingDir ) : NULL;
+               newproc->RootDir = oldproc->RootDir ? strdup( oldproc->RootDir ) : NULL;
                newproc->nThreads = 1;
                // Reference all handles in the VFS
                VFS_ReferenceUserHandles();
+               
+               // Add to global list
+               newproc->Prev = NULL;
+               // TODO: RWLock
+               newproc->Next = gAllProcesses;
+               gAllProcesses = newproc;
 
                newproc->FirstThread = new;
                new->ProcessNext = NULL;
@@ -1045,11 +1064,27 @@ void Threads_SegFault(tVAddr Addr)
 }
 
 
+void Threads_PostSignalTo(tThread *Thread, int SignalNum)
+{
+       ASSERT(Thread);
+       Log_Debug("Threads", "Signalling %i(%s) with %i", Thread->TID, Thread->ThreadName, SignalNum);
+       Thread->PendingSignal = SignalNum;
+       Threads_PostEvent(Thread, THREAD_EVENT_SIGNAL);
+}
 void Threads_PostSignal(int SignalNum)
 {
-       tThread *cur = Proc_GetCurThread();
-       cur->PendingSignal = SignalNum;
-       Threads_PostEvent(cur, THREAD_EVENT_SIGNAL);
+       Threads_PostSignalTo( Proc_GetCurThread(), SignalNum );
+}
+
+void Threads_SignalGroup(tPGID PGID, int Signal)
+{
+       for( tProcess *proc = gAllProcesses; proc; proc = proc->Next )
+       {
+               if(proc->PGID == PGID)
+               {
+                       Threads_PostSignalTo(proc->FirstThread, Signal);
+               }
+       }
 }
 
 /**
@@ -1059,7 +1094,13 @@ int Threads_GetPendingSignal(void)
        tThread *cur = Proc_GetCurThread();
        
        // Atomic AND with 0 fetches and clears in one operation
-       return __sync_fetch_and_and( &cur->PendingSignal, 0 );
+       int ret = __sync_fetch_and_and( &cur->PendingSignal, 0 );
+       if( ret )
+       {
+               Log_Debug("Threads", "Thread %i(%s) has signal %i pending",
+                       cur->TID, cur->ThreadName, ret);
+       }
+       return ret;
 }
 
 /*
@@ -1090,13 +1131,15 @@ void *Threads_GetSignalHandler(int SignalNum)
                case SIGINT:
                case SIGKILL:
                case SIGSEGV:
-//                     ret = User_Signal_Kill;
+               case SIGHUP:
+                       ret = User_Signal_Kill;
                        break;
                default:
                        ret = NULL;
                        break;
                }
        }
+       Log_Debug("Threads", "Handler %p for signal %i", ret, SignalNum);
        return ret;
 }
 
index b52414f..d4c5cd8 100644 (file)
@@ -5,7 +5,6 @@
  * select.c
  * - Implements the select() system call (and supporting code)
  *
- * TODO: Implment timeouts (via an alarm event?)
  * TODO: Remove malloc for read/write queues
  */
 #define DEBUG  0
@@ -89,7 +88,7 @@ int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *N
        {
                LOG("Semaphore_Wait()");
                // TODO: Actual timeout
-               Threads_WaitEvents( THREAD_EVENT_VFS );
+               Threads_WaitEvents( THREAD_EVENT_VFS|THREAD_EVENT_SIGNAL );
        }
        else if( *Timeout > 0 )
        {
@@ -100,7 +99,7 @@ int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *N
                LOG("Timeout %lli ms", *Timeout);
                Time_ScheduleTimer( t, *Timeout );
                // Wait for the timer or a VFS event
-               Threads_WaitEvents( THREAD_EVENT_VFS|THREAD_EVENT_TIMER );
+               Threads_WaitEvents( THREAD_EVENT_VFS|THREAD_EVENT_TIMER|THREAD_EVENT_SIGNAL );
                Time_FreeTimer(t);
        }
        
@@ -166,7 +165,7 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set
        {
                LOG("Semaphore_Wait()");
                // TODO: Actual timeout
-               Threads_WaitEvents( THREAD_EVENT_VFS|ExtraEvents );
+               Threads_WaitEvents( THREAD_EVENT_VFS|THREAD_EVENT_SIGNAL|ExtraEvents );
        }
        else if( *Timeout > 0 )
        {

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