Initial commit of kernel only
[tpg/acess2.git] / Kernel / messages.c
1 /*
2  * AcessOS Microkernel Version
3  * messages.c
4  */
5 #include <common.h>
6 #include <proc.h>
7 #include <errno.h>
8
9 // === CODE ===
10 /**
11  * \fn int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data)
12  * \brief Send an IPC message
13  * \param Err   Pointer to the errno variable
14  * \param Dest  Destination Thread
15  */
16 int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data)
17 {
18         tThread *thread;
19         tMsg    *msg;
20         
21         Log("Proc_SendMessage: (Err=%p, Dest=%i, Length=%i, Data=%p)", Err, Dest, Length, Data);
22         
23         if(Length <= 0 || !Data) {
24                 *Err = -EINVAL;
25                 return -1;
26         }
27         
28         // Get thread
29         thread = Proc_GetThread( Dest );
30         
31         // Error check
32         if(!thread) {   return -1;      }
33         
34         // Get Spinlock
35         LOCK( &thread->IsLocked );
36         
37         // Check if thread is still alive
38         if(thread->Status == THREAD_STAT_DEAD)  return -1;
39         
40         // Create message
41         msg = malloc( sizeof(tMsg)+Length );
42         msg->Next = NULL;
43         msg->Source = gCurrentThread->TID;
44         msg->Length = Length;
45         memcpy(msg->Data, Data, Length);
46         
47         // If there are already messages
48         if(thread->LastMessage) {
49                 thread->LastMessage->Next = msg;
50                 thread->LastMessage = msg;
51         } else {
52                 thread->Messages = msg;
53                 thread->LastMessage = msg;
54         }
55         
56         RELEASE(&thread->IsLocked);
57         
58         Thread_Wake( thread );
59         
60         return 0;
61 }
62
63 /**
64  * \fn int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer)
65  * \brief Gets a message
66  */
67 int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer)
68 {
69          int    ret;
70         void *tmp;
71         
72         // Check if queue has any items
73         if(!gCurrentThread->Messages) {
74                 return 0;
75         }
76
77         LOCK( &gCurrentThread->IsLocked );
78         
79         if(Source)
80                 *Source = gCurrentThread->Messages->Source;
81         
82         // Get message length
83         if( !Buffer ) {
84                 ret = gCurrentThread->Messages->Length;
85                 RELEASE( &gCurrentThread->IsLocked );
86                 return ret;
87         }
88         
89         // Get message
90         if(Buffer != GETMSG_IGNORE)
91                 memcpy(Buffer, gCurrentThread->Messages->Data, gCurrentThread->Messages->Length);
92         ret = gCurrentThread->Messages->Length;
93         
94         // Remove from list
95         tmp = gCurrentThread->Messages->Next;
96         free(gCurrentThread->Messages);
97         gCurrentThread->Messages = tmp;
98         
99         RELEASE( &gCurrentThread->IsLocked );
100         
101         return ret;
102 }

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