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

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