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

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