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

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