1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\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
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
14 * -------------------------------- Arctic Core ------------------------------*/
\r
16 #include <sys/queue.h>
\r
19 #include "internal.h"
\r
21 #define VALIDATE_W_RV(_exp,_rv) \
\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
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
38 * @param Mask Mask of the events waited for
\r
42 StatusType WaitEvent( EventMaskType Mask ) {
\r
44 OsPcbType *curr_pcb = get_curr_pcb();
\r
45 StatusType rv = E_OK;
\r
47 OS_DEBUG(D_EVENT,"# WaitEvent %s\n",Os_TaskGetCurrent()->name);
\r
49 if( os_sys.int_nest_cnt != 0 ) {
\r
54 if (curr_pcb->proc_type != PROC_EXTENDED) {
\r
59 if ( Os_TaskOccupiesResources(curr_pcb) ) {
\r
64 /* Remove from ready queue */
\r
67 // 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
68 // WaitEvent is already set. In this case WaitEvent does not lead to a rescheduling.
\r
69 if( !(curr_pcb->ev_set & Mask) ) {
\r
71 curr_pcb->ev_wait = Mask;
\r
73 if ( Os_SchedulerResourceIsFree() ) {
\r
74 // Os_TaskMakeWaiting(curr_pcb);
\r
75 Os_Dispatch(OP_WAIT_EVENT);
\r
76 assert( curr_pcb->state & ST_RUNNING );
\r
78 Os_TaskMakeWaiting(curr_pcb);
\r
84 // The following line disables the unused label warning. Remove when
\r
85 // proper error handling is implemented.
\r
88 OS_STD_END_1(OSServiceId_WaitEvent,Mask);
\r
92 * The events of task <TaskID> are set according to the event
\r
93 * mask <Mask>. Calling SetEvent causes the task <TaskID> to
\r
94 * be transferred to the ready state, if it was waiting for at least
\r
95 * one of the events specified in <Mask>.
\r
97 * @param TaskID - Reference to the task for which one or several events are to be set.
\r
98 * @param Mask - Mask of the events to be set
\r
102 StatusType SetEvent( TaskType TaskID, EventMaskType Mask ) {
\r
103 StatusType rv = E_OK;
\r
104 OsPcbType *dest_pcb;
\r
105 OsPcbType *currPcbPtr;
\r
108 OS_DEBUG(D_EVENT,"# SetEvent %s\n",Os_TaskGetCurrent()->name);
\r
110 if( TaskID >= OS_TASK_CNT ) {
\r
115 dest_pcb = os_get_pcb(TaskID);
\r
117 #if (OS_STATUS_EXTENDED == STD_ON )
\r
118 if( dest_pcb->proc_type != PROC_EXTENDED ) {
\r
123 if( (dest_pcb->state & ST_SUSPENDED ) ) {
\r
131 /* Calling SetEvent causes the task <TaskID> to be transferred
\r
132 * to the ready state, if it was waiting for at least one of the
\r
133 * events specified in <Mask>.
\r
135 * OSEK/VDX 4.6.1, rescheduling is performed in all of the following cases:
\r
137 * Setting an event to a waiting task at task level (e.g. system service SetEvent,
\r
138 * see chapter 13.5.3.1, message notification mechanism, alarm expiration, if event setting
\r
139 * defined, see chapter 9.2)
\r
142 dest_pcb->ev_set |= Mask;
\r
144 if( (Mask & dest_pcb->ev_wait) ) {
\r
145 /* We have an event match */
\r
146 if( dest_pcb->state & ST_WAITING) {
\r
147 Os_TaskMakeReady(dest_pcb);
\r
149 currPcbPtr = Os_TaskGetCurrent();
\r
150 /* Checking "4.6.2 Non preemptive scheduling" it does not dispatch if NON */
\r
151 if( (os_sys.int_nest_cnt == 0) &&
\r
152 (currPcbPtr->scheduling == FULL) &&
\r
153 (dest_pcb->prio > currPcbPtr->prio) &&
\r
154 (Os_SchedulerResourceIsFree()) )
\r
156 Os_Dispatch(OP_SET_EVENT);
\r
159 } else if(dest_pcb->state & (ST_READY|ST_RUNNING) ) {
\r
160 /* Hmm, we do nothing */
\r
166 Irq_Restore(flags);
\r
168 OS_STD_END_2(OSServiceId_SetEvent,TaskID, Mask);
\r
173 * This service returns the current state of all event bits of the task
\r
174 * <TaskID>, not the events that the task is waiting for.
\r
175 * The service may be called from interrupt service routines, task
\r
176 * level and some hook routines (see Figure 12-1).
\r
177 * The current status of the event mask of task <TaskID> is copied
\r
180 * @param TaskId Task whose event mask is to be returned.
\r
181 * @param Mask Reference to the memory of the return data.
\r
184 StatusType GetEvent( TaskType TaskId, EventMaskRefType Mask) {
\r
186 OsPcbType *dest_pcb;
\r
187 StatusType rv = E_OK;
\r
189 if( TaskId >= OS_TASK_CNT ) {
\r
194 dest_pcb = os_get_pcb(TaskId);
\r
196 VALIDATE_W_RV(dest_pcb->proc_type != PROC_EXTENDED,E_OS_ACCESS);
\r
197 VALIDATE_W_RV(dest_pcb->state & ST_SUSPENDED,E_OS_STATE);
\r
199 *Mask = dest_pcb->ev_set;
\r
203 OS_STD_END_2(OSServiceId_GetEvent,TaskId, Mask);
\r
208 * The events of the extended task calling ClearEvent are cleared
\r
209 * according to the event mask <Mask>.
\r
215 StatusType ClearEvent( EventMaskType Mask) {
\r
216 StatusType rv = E_OK;
\r
219 if( os_sys.int_nest_cnt != 0 ) {
\r
220 rv = E_OS_CALLEVEL;
\r
224 pcb = get_curr_pcb();
\r
226 if (pcb->proc_type != PROC_EXTENDED) {
\r
231 pcb->ev_set &= ~Mask;
\r
235 OS_STD_END_1(OSServiceId_ClearEvent,Mask);
\r