3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32 extern unsigned long timer_ticks
;
34 unsigned task_id
= NULL
;
36 SPINLOCK_CREATE (sched_spinlock
);
40 * Function, which handle each task.
41 * It jump from task to another task in moment, when schedule () is called.
50 if (_curr_task
->spinlock
)
51 if (_curr_task
->spinlock
->locked
)
54 /* we dont need check spinlock now, because we check it below,
55 when we are sure about running task */
56 spinlock_lock (&sched_spinlock
);
58 /* check task with priority > 0 */
59 if (_curr_task
->priority
) { /* is it on kernel level ? No ? Let's continue */
60 _curr_task
->attick
++;
62 _curr_task
->lasttick
= timer_ticks
; /* remember current tick time */
64 if (_curr_task
->attick
< 256/_curr_task
->priority
) /* calculate when process have to be block and when not */
67 _curr_task
->attick
= 0; /* handle current task and null attick counter */
69 /*if (_curr_task->attick < 256/_curr_task->priority)*/ /* calculate when process have to be block and when not */
72 _curr_task
->attick
= 0; /* handle current task and null attick counter */
74 } else /* we dont need use everytime 100% of cpu time - wait a tick */
77 /* set current task */
78 if (arch_task_set (_curr_task
))
83 /* continue on next task */
84 _curr_task
= _curr_task
->next
;
86 /* task is out of task_list structure */
87 if (_curr_task
== &task_list
)
88 _curr_task
= task_list
.next
; /* current task is first task in task_list structure */
90 /* Is current task running ? */
91 if (_curr_task
->status
== TS_RUNNABLE
) {
93 /* switch page directory for current task */
94 if (_curr_task
->page_cover
)
95 page_dir_switch (_curr_task
->page_cover
->page_dir
);
96 else /* when page_cover pointer is NULL, it mean that kernel task is current */
97 page_dir_switch (task_list
.next
->page_cover
->page_dir
);
102 if (_curr_task
->spinlock
)
103 if (_curr_task
->spinlock
->locked
)
104 spinlock_unlock (&sched_spinlock
);
107 /* switch to new/current task */
108 arch_task_switch (_curr_task
);
115 /*****************************************************************************
116 *****************************************************************************/
117 void task_schedule ()
123 extern unsigned short *vesafb
;
124 extern unsigned char vgagui
;
125 task_t
*task_create (char *name
, unsigned entry
, unsigned priority
)
127 if (priority
> 255) /* priority 256 is max */
130 /* alloc and init context */
131 task_t
*task
= (task_t
*) kmalloc (sizeof (task_t
));
133 /* out of memory ? */
135 DPRINT (DBG_SCHED
, "task_create () - !task");
136 task
= (task_t
*) kmalloc (sizeof (task_t
));
143 /* mark task #0 (idle task) runnable */
144 task
->status
= TS_RUNNABLE
;
146 task
->priority
= priority
;
148 strcpy (task
->name
, name
);
150 task
->spinlock
= &sched_spinlock
;
154 task
->page_cover
= 0;
156 task
->page_cover
= (page_ent_t
*) page_cover_create ();
158 /* kernel covering by paging */
159 page_mmap (task
->page_cover
, 0, (void *) 0x400000, 1, 0);
161 /* framebuffer covering by paging */
162 page_mmap (task
->page_cover
, (void *) 0x400000, (void *) 0x500000, 1, 1);
164 /* user-space covering by paging */
165 page_mmap (task
->page_cover
, (void *) 0x500000, (void *) 0x800000, 1, 0);
168 // page_mmap (task->page_cover, (void *) vesafb, (void *) ((void *) vesafb+(800*600*4)), 1, 0);
170 page_mmap (task->page_cover, (void *) PAGE_MEM_LOW, (void *) ((void *) PAGE_MEM_LOW+0x100000+800*600*vgagui), 1, 1);
172 //vesafb = (void *) PAGE_MEM_LOW;
175 page_dir_switch (task
->page_cover
->page_dir
);
180 for (p = 0; p < 800*600; p ++)
185 task
->next
= &task_list
;
186 task
->prev
= task_list
.prev
;
187 task
->prev
->next
= task
;
188 task
->next
->prev
= task
;
190 /* set _curr_task so schedule() will save state of task #0 */
193 /* NOTE: ARM need to start new fake of main kernel task */
194 arch_task_init (task
, (unsigned) &task_schedule
);
199 arch_task_init (task
, entry
);
201 task_id
++; // increase id number for new task
204 task
->status
= TS_RUNNABLE
;
205 // task priority - how offten will be active
206 task
->priority
= priority
;
207 // task attick - how ofter per all time line handle this task (not in %)
208 task
->attick
= task_id
- 1;
210 strcpy (task
->name
, name
);
211 // spinlock is not available by default
213 // page covering of process
214 task
->page_cover
= 0;
215 // task identification number - usefully on process level (multi-threaded apps)
217 // task's time stamp of last tick
221 task
->next
= &task_list
;
222 task
->prev
= task_list
.prev
;
223 task
->prev
->next
= task
;
224 task
->next
->prev
= task
;
226 DPRINT (DBG_SCHED
, "task -> %s (%d)", name
, task_id
);
231 bool task_done (task_t
*task
)
234 DPRINT (DBG_SCHED
, "task -> %s done", task
->name
);
236 task
->status
= TS_NULL
;
238 task
->next
->prev
= task
->prev
;
239 task
->prev
->next
= task
->next
;
249 task_t
*task_find (unsigned short id
)
252 for (task
= task_list
.next
; task
!= &task_list
; task
= task
->next
) {
260 unsigned int init_tasks (void)
262 task_list
.next
= &task_list
;
263 task_list
.prev
= &task_list
;
265 /* NOTE: NULL entry point task can't be created multiple times ! */
266 task_create ("kernel", NULL
, 0);