00001 /***************************************************************************************** 00002 Copyright (c) 2002-2004 The UbixOS Project 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are 00006 permitted provided that the following conditions are met: 00007 00008 Redistributions of source code must retain the above copyright notice, this list of 00009 conditions, the following disclaimer and the list of authors. Redistributions in binary 00010 form must reproduce the above copyright notice, this list of conditions, the following 00011 disclaimer and the list of authors in the documentation and/or other materials provided 00012 with the distribution. Neither the name of the UbixOS Project nor the names of its 00013 contributors may be used to endorse or promote products derived from this software 00014 without specific prior written permission. 00015 00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 00017 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00018 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 00019 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00020 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00021 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00022 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 00023 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00025 00026 $Id$ 00027 00028 *****************************************************************************************/ 00029 00030 #include <ubixos/sched.h> 00031 #include <ubixos/kpanic.h> 00032 #include <ubixos/spinlock.h> 00033 #include <ubixos/endtask.h> 00034 #include <ubixos/vitals.h> 00035 #include <vfs/mount.h> 00036 #include <lib/kmalloc.h> 00037 #include <lib/kprintf.h> 00038 #include <vmm/vmm.h> 00039 #include <sys/gdt.h> 00040 #include <sys/idt.h> 00041 #include <sys/kern_descrip.h> 00042 #include <isa/8259.h> 00043 #include <string.h> 00044 #include <assert.h> 00045 00046 #include <ubixos/spinlock.h> 00047 00048 static kTask_t *taskList = 0x0; 00049 static kTask_t *delList = 0x0; 00050 static uInt32 nextID = -1; 00051 00052 kTask_t *_current = 0x0; 00053 kTask_t *_usedMath = 0x0; 00054 00055 static spinLock_t schedulerSpinLock = SPIN_LOCK_INITIALIZER; 00056 00057 /************************************************************************ 00058 00059 Function: int sched_init() 00060 00061 Description: This function is used to enable the kernel scheduler 00062 00063 Notes: 00064 00065 02/20/2004 - Approved for quality 00066 00067 ************************************************************************/ 00068 00069 00070 int sched_init() { 00071 taskList = (kTask_t *)kmalloc(sizeof(kTask_t)); 00072 if(taskList == 0x0) 00073 kpanic("Unable to create task list"); 00074 00075 taskList->id = nextID++; 00076 00077 /* Print out information on scheduler */ 00078 kprintf("sched0 - Address: [0x%X]\n", taskList); 00079 00080 /* Return so we know everything went well */ 00081 return(0x0); 00082 } 00083 00084 00085 void sched(){ 00086 uInt32 memAddr = 0x0; 00087 kTask_t *tmpTask = 0x0; 00088 kTask_t *delTask = 0x0; 00089 00090 if (!spinTryLock(&schedulerSpinLock)) 00091 return; 00092 00093 tmpTask = _current->next; 00094 //outportByte(0xE9,_current->id + '0'); 00095 schedStart: 00096 00097 /* Yield the next task from the current prio queue */ 00098 for (;tmpTask != 0x0; tmpTask = tmpTask->next) { 00099 if (tmpTask->state > 0x0) { 00100 _current = tmpTask; 00101 if (_current->state == FORK) 00102 _current->state = READY; 00103 break; 00104 } 00105 else if (tmpTask->state == DEAD) 00106 { 00107 delTask = tmpTask; 00108 tmpTask = tmpTask->next; 00109 sched_deleteTask(delTask->id); 00110 sched_addDelTask(delTask); 00111 goto schedStart; 00112 } 00113 } 00114 00115 /* Finished all the tasks, restarting the list */ 00116 if (0x0 == tmpTask) { 00117 tmpTask = taskList; 00118 goto schedStart; 00119 } 00120 00121 00122 if (_current->state > 0x0) { 00123 if (_current->oInfo.v86Task == 0x1) 00124 irqDisable(0x0); 00125 asm("cli"); 00126 memAddr = (uInt32)&(_current->tss); 00127 ubixGDT[4].descriptor.baseLow = (memAddr & 0xFFFF); 00128 ubixGDT[4].descriptor.baseMed = ((memAddr >> 16) & 0xFF); 00129 ubixGDT[4].descriptor.baseHigh = (memAddr >> 24); 00130 ubixGDT[4].descriptor.access = '\x89'; 00131 spinUnlock(&schedulerSpinLock); 00132 asm("sti"); 00133 asm("ljmp $0x20,$0\n"); 00134 } 00135 else 00136 { 00137 spinUnlock(&schedulerSpinLock); 00138 } 00139 00140 return; 00141 } 00142 00143 00144 kTask_t *schedNewTask() { 00145 int i = 0; 00146 kTask_t *tmpTask = (kTask_t *)kmalloc(sizeof(kTask_t)); 00147 struct file *fp = 0x0; 00148 if (tmpTask == 0x0) 00149 kpanic("Error: schedNewTask() - kmalloc failed trying to initialize a new task struct\n"); 00150 00151 memset(tmpTask,0x0,sizeof(kTask_t)); 00152 /* Filling in tasks attrs */ 00153 tmpTask->usedMath = 0x0; 00154 tmpTask->state = NEW; 00155 00156 /* HACK */ 00157 for (i=0;i<3;i++) { 00158 fp = kmalloc(sizeof(struct file)); 00159 tmpTask->td.o_files[i] = fp; 00160 fp->f_flag = 0x4; 00161 } 00162 00163 spinLock(&schedulerSpinLock); 00164 tmpTask->id = nextID++; 00165 tmpTask->next = taskList; 00166 tmpTask->prev = 0x0; 00167 taskList->prev = tmpTask; 00168 taskList = tmpTask; 00169 00170 spinUnlock(&schedulerSpinLock); 00171 00172 return(tmpTask); 00173 } 00174 00175 00176 int sched_deleteTask(pidType id) { 00177 kTask_t *tmpTask = 0x0; 00178 00179 /* Checking each task from the prio queue */ 00180 for (tmpTask = taskList; tmpTask != 0x0; tmpTask = tmpTask->next) { 00181 if (tmpTask->id == id) { 00182 if (tmpTask->prev != 0x0) 00183 tmpTask->prev->next = tmpTask->next; 00184 if (tmpTask->next != 0x0) 00185 tmpTask->next->prev = tmpTask->prev; 00186 if (taskList == tmpTask) 00187 taskList = tmpTask->next; 00188 00189 return(0x0); 00190 } 00191 } 00192 return(0x1); 00193 } 00194 00195 int sched_addDelTask(kTask_t *tmpTask) { 00196 tmpTask->next = delList; 00197 tmpTask->prev = 0x0; 00198 if (delList != 0x0) 00199 delList->prev = tmpTask; 00200 delList = tmpTask; 00201 return(0x0); 00202 } 00203 00204 kTask_t *sched_getDelTask() { 00205 kTask_t *tmpTask = 0x0; 00206 00207 if (delList == 0x0) 00208 return(0x0); 00209 00210 tmpTask = delList; 00211 delList = delList->next; 00212 return(tmpTask); 00213 } 00214 00215 00216 kTask_t * 00217 schedFindTask(uInt32 id) 00218 { 00219 kTask_t *tmpTask = 0x0; 00220 00221 for (tmpTask = taskList; tmpTask; tmpTask = tmpTask->next) { 00222 if (tmpTask->id == id) 00223 return(tmpTask); 00224 } 00225 00226 return(0x0); 00227 } 00228 00229 00230 /************************************************************************ 00231 00232 Function: void schedEndTask() 00233 00234 Description: This function will end a task 00235 00236 Notes: 00237 00238 02/20/2004 - Approved for quality 00239 00240 ************************************************************************/ 00241 void 00242 schedEndTask(pidType pid) { 00243 endTask(_current->id); 00244 sched_yield(); 00245 } 00246 00247 /************************************************************************ 00248 00249 Function: int schedEndTask() 00250 00251 Description: This function will yield a task 00252 00253 Notes: 00254 00255 02/20/2004 - Approved for quality 00256 00257 ************************************************************************/ 00258 00259 void 00260 sched_yield() { 00261 sched(); 00262 } 00263 00264 /* 00265 asm( 00266 ".globl sched_yield \n" 00267 "sched_yield: \n" 00268 " cli \n" 00269 " call sched \n" 00270 ); 00271 */ 00272 00273 /************************************************************************ 00274 00275 Function: int sched_setStatus(pidType pid,tState state) 00276 00277 Description: Change the tasks status 00278 00279 Notes: 00280 00281 ************************************************************************/ 00282 int sched_setStatus(pidType pid,tState state) { 00283 kTask_t *tmpTask = schedFindTask(pid); 00284 if (tmpTask == 0x0) 00285 return(0x1); 00286 tmpTask->state = state; 00287 return(0x0); 00288 } 00289 00290 /*** 00291 END 00292 ***/ 00293
1.4.7