]> rtime.felk.cvut.cz Git - arc.git/blob - system/kernel/event.c
Merge with tip
[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         OS_DEBUG(D_EVENT,"# WaitEvent %s\n",Os_TaskGetCurrent()->name);\r
48 \r
49         if( os_sys.int_nest_cnt != 0 ) {\r
50                 rv =  E_OS_CALLEVEL;\r
51                 goto err;\r
52         }\r
53 \r
54         if (curr_pcb->proc_type != PROC_EXTENDED) {\r
55                 rv = E_OS_ACCESS;\r
56                 goto err;\r
57         }\r
58 \r
59         if ( Os_TaskOccupiesResources(curr_pcb) ||\r
60                  !Os_SchedulerResourceIsFree() ) {\r
61                 rv = E_OS_RESOURCE;\r
62                 goto err;\r
63         }\r
64 \r
65         /* Remove from ready queue */\r
66         Irq_Disable();\r
67 \r
68         // 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
69     // WaitEvent is already set. In this case WaitEvent does not lead to a rescheduling.\r
70         if( !(curr_pcb->ev_set & Mask) ) {\r
71 \r
72                 curr_pcb->ev_wait = Mask;\r
73 \r
74                 Os_Dispatch(OP_WAIT_EVENT);\r
75                 assert( curr_pcb->state & ST_RUNNING );\r
76         }\r
77 \r
78         Irq_Enable();\r
79 \r
80         // The following line disables the unused label warning. Remove when\r
81         // proper error handling is implemented.\r
82         if (0) goto err;\r
83 \r
84         OS_STD_END_1(OSServiceId_WaitEvent,Mask);\r
85 }\r
86 \r
87 /**\r
88  * The events of task <TaskID> are set according to the event\r
89  * mask <Mask>. Calling SetEvent causes the task <TaskID> to\r
90  * be transferred to the  ready state, if it was waiting for at least\r
91  * one of the events specified in <Mask>.\r
92  *\r
93  * @param TaskID - Reference to the task for which one or several events are to be set.\r
94  * @param Mask - Mask of the events to be set\r
95  * @return\r
96  */\r
97 \r
98 StatusType SetEvent( TaskType TaskID, EventMaskType Mask ) {\r
99         StatusType rv = E_OK;\r
100         OsPcbType *dest_pcb;\r
101         OsPcbType *currPcbPtr;\r
102         uint32_t flags;\r
103 \r
104         OS_DEBUG(D_EVENT,"# SetEvent %s\n",Os_TaskGetCurrent()->name);\r
105 \r
106         if( TaskID  >= OS_TASK_CNT ) {\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 (OS_STATUS_EXTENDED == STD_ON )\r
114         if( dest_pcb->proc_type != PROC_EXTENDED ) {\r
115                 rv = E_OS_ACCESS;\r
116                 goto err;\r
117         }\r
118 \r
119         if( (dest_pcb->state & ST_SUSPENDED ) ) {\r
120                 rv = E_OS_STATE;\r
121                 goto err;\r
122         }\r
123 #endif\r
124 \r
125         Irq_Save(flags);\r
126 \r
127         /* Calling  SetEvent  causes  the  task  <TaskID>  to be  transferred\r
128          * to  the  ready  state,  if  it  was  waiting  for  at  least one of the\r
129          * events specified in <Mask>.\r
130          *\r
131          * OSEK/VDX 4.6.1,  rescheduling is performed in all of the following cases:\r
132          * ..\r
133          * Setting an event to a waiting task at task level (e.g. system service SetEvent,\r
134          * see chapter 13.5.3.1, message notification mechanism, alarm expiration, if event setting\r
135          * defined, see chapter 9.2)\r
136          * ... */\r
137 \r
138         dest_pcb->ev_set |= Mask;\r
139 \r
140         if( (Mask & dest_pcb->ev_wait)\r
141 #if defined(USE_KERNEL_EXTRA)\r
142                         /* Don't dispatch if target task is sleeping */\r
143                         && !(dest_pcb->state & ST_SLEEPING)\r
144 #endif\r
145 \r
146         ) {\r
147                 assert(dest_pcb->state & ST_WAITING );\r
148 \r
149                 Os_TaskMakeReady(dest_pcb);\r
150 \r
151                 currPcbPtr = Os_TaskGetCurrent();\r
152                 /* Checking "4.6.2  Non preemptive scheduling" it does not dispatch if NON  */\r
153                 if( (os_sys.int_nest_cnt == 0) &&\r
154                         (currPcbPtr->scheduling == FULL) &&\r
155                         (dest_pcb->prio > currPcbPtr->prio) &&\r
156                         (Os_SchedulerResourceIsFree()) )\r
157                 {\r
158                         Os_Dispatch(OP_SET_EVENT);\r
159                 }\r
160         }\r
161 \r
162         Irq_Restore(flags);\r
163 \r
164         OS_STD_END_2(OSServiceId_SetEvent,TaskID, Mask);\r
165 }\r
166 \r
167 \r
168 /**\r
169  * This service returns the current state of all event bits of the task\r
170  * <TaskID>, not the events that the task is waiting for.\r
171  * The service may be called from interrupt service routines, task\r
172  * level and some hook routines (see Figure 12-1).\r
173  *  The current status of the event mask of task <TaskID> is copied\r
174  * to <Event>.\r
175  *\r
176  * @param TaskId Task whose event mask is to be returned.\r
177  * @param Mask   Reference to the memory of the return data.\r
178  * @return\r
179  */\r
180 StatusType GetEvent( TaskType TaskId, EventMaskRefType Mask) {\r
181 \r
182         OsPcbType *dest_pcb;\r
183         StatusType rv = E_OK;\r
184 \r
185         if( TaskId  >= OS_TASK_CNT ) {\r
186                 rv = E_OS_ID;\r
187                 goto err;\r
188         }\r
189 \r
190         dest_pcb = os_get_pcb(TaskId);\r
191 \r
192         VALIDATE_W_RV(dest_pcb->proc_type != PROC_EXTENDED,E_OS_ACCESS);\r
193         VALIDATE_W_RV(dest_pcb->state & ST_SUSPENDED,E_OS_STATE);\r
194 \r
195         *Mask = dest_pcb->ev_set;\r
196 \r
197         if (0) goto err;\r
198 \r
199         OS_STD_END_2(OSServiceId_GetEvent,TaskId, Mask);\r
200 }\r
201 \r
202 \r
203 /**\r
204  * The events of the extended task calling ClearEvent are cleared\r
205  * according to the event mask <Mask>.\r
206  *\r
207  *\r
208  * @param Mask\r
209  * @return\r
210  */\r
211 StatusType ClearEvent( EventMaskType Mask) {\r
212     StatusType rv = E_OK;\r
213         OsPcbType *pcb;\r
214 \r
215         if( os_sys.int_nest_cnt != 0 ) {\r
216                 rv =  E_OS_CALLEVEL;\r
217                 goto err;\r
218         }\r
219 \r
220         pcb = get_curr_pcb();\r
221 \r
222         if (pcb->proc_type != PROC_EXTENDED) {\r
223                 rv = E_OS_ACCESS;\r
224                 goto err;\r
225         }\r
226 \r
227         pcb->ev_set &= ~Mask;\r
228 \r
229         if (0) goto err;\r
230 \r
231         OS_STD_END_1(OSServiceId_ClearEvent,Mask);\r
232 }\r
233 \r
234 \r
235 \r
236 \r
237 \r