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
60 !Os_SchedulerResourceIsFree() ) {
\r
65 /* Remove from ready queue */
\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
72 curr_pcb->ev_wait = Mask;
\r
74 Os_Dispatch(OP_WAIT_EVENT);
\r
75 assert( curr_pcb->state & ST_RUNNING );
\r
80 // The following line disables the unused label warning. Remove when
\r
81 // proper error handling is implemented.
\r
84 OS_STD_END_1(OSServiceId_WaitEvent,Mask);
\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
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
98 StatusType SetEvent( TaskType TaskID, EventMaskType Mask ) {
\r
99 StatusType rv = E_OK;
\r
100 OsPcbType *dest_pcb;
\r
101 OsPcbType *currPcbPtr;
\r
104 OS_DEBUG(D_EVENT,"# SetEvent %s\n",Os_TaskGetCurrent()->name);
\r
106 if( TaskID >= OS_TASK_CNT ) {
\r
111 dest_pcb = os_get_pcb(TaskID);
\r
113 #if (OS_STATUS_EXTENDED == STD_ON )
\r
114 if( dest_pcb->proc_type != PROC_EXTENDED ) {
\r
119 if( (dest_pcb->state & ST_SUSPENDED ) ) {
\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
131 * OSEK/VDX 4.6.1, rescheduling is performed in all of the following cases:
\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
138 dest_pcb->ev_set |= Mask;
\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
147 assert(dest_pcb->state & ST_WAITING );
\r
149 Os_TaskMakeReady(dest_pcb);
\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
158 Os_Dispatch(OP_SET_EVENT);
\r
162 Irq_Restore(flags);
\r
164 OS_STD_END_2(OSServiceId_SetEvent,TaskID, Mask);
\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
176 * @param TaskId Task whose event mask is to be returned.
\r
177 * @param Mask Reference to the memory of the return data.
\r
180 StatusType GetEvent( TaskType TaskId, EventMaskRefType Mask) {
\r
182 OsPcbType *dest_pcb;
\r
183 StatusType rv = E_OK;
\r
185 if( TaskId >= OS_TASK_CNT ) {
\r
190 dest_pcb = os_get_pcb(TaskId);
\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
195 *Mask = dest_pcb->ev_set;
\r
199 OS_STD_END_2(OSServiceId_GetEvent,TaskId, Mask);
\r
204 * The events of the extended task calling ClearEvent are cleared
\r
205 * according to the event mask <Mask>.
\r
211 StatusType ClearEvent( EventMaskType Mask) {
\r
212 StatusType rv = E_OK;
\r
215 if( os_sys.int_nest_cnt != 0 ) {
\r
216 rv = E_OS_CALLEVEL;
\r
220 pcb = get_curr_pcb();
\r
222 if (pcb->proc_type != PROC_EXTENDED) {
\r
227 pcb->ev_set &= ~Mask;
\r
231 OS_STD_END_1(OSServiceId_ClearEvent,Mask);
\r