Mon 16 Mar 11:09:06 CET 2026
This commit is contained in:
parent
4b4274f9bd
commit
80e8557dd9
190
src/run.c
Normal file
190
src/run.c
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
VM handlers (and network message handlers)
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "lexer.h"
|
||||
#include "tokens.h"
|
||||
#include "mem.h"
|
||||
#include "reg.h"
|
||||
#include "stack.h"
|
||||
#include "ops.h"
|
||||
#include "context.h"
|
||||
#include "code.h"
|
||||
#include "event.h"
|
||||
#include "vm.h"
|
||||
#include "var.h"
|
||||
#include "printf.h"
|
||||
#include "ccall.h"
|
||||
#include "version.h"
|
||||
#include "debug.h"
|
||||
#include "cconst.h"
|
||||
#include "net.h"
|
||||
#include "run.h"
|
||||
#include "debug.h"
|
||||
#include "error.h"
|
||||
#include "str.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifdef IOAWAIT
|
||||
/*
|
||||
Main VM Execution and IO Loop
|
||||
Returns: -1: error 0: no ready context, 1: ready context
|
||||
*/
|
||||
int Loop(context_t *C0,char service) {
|
||||
int error=0,status,idle=0,run=0,ready=0;
|
||||
context_t *C=C0; // root context
|
||||
#if DEBUG > 0
|
||||
log(LOGDEBUG1,"Loop: Enter.\n",NULL);
|
||||
#endif
|
||||
do {
|
||||
C=C0;
|
||||
idle=0;run=ready=0;
|
||||
while (C) {
|
||||
reg_t *R=C->R;
|
||||
#if DEBUG>0
|
||||
log(LOGDEBUG2,"Loop: Context #%d ",CONTEXTID(C));
|
||||
if (log_level<=LOGDEBUG2) PrintState(C->R);
|
||||
#endif
|
||||
status=Run(C);
|
||||
if (R->error) {
|
||||
error=R->error;
|
||||
break;
|
||||
}
|
||||
if (R->state&PIDLE) idle++; else run++; // still processing a program, maybe suspended
|
||||
if (R->state&(PRUNNING|PHANDLER)) ready++; // pending VM ops
|
||||
C=C->next;
|
||||
}
|
||||
if (!error && !ready && (run||service)) status=IOAWAIT(Context[0],ready);
|
||||
} while (!error && (run||service));
|
||||
#if DEBUG > 0
|
||||
log(LOGDEBUG2,"Loop: Exit (ready=%d run=%d error=%d service=%d status=%d).\n",ready,run,error,service,status);
|
||||
#endif
|
||||
return error?-1:ready;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
Main VM Execution Loop, embedded in an external main IO loop
|
||||
Returns: -1: error 0: no ready context, 1: ready context
|
||||
*/
|
||||
int Loop(context_t *C0) {
|
||||
int error=0,status,idle=0,run=0,ready=0;
|
||||
context_t *C=C0; // root context
|
||||
#if DEBUG > 0
|
||||
log(LOGDEBUG2,"Loop enter.\n",NULL);
|
||||
#endif
|
||||
do {
|
||||
C=C0;
|
||||
idle=0;run=ready=0;
|
||||
while (C) {
|
||||
reg_t *R=C->R;
|
||||
#if DEBUG>0
|
||||
log(LOGDEBUG2,"Loop: Context #%d ",CONTEXTID(C));
|
||||
if (log_level<=LOGDEBUG2) PrintState(C->R);
|
||||
#endif
|
||||
status=Run(C);
|
||||
if (R->error) {
|
||||
error=R->error;
|
||||
break;
|
||||
}
|
||||
if (R->state&PIDLE) idle++; else run++; // still processing a program, maybe suspended
|
||||
if (R->state&(PRUNNING|PHANDLER)) ready++; // pending VM ops
|
||||
C=C->next;
|
||||
}
|
||||
} while (!error && ready);
|
||||
#if DEBUG > 0
|
||||
log(LOGDEBUG2,"Loop: Exit (ready=%d run=%d error=%d service=%d status=%d).\n",ready,run,error,service,status);
|
||||
#endif
|
||||
return error?-1:ready;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_NET > 0
|
||||
/*
|
||||
Program Code Message Handler
|
||||
*/
|
||||
int MessageHandlerCode(port_t *P,message_type_t t) {
|
||||
index_t top = P->rxTop;
|
||||
#if PROFILE>0
|
||||
unsigned long t0,t1;
|
||||
#endif
|
||||
context_t *c=NULL;
|
||||
lexer_t L;
|
||||
mem_t *m;
|
||||
if (!Context[0]) { P->rxBottom=top; return -1; }
|
||||
#if DEBUG >0
|
||||
log(LOGDEBUG1,"MessageHandlerCode (%d) %d:[%s]\n",t,P->rxBottom,&P->rxBuffer[P->rxBottom]);
|
||||
#endif
|
||||
switch (t) {
|
||||
case MSGPROGRAMPART:
|
||||
c=Context[0];
|
||||
case MSGCOMMAND:
|
||||
// compile and run command
|
||||
// use 1 or 0 (if IDLE) for command lines
|
||||
if (!c) c=Context[ContextTop>1?1:0];
|
||||
case MSGPROGRAM:
|
||||
if (!c) c=Context[0]; // program for primary context
|
||||
m=c->M;
|
||||
if (string_cmp(&P->rxBuffer[P->rxBottom],"new",0)) {
|
||||
// reset entire context chain including stacks, registers, events
|
||||
ContextResetAll(NULL);
|
||||
P->rxBottom=top;
|
||||
return 0;
|
||||
}
|
||||
// TODO check IDLE state
|
||||
if (t==MSGPROGRAM) ContextResetAll(NULL); // a new main program must reset the entire VM context chain!
|
||||
else if (t==MSGCOMMAND) ContextReset(c);
|
||||
log(LOGINFO,"MessageHandlerCode ContextReset(%d) \n",CONTEXTID(c));
|
||||
#if PROFILE>0
|
||||
t0=MICROS();
|
||||
#endif
|
||||
// sync. compiling
|
||||
Compile(&L,&P->rxBuffer[P->rxBottom],c,PRUNNING);
|
||||
P->rxBottom=top;
|
||||
if (P->rxBottom==P->rxTop) P->rxBottom=P->rxTop=0;
|
||||
#if PROFILE>0
|
||||
t1=MICROS();
|
||||
#endif
|
||||
if (c->R->error) {
|
||||
log(LOGERROR,"Compiler error %d(%s) in line %d\n",c->R->error,Errors[c->R->error],L.line);
|
||||
#if DEBUG >0
|
||||
PrintLexerToken(&L);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
#if PROFILE>0
|
||||
c->S->ntoken=L.ntoken;
|
||||
c->S->micros=t1-t0;
|
||||
#endif
|
||||
log(LOGINFO,"MessageHandlerCode Done(%d) pc=%d state=%d\n",CONTEXTID(c),c->R->pc,c->R->state);
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/* handle received event message */
|
||||
int MessageHandlerEvent(port_t *P,message_type_t t) {
|
||||
P->rxBottom=P->rxTop;
|
||||
}
|
||||
static index_t evmsgportall=-1;
|
||||
/* handle received user message */
|
||||
int MessageHandlerUser(port_t *P,message_type_t t) {
|
||||
// raise EVMESSAGE event
|
||||
// speed up and cache event index
|
||||
if (evmsgportall!=-1) {
|
||||
#if DEBUG >0
|
||||
log(LOGDEBUG1,"MessageHandlerUser (%d)\n",evmsgportall);
|
||||
#endif
|
||||
RaiseEventIndex(evmsgportall);
|
||||
return evmsgportall;
|
||||
}
|
||||
index_t evid=RaiseEvent("message",-1); // PORTALL
|
||||
if (evid!=-1) evmsgportall=evid;
|
||||
#if DEBUG >0
|
||||
log(LOGDEBUG1,"MessageHandlerUser (%d)\n",evid);
|
||||
#endif
|
||||
return evid;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user