Kernel - Split Mutexes/Semaphores out
[tpg/acess2.git] / Kernel / messages.c
1 /*
2  * Acess2 Kernel
3  * - By John Hodge (thePowersGang)
4  *
5  * messages.c
6  * - IPC Messages
7  */
8 #define DEBUG   0
9 #include <acess.h>
10 #include <threads.h>
11 #include <threads_int.h>
12 #include <errno.h>
13
14 // === CODE ===
15 /**
16  * \fn int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data)
17  * \brief Send an IPC message
18  * \param Err   Pointer to the errno variable
19  * \param Dest  Destination Thread
20  * \param Length        Length of the message
21  * \param Data  Message data
22  */
23 int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data)
24 {
25         tThread *thread;
26         tMsg    *msg;
27         
28         ENTER("pErr iDest iLength pData", Err, Dest, Length, Data);
29         
30         if(Length <= 0 || !Data) {
31                 *Err = -EINVAL;
32                 LEAVE_RET('i', -1);
33         }
34         
35         // Get thread
36         thread = Threads_GetThread( Dest );
37         
38         // Error check
39         if(!thread)     LEAVE_RET('i', -1);
40         
41         // Get Spinlock
42         SHORTLOCK( &thread->IsLocked );
43         
44         // Check if thread is still alive
45         if(thread->Status == THREAD_STAT_DEAD) {
46                 SHORTREL( &thread->IsLocked );
47                 LEAVE_RET('i', -1);
48         }
49         
50         // Create message
51         msg = malloc( sizeof(tMsg)+Length );
52         msg->Next = NULL;
53         msg->Source = Proc_GetCurThread()->TID;
54         msg->Length = Length;
55         memcpy(msg->Data, Data, Length);
56         
57         // If there are already messages
58         if(thread->LastMessage) {
59                 thread->LastMessage->Next = msg;
60                 thread->LastMessage = msg;
61         } else {
62                 thread->Messages = msg;
63                 thread->LastMessage = msg;
64         }
65         
66         SHORTREL(&thread->IsLocked);
67         
68         SHORTLOCK(&glThreadListLock);
69         LOG("Waking %p (%i %s)", thread, thread->TID, thread->ThreadName);
70         Threads_Wake( thread );
71         SHORTREL(&glThreadListLock);
72         
73         LEAVE_RET('i', 0);
74 }
75
76 /**
77  * \fn int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer)
78  * \brief Gets a message
79  * \param Err   Pointer to \a errno
80  * \param Source        Where to put the source TID
81  * \param Buffer        Buffer to place the message data (set to NULL to just get message length)
82  */
83 int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer)
84 {
85          int    ret;
86         void    *tmp;
87         tThread *cur = Proc_GetCurThread();
88
89         ENTER("pSource pBuffer", Source, Buffer);
90         
91         // Check if queue has any items
92         if(!cur->Messages) {
93                 LEAVE('i', 0);
94                 return 0;
95         }
96
97         SHORTLOCK( &cur->IsLocked );
98         
99         if(Source) {
100                 *Source = cur->Messages->Source;
101                 LOG("*Source = %i", *Source);
102         }
103         
104         // Get message length
105         if( !Buffer ) {
106                 ret = cur->Messages->Length;
107                 SHORTREL( &cur->IsLocked );
108                 LEAVE('i', ret);
109                 return ret;
110         }
111         
112         // Get message
113         if(Buffer != GETMSG_IGNORE)
114         {
115                 if( !CheckMem( Buffer, cur->Messages->Length ) )
116                 {
117                         LOG("Invalid buffer");
118                         *Err = -EINVAL;
119                         SHORTREL( &cur->IsLocked );
120                         LEAVE('i', -1);
121                         return -1;
122                 }
123                 LOG("Copied to buffer");
124                 memcpy(Buffer, cur->Messages->Data, cur->Messages->Length);
125         }
126         ret = cur->Messages->Length;
127         
128         // Remove from list
129         tmp = cur->Messages;
130         cur->Messages = cur->Messages->Next;
131         if(cur->Messages == NULL)       cur->LastMessage = NULL;
132         
133         SHORTREL( &cur->IsLocked );
134         
135         free(tmp);      // Free outside of lock
136
137         LEAVE('i', ret);
138         return ret;
139 }

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