Beispiel #1
0
/* 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;
}