Kernel - Fixed a double-lock in message handling
[tpg/acess2.git] / Kernel / messages.c
index 31ae8f3..1391d99 100644 (file)
@@ -1,9 +1,14 @@
 /*
- * AcessOS Microkernel Version
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
  * messages.c
+ * - IPC Messages
  */
-#include <common.h>
-#include <proc.h>
+#define DEBUG  0
+#include <acess.h>
+#include <threads.h>
+#include <threads_int.h>
 #include <errno.h>
 
 // === CODE ===
  * \brief Send an IPC message
  * \param Err  Pointer to the errno variable
  * \param Dest Destination Thread
+ * \param Length       Length of the message
+ * \param Data Message data
  */
 int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data)
 {
        tThread *thread;
        tMsg    *msg;
        
-       Log("Proc_SendMessage: (Err=%p, Dest=%i, Length=%i, Data=%p)", Err, Dest, Length, Data);
+       ENTER("pErr iDest iLength pData", Err, Dest, Length, Data);
        
        if(Length <= 0 || !Data) {
                *Err = -EINVAL;
-               return -1;
+               LEAVE_RET('i', -1);
        }
        
        // Get thread
-       thread = Proc_GetThread( Dest );
+       thread = Threads_GetThread( Dest );
        
        // Error check
-       if(!thread) {   return -1;      }
+       if(!thread)     LEAVE_RET('i', -1);
        
        // Get Spinlock
-       LOCK( &thread->IsLocked );
+       SHORTLOCK( &thread->IsLocked );
        
        // Check if thread is still alive
-       if(thread->Status == THREAD_STAT_DEAD)  return -1;
+       if(thread->Status == THREAD_STAT_DEAD) {
+               SHORTREL( &thread->IsLocked );
+               LEAVE_RET('i', -1);
+       }
        
        // 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);
        
@@ -53,50 +63,75 @@ int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data)
                thread->LastMessage = msg;
        }
        
-       RELEASE(&thread->IsLocked);
+       SHORTREL(&thread->IsLocked);
        
-       Thread_Wake( thread );
+       LOG("Waking %p (%i %s)", thread, thread->TID, thread->ThreadName);
+       Threads_Wake( thread );
        
-       return 0;
+       LEAVE_RET('i', 0);
 }
 
 /**
  * \fn int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer)
  * \brief Gets a message
+ * \param Err  Pointer to \a errno
+ * \param Source       Where to put the source TID
+ * \param Buffer       Buffer to place the message data (set to NULL to just get message length)
  */
 int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer)
 {
         int    ret;
-       void *tmp;
+       void    *tmp;
+       tThread *cur = Proc_GetCurThread();
+
+       ENTER("pSource pBuffer", Source, Buffer);
        
        // Check if queue has any items
-       if(!gCurrentThread->Messages) {
+       if(!cur->Messages) {
+               LEAVE('i', 0);
                return 0;
        }
 
-       LOCK( &gCurrentThread->IsLocked );
+       SHORTLOCK( &cur->IsLocked );
        
-       if(Source)
-               *Source = gCurrentThread->Messages->Source;
+       if(Source) {
+               *Source = cur->Messages->Source;
+               LOG("*Source = %i", *Source);
+       }
        
        // Get message length
        if( !Buffer ) {
-               ret = gCurrentThread->Messages->Length;
-               RELEASE( &gCurrentThread->IsLocked );
+               ret = cur->Messages->Length;
+               SHORTREL( &cur->IsLocked );
+               LEAVE('i', ret);
                return ret;
        }
        
        // Get message
        if(Buffer != GETMSG_IGNORE)
-               memcpy(Buffer, gCurrentThread->Messages->Data, gCurrentThread->Messages->Length);
-       ret = gCurrentThread->Messages->Length;
+       {
+               if( !CheckMem( Buffer, cur->Messages->Length ) )
+               {
+                       LOG("Invalid buffer");
+                       *Err = -EINVAL;
+                       SHORTREL( &cur->IsLocked );
+                       LEAVE('i', -1);
+                       return -1;
+               }
+               LOG("Copied to buffer");
+               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;
+       cur->Messages = cur->Messages->Next;
+       if(cur->Messages == NULL)       cur->LastMessage = NULL;
        
-       RELEASE( &gCurrentThread->IsLocked );
+       SHORTREL( &cur->IsLocked );
        
+       free(tmp);      // Free outside of lock
+
+       LEAVE('i', ret);
        return ret;
 }

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