/* the big main central interpreter loop. processes return codes from eval(). 0 indicate noerror yieldtocaller indicates `showpage` has been called using SHOWPAGE_RETURN semantics. ioblock indicates a blocked io operation. contextswitch indicates the `yield` operator has been called. all other values indicate an error condition to be returned to postscript. */ int mainloop(Xpost_Context *ctx) { int ret; ctxswitch: xpost_ctx = ctx = _switch_context(ctx); itpdata->cid = ctx->id; while(!ctx->quit) { ret = eval(ctx); if (ret) switch (ret) { case yieldtocaller: return 1; case ioblock: ctx->state = C_IOBLOCK; /* fallthrough */ case contextswitch: goto ctxswitch; default: _onerror(ctx, ret); } } return 0; }
static void * _yield(struct coroutine *co) { assert(_scheduler() == co->sched); co->stack_lowest = (uint8_t*)&co; co->result = NULL; _switch_context(&co->ctx, &co->sched->ctx); return co->result; }
inline static void _resume(struct coroutine *co) { struct scheduler *s = co->sched; assert(s == _scheduler()); if (co->inited) { _copy_stack(co); } else { // init in the same thread as coroutine context. co->inited = true; _make_context(co, &s->ctx, &s->stack); } co->status = STATUS_RUNNING; _switch_context(&s->ctx, &co->ctx); }
/** \internal * \brief Voluntarily release the processor so that another thread * can be scheduled to run. * * \author Wesley Peck <*****@*****.**> * * This function is the system call routine which implements the * hthread_yield functionality for hthreads. The user space function * hthread_yield invokes this function to yield the processor. * * \return The return value is one of the following: * - SUCCESS : Currently there is no way for this function * to fail */ Hint _syscall_yield( void ) { Huint curr; Huint next; // Print out a trace message about this system call TRACE_PRINTF( TRACE_FINE, TRACE_SYSCALL, "SYSCALL: (OP=YIELD)\n" ); // Get the currently running thread curr = _current_thread(); // Get the next thread to run next = _yield_thread(); // Print out a trace message about this system call TRACE_PRINTF( TRACE_FINE, TRACE_SYSCALL, "SYSCALL DONE: (OP=YIELD)\n" ); // If they are not the same thread then switch to the new thread if( curr != next ) _switch_context( curr, next ); return SUCCESS; }