forked from enlightenment/efl
instruction limiter on the amx lets u limit function runs in instruction count
SVN revision: 11905
This commit is contained in:
parent
f8ce9df3fa
commit
78e5656a61
|
@ -209,6 +209,7 @@ main(int argc,char *argv[])
|
||||||
int r = EMBRYO_PROGRAM_OK;
|
int r = EMBRYO_PROGRAM_OK;
|
||||||
int err;
|
int err;
|
||||||
int args = 0;
|
int args = 0;
|
||||||
|
int instruct = 0;
|
||||||
char *file = NULL;
|
char *file = NULL;
|
||||||
char *func = NULL;
|
char *func = NULL;
|
||||||
|
|
||||||
|
@ -273,23 +274,36 @@ main(int argc,char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r = EMBRYO_PROGRAM_OK;
|
r = EMBRYO_PROGRAM_OK;
|
||||||
|
fn = EMBRYO_FUNCTION_MAIN;
|
||||||
if (func)
|
if (func)
|
||||||
{
|
{
|
||||||
fn = embryo_program_function_find(ep, func);
|
fn = embryo_program_function_find(ep, func);
|
||||||
if (fn != EMBRYO_FUNCTION_NONE)
|
if (fn == EMBRYO_FUNCTION_NONE)
|
||||||
{
|
|
||||||
while ((r = embryo_program_run(ep, fn)) == EMBRYO_PROGRAM_SLEEP);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
printf("Unable to find public function %s()\n"
|
printf("Unable to find public function %s()\n"
|
||||||
"Executing main() instead\n", func);
|
"Executing main() instead\n", func);
|
||||||
while ((r = embryo_program_run(ep, EMBRYO_FUNCTION_MAIN)) == EMBRYO_PROGRAM_SLEEP);
|
fn = EMBRYO_FUNCTION_MAIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
embryo_program_max_cycle_run_set(ep, 100000000);
|
||||||
|
for (;;)
|
||||||
{
|
{
|
||||||
while ((r = embryo_program_run(ep, EMBRYO_FUNCTION_MAIN)) == EMBRYO_PROGRAM_SLEEP);
|
r = embryo_program_run(ep, fn);
|
||||||
|
if (r == EMBRYO_PROGRAM_SLEEP)
|
||||||
|
{
|
||||||
|
fn = EMBRYO_FUNCTION_CONT;
|
||||||
|
printf("SLEEP INSTRUCTION!\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (r == EMBRYO_PROGRAM_TOOLONG)
|
||||||
|
{
|
||||||
|
fn = EMBRYO_FUNCTION_CONT;
|
||||||
|
instruct++;
|
||||||
|
printf("Executed %i00 million instructions!\n", instruct);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
embryo_program_vm_pop(ep);
|
embryo_program_vm_pop(ep);
|
||||||
if (r == EMBRYO_PROGRAM_FAIL)
|
if (r == EMBRYO_PROGRAM_FAIL)
|
||||||
|
|
|
@ -43,10 +43,11 @@ extern "C" {
|
||||||
/** An invalid cell reference */
|
/** An invalid cell reference */
|
||||||
#define EMBRYO_CELL_NONE 0x7fffffff
|
#define EMBRYO_CELL_NONE 0x7fffffff
|
||||||
/* program run return values */
|
/* program run return values */
|
||||||
#define EMBRYO_PROGRAM_OK 1
|
#define EMBRYO_PROGRAM_OK 1
|
||||||
#define EMBRYO_PROGRAM_SLEEP 2
|
#define EMBRYO_PROGRAM_SLEEP 2
|
||||||
#define EMBRYO_PROGRAM_BUSY 3
|
#define EMBRYO_PROGRAM_BUSY 3
|
||||||
#define EMBRYO_PROGRAM_FAIL 0
|
#define EMBRYO_PROGRAM_TOOLONG 4
|
||||||
|
#define EMBRYO_PROGRAM_FAIL 0
|
||||||
|
|
||||||
typedef unsigned int Embryo_UCell;
|
typedef unsigned int Embryo_UCell;
|
||||||
typedef int Embryo_Cell;
|
typedef int Embryo_Cell;
|
||||||
|
@ -94,6 +95,8 @@ extern "C" {
|
||||||
int embryo_program_recursion_get(Embryo_Program *ep);
|
int embryo_program_recursion_get(Embryo_Program *ep);
|
||||||
int embryo_program_run(Embryo_Program *ep, Embryo_Function func);
|
int embryo_program_run(Embryo_Program *ep, Embryo_Function func);
|
||||||
Embryo_Cell embryo_program_return_value_get(Embryo_Program *ep);
|
Embryo_Cell embryo_program_return_value_get(Embryo_Program *ep);
|
||||||
|
void embryo_program_max_cycle_run_set(Embryo_Program *ep, int max);
|
||||||
|
int embryo_program_max_cycle_run_get(Embryo_Program *ep);
|
||||||
int embryo_parameter_cell_push(Embryo_Program *ep, Embryo_Cell cell);
|
int embryo_parameter_cell_push(Embryo_Program *ep, Embryo_Cell cell);
|
||||||
int embryo_parameter_string_push(Embryo_Program *ep, char *str);
|
int embryo_parameter_string_push(Embryo_Program *ep, char *str);
|
||||||
int embryo_parameter_cell_array_push(Embryo_Program *ep, Embryo_Cell *cells, int num);
|
int embryo_parameter_cell_array_push(Embryo_Program *ep, Embryo_Cell *cells, int num);
|
||||||
|
|
|
@ -1013,6 +1013,8 @@ embryo_program_recursion_get(Embryo_Program *ep)
|
||||||
* @return @c EMBRYO_PROGRAM_OK on success. @c EMBRYO_PROGRAM_SLEEP if the
|
* @return @c EMBRYO_PROGRAM_OK on success. @c EMBRYO_PROGRAM_SLEEP if the
|
||||||
* program is halted by the Small @c sleep call.
|
* program is halted by the Small @c sleep call.
|
||||||
* @c EMBRYO_PROGRAM_FAIL if there is an error.
|
* @c EMBRYO_PROGRAM_FAIL if there is an error.
|
||||||
|
* @c EMBRYO_PROGRAM_TOOLONG if the program executes for longer than
|
||||||
|
* it is allowed to in abstract machine instruction count.
|
||||||
* @ingroup Embryo_Run_Group
|
* @ingroup Embryo_Run_Group
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
@ -1028,6 +1030,8 @@ embryo_program_run(Embryo_Program *ep, Embryo_Function fn)
|
||||||
unsigned char op;
|
unsigned char op;
|
||||||
Embryo_Cell offs;
|
Embryo_Cell offs;
|
||||||
int num;
|
int num;
|
||||||
|
int max_run_cycles;
|
||||||
|
int cycle_count;
|
||||||
#ifdef EMBRYO_EXEC_JUMPTABLE
|
#ifdef EMBRYO_EXEC_JUMPTABLE
|
||||||
/* we limit the jumptable to 256 elements. why? above we forced "op" to be
|
/* we limit the jumptable to 256 elements. why? above we forced "op" to be
|
||||||
* a unsigned char - that means 256 max values. we limit opcode overflow
|
* a unsigned char - that means 256 max values. we limit opcode overflow
|
||||||
|
@ -1346,10 +1350,19 @@ embryo_program_run(Embryo_Program *ep, Embryo_Function fn)
|
||||||
|
|
||||||
/* track recursion depth */
|
/* track recursion depth */
|
||||||
ep->run_count++;
|
ep->run_count++;
|
||||||
|
|
||||||
|
max_run_cycles = ep->max_run_cycles;
|
||||||
/* start running */
|
/* start running */
|
||||||
for (;;)
|
for (cycle_count = 0;;)
|
||||||
{
|
{
|
||||||
|
if (max_run_cycles > 0)
|
||||||
|
{
|
||||||
|
if (cycle_count >= max_run_cycles)
|
||||||
|
{
|
||||||
|
TOOLONG(ep);
|
||||||
|
}
|
||||||
|
cycle_count++;
|
||||||
|
}
|
||||||
op = (Embryo_Opcode)*cip++;
|
op = (Embryo_Opcode)*cip++;
|
||||||
SWITCH(op);
|
SWITCH(op);
|
||||||
CASE(EMBRYO_OP_LOAD_PRI);
|
CASE(EMBRYO_OP_LOAD_PRI);
|
||||||
|
@ -2106,10 +2119,9 @@ embryo_program_run(Embryo_Program *ep, Embryo_Function fn)
|
||||||
#endif
|
#endif
|
||||||
SWITCHEND;
|
SWITCHEND;
|
||||||
}
|
}
|
||||||
|
ep->max_run_cycles = max_run_cycles;
|
||||||
ep->run_count--;
|
ep->run_count--;
|
||||||
|
|
||||||
ep->hea = hea_start;
|
ep->hea = hea_start;
|
||||||
|
|
||||||
return EMBRYO_PROGRAM_OK;
|
return EMBRYO_PROGRAM_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2128,6 +2140,81 @@ embryo_program_return_value_get(Embryo_Program *ep)
|
||||||
return ep->retval;
|
return ep->retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum number of abstract machine cycles any given program run
|
||||||
|
* can execute before being put to sleep and returning.
|
||||||
|
*
|
||||||
|
* @param ep The given program.
|
||||||
|
* @param max The number of machine cycles as a limit.
|
||||||
|
*
|
||||||
|
* This sets the maximum number of abstract machine (virtual machine)
|
||||||
|
* instructions that a single run of an embryo function (even if its main)
|
||||||
|
* can use before embryo embryo_program_run() reutrns with the value
|
||||||
|
* EMBRYO_PROGRAM_TOOLONG. If the function fully executes within this number
|
||||||
|
* of cycles, embryo_program_run() will return as normal with either
|
||||||
|
* EMBRYO_PROGRAM_OK, EMBRYO_PROGRAM_FAIL or EMBRYO_PROGRAM_SLEEP. If the
|
||||||
|
* run exceeds this instruction count, then EMBRYO_PROGRAM_TOOLONG will be
|
||||||
|
* returned indicating the program exceeded its run count. If the app wishes
|
||||||
|
* to continue running this anyway - it is free to process its own events or
|
||||||
|
* whatever it wants and continue the function by calling
|
||||||
|
* embryo_program_run(program, EMBRYO_FUNCTION_CONT); which will start the
|
||||||
|
* run again until the instruction count is reached. This can keep being done
|
||||||
|
* to allow the calling program to still be able to control things outside the
|
||||||
|
* embryo function being called. If the maximum run cycle count is 0 then the
|
||||||
|
* program is allowed to run forever only returning when it is done.
|
||||||
|
*
|
||||||
|
* It is important to note that abstract machine cycles are NOT the same as
|
||||||
|
* the host machine cpu cycles. They are not fixed in runtime per cycle, so
|
||||||
|
* this is more of a helper tool than a way to HARD-FORCE a script to only
|
||||||
|
* run for a specific period of time. If the cycle count is set to something
|
||||||
|
* low like 5000 or 1000, then every 1000 (or 5000) cycles control will be
|
||||||
|
* returned to the calling process where it can check a timer to see if a
|
||||||
|
* physical runtime limit has been elapsed and then abort runing further
|
||||||
|
* assuming a "runaway script" or keep continuing the script run. This
|
||||||
|
* limits resolution to only that many cycles which do not take a determined
|
||||||
|
* amount of time to execute, as this varies from cpu to cpu and also depends
|
||||||
|
* on how loaded the system is. Making the max cycle run too low will
|
||||||
|
* impact performance requiring the abstract machine to do setup and teardown
|
||||||
|
* cycles too often comapred to cycles actually executed.
|
||||||
|
*
|
||||||
|
* Also note it does NOT include nested abstract machines. IF this abstract
|
||||||
|
* machine run calls embryo script that calls a native function that in turn
|
||||||
|
* calls more embryo script, then the 2nd (and so on) levels are not included
|
||||||
|
* in this run count. They can set their own max instruction count values
|
||||||
|
* separately.
|
||||||
|
*
|
||||||
|
* The default max cycle run value is 0 in any program until set with this
|
||||||
|
* function.
|
||||||
|
*
|
||||||
|
* @ingroup Embryo_Run_Group
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
embryo_program_max_cycle_run_set(Embryo_Program *ep, int max)
|
||||||
|
{
|
||||||
|
if (!ep) return;
|
||||||
|
if (max < 0) max = 0;
|
||||||
|
ep->max_run_cycles = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retreives the maximum number of abstract machine cycles a program is allowed
|
||||||
|
* to run.
|
||||||
|
* @param ep The given program.
|
||||||
|
* @return The number of cycles a run cycle is allowed to run for this
|
||||||
|
* program.
|
||||||
|
*
|
||||||
|
* This returns the value set by embryo_program_max_cycle_run_set(). See
|
||||||
|
* embryo_program_max_cycle_run_set() for more information.
|
||||||
|
*
|
||||||
|
* @ingroup Embryo_Run_Group
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
embryo_program_max_cycle_run_get(Embryo_Program *ep)
|
||||||
|
{
|
||||||
|
if (!ep) return 0;
|
||||||
|
return ep->max_run_cycles;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup Embryo_Parameter_Group Function Parameter Functions
|
* @defgroup Embryo_Parameter_Group Function Parameter Functions
|
||||||
*
|
*
|
||||||
|
|
|
@ -189,16 +189,17 @@ __entryswap32(*((unsigned int *)(entry) + 1))) \
|
||||||
#define EMBRYO_MAGIC 0xf1e0 /* magic byte pattern */
|
#define EMBRYO_MAGIC 0xf1e0 /* magic byte pattern */
|
||||||
#define EMBRYO_FLAG_COMPACT 0x04 /* compact encoding */
|
#define EMBRYO_FLAG_COMPACT 0x04 /* compact encoding */
|
||||||
#define EMBRYO_FLAG_RELOC 0x8000 /* jump/call addresses relocated */
|
#define EMBRYO_FLAG_RELOC 0x8000 /* jump/call addresses relocated */
|
||||||
#define GETPARAM(v) (v = *(Embryo_Cell *)cip++)
|
#define GETPARAM(v) (v = *(Embryo_Cell *)cip++)
|
||||||
#define PUSH(v) (stk -= sizeof(Embryo_Cell), *(Embryo_Cell *)(data + (int)stk) = v)
|
#define PUSH(v) (stk -= sizeof(Embryo_Cell), *(Embryo_Cell *)(data + (int)stk) = v)
|
||||||
#define POP(v) (v = *(Embryo_Cell *)(data + (int)stk), stk += sizeof(Embryo_Cell))
|
#define POP(v) (v = *(Embryo_Cell *)(data + (int)stk), stk += sizeof(Embryo_Cell))
|
||||||
#define ABORT(ep,v) {(ep)->stk = reset_stk; (ep)->hea = reset_hea; ep->run_count--; ep->error = v; return 0;}
|
#define ABORT(ep,v) {(ep)->stk = reset_stk; (ep)->hea = reset_hea; (ep)->run_count--; ep->error = v; (ep)->max_run_cycles = max_run_cycles; return EMBRYO_PROGRAM_FAIL;}
|
||||||
#define OK(ep,v) {(ep)->stk = reset_stk; (ep)->hea = reset_hea; ep->run_count--; ep->error = v; return 1;}
|
#define OK(ep,v) {(ep)->stk = reset_stk; (ep)->hea = reset_hea; (ep)->run_count--; ep->error = v; (ep)->max_run_cycles = max_run_cycles; return EMBRYO_PROGRAM_OK;}
|
||||||
#define STKMARGIN ((Embryo_Cell)(16 * sizeof(Embryo_Cell)))
|
#define TOOLONG(ep) {(ep)->pri = pri; (ep)->cip = (Embryo_Cell)((unsigned char *)cip - code); (ep)->alt = alt; (ep)->frm = frm; (ep)->stk = stk; (ep)->hea = hea; (ep)->reset_stk = reset_stk; (ep)->reset_hea = reset_hea; (ep)->run_count--; (ep)->max_run_cycles = max_run_cycles; return EMBRYO_PROGRAM_TOOLONG;}
|
||||||
#define CHKMARGIN() if ((hea + STKMARGIN) > stk) {ep->error = EMBRYO_ERROR_STACKERR; return 0;}
|
#define STKMARGIN ((Embryo_Cell)(16 * sizeof(Embryo_Cell)))
|
||||||
#define CHKSTACK() if (stk > ep->stp) {ep->run_count--; ep->error = EMBRYO_ERROR_STACKLOW; return 0;}
|
#define CHKMARGIN() if ((hea + STKMARGIN) > stk) {ep->error = EMBRYO_ERROR_STACKERR; return 0;}
|
||||||
#define CHKHEAP() if (hea < ep->hlw) {ep->run_count--; ep->error = EMBRYO_ERROR_HEAPLOW; return 0;}
|
#define CHKSTACK() if (stk > ep->stp) {ep->run_count--; ep->error = EMBRYO_ERROR_STACKLOW; return 0;}
|
||||||
#define CHKMEM(x) if ((((x) >= hea) && ((x) < stk)) || ((Embryo_UCell)(x) >= (Embryo_UCell)ep->stp)) ABORT(ep, EMBRYO_ERROR_MEMACCESS);
|
#define CHKHEAP() if (hea < ep->hlw) {ep->run_count--; ep->error = EMBRYO_ERROR_HEAPLOW; return 0;}
|
||||||
|
#define CHKMEM(x) if ((((x) >= hea) && ((x) < stk)) || ((Embryo_UCell)(x) >= (Embryo_UCell)ep->stp)) ABORT(ep, EMBRYO_ERROR_MEMACCESS);
|
||||||
|
|
||||||
typedef struct _Embryo_Param Embryo_Param;
|
typedef struct _Embryo_Param Embryo_Param;
|
||||||
typedef struct _Embryo_Header Embryo_Header;
|
typedef struct _Embryo_Header Embryo_Header;
|
||||||
|
@ -249,6 +250,8 @@ struct _Embryo_Program
|
||||||
|
|
||||||
int run_count;
|
int run_count;
|
||||||
|
|
||||||
|
int max_run_cycles;
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue