Example #1
0
void isr_thread_yield(void)
{
    DEBUG("isr_thread_yield\n");

    if (_native_sigpend > 0) {
        DEBUG("isr_thread_yield(): handling signals\n\n");
        native_irq_handler();
    }

    sched_run();
    ucontext_t *ctx = (ucontext_t *)(sched_active_thread->sp);
    DEBUG("isr_thread_yield: switching to(%" PRIkernel_pid ")\n\n", sched_active_pid);

    native_interrupts_enabled = 1;
    _native_mod_ctx_leave_sigh(ctx);

    if (setcontext(ctx) == -1) {
        err(EXIT_FAILURE, "isr_thread_yield: setcontext");
    }
}
Example #2
0
void isr_cpu_switch_context_exit(void)
{
    ucontext_t *ctx;

    DEBUG("isr_cpu_switch_context_exit\n");
    if ((sched_context_switch_request == 1) || (sched_active_thread == NULL)) {
        sched_run();
    }

    DEBUG("isr_cpu_switch_context_exit: calling setcontext(%" PRIkernel_pid ")\n\n", sched_active_pid);
    ctx = (ucontext_t *)(sched_active_thread->sp);

    native_interrupts_enabled = 1;
    _native_mod_ctx_leave_sigh(ctx);

    if (setcontext(ctx) == -1) {
        err(EXIT_FAILURE, "isr_cpu_switch_context_exit: setcontext");
    }
    errx(EXIT_FAILURE, "2 this should have never been reached!!");
}
Example #3
0
int mypthread_yield(void) {
	
	mypthread_t thread = getPausedThread(); //I assume this gets the thread that the current thread is going to yield TO
	if(thread == 0) {
		printf("Error, either by user or yield getPausedThread() failed");
	}

	if(currThread == NULL) {
		//Should only happen on very first attempted join/ yield
		//Means main thread needs to be set up
		mypthread_t mainThread = getUnusedThread(); //this grabs the current calling thread? at least i think
		mainThread->status = PAUSED;

		thread->status = ACTIVE;
		currThread = thread;

		if(swapcontext(&(mainThread->ctx), &(currThread->ctx)) == -1 ) { //begin with whatever the thread yielded to wanted to do
			printf("SwapContext failed\n");
			return -1;
		}
		
		return 0;
	}

	//same stuff as above
	mypthread_real *oldThread = currThread;

	oldThread->status = PAUSED;
	thread->status = ACTIVE;

	currThread = thread;

	if(setcontext(&(currThread->ctx)) == -1) {
		//panic!
		fprintf(stderr, "Unable to set context!\n");
		return -1;
	}

	return 0;
	
}
Example #4
0
void kill_thread()
{
	ucontext_t temp;
	if(head->next==NULL)
	{
		currrent_thread=NULL;
		it.it_interval.tv_sec=0;
		it.it_interval.tv_usec=0;
		it.it_value.tv_sec=0;
		it.it_value.tv_usec=0;
		setitimer(ITIMER_PROF,&it,NULL);
		setcontext(&Main);
		return ;
	}
	else
	{
		currrent_thread=head->next->task;
		head=head->next;
		swapcontext(&temp,currrent_thread);
	}
}
Example #5
0
extern void thread_exit(void *retval) { 
  // Si l'on a jamais appelé thread_create
  if (thread_set == NULL)
    exit(0);
  
  struct thread* current = thread_current; 
  thread_current->isfinished = 1;
  thread_current->retval = retval;   
 
  // Si on l'attend on passe la main à celui qui attend, sinon à un autre
  if (current->joiner != NULL){
    thread_current = current->joiner;
  } else {
    thread_current = structure_get(thread_set);
  }
  // Si il n'y a plus de thread à exécuter
  if ( thread_current == NULL)
    exit(0);
  setcontext(thread_current->context);    
  exit(-1);
}
Example #6
0
void isr_cpu_switch_context_exit(void)
{
    ucontext_t *ctx;

    DEBUG("XXX: cpu_switch_context_exit()\n");
    if ((sched_context_switch_request == 1) || (active_thread == NULL)) {
        sched_run();
    }

    DEBUG("XXX: cpu_switch_context_exit(): calling setcontext(%s)\n\n", active_thread->name);
    ctx = (ucontext_t *)(active_thread->sp);

    /* the next context will have interrupts enabled due to ucontext */
    DEBUG("XXX: cpu_switch_context_exit: native_interrupts_enabled = 1;\n");
    native_interrupts_enabled = 1;
    _native_in_isr = 0;

    if (setcontext(ctx) == -1) {
        err(EXIT_FAILURE, "cpu_switch_context_exit(): setcontext():");
    }
}
Example #7
0
Tid thread_exit(Tid tid) {
    int enabled = interrupts_set(0);
    if (tid == THREAD_SELF) {
        if (READY_HEAD == NULL)
            return THREAD_NONE;
        interrupts_enabled(0);
        struct thread *temp = RUNNING_THREAD;
        struct thread *new_run = READY_HEAD;
        READY_HEAD = READY_HEAD->next;
        temp->next = NULL;
        thread_id_array[temp->tid] = 0;
        insert_thread_to_delete(temp);
        new_run->next = NULL;
        new_run->state = RECOVER_STATE;
        RUNNING_THREAD = new_run;
        setcontext(&(new_run->thread_context));
    } else if (tid == THREAD_ANY) {
        if (READY_HEAD == NULL)
            return THREAD_NONE;
        struct thread *temp = READY_HEAD;
        Tid returned_tid = temp->tid;
        temp->flag = 1;
        interrupts_set(enabled);
        return returned_tid;
    } else {
        if (tid > THREAD_MAX_THREADS - 1 || tid < THREAD_FAILED || !thread_id_array[tid])
            return THREAD_INVALID;
        if (READY_HEAD == NULL)
            return THREAD_NONE;
        struct thread *temp = READY_HEAD;
        while (temp->tid != tid)
            temp = temp->next;
        Tid returned_tid = temp->tid;
        temp->flag = 1;
        interrupts_set(enabled);
        return returned_tid;
    }
    interrupts_set(enabled);
    return THREAD_FAILED;
}
Example #8
0
extern int thread_join(struct thread* thread, void **retval){
  struct thread* current = thread_current;  
  struct thread* tmp = NULL;
  int i = 0;
  // Si l'on a jamais appelé thread_create
  if (thread_current == NULL)
    exit(-1);

  //structure_print(thread_set);
  
  // Si le thread n'est pas déjà fini
  if (!thread->isfinished) {
    thread->joiner = thread_current;
    // passer la main
    tmp = structure_get(thread_set);
    if (tmp == NULL){
      fprintf(stderr, "%s l.%d:\t%s\n", __FILE__, __LINE__, "Problème si l'on attends un thread qui n'existe pas");
      exit(-1);
    }
    thread_current = tmp; 
    i = 0;
    if (getcontext(current->context))
      return -1;
    if ( i == 0 ){
      i = 1;
      if (setcontext(thread_current->context))
	return -1;
    } 
  }
  
  // Ici on a repris la main
  if (retval != NULL)
    *retval = thread->retval;
  if (thread_delete(thread))
    return -1;
  
  return 0; 
}
      ucontext_thread_group(int num_threads, Function f)
        : thread_group()
    {
      if(num_threads)
      {
        // make a copy of the parameters for each thread
        // for arguments to makecontext
        typedef std::pair<ucontext_thread_group*,Function> exec_parms_t;
        void (*exec)(exec_parms_t *) = exec_thread<Function>;
        std::vector<exec_parms_t> exec_parms(num_threads, std::make_pair(this,f));

        // save the return state
        state join_state;
        getcontext(&join_state);
        if(thread_state.empty())
        {
          thread_state.resize(num_threads);

          for(int i = 0; i < thread_state.size(); ++i)
          {
            getcontext(&thread_state[i]);
            thread_state[i].uc_link = &join_state;
            thread_state[i].uc_stack.ss_sp = thread_state[i].stack;
            thread_state[i].uc_stack.ss_size = sizeof(thread_state[i].stack);
            makecontext(&thread_state[i], (void(*)())exec, 1, &exec_parms[i]);
          }

          // start thread 0
          set_current_thread_id(0);
          setcontext(&thread_state[0]);
        }

        // when we've reached this point, all the threads in the group have terminated
      } // end if

      // null the current thread_group
      this_thread_group::__singleton = 0;
    }
Example #10
0
Expr_t*
exopen(register Exdisc_t* disc)
{
	register Expr_t*	program;
	register Exid_t*	sym;
	int			debug;

	if (!(program = newof(0, Expr_t, 1, 0)))
		return 0;
	program->symdisc.key = offsetof(Exid_t, name);
	debug = getenv("VMDEBUG") != 0;
	if (!(program->symbols = dtopen(&program->symdisc, Dtset)) ||
	    !(program->tmp = sfstropen()) ||
	    !(program->vm = (debug ? vmopen(Vmdcsbrk, Vmdebug, VM_DBCHECK|VM_DBABORT) : vmopen(Vmdcheap, Vmbest, 0))) ||
	    !(program->ve = (debug ? vmopen(Vmdcsbrk, Vmdebug, VM_DBCHECK|VM_DBABORT) : vmopen(Vmdcheap, Vmbest, 0))))
	{
		exclose(program, 1);
		return 0;
	}
	program->id = "libexpr:expr";
	program->disc = disc;
	setcontext(program);
	program->file[0] = sfstdin;
	program->file[1] = sfstdout;
	program->file[2] = sfstderr;
	strcpy(program->main.name, "main");
	program->main.lex = PROCEDURE;
	program->main.index = PROCEDURE;
	dtinsert(program->symbols, &program->main);
	if (!(disc->flags & EX_PURE))
		for (sym = exbuiltin; *sym->name; sym++)
			dtinsert(program->symbols, sym);
	if ((sym = disc->symbols))
		for (; *sym->name; sym++)
			dtinsert(program->symbols, sym);
	return program;
}
Example #11
0
afs_int32
savecontext(void (*ep) (void), struct lwp_context *savearea, char *newsp)
{
#if defined(AFS_LINUX20_ENV)
    /* getcontext does not export stack info */
    int stackvar;
#endif

    PRE_Block = 1;

    savearea->state = 0;
    getcontext(&savearea->ucontext);
#if defined(AFS_LINUX20_ENV)
    savearea->topstack = &stackvar;
#else
    savearea->topstack = savearea->ucontext.uc_stack.ss_sp;
#endif
    switch (savearea->state) {
    case 0:
	if (newsp) {
	    ucontext_t thread;

	    getcontext(&thread);
	    thread.uc_stack.ss_sp =
		newsp - AFS_LWP_MINSTACKSIZE + sizeof(void *) +
		sizeof(void *);
	    thread.uc_stack.ss_size = AFS_LWP_MINSTACKSIZE - sizeof(void *);
	    makecontext(&thread, ep, 0);
	    setcontext(&thread);
	} else
	    (*ep) ();
	break;
    case 2:
	break;
    }
    return 0;
}
Example #12
0
int main(int argc, char* argv[])
{
    HMODULE h = NULL;
    FILE* fp = NULL;
    jmp_buf env;
    int i;
    char* buf;
    ucontext_t context;

    h = LoadLibrary("windll.dll");
    if (h != NULL) {
        pFunc = (void*)GetProcAddress(h, "windll");
        if (pFunc != NULL) {
            printf("winmain: Call windll\n");
            pFunc();
        }
    }

    if (argc >= 3) {
        memcpy(env, argv[argc-2], sizeof(jmp_buf));
        sscanf(argv[argc-1], "%p", &__longjmp);

        fp = fopen("__funp.txt", "w");
        if (fp != NULL)
            fprintf(fp, "%p\n", pFunc);
        fclose(fp);

        fp = fopen("__env.bin", "rb");
        if (fp != NULL)
            fread(&context, sizeof(char), sizeof(ucontext_t), fp);
        fclose(fp);
        setcontext(&context);

        __longjmp(env, 2);
        printf("Never Executed!\n");
    }
}
Example #13
0
	int
main()
{
	int i;
	struct itimerval it;

	fprintf(stderr,"Process Id: %d\n", (int)getpid());

	/* allocate the global signal/interrupt stack */
	signal_stack = malloc(STACKSIZE);
	if (signal_stack == NULL) {
		perror("malloc");
		exit(1);
	}

	/* make all our contexts */
	mkcontext(&contexts[0], (void*)thread2);
	for(i=1; i < NUMCONTEXTS; i++)
		mkcontext(&contexts[i], (void*)thread1);


	/* initialize the signal handlers */
	setup_signals();

	/* setup our timer */
	it.it_interval.tv_sec = 0;
	it.it_interval.tv_usec = INTERVAL * 1000;
	it.it_value = it.it_interval;
	if (setitimer(ITIMER_REAL, &it, NULL) ) perror("setitiimer");

	/* force a swap to the first context */
	cur_context = &contexts[0];
	setcontext(&contexts[0]);

	return 0; /* make gcc happy */
}
Example #14
0
/*===========================================================================*
 *				swapcontext				     *
 *===========================================================================*/
PUBLIC int swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
{
  int r;

  if ((oucp == NULL) || (ucp == NULL)) {
	errno = EFAULT;
	return(-1);
  }

  if (ucp->uc_mcontext.mc_p_reg.sp == 0) {
	/* No stack space. Bail out. */
	errno = ENOMEM;
	return(-1);
  } 

  oucp->uc_flags &= ~UCF_SWAPPED;
  r = getcontext(oucp);
  if ((r == 0) && !(oucp->uc_flags & UCF_SWAPPED)) {
	oucp->uc_flags |= UCF_SWAPPED;
	r = setcontext(ucp);
  }

  return(r);
}
Example #15
0
// pour le moment sans priorité
extern int thread_yield (void) {
  // Sauvegarder le contexte courant, charger le suivant et changer le current
  struct thread* tmp = structure_get(thread_set);
  struct thread* current;
  int i;
  if (tmp != NULL){
    current = thread_current;
    if (structure_add(thread_set, thread_current))
      return -1;
    thread_current = tmp; 
    
    i = 0;
    if (!current->isfinished)
      if (getcontext(current->context))
	return -1;
    if (i==0){
      i++;
      if (setcontext(thread_current->context))
	return -1;
    }
    return 0;
  }
  return -1;
}
Example #16
0
void nextThread()
{
    is_it_manager_running=1;
    if(is_thread_queue_empty()) return;

#ifdef DEBUG
		printf("Running: nextThread\n");
#endif

		while(1)
		{
			current_thread++;
			current_thread%=THREAD_QUEUE_SIZE;
      if(is_thread_queue_empty()) return;
#ifdef DEBUG
      printf("%s waiting for %d\n", thread_ready_queue[current_thread]->name, thread_ready_queue[current_thread]->waiting_for);
#endif
      if(thread_ready_queue[current_thread]->waiting_for != -1)
				send_to_the_end();
			else break;
		}
    
    /* 
     * Here I unblock the interrupts just to let
     * my check work properly on the yield method.
     */
    unblockInterrupts();
    getcontext(&manager);
    makecontext(&manager, nextThread, 0);
    
#ifdef DEBUG
    printf("Running \"%s\"\n", thread_ready_queue[current_thread]->name);
#endif
    is_it_manager_running=0;
    setcontext(&(thread_ready_queue[current_thread]->context));
}
void MyThreadExit(void)
{
	setcontext(&controller);
}
Example #18
0
void __asmSwitchToContext(long* context) {
	contextT = (ucontext_t*) context;
	setcontext(contextT); /* go */
}
void CheckForUnblocking()
{

	int isReadyEmpty = 0;
	if(ready_queue == NULL)
		isReadyEmpty = 1;

	printf("\nStarting Checking of Unblocking");
	int i;
	int flag = 0;
	printQueues(); //getting segmentation fault here, need to check further - only for the last blocked thread.
	printf("CP1");
	if(blocked_queue == NULL)
		return;
	printf("CP2");
	MyThread* trav = blocked_queue;
	MyThread* temp;

		flag = 0;
		for(i=0; i<ARR_SIZE; i++)
		{
			if(trav->blockedFor[i] == 0)
				break;
			if(presentInReadyQueue(trav->blockedFor[i]))
			{
				flag = 1;
				printf("\nFlagged 1");
				break;
			}
			if(presentInSemaphoreBlockedQueue(trav->blockedFor[i]))
			{
				//printQueues();
				flag = 1;
				printf("\nFlagged 1");
				//printQueues();

				break;
			}	
		}
		printf("CP3");
		if(flag == 0)
		{
			blocked_queue = blocked_queue->next;
			printf("\n Before inserting to ready queue: %d", trav->id);
			insertIntoReadyQueue(trav);
			if(blocked_queue == NULL)
			{
				printf("\nUnblocking Last Node at Head: %d", trav->id);
				if(isReadyEmpty == 1)
				{
					printf("Yayy! it works!");
					setcontext(&ready_queue->context);
				}
				return;			
			}			
		}

	
		
	MyThread* prev = blocked_queue;
	trav = blocked_queue;
	while(trav != NULL)
	{
		flag = 0;
		for(i=0; i<ARR_SIZE; i++)
		{
			if(trav->blockedFor[i] == 0)
				break;
			if(presentInReadyQueue(trav->blockedFor[i]))
			{
				flag = 1;
				break;
			}	
			if(presentInSemaphoreBlockedQueue(trav->blockedFor[i]))
			{
				//printQueues();
				flag = 1;
				printf("\nFlagged 1");
				//printQueues();

				break;
			}
		}
		if(flag == 0)
		{
			//printf("Before Inserting - id: %d", trav->id);
			temp = trav;
			if(prev == trav)
			{
				blocked_queue = blocked_queue->next;
				prev = blocked_queue;
				trav = blocked_queue;
			}
			else
			{
				trav = trav->next;
			}
			trav->next = trav->next->next;
			insertIntoReadyQueue(temp);
			//printf("Inserted Node");
			//printf("\nUnblocking Node: %d", temp->id);
			
		}
		else
		{
			prev = trav;
			trav = trav->next;
		}
			
	}

	if(isReadyEmpty == 1)
	{
		printf("Yayy! it works!");
		setcontext(&ready_queue->context);
	}
	
}
void sort()
{
	sigprocmask(SIG_BLOCK, &sigProcMask, NULL);
    TCB currentThread = getSortHead(threadsQueue);
    TCB previousThread = threadsQueue->currentThread;
    if(previousThread == NULL && currentThread == NULL)
    {
        //Deadlock
        fprintf(debuggingFile,"Sorteo: Se ha presentado un error no controlado, posible DEADLOCK entre los hilos creados.\n"); 
        fflush(debuggingFile);
        exit(1);
    }
    else if(currentThread == NULL)
    {
        //DEBUGGING
        fprintf(debuggingFile,"Sorteo: currentThread presenta un valor de NULL\n");
        fflush(debuggingFile);
        //DEBUGGING
        //Todos los threads existentes administrados por el scheduler tipo Sorteo estan bloqueados, probablemente a la espera de que se desbloque uno de tipo RoundRobin o bien 
        //ya no existen threads administrados por Sorteo para colocar.
        threadsQueue->currentThreadCopy = threadsQueue->currentThread;
        threadsQueue->currentThread = NULL;
        sigprocmask(SIG_UNBLOCK, &sigProcMask, NULL);
        myThreadYield();
    }
    else if(previousThread == NULL && currentThread != threadsQueue->currentThreadCopy)
    {
        //Es posible que el scheduler tipo RoundRobin se quedara sin threads para colocar o tenga todos bloqueados a la espera que se libere uno de tipo Sorteo, 
        //o bien que el thread anterior tambien fuese de tipo Sorteo y ya estuviera completo.
        threadsQueue->currentThread = currentThread;
        timeQuantum.it_value.tv_usec = timeInterval;
        if(threadsQueue->currentThreadCopy != NULL)
        {
            //DEBUGGING
            fprintf(debuggingFile, "Sorteo: previousThread presenta un valor de NULL, haciendo el cambio de contexto, remplazando thread %d por thread %d\n", (int)threadsQueue->currentThreadCopy->threadID, (int)currentThread->threadID );
            fflush(debuggingFile);
            //DEBUGGING
            TCB auxTCB = threadsQueue->currentThreadCopy;
            threadsQueue->currentThreadCopy = NULL;
            sigprocmask(SIG_UNBLOCK, &sigProcMask, NULL);
            swapcontext(&(auxTCB->threadContext), &(currentThread->threadContext));
        }
        else
        {
            //DEBUGGING
            fprintf(debuggingFile,"Sorteo: previousThread presenta un valor de NULL, colocando en contexto el thread %d\n", (int)currentThread->threadID);
            fflush(debuggingFile);
            //DEBUGGING
            sigprocmask(SIG_UNBLOCK, &sigProcMask, NULL);
            setcontext(&(currentThread->threadContext));
        }
    }
    else
    {
        if(previousThread != NULL && previousThread != currentThread)
        {
        	//DEBUGGING
            fprintf(debuggingFile,"Sorteo: Haciendo el cambio de contexto, remplazando thread %d por thread %d\n", (int)previousThread->threadID, (int)currentThread->threadID);
            fflush(debuggingFile);
            //DEBUGGING
            //El anterior puede ser tipo Sorteo o RoundRobin pero deben ser diferentes a currentThread pues si es igual quiere decir que solo existe un thread en ejecucion en toda la progra,
            //probablemente el main.
            threadsQueue->currentThread = currentThread;
            threadsQueue->currentThreadCopy = NULL;
            timeQuantum.it_value.tv_usec = timeInterval;
            sigprocmask(SIG_UNBLOCK, &sigProcMask, NULL);
            swapcontext(&(previousThread->threadContext), &(currentThread->threadContext));
        }
        else
        {
            threadsQueue->currentThread = currentThread;
        }
        sigprocmask(SIG_UNBLOCK, &sigProcMask, NULL);
    }
}
Example #21
0
void
__longjmp14(jmp_buf env, int val)
{
	struct sigcontext *sc = (void *)env;
	ucontext_t uc;

	/* Ensure non-zero SP and sigcontext magic number is present */
	if (sc->sc_regs[_R_SP] == 0 || sc->sc_regs[_R_ZERO] != 0xACEDBADE)
		goto err;

	/* Ensure non-zero return value */
	if (val == 0)
		val = 1;

	/*
	 * Set _UC_{SET,CLR}STACK according to SS_ONSTACK.
	 *
	 * Restore the signal mask with sigprocmask() instead of _UC_SIGMASK,
	 * since libpthread may want to interpose on signal handling.
	 */
	uc.uc_flags = _UC_CPU | (sc->sc_onstack ? _UC_SETSTACK : _UC_CLRSTACK);

	sigprocmask(SIG_SETMASK, &sc->sc_mask, NULL);

	/* Clear uc_link */
	uc.uc_link = 0;

	/* Save return value in context */
	uc.uc_mcontext.__gregs[_R_V0] = val;

	/* Copy saved registers */
	uc.uc_mcontext.__gregs[_REG_S0] = sc->sc_regs[_R_S0];
	uc.uc_mcontext.__gregs[_REG_S1] = sc->sc_regs[_R_S1];
	uc.uc_mcontext.__gregs[_REG_S2] = sc->sc_regs[_R_S2];
	uc.uc_mcontext.__gregs[_REG_S3] = sc->sc_regs[_R_S3];
	uc.uc_mcontext.__gregs[_REG_S4] = sc->sc_regs[_R_S4];
	uc.uc_mcontext.__gregs[_REG_S5] = sc->sc_regs[_R_S5];
	uc.uc_mcontext.__gregs[_REG_S6] = sc->sc_regs[_R_S6];
	uc.uc_mcontext.__gregs[_REG_S7] = sc->sc_regs[_R_S7];
	uc.uc_mcontext.__gregs[_REG_S8] = sc->sc_regs[_R_S8];
	uc.uc_mcontext.__gregs[_REG_SP] = sc->sc_regs[_R_SP];
	uc.uc_mcontext.__gregs[_REG_RA] = sc->sc_regs[_R_RA];
	uc.uc_mcontext.__gregs[_REG_EPC] = sc->sc_pc;

	/* Copy FP state */
	if (sc->sc_fpused) {
		/* FP saved regs are $f20 .. $f31 */
		memcpy(&uc.uc_mcontext.__fpregs.__fp_r.__fp_regs[20],
		    &sc->sc_fpregs[20], 32 - 20);
		uc.uc_mcontext.__fpregs.__fp_csr =
		    sc->sc_fpregs[_R_FSR - _FPBASE];
		/* XXX sc_fp_control */
		uc.uc_flags |= _UC_FPU;
	}

	setcontext(&uc);
 err:
	longjmperror();
	abort();
	/* NOTREACHED */
}
Example #22
0
void
__longjmp14(jmp_buf env, int val)
{
	ucontext_t uc;
	struct sigcontext *sc = (void *)env;
	register_t *regs = (void *)(sc + 1);
	register register_t dp __asm("r27");

	/* Ensure non-zero SP */
	if (sc->sc_sp == 0)
		goto err;

	/* Make return value non-zero */
	if (val == 0)
		val = 1;

	/* Copy callee-saved regs */
	regs -= 3;
	uc.uc_mcontext.__gregs[3] = regs[3];
	uc.uc_mcontext.__gregs[4] = regs[4];
	uc.uc_mcontext.__gregs[5] = regs[5];
	uc.uc_mcontext.__gregs[6] = regs[6];
	uc.uc_mcontext.__gregs[7] = regs[7];
	uc.uc_mcontext.__gregs[8] = regs[8];
	uc.uc_mcontext.__gregs[9] = regs[9];
	uc.uc_mcontext.__gregs[10] = regs[10];
	uc.uc_mcontext.__gregs[11] = regs[11];
	uc.uc_mcontext.__gregs[12] = regs[12];
	uc.uc_mcontext.__gregs[13] = regs[13];
	uc.uc_mcontext.__gregs[14] = regs[14];
	uc.uc_mcontext.__gregs[15] = regs[15];
	uc.uc_mcontext.__gregs[16] = regs[16];
	uc.uc_mcontext.__gregs[17] = regs[17];
	uc.uc_mcontext.__gregs[18] = regs[18];

	/* Preserve the current value of DP */
	/* LINTED dp is r27, so is "initialized" */
	uc.uc_mcontext.__gregs[27] = dp;

	/* Set the desired return value. */
	uc.uc_mcontext.__gregs[_REG_RET0] = val;

	/*
	 * Set _UC_{SET,CLR}STACK according to SS_ONSTACK.
	 *
	 * Restore the signal mask with sigprocmask() instead of _UC_SIGMASK,
	 * since libpthread may want to interpose on signal handling.
	 */
	uc.uc_flags = _UC_CPU | (sc->sc_onstack ? _UC_SETSTACK : _UC_CLRSTACK);

	sigprocmask(SIG_SETMASK, &sc->sc_mask, NULL);

	/* Clear uc_link */
	uc.uc_link = 0;

	/* Copy signal mask */
	uc.uc_sigmask = sc->sc_mask;

	/* Copy special regs */
	uc.uc_mcontext.__gregs[_REG_PSW] = sc->sc_ps;
	uc.uc_mcontext.__gregs[_REG_SP] = sc->sc_sp;
	uc.uc_mcontext.__gregs[_REG_PCSQH] = sc->sc_pcsqh;
	uc.uc_mcontext.__gregs[_REG_PCOQH] = sc->sc_pcoqh;
	uc.uc_mcontext.__gregs[_REG_PCSQT] = sc->sc_pcsqt;
	uc.uc_mcontext.__gregs[_REG_PCOQT] = sc->sc_pcoqt;

	setcontext(&uc);
 err:
	longjmperror();
	abort();
	/* NOTREACHED */
}
void MyThreadInit(void(*start_funct)(void *), void *args)
{
start = 1;
	
	MyThread* node;
    	//printf("\nCP1");
	ready_queue = malloc(sizeof(MyThread));
	getcontext(&ready_queue->context);
 	ready_queue->context.uc_link=&controller;
 	ready_queue->context.uc_stack.ss_sp=malloc(MEM);
 	ready_queue->context.uc_stack.ss_size=MEM;
 	ready_queue->context.uc_stack.ss_flags=0;
	ready_queue->id = threadCount++;
	//printf("Allocation Initial Id: %d", ready_queue->id);

	makecontext(&ready_queue->context, (void*)start_funct, 1, (int)args);

	ucontext_t next;
	int id;	

	getcontext(&controller);

	//printf("\nAbout to Start Checking of Unblocking");
	//printQueues();
	CheckForUnblocking();
	//printf("\nChecked for Block");

	
	//printQueues();


	if(ready_queue != NULL)
	{
		
		
		if(start == 1)
		{
			next = ready_queue->context;
			id = ready_queue->id;
			//printf("\n 2 Should Repeat:");
			//printf("\n4Allocation Initial Id: %d", ready_queue->id);
			start = 0;
			//printQueues();
			setcontext(&next);
		}
		else if (ready_queue->next != NULL)
		{	
			ready_queue = ready_queue->next;
			//CheckForUnblocking();
			next = ready_queue->context;
			id = ready_queue->id;
			//printf("\n 2 Should Repeat:");
			//printf("\nSetting Context Id: %d",id);


			//printQueues();

			setcontext(&next);
		}
		else 
		{	
			//printf("1Entering New Code");
			ready_queue = NULL;
			//printf("2Entering New Code");
			//printQueues();
			CheckForUnblocking();
			//printf("1Entering New Code");
			if (ready_queue != NULL)
			{
				next = ready_queue->context;
				id = ready_queue->id;
				//printf("\n 2 Should Repeat:");
				//printf("\nSetting Context Id: %d",id);


				//printQueues();

				setcontext(&next);
			}
		}
	}
 	printf("completed\n");
 	printQueues();
 	printf("Final Queue Remains: ");
 	MySemaphoreDestroy(sem1);
 	MySemaphoreDestroy(sem2);
 	printQueues();

}
Example #24
0
// SELECTS NEXT RUNNING THREAD
void schedule(){
	
	// IF RUNNING THREAD IS NOT FINISHED
	// PUTS THE THREAD IN ONE OF THE TWO
	// ABLE QUEUES
	if(runningThread->state != FINISHED){
		DecreaseCredits(runningThread);
		
		if(runningThread->state == ABLE){

			if (runningThread->credReal == 0){
				expiredThreads = AddThread(expiredThreads, runningThread);
			}
			else{
				activeThreads = AddThread(activeThreads, runningThread);
			}
		}
		else{
			if(runningThread->state == BLOCKED){
				if(mutexBlock){
					//if it was blocked while locking a mutex
					//reset the flag and it was added to another queue
					//in the pilock function
					mutexBlock = 0;
				}
				else{
					blockedThreads = AddThread(blockedThreads, runningThread);
				}
			}
		}
	}
	else{
		// IF THE THREAD IS FINISHED,
		// FREE THE TCB MEMORY
		
		free(runningThread);
	}

	// SELECTS NEXT THREAD TO RUN

	runningThread = activeThreads;
	if (runningThread == NULL){
		
		SwapQueues(&activeThreads, &expiredThreads);

		activeThreads = RestoreCredits(activeThreads);

		runningThread = activeThreads;
	}
	
	activeThreads = activeThreads->next;
	runningThread->next = NULL;
	runningThread->prev = NULL;

	if(activeThreads)
		activeThreads->prev = NULL;

	runningThread->state = EXECUTION;

	
	setcontext(&runningThread->context);
}
int mythread_scheduler(void *args)
{
   kargs *tempargs;
   tempargs = (kargs *)args;
   int kmode;
   mypthread_t thread;
   kmode = tempargs->kmode;
   thread = tempargs->thread; 
   
   
        if (kmode == 1)
        {
           mypthread_t* cur_thread = search_thread(mythread_q, cur_thread_id);

           cur_thread->pthread->thread_state = PS_DEAD;
           free(cur_thread->pthread->ucontext);

           if (cur_thread->pthread->joined_from_th != 0)
           {
               mypthread_t *join_thread = search_thread(mythread_q,cur_thread->pthread->joined_from_th);
               join_thread->pthread->thread_state = PS_ACTIVE;

           }   
           mypthread_t* next_thread = return_head(mythread_q);
           cur_thread_id = next_thread->pthread->thread_id;
           //sem_post(&sem_main);
           setcontext(next_thread->pthread->ucontext);
       }
       else if(kmode == 2)
       {
            int target_thread_id = thread.pthread->thread_id;
            mypthread_t *current_thread = search_thread(mythread_q,cur_thread_id);
            mypthread_t *target_thread = search_thread(mythread_q,target_thread_id);
            if (target_thread->pthread->thread_state != PS_ACTIVE)
            {
                  //sem_post(&sem_main);
                   return;
            }
            else
            {
                current_thread->pthread->thread_state = PS_BLOCKED;
                target_thread->pthread->joined_from_th = cur_thread_id;
                cur_thread_id = target_thread_id;
                //sem_post(&sem_main);
                swapcontext(current_thread->pthread->ucontext, target_thread->pthread->ucontext);
            }
    

       } 
       else if(kmode == 3)
       {
            mypthread_t *current_thread = search_thread(mythread_q, cur_thread_id);
            mypthread_t *next_thread = next_active_thread(mythread_q);
            //printf("Current thread id = %d , next thread id = %d\n", cur_thread_id, next_thread->pthread->thread_id);
            if (cur_thread_id == next_thread->pthread->thread_id)
            {
                return;
            }
            //printf("Thread %d Yielding\n",cur_thread_id);
            cur_thread_id = next_thread->pthread->thread_id;
           //sem_post(&sem_main);
            swapcontext(current_thread->pthread->ucontext, next_thread->pthread->ucontext);
       }
}
Example #26
0
int main(void)
{
  start(51);

  atexit(verify_main_reenter);

  /* Save current context in ctx[0] */
  if (getcontext(&ctx[0]) != 0) {
	/* Don't verify reentering main, not going to happen */
	atexit(just_exit); 
	err(1, 1);
  }

  ctx[1] = ctx[0];
  ctx[1].uc_stack.ss_sp = st_stack;
  ctx[1].uc_stack.ss_size = SSIZE;
  ctx[1].uc_link = &ctx[0]; /* When done running, return here */

  /* ctx[1] is going to run func1 and then return here (uc_link). */
  /* We'll see later on whether makecontext worked. */
  makecontext(&ctx[1], (void (*) (void)) func1, 28,
  	      (0x0000001 << shift), (0x0000004 << shift), 
	      (0x0000010 << shift), (0x0000040 << shift),
	      (0x0000100 << shift), (0x0000400 << shift),
	      (0x0001000 << shift), (0x0004000 << shift),
	      (0x0010000 << shift), (0x0040000 << shift),
	      (0x0100000 << shift), (0x0400000 << shift),
	      (0x1000000 << shift), (0x4000000 << shift),
	      (0x0000002 << shift), (0x0000008 << shift),
	      (0x0000020 << shift), (0x0000080 << shift),
	      (0x0000200 << shift), (0x0000800 << shift),
	      (0x0002000 << shift), (0x0008000 << shift),
	      (0x0020000 << shift), (0x0080000 << shift),
	      (0x0200000 << shift), (0x0800000 << shift),
	      (0x2000000 << shift), (0x8000000 << shift));

  if (++global == 1) {
	/* First time we're here. Let's run ctx[1] and return to ctx[0] when
	 * we're done. Note that we return to above the 'makecontext' call. */
	if (setcontext(&ctx[1]) != 0) err(1, 2);
  }
  if (global != 2) {
	/* When ++global was 1 we let ctx[1] run and returned to ctx[0], so
	   above ++global is executed again and should've become 2. */
	err(1, 3);
  }

  /* Setup ctx[2] to run func2 */
  if (getcontext(&ctx[2]) != 0) err(1, 4);
  ctx[2].uc_stack.ss_sp = malloc(SSIZE);
  ctx[2].uc_stack.ss_size = SSIZE;
  ctx[2].uc_link = &ctx[1];
  makecontext(&ctx[2], (void (*) (void)) func2, 0);

  /* Now things become tricky. ctx[2] is set up such that when it finishes 
     running, and starts ctx[1] again. However, func1 swaps back to func2. Then,
     when func2 has finished running, we continue with ctx[1] and, finally, we
     return to ctx[0]. */
  if (swapcontext(&ctx[0], &ctx[2]) != 0) err(1, 5); /* makecontext failed? */
  reentered_main = 1;

  /* The call graph is as follows:
   *
   *                       ########
   *             /--------># main #
   *             7    /----########----\
   *             |    |    ^           |
   *             |    1    2           3
   *             |    V    |           V
   *          #########----/           #########
   *          # func1 #<-------4-------# func2 #
   *          #########--------5------>#########
   *                 ^                  |
   *                 |                  |
   *                 \---------6--------/
   *
   * Main calls func1, func1 increases entered_func1, and returns to main. Main
   * calls func2, swaps to func1, swaps to func2, which increases entered_func2,
   * continues with func1, which increases entered_func1 again, continues to
   * main, where reentered_main is set to 1. In effect, entered_func1 == 2,
   * entered_func2 == 1, reentered_main == 1. Verify that. */

  if (entered_func1 != 2) err(1, 6);
  if (entered_func2 != 1) err(1, 7);
  /* reentered_main == 1 is verified upon exit */
  
  /* Try to allocate too small a stack */
  free(ctx[2].uc_stack.ss_sp); /* Deallocate stack space first */
  if (getcontext(&ctx[2]) != 0) err(1, 8);
  ctx[2].uc_stack.ss_sp = malloc(MINSIGSTKSZ-1);
  ctx[2].uc_stack.ss_size = MINSIGSTKSZ-1;
  ctx[2].uc_link = &ctx[0];
  makecontext(&ctx[2], (void (*) (void)) fail, 0);
  /* Because makecontext is void, we can only detect an error by trying to use
     the invalid context */
  if (swapcontext(&ctx[0], &ctx[2]) == 0) err(1, 9);

  /* Try to allocate a huge stack to force the usage of brk/sbrk system call
     to enlarge the data segment. Because we are fiddling with the stack
     pointer, the OS might think the stack segment and data segment have
     collided and kill us. This is wrong and therefore the following should
     work. */
  free(ctx[2].uc_stack.ss_sp); /* Deallocate stack space first */
  if (getcontext(&ctx[2]) != 0) err(1, 14);
  ctx[2].uc_stack.ss_sp = malloc(8 * 1024 * 1024); /* 8 MB */
  ctx[2].uc_stack.ss_size = 8 * 1024 * 1024;
  ctx[2].uc_link = &ctx[0];
  makecontext(&ctx[2], (void (*) (void)) test_brk, 0);
  if (swapcontext(&ctx[0], &ctx[2]) != 0) err(1, 15);

  ctx[1].uc_link = &ctx[0];
  ctx[2].uc_link = NULL;
  makecontext(&ctx[1], (void (*) (void)) do_parent, 0);
  makecontext(&ctx[2], (void (*) (void)) do_child, 0);
  if (swapcontext(&ctx[0], &ctx[2]) == -1) err(1, 16);

  quit();
  return(-1);
}
Example #27
0
int s_poll_wait(s_poll_set *fds, int sec, int msec) {
    CONTEXT *context; /* current context */
    static CONTEXT *to_free=NULL; /* delayed memory deallocation */

    /* FIXME: msec parameter is currently ignored with UCONTEXT threads */
    (void)msec; /* skip warning about unused parameter */

    /* remove the current context from ready queue */
    context=ready_head;
    ready_head=ready_head->next;
    if(!ready_head) /* the queue is empty */
        ready_tail=NULL;
    /* it it safe to s_log() after new ready_head is set */

    /* it's illegal to deallocate the stack of the current context */
    if(to_free) { /* a delayed deallocation is scheduled */
#ifdef DEBUG_UCONTEXT
        s_log(LOG_DEBUG, "Releasing context %ld", to_free->id);
#endif
        str_free(to_free->stack);
        str_free(to_free);
        to_free=NULL;
    }

    /* manage the current thread */
    if(fds) { /* something to wait for -> swap the context */
        context->fds=fds; /* set file descriptors to wait for */
        context->finish=sec<0 ? -1 : time(NULL)+sec;

        /* append the current context to the waiting queue */
        context->next=NULL;
        if(waiting_tail)
            waiting_tail->next=context;
        waiting_tail=context;
        if(!waiting_head)
            waiting_head=context;
    } else { /* nothing to wait for -> drop the context */
        to_free=context; /* schedule for delayed deallocation */
    }

    while(!ready_head) /* wait until there is a thread to switch to */
        scan_waiting_queue();

    /* switch threads */
    if(fds) { /* swap the current context */
        if(context->id!=ready_head->id) {
#ifdef DEBUG_UCONTEXT
            s_log(LOG_DEBUG, "Context swap: %ld -> %ld",
                context->id, ready_head->id);
#endif
            swapcontext(&context->context, &ready_head->context);
#ifdef DEBUG_UCONTEXT
            s_log(LOG_DEBUG, "Current context: %ld", ready_head->id);
#endif
        }
        return ready_head->ready;
    } else { /* drop the current context */
#ifdef DEBUG_UCONTEXT
        s_log(LOG_DEBUG, "Context set: %ld (dropped) -> %ld",
            context->id, ready_head->id);
#endif
        setcontext(&ready_head->context);
        ioerror("setcontext"); /* should not ever happen */
        return 0;
    }
}
Example #28
0
int
main (void)
{
  atexit (check_called);

  char st1[32768];
  stack_t stack_before, stack_after;

  sigaltstack (NULL, &stack_before);

  puts ("making contexts");
  if (getcontext (&ctx[1]) != 0)
    {
      if (errno == ENOSYS)
	{
	  back_in_main = 1;
	  exit (0);
	}

      printf ("%s: getcontext: %m\n", __FUNCTION__);
      exit (1);
    }

  test_stack (1, 2, 3, 4);

  /* Play some tricks with this context.  */
  if (++global == 1)
    if (setcontext (&ctx[1]) != 0)
      {
	printf ("%s: setcontext: %m\n", __FUNCTION__);
	exit (1);
      }
  if (global != 2)
    {
      printf ("%s: 'global' not incremented twice\n", __FUNCTION__);
      exit (1);
    }

  ctx[1].uc_stack.ss_sp = st1;
  ctx[1].uc_stack.ss_size = sizeof st1;
  ctx[1].uc_link = &ctx[0];
  {
    ucontext_t tempctx = ctx[1];
    makecontext (&ctx[1], (void (*) (void)) f1, 4, 1, 2, 3, -4);

    /* Without this check, a stub makecontext can make us spin forever.  */
    if (memcmp (&tempctx, &ctx[1], sizeof ctx[1]) == 0)
      {
	puts ("makecontext was a no-op, presuming not implemented");
	return 0;
      }
  }

  if (getcontext (&ctx[2]) != 0)
    {
      printf ("%s: second getcontext: %m\n", __FUNCTION__);
      exit (1);
    }
  ctx[2].uc_stack.ss_sp = st2;
  ctx[2].uc_stack.ss_size = sizeof st2;
  ctx[2].uc_link = &ctx[1];
  makecontext (&ctx[2], f2, 0);

  puts ("swapping contexts");
  if (swapcontext (&ctx[0], &ctx[2]) != 0)
    {
      printf ("%s: swapcontext: %m\n", __FUNCTION__);
      exit (1);
    }
  puts ("back at main program");
  back_in_main = 1;

  sigaltstack (NULL, &stack_after);

  if (was_in_f1 == 0)
    {
      puts ("didn't reach f1");
      exit (1);
    }
  if (was_in_f2 == 0)
    {
      puts ("didn't reach f2");
      exit (1);
    }

  /* Check sigaltstack state is not clobbered as in BZ #16629.  */
  if (stack_before.ss_sp != stack_after.ss_sp)
    {
      printf ("stack ss_sp mismatch: %p %p\n",
	      stack_before.ss_sp, stack_after.ss_sp);
      exit (1);
    }

  if (stack_before.ss_size != stack_after.ss_size)
    {
      printf ("stack ss_size mismatch: %zd %zd\n",
	      stack_before.ss_size, stack_after.ss_size);
      exit (1);
    }

  puts ("test succeeded");
  return 0;
}
Example #29
0
static int
do_test (void)
{
  int n;
  pthread_t th[N];
  ucontext_t mctx;

  puts ("making contexts");
  if (getcontext (&mctx) != 0)
    {
      if (errno == ENOSYS)
	{
	  puts ("context handling not supported");
	  exit (0);
	}

      printf ("%s: getcontext: %m\n", __FUNCTION__);
      exit (1);
    }

  /* Play some tricks with this context.  */
  if (++global == 1)
    if (setcontext (&mctx) != 0)
      {
	puts ("setcontext failed");
	exit (1);
      }
  if (global != 2)
    {
      puts ("global not incremented twice");
      exit (1);
    }
  puts ("global OK");

  pthread_attr_t at;

  if (pthread_attr_init (&at) != 0)
    {
      puts ("attr_init failed");
      return 1;
    }

  if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
    {
      puts ("attr_setstacksize failed");
      return 1;
    }

  for (n = 0; n < N; ++n)
    if (pthread_create (&th[n], &at, tf, (void *) (long int) n) != 0)
      {
	puts ("create failed");
	exit (1);
      }

  if (pthread_attr_destroy (&at) != 0)
    {
      puts ("attr_destroy failed");
      return 1;
    }

  for (n = 0; n < N; ++n)
    if (pthread_join (th[n], NULL) != 0)
      {
	puts ("join failed");
	exit (1);
      }

  return failures;
}
Example #30
0
int
main(int argc, char *argv[])
{
#define	 check(ol,al)		if (argv[i][ol] || \
				badarg(argc-i-1,argv+i+1,al)) \
				goto badopt
#define	 bool(olen,var)		switch (argv[i][olen]) { \
				case '\0': var = !var; break; \
				case 'y': case 'Y': case 't': case 'T': \
				case '+': case '1': var = 1; break; \
				case 'n': case 'N': case 'f': case 'F': \
				case '-': case '0': var = 0; break; \
				default: goto badopt; }
	char	*curout = NULL;
	char	*binval = NULL;
	int	bincnt = 0;
	int	rval;
	int	i;
					/* global program name */
	progname = argv[0] = fixargv0(argv[0]);
	gargv = argv;
	gargc = argc;
					/* initialize calcomp routines early */
	initfunc();
	setcontext(RCCONTEXT);
					/* option city */
	for (i = 1; i < argc; i++) {
						/* expand arguments */
		while ((rval = expandarg(&argc, &argv, i)) > 0)
			;
		if (rval < 0) {
			sprintf(errmsg, "cannot expand '%s'", argv[i]);
			error(SYSTEM, errmsg);
		}
		if (argv[i] == NULL || argv[i][0] != '-')
			break;			/* break from options */
		if (!strcmp(argv[i], "-version")) {
			puts(VersionID);
			quit(0);
		}
		if (!strcmp(argv[i], "-defaults") ||
				!strcmp(argv[i], "-help")) {
			override_options();
			printdefaults();
			quit(0);
		}
		rval = getrenderopt(argc-i, argv+i);
		if (rval >= 0) {
			i += rval;
			continue;
		}
		switch (argv[i][1]) {
		case 'n':			/* number of cores */
			check(2,"i");
			nproc = atoi(argv[++i]);
			if (nproc <= 0)
				error(USER, "bad number of processes");
			break;
		case 'V':			/* output contributions */
			bool(2,contrib);
			break;
		case 'x':			/* x resolution */
			check(2,"i");
			xres = atoi(argv[++i]);
			break;
		case 'y':			/* y resolution */
			check(2,"i");
			yres = atoi(argv[++i]);
			break;
		case 'w':			/* warnings */
			rval = (erract[WARNING].pf != NULL);
			bool(2,rval);
			if (rval) erract[WARNING].pf = wputs;
			else erract[WARNING].pf = NULL;
			break;
		case 'e':			/* expression */
			check(2,"s");
			scompile(argv[++i], NULL, 0);
			break;
		case 'l':			/* limit distance */
			if (argv[i][2] != 'd')
				goto badopt;
			bool(3,lim_dist);
			break;
		case 'I':			/* immed. irradiance */
			bool(2,imm_irrad);
			break;
		case 'f':			/* file or force or format */
			if (!argv[i][2]) {
				check(2,"s");
				loadfunc(argv[++i]);
				break;
			}
			if (argv[i][2] == 'o') {
				bool(3,force_open);
				break;
			}
			setformat(argv[i]+2);
			break;
		case 'o':			/* output */
			check(2,"s");
			curout = argv[++i];
			break;
		case 'c':			/* input rays per output */
			check(2,"i");
			accumulate = atoi(argv[++i]);
			break;
		case 'r':			/* recover output */
			bool(2,recover);
			break;
		case 'h':			/* header output */
			bool(2,header);
			break;
		case 'b':			/* bin expression/count */
			if (argv[i][2] == 'n') {
				check(3,"s");
				bincnt = (int)(eval(argv[++i]) + .5);
				break;
			}
			check(2,"s");
			binval = argv[++i];
			break;
		case 'm':			/* modifier name */
			check(2,"s");
			addmodifier(argv[++i], curout, binval, bincnt);
			break;
		case 'M':			/* modifier file */
			check(2,"s");
			addmodfile(argv[++i], curout, binval, bincnt);
			break;
		default:
			goto badopt;
		}
	}
	if (nmods <= 0)
		error(USER, "missing required modifier argument");
					/* override some option settings */
	override_options();
					/* initialize object types */
	initotypes();
					/* initialize urand */
	if (rand_samp) {
		srandom((long)time(0));
		initurand(0);
	} else {
		srandom(0L);
		initurand(2048);
	}
					/* set up signal handling */
	sigdie(SIGINT, "Interrupt");
#ifdef SIGHUP
	sigdie(SIGHUP, "Hangup");
#endif
	sigdie(SIGTERM, "Terminate");
#ifdef SIGPIPE
	sigdie(SIGPIPE, "Broken pipe");
#endif
#ifdef SIGALRM
	sigdie(SIGALRM, "Alarm clock");
#endif
#ifdef	SIGXCPU
	sigdie(SIGXCPU, "CPU limit exceeded");
	sigdie(SIGXFSZ, "File size exceeded");
#endif
#ifdef	NICE
	nice(NICE);			/* lower priority */
#endif
					/* get octree */
	if (i == argc)
		octname = NULL;
	else if (i == argc-1)
		octname = argv[i];
	else
		goto badopt;
	if (octname == NULL)
		error(USER, "missing octree argument");

	readoct(octname, ~(IO_FILES|IO_INFO), &thescene, NULL);
	nsceneobjs = nobjects;

	marksources();			/* find and mark sources */

	setambient();			/* initialize ambient calculation */

	rcontrib();			/* trace ray contributions (loop) */

	ambsync();			/* flush ambient file */

	quit(0);	/* exit clean */

badopt:
	fprintf(stderr,
"Usage: %s [-n nprocs][-V][-r][-e expr][-f source][-o ospec][-b binv][-bn N] {-m mod | -M file} [rtrace options] octree\n",
			progname);
	sprintf(errmsg, "command line error at '%s'", argv[i]);
	error(USER, errmsg);
	return(1);	/* pro forma return */

#undef	check
#undef	bool
}