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