2 * Copyright Droids Corporation, Microb Technology, Eirbot (2005)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Revision : $Id: scheduler_interrupt.c,v 1.1.2.9 2009-11-08 17:33:14 zer0 Exp $
25 #include <scheduler_config.h>
26 #include <scheduler_private.h>
27 #include <scheduler_stats.h>
29 /** priority of the running event */
30 static volatile uint8_t priority_running=0;
32 /** number of imbricated scheduler interruptions */
33 static volatile uint8_t nb_stacking=0;
35 uint8_t scheduler_disable_save(void)
38 ret = priority_running;
39 priority_running = 255;
43 void scheduler_enable_restore(uint8_t old_prio)
45 priority_running = old_prio;
49 * this function is called from a timer interruption. If an event has
50 * to be scheduled, it will execute the fonction (IRQ are allowed
51 * during the execution of the function). This interruption can be
52 * interrupted by itself too, in this case only events with a higher
53 * priority can be scheduled.
55 * We assume that this function is called from a SIGNAL(), with
56 * global interrupt flag disabled --> that's why we can use cli() and
57 * sei() instead of IRQ_LOCK(flags).
60 scheduler_interrupt(void)
64 SLIST_HEAD(event_list_t, event_t) event_list;
65 struct event_t *e, *next_e, *prev_e=NULL;
67 /* maximize the number of imbrications */
68 if (nb_stacking >= SCHEDULER_NB_STACKING_MAX) {
69 SCHED_INC_STAT(max_stacking);
76 SLIST_INIT(&event_list);
78 /* browse events table to determine which events should be
80 for (i=0 ; i<SCHEDULER_NB_MAX_EVENT ; i++) {
83 /* the event is already present in a schedule list,
84 * only update its current time until it reaches 1 */
85 if (g_tab_event[i].state == SCHEDULER_EVENT_SCHEDULED) {
86 if (g_tab_event[i].current_time > 1) {
87 g_tab_event[i].current_time --;
92 SCHED_INC_STAT2(task_delayed, i);
98 /* nothing to do with other unactive events */
99 if (g_tab_event[i].state != SCHEDULER_EVENT_ACTIVE) {
104 /* decrement current time (we know it is >0 if it is
105 * in SCHEDULER_EVENT_ACTIVE state */
106 g_tab_event[i].current_time --;
108 /* don't need to schedule now */
109 if ( g_tab_event[i].current_time != 0 ) {
114 /* time to schedule, but priority is too low,
116 if (g_tab_event[i].priority <= priority_running) {
117 g_tab_event[i].current_time = 1;
118 SCHED_INC_STAT2(task_delayed, i);
123 /* reload event (it is 0 if it is non-periodical) */
124 g_tab_event[i].current_time = g_tab_event[i].period;
127 g_tab_event[i].state = SCHEDULER_EVENT_SCHEDULED;
128 SCHED_INC_STAT2(task_scheduled, i);
131 /* insert it in the list (list is ordered).
132 this should be quite fast since the list is
133 expected to be small. */
135 e = SLIST_FIRST(&event_list);
136 /* easy case : list is empty */
138 SLIST_INSERT_HEAD(&event_list, &g_tab_event[i], next);
142 /* insert at head if it's the event with highest prio */
143 if (g_tab_event[i].priority >= e->priority) {
144 SLIST_INSERT_HEAD(&event_list, &g_tab_event[i], next);
148 /* harder : find the good place in list */
149 SLIST_FOREACH(e, &event_list, next) {
150 next_e = SLIST_NEXT(e, next);
151 if (next_e == NULL ||
152 g_tab_event[i].priority >= next_e->priority) {
153 SLIST_INSERT_AFTER(e, &g_tab_event[i], next);
159 /* only called if SCHEDULER_DEBUG is defined */
163 priority_tmp = priority_running;
165 SLIST_FOREACH(e, &event_list, next) {
166 /* remove previous elt from list */
168 SLIST_NEXT(prev_e, next) = NULL;
170 /* set running priority */
171 priority_running = e->priority;
174 /* the following fields (f and data) can't be modified
175 * while an event is in state SCHEDULED */
179 /* free it if it is single (non-periodical) */
181 e->state = SCHEDULER_EVENT_FREE;
184 /* free event if someone asked for deletion during
186 if (e->state == SCHEDULER_EVENT_DELETING) {
187 e->state = SCHEDULER_EVENT_FREE;
190 /* end of schedule, mark it as active */
191 if (e->state == SCHEDULER_EVENT_SCHEDULED) {
192 e->state = SCHEDULER_EVENT_ACTIVE;
197 /* remove previous elt from list */
199 SLIST_NEXT(prev_e, next) = NULL;
201 priority_running = priority_tmp;