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: sched_8c-source.html 88 2016-01-12 00:11:29Z reddawg $ 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 <vfs/mount.h> 00035 #include <lib/kmalloc.h> 00036 #include <lib/kprintf.h> 00037 #include <vmm/vmm.h> 00038 #include <sys/gdt.h> 00039 #include <sys/idt.h> 00040 #include <sys/kern_descrip.h> 00041 #include <isa/8259.h> 00042 #include <string.h> 00043 #include <assert.h> 00044 00045 #include <ubixos/spinlock.h> 00046 00047 static kTask_t *taskList = 0x0; 00048 static kTask_t *delList = 0x0; 00049 static uInt32 nextID = -1; 00050 00051 kTask_t *_current = 0x0; 00052 kTask_t *_usedMath = 0x0; 00053 00054 static spinLock_t schedulerSpinLock = SPIN_LOCK_INITIALIZER; 00055 00056 /************************************************************************ 00057 00058 Function: int sched_init() 00059 00060 Description: This function is used to enable the kernel scheduler 00061 00062 Notes: 00063 00064 02/20/2004 - Approved for quality 00065 00066 ************************************************************************/ 00067 00068 00069 int sched_init() { 00070 taskList = (kTask_t *)kmalloc(sizeof(kTask_t)); 00071 if(taskList == 0x0) 00072 kpanic("Unable to create task list"); 00073 00074 taskList->id = nextID++; 00075 00076 /* Print out information on scheduler */ 00077 kprintf("sched0 - Address: [0x%X]\n", taskList); 00078 00079 /* Return so we know everything went well */ 00080 return(0x0); 00081 } 00082 00083 00084 void sched(){ 00085 uInt32 memAddr = 0x0; 00086 kTask_t *tmpTask = 0x0; 00087 kTask_t *delTask = 0x0; 00088 00089 if (!spinTryLock(&schedulerSpinLock)) 00090 return; 00091 00092 tmpTask = _current->next; 00093 //outportByte(0xE9,_current->id + '0'); 00094 schedStart: 00095 00096 /* Yield the next task from the current prio queue */ 00097 for (;tmpTask != 0x0; tmpTask = tmpTask->next) { 00098 if (tmpTask->state > 0x0) { 00099 _current = tmpTask; 00100 if (_current->state == FORK) 00101 _current->state = READY; 00102 break; 00103 } 00104 else if (tmpTask->state == DEAD) 00105 { 00106 delTask = tmpTask; 00107 tmpTask = tmpTask->next; 00108 sched_deleteTask(delTask->id); 00109 sched_addDelTask(delTask); 00110 goto schedStart; 00111 } 00112 } 00113 00114 /* Finished all the tasks, restarting the list */ 00115 if (0x0 == tmpTask) { 00116 tmpTask = taskList; 00117 goto schedStart; 00118 } 00119 00120 00121 if (_current->state > 0x0) { 00122 if (_current->oInfo.v86Task == 0x1) 00123 irqDisable(0x0); 00124 asm("cli"); 00125 memAddr = (uInt32)&(_current->tss); 00126 ubixGDT[4].descriptor.baseLow = (memAddr & 0xFFFF); 00127 ubixGDT[4].descriptor.baseMed = ((memAddr >> 16) & 0xFF); 00128 ubixGDT[4].descriptor.baseHigh = (memAddr >> 24); 00129 ubixGDT[4].descriptor.access = '\x89'; 00130 spinUnlock(&schedulerSpinLock); 00131 asm("sti"); 00132 asm("ljmp $0x20,$0\n"); 00133 } 00134 else 00135 { 00136 spinUnlock(&schedulerSpinLock); 00137 } 00138 00139 return; 00140 } 00141 00142 00143 kTask_t *schedNewTask() { 00144 int i = 0; 00145 kTask_t *tmpTask = (kTask_t *)kmalloc(sizeof(kTask_t)); 00146 struct file *fp = 0x0; 00147 if (tmpTask == 0x0) 00148 kpanic("Error: schedNewTask() - kmalloc failed trying to initialize a new task struct\n"); 00149 00150 memset(tmpTask,0x0,sizeof(kTask_t)); 00151 /* Filling in tasks attrs */ 00152 tmpTask->usedMath = 0x0; 00153 tmpTask->state = NEW; 00154 00155 /* HACK */ 00156 for (i=0;i<3;i++) { 00157 fp = kmalloc(sizeof(struct file)); 00158 tmpTask->td.o_files[i] = (uint32_t)fp; 00159 fp->f_flag = 0x4; 00160 } 00161 00162 spinLock(&schedulerSpinLock); 00163 tmpTask->id = nextID++; 00164 tmpTask->next = taskList; 00165 tmpTask->prev = 0x0; 00166 taskList->prev = tmpTask; 00167 taskList = tmpTask; 00168 00169 spinUnlock(&schedulerSpinLock); 00170 00171 return(tmpTask); 00172 } 00173 00174 00175 int sched_deleteTask(pidType id) { 00176 kTask_t *tmpTask = 0x0; 00177 00178 /* Checking each task from the prio queue */ 00179 for (tmpTask = taskList; tmpTask != 0x0; tmpTask = tmpTask->next) { 00180 if (tmpTask->id == id) { 00181 if (tmpTask->prev != 0x0) 00182 tmpTask->prev->next = tmpTask->next; 00183 if (tmpTask->next != 0x0) 00184 tmpTask->next->prev = tmpTask->prev; 00185 if (taskList == tmpTask) 00186 taskList = tmpTask->next; 00187 00188 return(0x0); 00189 } 00190 } 00191 return(0x1); 00192 } 00193 00194 int sched_addDelTask(kTask_t *tmpTask) { 00195 tmpTask->next = delList; 00196 tmpTask->prev = 0x0; 00197 if (delList != 0x0) 00198 delList->prev = tmpTask; 00199 delList = tmpTask; 00200 return(0x0); 00201 } 00202 00203 kTask_t *sched_getDelTask() { 00204 kTask_t *tmpTask = 0x0; 00205 00206 if (delList == 0x0) 00207 return(0x0); 00208 00209 tmpTask = delList; 00210 delList = delList->next; 00211 return(tmpTask); 00212 } 00213 00214 00215 kTask_t * 00216 schedFindTask(uInt32 id) 00217 { 00218 kTask_t *tmpTask = 0x0; 00219 00220 for (tmpTask = taskList; tmpTask; tmpTask = tmpTask->next) { 00221 if (tmpTask->id == id) 00222 return(tmpTask); 00223 } 00224 00225 return(0x0); 00226 } 00227 00228 00229 /************************************************************************ 00230 00231 Function: void schedEndTask() 00232 00233 Description: This function will end a task 00234 00235 Notes: 00236 00237 02/20/2004 - Approved for quality 00238 00239 ************************************************************************/ 00240 void 00241 schedEndTask(pidType pid) { 00242 endTask(_current->id); 00243 sched_yield(); 00244 } 00245 00246 /************************************************************************ 00247 00248 Function: int schedEndTask() 00249 00250 Description: This function will yield a task 00251 00252 Notes: 00253 00254 02/20/2004 - Approved for quality 00255 00256 ************************************************************************/ 00257 00258 void 00259 sched_yield() { 00260 sched(); 00261 } 00262 00263 /* 00264 asm( 00265 ".globl sched_yield \n" 00266 "sched_yield: \n" 00267 " cli \n" 00268 " call sched \n" 00269 ); 00270 */ 00271 00272 /************************************************************************ 00273 00274 Function: int sched_setStatus(pidType pid,tState state) 00275 00276 Description: Change the tasks status 00277 00278 Notes: 00279 00280 ************************************************************************/ 00281 int sched_setStatus(pidType pid,tState state) { 00282 kTask_t *tmpTask = schedFindTask(pid); 00283 if (tmpTask == 0x0) 00284 return(0x1); 00285 tmpTask->state = state; 00286 return(0x0); 00287 } 00288 00289 /*** 00290 END 00291 ***/ 00292