]> rtime.felk.cvut.cz Git - arc.git/blob - system/kernel/event.c
merge with osek-ctest
[arc.git] / system / kernel / event.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 #include <sys/queue.h>\r
17 #include <stdlib.h>\r
18 #include "Os.h"\r
19 #include "internal.h"\r
20 \r
21 #define VALIDATE_W_RV(_exp,_rv) \\r
22         if( (_exp) ) { \\r
23                 ERRORHOOK(_rv); \\r
24                 return _rv; \\r
25         }\r
26 \r
27 \r
28 /**\r
29  * The state of the calling task is set to waiting, unless at least one\r
30  * of the events specified in <Mask> has already been set.\r
31  *\r
32  * This call enforces rescheduling, if the wait condition occurs. If\r
33  * rescheduling takes place, the internal resource of the task is\r
34  * released while the task is in the waiting state.\r
35  * This service shall only be called from the extended task owning\r
36  * the event.\r
37  *\r
38  * @param Mask Mask of the events waited for\r
39  * @return\r
40  */\r
41 \r
42 StatusType WaitEvent( EventMaskType Mask ) {\r
43 \r
44         OsPcbType *curr_pcb = get_curr_pcb();\r
45         StatusType rv = E_OK;\r
46 \r
47         if( os_sys.int_nest_cnt != 0 ) {\r
48                 rv =  E_OS_CALLEVEL;\r
49                 goto err;\r
50         }\r
51 \r
52         if (curr_pcb->proc_type != PROC_EXTENDED) {\r
53                 rv = E_OS_ACCESS;\r
54                 goto err;\r
55         }\r
56 \r
57         if ( Os_TaskOccupiesResouces(curr_pcb) ) {\r
58                 rv = E_OS_RESOURCE;\r
59                 goto err;\r
60         }\r
61 \r
62         /* Remove from ready queue */\r
63         Irq_Disable();\r
64 \r
65         // OSEK/VDX footnote 5. The call of WaitEvent does not lead to a waiting state if one of the events passed in the event mask to\r
66     // WaitEvent is already set. In this case WaitEvent does not lead to a rescheduling.\r
67         if( !(curr_pcb->ev_set & Mask) ) {\r
68 \r
69                 curr_pcb->ev_wait = Mask;\r
70 \r
71                 if ( Os_SchedulerResourceIsFree() ) {\r
72                         POSTTASKHOOK();\r
73                         Os_TaskMakeWaiting(curr_pcb);\r
74                         Os_Dispatch(0);\r
75                 } else {\r
76                         Os_TaskMakeWaiting(curr_pcb);\r
77                 }\r
78         }\r
79 \r
80         Irq_Enable();\r
81 \r
82         // The following line disables the unused label warning. Remove when\r
83         // proper error handling is implemented.\r
84         if (0) goto err;\r
85 \r
86         OS_STD_END_1(OSServiceId_WaitEvent,Mask);\r
87 }\r
88 \r
89 /**\r
90  * The events of task <TaskID> are set according to the event\r
91  * mask <Mask>. Calling SetEvent causes the task <TaskID> to\r
92  * be transferred to the  ready state, if it was waiting for at least\r
93  * one of the events specified in <Mask>.\r
94  *\r
95  * @param TaskID - Reference to the task for which one or several events are to be set.\r
96  * @param Mask - Mask of the events to be set\r
97  * @return\r
98  */\r
99 \r
100 StatusType SetEvent( TaskType TaskID, EventMaskType Mask ) {\r
101         StatusType rv = E_OK;\r
102         OsPcbType *dest_pcb;\r
103         OsPcbType *currPcbPtr;\r
104         uint32_t flags;\r
105 \r
106         if( TaskID  >= Os_CfgGetTaskCnt() ) {\r
107                 rv = E_OS_ID;\r
108                 goto err;\r
109         }\r
110 \r
111         dest_pcb = os_get_pcb(TaskID);\r
112 \r
113         if( (dest_pcb->state & ST_SUSPENDED ) ) {\r
114                 rv = E_OS_STATE;\r
115                 goto err;\r
116         }\r
117 \r
118         if( dest_pcb->proc_type != PROC_EXTENDED ) {\r
119                 rv = E_OS_ACCESS;\r
120                 goto err;\r
121         }\r
122 \r
123         Irq_Save(flags);\r
124 \r
125         /* Calling  SetEvent  causes  the  task  <TaskID>  to be  transferred\r
126          * to  the  ready  state,  if  it  was  waiting  for  at  least one of the\r
127          * events specified in <Mask>.\r
128          *\r
129          * OSEK/VDX 4.6.1,  rescheduling is performed in all of the following cases:\r
130          * ..\r
131          * Setting an event to a waiting task at task level (e.g. system service SetEvent,\r
132          * see chapter 13.5.3.1, message notification mechanism, alarm expiration, if event setting\r
133          * defined, see chapter 9.2)\r
134          * ... */\r
135 \r
136         dest_pcb->ev_set |= Mask;\r
137 \r
138         if( (Mask & dest_pcb->ev_wait) ) {\r
139                 /* We have an event match */\r
140                 if( dest_pcb->state & ST_WAITING) {\r
141                         Os_TaskMakeReady(dest_pcb);\r
142 \r
143                         currPcbPtr = Os_TaskGetCurrent();\r
144                         /* Checking "4.6.2  Non preemptive scheduling" it does not dispatch if NON  */\r
145                         if( (os_sys.int_nest_cnt == 0) &&\r
146                                 (currPcbPtr->scheduling == FULL) &&\r
147                                 (dest_pcb->prio > currPcbPtr->prio) &&\r
148                                 (Os_SchedulerResourceIsFree()) )\r
149                         {\r
150                                 Os_SetOp(OP_SET_EVENT);\r
151                                 Os_Dispatch(0);\r
152                         }\r
153 \r
154                 }  else if(dest_pcb->state & ST_READY ) {\r
155                         /* Hmm, we do nothing */\r
156                 }\r
157         }\r
158 \r
159         Irq_Restore(flags);\r
160 \r
161         OS_STD_END_2(OSServiceId_SetEvent,TaskID, Mask);\r
162 }\r
163 \r
164 \r
165 /**\r
166  * This service returns the current state of all event bits of the task\r
167  * <TaskID>, not the events that the task is waiting for.\r
168  * The service may be called from interrupt service routines, task\r
169  * level and some hook routines (see Figure 12-1).\r
170  *  The current status of the event mask of task <TaskID> is copied\r
171  * to <Event>.\r
172  *\r
173  * @param TaskId Task whose event mask is to be returned.\r
174  * @param Mask   Reference to the memory of the return data.\r
175  * @return\r
176  */\r
177 StatusType GetEvent( TaskType TaskId, EventMaskRefType Mask) {\r
178 \r
179         OsPcbType *dest_pcb;\r
180         StatusType rv = E_OK;\r
181 \r
182         if( TaskId  >= Os_CfgGetTaskCnt() ) {\r
183                 rv = E_OS_ID;\r
184                 goto err;\r
185         }\r
186 \r
187         dest_pcb = os_get_pcb(TaskId);\r
188 \r
189         VALIDATE_W_RV(dest_pcb->state & ST_SUSPENDED,E_OS_STATE);\r
190         VALIDATE_W_RV(dest_pcb->proc_type != PROC_EXTENDED,E_OS_ACCESS);\r
191 \r
192         *Mask = dest_pcb->ev_set;\r
193 \r
194         if (0) goto err;\r
195 \r
196         OS_STD_END_2(OSServiceId_GetEvent,TaskId, Mask);\r
197 }\r
198 \r
199 \r
200 /**\r
201  * The events of the extended task calling ClearEvent are cleared\r
202  * according to the event mask <Mask>.\r
203  *\r
204  *\r
205  * @param Mask\r
206  * @return\r
207  */\r
208 StatusType ClearEvent( EventMaskType Mask) {\r
209     StatusType rv = E_OK;\r
210         OsPcbType *pcb;\r
211 \r
212         if( os_sys.int_nest_cnt != 0 ) {\r
213                 rv =  E_OS_CALLEVEL;\r
214                 goto err;\r
215         }\r
216 \r
217         pcb = get_curr_pcb();\r
218 \r
219         if (pcb->proc_type != PROC_EXTENDED) {\r
220                 rv = E_OS_ACCESS;\r
221                 goto err;\r
222         }\r
223 \r
224         pcb->ev_set &= ~Mask;\r
225 \r
226         if (0) goto err;\r
227 \r
228         OS_STD_END_1(OSServiceId_ClearEvent,Mask);\r
229 }\r
230 \r
231 \r
232 \r
233 \r
234 \r