/* Crea un proceso */ int procCreate(char *name, process_t p, void *stack, void *heap, int fds[],int files, int argc, char **argv, int tty, int orphan, int priority){ int slot = getFreeSlot(); /* Obtengo un semaforo para controlar la salida de los hijos */ proc[slot].semChild = semGetID(0); proc[slot].semFather = semGetID(0); /* Obtengo un pid para el cual pid%MAX_PROCESS de el slot obtenido */ proc[slot].pid = proc[slot].pid + MAX_PROCESS; /* Si el proceso es huerfano, es hijo de INIT */ proc[slot].ppid = (orphan)? INIT_PROCESS : schedCurrentProcess(); /* Aumento en 1 la cantidad de hijos del padre */ proc[proc[slot].ppid%MAX_PROCESS].childCount++; strcpy(proc[slot].name, name); proc[slot].status = READY; /* No está implementado el uso del heap, pero se podría agregar muy * sencillamente asignando el heap, y luego a travez de un syscall * se pueda retornar, además un malloc podría administrar esta memoria * y en caso de que necesite más memoria podría pedir más páginas */ proc[slot].heapPages[0] = heap; proc[slot].usedheapPages = 0; /* Este proceso no tiene hijos */ proc[slot].childCount = 0; proc[slot].stackPages[0] = stack; proc[slot].usedstackPages = 1; proc[slot].attachedTTY = tty; proc[slot].retval = 0; memcpy(proc[slot].fds, fds, files*sizeof(int)); proc[slot].ESP = (byte*) buildStack(stack, p, argc, argv); /* Agregarlo al scheduler para que lo empiece a correr */ schedAdd(proc[slot].pid, name, priority); schedContinue(proc[slot].pid); return proc[slot].pid; }
int prSystemClock_SchedAbs(struct VMGlobals *g, int numArgsPushed) { //PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; double time; int err = slotDoubleVal(b, &time) || (time == dInfinity); if (err) return errNone; // return nil OK, just don't schedule PyrObject* inQueue = slotRawObject(&g->process->sysSchedulerQueue); schedAdd(g, inQueue, time, c); return errNone; }
int prSystemClock_Sched(struct VMGlobals *g, int numArgsPushed) { //PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; double delta, seconds; int err = slotDoubleVal(b, &delta); if (err) return errNone; // return nil OK, just don't schedule err = slotDoubleVal(&g->thread->seconds, &seconds); if (err) return errNone; // return nil OK, just don't schedule seconds += delta; if (seconds == dInfinity) return errNone; // return nil OK, just don't schedule PyrObject* inQueue = slotRawObject(&g->process->sysSchedulerQueue); schedAdd(g, inQueue, seconds, c); return errNone; }
void* schedRunFunc(void* arg) { pthread_mutex_lock (&gLangMutex); VMGlobals *g = gMainVMGlobals; PyrObject* inQueue = slotRawObject(&g->process->sysSchedulerQueue); //dumpObject(inQueue); gRunSched = true; while (true) { assert(inQueue->size); //postfl("wait until there is something in scheduler\n"); // wait until there is something in scheduler while (inQueue->size == 1) { //postfl("wait until there is something in scheduler\n"); pthread_cond_wait (&gSchedCond, &gLangMutex); if (!gRunSched) goto leave; } //postfl("wait until an event is ready\n"); // wait until an event is ready double elapsed; do { elapsed = elapsedTime(); if (elapsed >= slotRawFloat(inQueue->slots + 1)) break; struct timespec abstime; //doubleToTimespec(inQueue->slots->uf, &abstime); ElapsedTimeToTimespec(slotRawFloat(inQueue->slots + 1), &abstime); //postfl("wait until an event is ready\n"); pthread_cond_timedwait (&gSchedCond, &gLangMutex, &abstime); if (!gRunSched) goto leave; //postfl("time diff %g\n", elapsedTime() - inQueue->slots->uf); } while (inQueue->size > 1); //postfl("perform all events that are ready %d %.9f\n", inQueue->size, elapsed); // perform all events that are ready //postfl("perform all events that are ready\n"); while ((inQueue->size > 1) && elapsed >= slotRawFloat(inQueue->slots + 1)) { double schedtime, delta; PyrSlot task; //postfl("while %.6f >= %.6f\n", elapsed, inQueue->slots->uf); getheap(g, inQueue, &schedtime, &task); if (isKindOfSlot(&task, class_thread)) { SetNil(&slotRawThread(&task)->nextBeat); } slotCopy((++g->sp), &task); SetFloat(++g->sp, schedtime); SetFloat(++g->sp, schedtime); ++g->sp; SetObject(g->sp, s_systemclock->u.classobj); runAwakeMessage(g); long err = slotDoubleVal(&g->result, &delta); if (!err) { // add delta time and reschedule double time = schedtime + delta; schedAdd(g, inQueue, time, &task); } } //postfl("loop\n"); } //postfl("exitloop\n"); leave: pthread_mutex_unlock (&gLangMutex); return 0; }