3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
33 extern unsigned long timer_ticks
;
35 unsigned task_id
= NULL
;
37 SPINLOCK_CREATE (sched_spinlock
);
41 * Function, which handle each task.
42 * It jump from task to another task in moment, when schedule () is called.
51 if (_curr_task
->spinlock
)
52 if (_curr_task
->spinlock
->locked
)
55 /* we dont need check spinlock now, because we check it below,
56 when we are sure about running task */
57 spinlock_lock (&sched_spinlock
);
59 /* check task with priority > 0 */
60 if (_curr_task
->priority
) { /* is it on kernel level ? No ? Let's continue */
61 _curr_task
->attick
++;
63 _curr_task
->lasttick
= timer_ticks
; /* remember current tick time */
65 if (_curr_task
->attick
< 256/_curr_task
->priority
) /* calculate when process have to be block and when not */
68 _curr_task
->attick
= 0; /* handle current task and null attick counter */
70 /*if (_curr_task->attick < 256/_curr_task->priority)*/ /* calculate when process have to be block and when not */
73 _curr_task
->attick
= 0; /* handle current task and null attick counter */
77 /* set current task */
78 if (arch_task_set (_curr_task
))
82 /* continue on next task */
83 _curr_task
= _curr_task
->next
;
85 /* task is out of task_list structure */
86 if (_curr_task
== &task_list
)
87 _curr_task
= task_list
.next
; /* current task is first task in task_list structure */
89 /* Is current task running ? */
90 if (_curr_task
->status
== TS_RUNNABLE
) {
92 /* switch page directory for current task */
93 if (_curr_task
->page_cover
)
94 page_dir_switch (_curr_task
->page_cover
->page_dir
);
95 else /* when page_cover pointer is NULL, it mean that kernel task is current */
96 page_dir_switch (task_list
.next
->page_cover
->page_dir
);
101 if (_curr_task
->spinlock
)
102 if (_curr_task
->spinlock
->locked
)
103 spinlock_unlock (&sched_spinlock
);
106 /* switch to new/current task */
107 arch_task_switch (_curr_task
);
114 /*****************************************************************************
115 *****************************************************************************/
116 void task_schedule ()
122 extern unsigned short *vesafb
;
123 extern unsigned char vgagui
;
124 task_t
*task_create (char *name
, unsigned entry
, unsigned priority
)
126 if (priority
> 255) /* priority 256 is max */
129 /* alloc and init context */
130 task_t
*task
= (task_t
*) kmalloc (sizeof (task_t
));
132 /* out of memory ? */
134 DPRINT (DBG_SCHED
, "task_create () - !task");
135 task
= (task_t
*) kmalloc (sizeof (task_t
));
142 /* mark task #0 (idle task) runnable */
143 task
->status
= TS_RUNNABLE
;
145 task
->priority
= priority
;
147 strcpy (task
->name
, name
);
149 task
->spinlock
= &sched_spinlock
;
153 task
->page_cover
= 0;
155 task
->page_cover
= (page_ent_t
*) page_cover_create ();
157 /* kernel covering by paging */
158 page_mmap (task
->page_cover
, 0, (void *) PAGE_MEM_LOW
, 1, 0);
160 /* framebuffer covering by paging */
161 page_mmap (task
->page_cover
, (void *) PAGE_MEM_LOW
, (void *) PAGE_MEM_FB
, 1, 1);
163 /* user-space covering by paging */
164 page_mmap (task
->page_cover
, (void *) PAGE_MEM_FB
, (void *) PAGE_MEM_HIGH
, 1, 0);
166 page_dir_switch (task
->page_cover
->page_dir
);
171 task
->next
= &task_list
;
172 task
->prev
= task_list
.prev
;
173 task
->prev
->next
= task
;
174 task
->next
->prev
= task
;
176 /* set _curr_task so schedule() will save state of task #0 */
179 /* NOTE: ARM need to start new fake of main kernel task */
180 arch_task_init (task
, (unsigned) &task_schedule
);
185 arch_task_init (task
, entry
);
187 task_id
++; // increase id number for new task
190 task
->status
= TS_RUNNABLE
;
191 // task priority - how offten will be active
192 task
->priority
= priority
;
193 // task attick - how ofter per all time line handle this task (not in %)
194 task
->attick
= task_id
- 1;
196 strcpy (task
->name
, name
);
197 // spinlock is not available by default
199 // page covering of process
200 task
->page_cover
= 0;
201 // task identification number - usefully on process level (multi-threaded apps)
203 // task's time stamp of last tick
207 task
->next
= &task_list
;
208 task
->prev
= task_list
.prev
;
209 task
->prev
->next
= task
;
210 task
->next
->prev
= task
;
212 DPRINT (DBG_SCHED
, "task -> %s (%d)", name
, task_id
);
217 bool task_done (task_t
*task
)
220 DPRINT (DBG_SCHED
, "task -> %s done", task
->name
);
222 task
->status
= TS_NULL
;
224 task
->next
->prev
= task
->prev
;
225 task
->prev
->next
= task
->next
;
235 task_t
*task_find (unsigned short id
)
238 for (task
= task_list
.next
; task
!= &task_list
; task
= task
->next
) {
246 unsigned int init_tasks (void)
248 task_list
.next
= &task_list
;
249 task_list
.prev
= &task_list
;
251 /* NOTE: NULL entry point task can't be created multiple times ! */
252 task_create ("kernel", NULL
, 0);