Fixed buffer overflow in mserver; fixed type of checkinfo () 2nd parameter; memory
[ZeXOS.git] / kernel / core / sched.c
blobb3ae7b89cd86a09acf296d3a6974676e31344502
1 /*
2 * ZeX/OS
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/>.
23 #include <build.h>
24 #include <system.h>
25 #include <arch/io.h>
26 #include <string.h>
27 #include <setjmp.h>
28 #include <task.h>
29 #include <spinlock.h>
31 task_t task_list;
32 task_t *_curr_task;
33 extern unsigned long timer_ticks;
35 unsigned task_id = NULL;
37 SPINLOCK_CREATE (sched_spinlock);
40 /** SCHEDULE
41 * Function, which handle each task.
42 * It jump from task to another task in moment, when schedule () is called.
45 void schedule (void)
47 /* avoid for crash */
48 if (!_curr_task)
49 return;
51 if (_curr_task->spinlock)
52 if (_curr_task->spinlock->locked)
53 return;
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 */
64 #ifdef ARCH_i386
65 if (_curr_task->attick < 256/_curr_task->priority) /* calculate when process have to be block and when not */
66 return;
67 else
68 _curr_task->attick = 0; /* handle current task and null attick counter */
69 #else
70 /*if (_curr_task->attick < 256/_curr_task->priority)*/ /* calculate when process have to be block and when not */
71 // return;
72 /*else*/
73 _curr_task->attick = 0; /* handle current task and null attick counter */
74 #endif
77 /* set current task */
78 if (arch_task_set (_curr_task))
79 return;
81 for (;;) {
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) {
91 #ifdef ARCH_i386
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);
97 #endif
98 if (!int_disable ())
99 return;
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);
109 return;
114 /*****************************************************************************
115 *****************************************************************************/
116 void task_schedule ()
118 for (;;)
119 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 */
127 priority = 255;
129 /* alloc and init context */
130 task_t *task = (task_t *) kmalloc (sizeof (task_t));
132 /* out of memory ? */
133 if (!task)
134 return 0;
136 /* kernel ? */
137 if (entry == NULL) {
138 /* mark task #0 (idle task) runnable */
139 task->status = TS_RUNNABLE;
141 task->priority = priority;
142 // add name of the task
143 strcpy (task->name, name);
145 task->spinlock = &sched_spinlock;
147 task->id = task_id;
148 #ifdef ARCH_i386
149 task->page_cover = (page_ent_t *) page_cover_create ();
151 /* kernel covering by paging */
152 page_mmap (task->page_cover, 0, (void *) PAGE_MEM_LOW, 1, 0);
154 /* framebuffer covering by paging */
155 page_mmap (task->page_cover, (void *) PAGE_MEM_LOW, (void *) PAGE_MEM_FB, 1, 1);
157 /* user-space covering by paging */
158 page_mmap (task->page_cover, (void *) PAGE_MEM_FB, (void *) PAGE_MEM_HIGH, 1, 0);
160 page_dir_switch (task->page_cover->page_dir);
162 paging_enable ();
163 #endif
164 /* add into list */
165 task->next = &task_list;
166 task->prev = task_list.prev;
167 task->prev->next = task;
168 task->next->prev = task;
170 /* set _curr_task so schedule() will save state of task #0 */
171 _curr_task = task;
172 #ifdef ARCH_arm
173 /* NOTE: ARM need to start new fake of main kernel task */
174 arch_task_init (task, (unsigned) &task_schedule);
175 #endif
176 return task;
179 arch_task_init (task, entry);
181 task_id ++; // increase id number for new task
183 // mark it runnable
184 task->status = TS_RUNNABLE;
185 // task priority - how offten will be active
186 task->priority = priority;
187 // task attick - how ofter per all time line handle this task (not in %)
188 task->attick = task_id - 1;
189 // add name of task
190 strcpy (task->name, name);
191 // spinlock is not available by default
192 task->spinlock = 0;
193 // page covering of process
194 task->page_cover = 0;
195 // task identification number - usefully on process level (multi-threaded apps)
196 task->id = task_id;
197 // task's time stamp of last tick
198 task->lasttick = 0;
200 /* add into list */
201 task->next = &task_list;
202 task->prev = task_list.prev;
203 task->prev->next = task;
204 task->next->prev = task;
206 DPRINT (DBG_SCHED, "task -> %s (%d)", name, task_id);
208 return task;
211 bool task_done (task_t *task)
213 if (task) {
214 DPRINT (DBG_SCHED, "task -> %s done", task->name);
216 task->status = TS_NULL;
218 task->next->prev = task->prev;
219 task->prev->next = task->next;
221 kfree (task);
223 return 1;
226 return 0;
229 task_t *task_find (unsigned short id)
231 task_t *task;
232 for (task = task_list.next; task != &task_list; task = task->next) {
233 if (task->id == id)
234 return task;
237 return 0;
240 unsigned int init_tasks (void)
242 task_list.next = &task_list;
243 task_list.prev = &task_list;
245 /* NOTE: NULL entry point task can't be created multiple times ! */
246 task_create ("kernel", NULL, 0);
248 return 1;