From f01995144048412ce02524bba603c0ed66af409b Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 10 May 2017 00:27:07 +0200 Subject: [PATCH] Remove the timeout code It had fundamental problems which seem unlikely to be resolved. See also issues #664, #695, #765. --- .appveyor.yml | 1 - Makefile.rules | 1 - configure.ac | 5 +- doc/ref/function.xml | 11 -- doc/ref/makedocreldata.g | 1 - hpcgap/lib/error.g | 6 +- hpcgap/lib/read3.g | 3 - hpcgap/lib/system.g | 17 --- hpcgap/src/stats.c | 18 --- hpcgap/tst/testinstall/timeout.tst | 23 --- lib/error.g | 6 +- lib/function.gd | 76 ---------- lib/function.gi | 67 +------- lib/read3.g | 3 - lib/system.g | 17 --- src/gap.c | 204 ------------------------- src/gap.h | 11 -- src/stats.c | 20 --- src/sysfiles.c | 2 - src/sysfiles.h | 8 - src/system.h | 2 - src/systimers.c | 235 ----------------------------- tst/testinstall/timeout.tst | 23 --- 23 files changed, 4 insertions(+), 756 deletions(-) delete mode 100644 hpcgap/tst/testinstall/timeout.tst delete mode 100644 lib/function.gd delete mode 100644 src/systimers.c delete mode 100644 tst/testinstall/timeout.tst diff --git a/.appveyor.yml b/.appveyor.yml index 9d7cc8b1a52..c0000a6b71f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -35,7 +35,6 @@ build_script: - bash -lc "cd $APPVEYOR_BUILD_FOLDER && ./etc/ci-prepare.sh" test_script: - - bash -lc "rm $APPVEYOR_BUILD_FOLDER/tst/testinstall/timeout.tst" # HACK - bash -lc "cd $APPVEYOR_BUILD_FOLDER && ./etc/ci.sh" on_success: diff --git a/Makefile.rules b/Makefile.rules index 5162b41a85d..5067c49c728 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -90,7 +90,6 @@ SOURCES += src/streams.c SOURCES += src/stringobj.c SOURCES += src/sysfiles.c SOURCES += src/system.c -SOURCES += src/systimers.c SOURCES += src/tietze.c SOURCES += src/trans.c SOURCES += src/vars.c diff --git a/configure.ac b/configure.ac index 93273567165..4f8cc2767f9 100644 --- a/configure.ac +++ b/configure.ac @@ -535,10 +535,7 @@ AC_SEARCH_LIBS([dlopen], [dl], dnl check for timing functions AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_FUNCS([getrusage gettimeofday clock_gettime clock_getres]) -AC_CHECK_FUNCS([setitimer getitimer]) -AC_CHECK_LIB([rt], [timer_create]) -AC_CHECK_FUNCS([timer_settime timer_gettime timer_create]) -AC_CHECK_FUNCS([sys_timer_settime sys_timer_gettime sys_timer_create]) +AC_CHECK_FUNCS([setitimer]) dnl check for functions dealing with virtual memory AC_CHECK_FUNCS([vm_allocate sbrk madvise sysconf]) diff --git a/doc/ref/function.xml b/doc/ref/function.xml index cd9bc56cb5d..eb8c11744df 100644 --- a/doc/ref/function.xml +++ b/doc/ref/function.xml @@ -43,17 +43,6 @@ several arguments - -
-Calling a function with a time limit - - -<#Include Label="CallWithTimeout"> -<#Include Label="GAPInfo.TimeoutsSupported"> -
- - -
diff --git a/doc/ref/makedocreldata.g b/doc/ref/makedocreldata.g index 7b725360525..8b352bff2a1 100644 --- a/doc/ref/makedocreldata.g +++ b/doc/ref/makedocreldata.g @@ -65,7 +65,6 @@ GAPInfo.ManualDataRef:= rec( "../../lib/fpmon.gd", "../../lib/fpsemi.gd", "../../lib/function.g", - "../../lib/function.gd", "../../lib/galois.gd", "../../lib/gasman.gd", "../../lib/ghom.gd", diff --git a/hpcgap/lib/error.g b/hpcgap/lib/error.g index 48c018a7ab0..b19a1e9c971 100644 --- a/hpcgap/lib/error.g +++ b/hpcgap/lib/error.g @@ -111,10 +111,9 @@ Unbind(ErrorInner); BIND_GLOBAL("ErrorInner", function( arg ) local context, mayReturnVoid, mayReturnObj, lateMessage, earlyMessage, - x, prompt, res, errorLVars, justQuit, printThisStatement, timeout, + x, prompt, res, errorLVars, justQuit, printThisStatement, location; - timeout := STOP_TIMEOUT(); context := arg[1].context; if not IsLVarsBag(context) then PrintTo("*errout*", "ErrorInner: option context must be a local variables bag\n"); @@ -267,9 +266,6 @@ BIND_GLOBAL("ErrorInner", fi; JUMP_TO_CATCH(3); fi; - if timeout <> fail then - RESUME_TIMEOUT(timeout); - fi; if Length(res) > 0 then return res[1]; else diff --git a/hpcgap/lib/read3.g b/hpcgap/lib/read3.g index d07eb1d0f87..f07ef171beb 100644 --- a/hpcgap/lib/read3.g +++ b/hpcgap/lib/read3.g @@ -245,8 +245,5 @@ ReadLib("proto.gd"); ReadLib("gasman.gd"); -# files dealing with function calling -ReadLib("function.gd"); - # random sources ReadLib("random.gi"); diff --git a/hpcgap/lib/system.g b/hpcgap/lib/system.g index e6fd7a66919..061ea7366ad 100644 --- a/hpcgap/lib/system.g +++ b/hpcgap/lib/system.g @@ -520,23 +520,6 @@ BIND_GLOBAL("ARCH_IS_UNIX",function() return not ARCH_IS_WINDOWS(); end); -############################################################################# -## -#V GAPInfo.TimeoutsSupported -## -## <#GAPDoc Label="GAPInfo.TimeoutsSupported"> -## -## -## -## -## tests whether this installation of &GAP; supports the timeout functionality -## of and related functions. -## -## -## <#/GAPDoc> - -GAPInfo.TimeoutsSupported := TIMEOUTS_SUPPORTED(); - ############################################################################# ## #V GAPInfo.InitFiles diff --git a/hpcgap/src/stats.c b/hpcgap/src/stats.c index 24f63bf6f4e..f63f0e01116 100644 --- a/hpcgap/src/stats.c +++ b/hpcgap/src/stats.c @@ -1676,19 +1676,6 @@ sig_atomic_t volatile RealExecStatCopied; int volatile RealExecStatCopied; #endif -/**************************************************************************** -** -*F void CheckAndRespondToAlarm() -** -*/ - -static void CheckAndRespondToAlarm(void) { - if ( SyAlarmHasGoneOff ) { - assert(NumAlarmJumpBuffers); - syLongjmp(&(AlarmJumpBuffers[--NumAlarmJumpBuffers]),1); - } -} - /**************************************************************************** ** *F UInt TakeInterrupt() . . . . . . . . allow user interrupts @@ -1707,7 +1694,6 @@ UInt TakeInterrupt( void ) { if (STATE(CurrExecStatFuncs) == IntrExecStatFuncs) { assert(STATE(CurrExecStatFuncs) != ExecStatFuncs); STATE(CurrExecStatFuncs) = ExecStatFuncs; - CheckAndRespondToAlarm(); ErrorReturnVoid( "user interrupt", 0L, 0L, "you can 'return;'" ); return 1; } @@ -1732,10 +1718,6 @@ UInt ExecIntrStat ( /* change the entries in 'ExecStatFuncs' back to the original */ STATE(CurrExecStatFuncs) = ExecStatFuncs; - /* One reason we might be here is a timeout. If so longjump out to the - CallWithTimeLimit where we started */ - CheckAndRespondToAlarm(); - /* and now for something completely different */ HandleInterrupts(1, stat); diff --git a/hpcgap/tst/testinstall/timeout.tst b/hpcgap/tst/testinstall/timeout.tst deleted file mode 100644 index bceefca3250..00000000000 --- a/hpcgap/tst/testinstall/timeout.tst +++ /dev/null @@ -1,23 +0,0 @@ -gap> START_TEST("timeout.tst"); -gap> spinFor := function(ms, arg...) local t; -> t := Runtimes().user_time + Runtimes().system_time; -> while Runtimes().user_time + Runtimes().system_time < t + ms do od; -> if Length(arg) >= 1 -> then return arg[1]; else return; fi; end; -function( ms, arg... ) ... end -gap> spinFor(10); -gap> spinFor(10,0); -0 -gap> CallWithTimeout(50000,spinFor,1); -Error, Calling with time limits not supported in this GAP installation -gap> CallWithTimeout(5000,spinFor,50000); -Error, Calling with time limits not supported in this GAP installation -gap> CallWithTimeout(50000,spinFor,1,1); -Error, Calling with time limits not supported in this GAP installation -gap> CallWithTimeoutList(50000,spinFor,[1,1]); -Error, Calling with time limits not supported in this GAP installation -gap> CallWithTimeoutList(5000,spinFor,[50000,1]); -Error, Calling with time limits not supported in this GAP installation -gap> CallWithTimeoutList(50000,spinFor,[1]); -Error, Calling with time limits not supported in this GAP installation -gap> STOP_TEST( "timeout.tst", 1); diff --git a/lib/error.g b/lib/error.g index fd058622a43..450defe59c6 100644 --- a/lib/error.g +++ b/lib/error.g @@ -110,10 +110,9 @@ Unbind(ErrorInner); BIND_GLOBAL("ErrorInner", function( arg ) local context, mayReturnVoid, mayReturnObj, lateMessage, earlyMessage, - x, prompt, res, errorLVars, justQuit, printThisStatement, timeout, + x, prompt, res, errorLVars, justQuit, printThisStatement, location; - timeout := STOP_TIMEOUT(); context := arg[1].context; if not IsLVarsBag(context) then PrintTo("*errout*", "ErrorInner: option context must be a local variables bag\n"); @@ -255,9 +254,6 @@ BIND_GLOBAL("ErrorInner", fi; JUMP_TO_CATCH(3); fi; - if timeout <> fail then - RESUME_TIMEOUT(timeout); - fi; if Length(res) > 0 then return res[1]; else diff --git a/lib/function.gd b/lib/function.gd deleted file mode 100644 index 36b9303f8b5..00000000000 --- a/lib/function.gd +++ /dev/null @@ -1,76 +0,0 @@ - -############################################################################# -## -#W function.gd GAP library Steve Linton -## -## -#Y Copyright (C) 2015 The GAP Group -## -## This file contains the declarations of the functions and operations -## relating to functions and function-calling which are not so basic -## that they need to be in function.g -## - - -############################################################################# -## -#F CallWithTimeout( , [, [, ....]] ) -## . . call a function with a time limit -#F CallWithTimeoutList( , , ) -## -## <#GAPDoc Label="CallWithTimeout"> -## Timeouts -## -## -## -## -## -## CallWithTimeout and CallWithTimeoutList support calling a function -## with a limit on the CPU time it can consume.

-## -## This functionality may not be available on all systems and you should check -## before using this functionality.

-## -## CallWithTimeout is variadic. -## Its third and subsequent arguments, if any, are the arguments passed to func. -## CallWithTimeoutList in contrast takes exactly three arguments, of which the third is a list -## (possibly empty) or arguments to pass to func.

-## -## If the call completes within the allotted time and returns a value res, the result of -## CallWithTimeout[List] is a length 2 list of the form [ true, res ] .

-## -## If the call completes within the allotted time and returns no value, the result of -## CallWithTimeout[List] is a list of length 1 containing the value true.

-## -## If the call does not complete within the timeout, the result of CallWithTimeout[List] -## is a list of length 1 containing the value false In this case, just as if you had -## quit from a break loop, there is some risk that internal data structures in &GAP; may -## have been left in an inconsistent state, and you should proceed with caution.

-## -## The timer is suspended during execution of a break loop and abandoned when you quit from a break loop.

-## -## Timeouts may not be nested. That is, during execution of CallWithTimeout(timeout,func,...), -## func (or functions it calls) may not call CallWithTimeout or CallWithTimeoutList. -## This restriction may be lifted on at least some systems in future releases. It is -## permitted to use CallWithTimeout or CallWithTimeoutList from within a break loop, even if a -## suspended timeout exists, although there is limit on the depth of such nesting.

-## -## The limit timeout is specified as a record. At present the following components are recognised -## nanoseconds, microseconds, milliseconds, seconds, -## minutes, hours, days and weeks. Any of these -## components which is present should be bound to a positive integer, rational or float and the times -## represented are totalled to give the actual timeout. As a shorthand, a single positive -## integers may be supplied, and is taken as a number of microseconds. -## Further components are permitted and ignored, to allow for future functionality.

-## -## The precision of the timeouts is not guaranteed, and there is a system dependent upper limit on the timeout -## which is typically about 8 years on 32 bit systems and about 30 billion years on 64 bit systems. Timeouts longer -## than this will be reduced to this limit. On Windows systems, timing is based on elapsed time, not CPU time -## because the necessary POSIX CPU timing API is not supported.

-## -## -## <#/GAPDoc> - -DeclareGlobalFunction("CallWithTimeout"); -DeclareGlobalFunction("CallWithTimeoutList"); - diff --git a/lib/function.gi b/lib/function.gi index 2c8d1977a43..dc014dba470 100644 --- a/lib/function.gi +++ b/lib/function.gi @@ -5,76 +5,11 @@ ## #Y Copyright (C) 2015 The GAP Group ## - ## This file contains the implementations of the functions and operations +## This file contains the implementations of the functions and operations ## relating to functions and function-calling which are not so basic ## that they need to be in function.g ## - -############################################################################# -## -#F CallWithTimeout( , [, [, ....]] ) -## . . call a function with a time limit -#F CallWithTimeoutList( , , ) -## -## - -InstallGlobalFunction(CallWithTimeout, - function( timeout, func, arg... ) - return CallWithTimeoutList(timeout, func, arg); -end ); - -InstallGlobalFunction("CallWithTimeoutList", - function(timeout, func, arglist ) - local process, nano, seconds, microseconds; - process := function(name, scale) - local val; - if IsBound(timeout.(name)) then - val := timeout.(name); - if IsRat(val) or IsFloat(val) then - nano := nano + Int(val*scale); - else - Error("CallWithTimeout[List]: can't understand period of ",val," ",name,". Ignoring."); - fi; - fi; - end; - if not GAPInfo.TimeoutsSupported then - Error("Calling with time limits not supported in this GAP installation"); - return fail; - fi; - if IsInt(timeout) then - nano := 1000*timeout; - else - if not IsRecord(timeout) then - Error("CallWithTimeout[List]: timeout must be an integer or record"); - return fail; - fi; - nano := 0; - process("nanoseconds",1); - process("microseconds",1000); - process("milliseconds",1000000); - process("seconds",10^9); - process("minutes",60*10^9); - process("hours",3600*10^9); - process("days",24*3600*10^9); - process("weeks",7*24*3600*10^9); - fi; - if nano < 0 then - Error("Negative timeout is not permitted"); - return fail; - fi; - seconds := QuoInt(nano, 10^9); - microseconds := QuoInt(nano mod 10^9, 1000); - if seconds = 0 and microseconds = 0 then - # zero or tiny timeout. just simulate timeout now - return fail; - fi; - # make sure it's a small int. Cap timeouts at about 8 years on - # 32 bit systems - seconds := Minimum(seconds,2^(8*GAPInfo.BytesPerVariable-4)-1); - return CALL_WITH_TIMEOUT(seconds, microseconds, func, arglist); -end); - InstallMethod( ViewString, "for a function", true, [IsFunction], 0, function(func) local locks, nams, narg, i, isvarg, result; diff --git a/lib/read3.g b/lib/read3.g index 3ded747d86b..43c71897875 100644 --- a/lib/read3.g +++ b/lib/read3.g @@ -247,8 +247,5 @@ ReadLib("gasman.gd"); ReadLib("memusage.gd"); -# files dealing with function calling -ReadLib("function.gd"); - # random sources ReadLib("random.gi"); diff --git a/lib/system.g b/lib/system.g index 673b2e99b2e..bce6e60bab9 100644 --- a/lib/system.g +++ b/lib/system.g @@ -514,23 +514,6 @@ BIND_GLOBAL("ARCH_IS_UNIX",function() return not ARCH_IS_WINDOWS(); end); -############################################################################# -## -#V GAPInfo.TimeoutsSupported -## -## <#GAPDoc Label="GAPInfo.TimeoutsSupported"> -## -## -## -## -## tests whether this installation of &GAP; supports the timeout functionality -## of and related functions. -## -## -## <#/GAPDoc> - -GAPInfo.TimeoutsSupported := TIMEOUTS_SUPPORTED(); - ############################################################################# ## #V GAPInfo.InitFiles diff --git a/src/gap.c b/src/gap.c index 267b7ec483c..c9764af15a8 100644 --- a/src/gap.c +++ b/src/gap.c @@ -1172,197 +1172,6 @@ Obj FuncSetUserHasQuit( Obj Self, Obj value) } -#define MAX_TIMEOUT_NESTING_DEPTH 1024 - -syJmp_buf AlarmJumpBuffers[MAX_TIMEOUT_NESTING_DEPTH]; -UInt NumAlarmJumpBuffers = 0; - -Obj FuncTIMEOUTS_SUPPORTED(Obj self) { -#ifdef HPCGAP - return False; -#endif - return SyHaveAlarms ? True: False; -} - -Obj FuncCALL_WITH_TIMEOUT( Obj self, Obj seconds, Obj microseconds, Obj func, Obj args ) -{ -#ifdef HPCGAP - ErrorMayQuit("CALL_WITH_TIMEOUT: timeouts not supported in HPC-GAP", 0L, 0L); - return 0; -#else - Obj res; - volatile Obj currLVars; - Obj result; - volatile Int recursionDepth; - volatile Stat currStat; - volatile UInt newJumpBuf = 1; - volatile UInt mayNeedToRestore = 0; - volatile Int iseconds, imicroseconds; - volatile Int curr_seconds= 0, curr_microseconds=0, curr_nanoseconds=0; - Int restore_seconds = 0, restore_microseconds = 0; - - - if (!SyHaveAlarms) - ErrorMayQuit("CALL_WITH_TIMEOUT: timeouts not supported on this system", 0L, 0L); - if (!IS_INTOBJ(seconds) || 0 > INT_INTOBJ(seconds)) - ErrorMayQuit("CALL_WITH_TIMEOUT(, , , ):" - " must be a non-negative small integer",0,0); - if (!IS_INTOBJ(microseconds) || 0 > INT_INTOBJ(microseconds) || 999999 < INT_INTOBJ(microseconds)) - ErrorMayQuit("CALL_WITH_TIMEOUT(, , , ):" - " must be a non-negative small integer less than 10^9",0,0); - iseconds = INT_INTOBJ(seconds); - imicroseconds = INT_INTOBJ(microseconds); - if (!IS_FUNC(func)) - ErrorMayQuit("CALL_WITH_TIMEOUT(, , , ): must be a function",0,0); - if (!IS_LIST(args)) - ErrorMayQuit("CALL_WITH_TIMEOUT(, , , ): must be a list",0,0); - if (SyAlarmRunning) { - /* ErrorMayQuit("CALL_WITH_TIMEOUT cannot currently be nested except via break loops." - " There is already a timeout running", 0, 0); */ - SyStopAlarm((UInt *)&curr_seconds, (UInt *)&curr_nanoseconds); - curr_microseconds = curr_nanoseconds/1000; - if (iseconds > curr_seconds || (iseconds == curr_seconds && imicroseconds > curr_microseconds)) { - /* The existing timeout will go off before we would so don't bother to set a timeout - just reset the existing one and call the function */ - iseconds = curr_seconds; - imicroseconds = curr_microseconds; - newJumpBuf = 0; - } else { - /* We would time out before the other function, so we need to - set our timeout, but remember to reset things later */ - mayNeedToRestore = 1; - newJumpBuf = 1; - } - } - if (newJumpBuf) { - if (NumAlarmJumpBuffers >= MAX_TIMEOUT_NESTING_DEPTH-1) - ErrorMayQuit("Nesting depth of timeouts limited to %i", MAX_TIMEOUT_NESTING_DEPTH, 0L); - currLVars = STATE(CurrLVars); - currStat = STATE(CurrStat); - recursionDepth = STATE(RecursionDepth); - if (sySetjmp(AlarmJumpBuffers[NumAlarmJumpBuffers++])) { - /* Timeout happened */ - STATE(CurrLVars) = currLVars; - STATE(PtrLVars) = PTR_BAG(STATE(CurrLVars)); - STATE(PtrBody) = (Stat*)PTR_BAG(BODY_FUNC(CURR_FUNC)); - STATE(CurrStat) = currStat; - STATE(RecursionDepth) = recursionDepth; - if (mayNeedToRestore) { - /* In this case we used our ration of CPU time, - so we know how much we need to restore - - The jump buffer stack is already taken care of by the time we - get here */ - restore_seconds = curr_seconds - iseconds; - restore_microseconds = curr_microseconds - imicroseconds; - if (restore_microseconds < 0) { - restore_microseconds += 1000000; - restore_seconds -= 1; - } - SyInstallAlarm(restore_seconds, 1000*restore_microseconds); - } - res = NEW_PLIST(T_PLIST_DENSE+IMMUTABLE,1); - SET_ELM_PLIST(res,1,False); - SET_LEN_PLIST(res,1); - return res; - } - } - - /* The next timeout was too close, this is a bit of a hack, just as below */ - if ((iseconds==0) && (imicroseconds==0)) { - imicroseconds = 1; - } - /* Here we actually call the function */ - SyInstallAlarm( iseconds, 1000*imicroseconds); - result = CallFuncList(func, args); - - /* if newJumpBuf is false then we didn't set up our own alarm, - just reset the outer one, - and the outer one hasn't gone off yet, so we just return */ - if (newJumpBuf) { - /* Here we did set our own alarm, but it hasn't gone off */ - Int unused_seconds, unused_microseconds, unused_nanoseconds; - SyStopAlarm( (UInt *)&unused_seconds, (UInt *)&unused_nanoseconds); - unused_microseconds = unused_nanoseconds/1000; - /* Now the alarm might have gone off since we executed the last statement - of func. So */ - if (SyAlarmHasGoneOff) { - SyAlarmHasGoneOff = 0; - UnInterruptExecStat(); - } - assert(NumAlarmJumpBuffers); - NumAlarmJumpBuffers--; - - /* If there is an outer timer, we need to reset it */ - if (mayNeedToRestore) { - restore_seconds = curr_seconds - (iseconds - unused_seconds); - restore_microseconds = curr_microseconds - (imicroseconds - unused_microseconds); - while (restore_microseconds < 0) { - restore_microseconds += 1000000; - restore_seconds -= 1; - } - while (restore_microseconds > 999999) { - restore_microseconds -= 1000000; - restore_seconds += 1; - } - - /* nasty hack -- if the outer timer was right on the edge of going off - and we try to restore it to zero we will actually stop it */ - if (!restore_seconds && !restore_microseconds) - restore_microseconds = 1; - - SyInstallAlarm(restore_seconds, 1000*restore_microseconds); - } - - } - - /* assemble and return the result */ - res = NEW_PLIST(T_PLIST_DENSE+IMMUTABLE, 2); - SET_ELM_PLIST(res,1,True); - if (result) { - SET_LEN_PLIST(res,2); - SET_ELM_PLIST(res,2,result); - CHANGED_BAG(res); - } else { - SET_LEN_PLIST(res,1); - } - return res; -#endif -} - -Obj FuncSTOP_TIMEOUT( Obj self ) { - UInt seconds, nanoseconds; - if (!SyHaveAlarms || !SyAlarmRunning) - return Fail; - SyStopAlarm(&seconds, &nanoseconds); - Obj state = NEW_PLIST(T_PLIST_CYC+IMMUTABLE, 3); - SET_ELM_PLIST(state,1,INTOBJ_INT(seconds)); - SET_ELM_PLIST(state,2,INTOBJ_INT(nanoseconds/1000)); - SET_ELM_PLIST(state,3,INTOBJ_INT(NumAlarmJumpBuffers)); - SET_LEN_PLIST(state,3); - return state; -} - -Obj FuncRESUME_TIMEOUT( Obj self, Obj state ) { - if (!SyHaveAlarms || SyAlarmRunning) - return Fail; - if (!IS_PLIST(state) || LEN_PLIST(state) < 2) - return Fail; - if (!IS_INTOBJ(ELM_PLIST(state,1)) || - !IS_INTOBJ(ELM_PLIST(state,2))) - return Fail; - Int s = INT_INTOBJ(ELM_PLIST(state,1)); - Int us = INT_INTOBJ(ELM_PLIST(state,2)); - if (s < 0 || us < 0 || us > 999999) - return Fail; - Int depth = INT_INTOBJ(ELM_PLIST(state,3)); - if (depth < 0 || depth >= MAX_TIMEOUT_NESTING_DEPTH) - return Fail; - NumAlarmJumpBuffers = depth; - SyInstallAlarm(s, 1000*us); - return True; -} - /**************************************************************************** ** *F RegisterBreakloopObserver( ) @@ -3106,22 +2915,9 @@ static StructGVarFunc GVarFuncs [] = { { "CALL_WITH_CATCH", 2, "func, args", FuncCALL_WITH_CATCH, "src/gap.c:CALL_WITH_CATCH" }, - { "TIMEOUTS_SUPPORTED", 0, "", - FuncTIMEOUTS_SUPPORTED, "src/gap.c:TIMEOUTS_SUPPORTED" }, - - { "CALL_WITH_TIMEOUT", 4, "seconds, microseconds, func, args", - FuncCALL_WITH_TIMEOUT, "src/gap.c:CALL_WITH_TIMEOUT" }, - - {"STOP_TIMEOUT", 0, "", - FuncSTOP_TIMEOUT, "src/gap.c:FuncSTOP_TIMEOUT" }, - - {"RESUME_TIMEOUT", 1, "state", - FuncRESUME_TIMEOUT, "src/gap.c:FuncRESUME_TIMEOUT" }, - { "JUMP_TO_CATCH", 1, "payload", FuncJUMP_TO_CATCH, "src/gap.c:JUMP_TO_CATCH" }, - { "KERNEL_INFO", 0, "", FuncKERNEL_INFO, "src/gap.c:KERNEL_INFO" }, diff --git a/src/gap.h b/src/gap.h index ea574ef2af3..a4ea3243432 100644 --- a/src/gap.h +++ b/src/gap.h @@ -49,17 +49,6 @@ extern UInt Last3; */ extern UInt Time; -/**************************************************************************** -** -*V AlarmJumpBuffer . . . . . .long jump buffer used for timeouts -** -** Needs to be visible to code in read.c that stores away execution state -*/ - - -extern syJmp_buf AlarmJumpBuffers[]; -extern UInt NumAlarmJumpBuffers; - /**************************************************************************** ** diff --git a/src/stats.c b/src/stats.c index 076384d3fd9..ad15f6241a9 100644 --- a/src/stats.c +++ b/src/stats.c @@ -1674,20 +1674,6 @@ sig_atomic_t volatile RealExecStatCopied; int volatile RealExecStatCopied; #endif -/**************************************************************************** -** -*F void CheckAndRespondToAlarm() -** -*/ - -static void CheckAndRespondToAlarm(void) { - if ( SyAlarmHasGoneOff ) { - SyAlarmHasGoneOff = 0; - assert(NumAlarmJumpBuffers); - syLongjmp(&(AlarmJumpBuffers[--NumAlarmJumpBuffers]),1); - } -} - /**************************************************************************** ** *F UInt TakeInterrupt() . . . . . . . . allow user interrupts @@ -1705,7 +1691,6 @@ static void CheckAndRespondToAlarm(void) { UInt TakeInterrupt( void ) { if (HaveInterrupt()) { UnInterruptExecStat(); - CheckAndRespondToAlarm(); ErrorReturnVoid( "user interrupt", 0L, 0L, "you can 'return;'" ); return 1; @@ -1751,11 +1736,6 @@ UInt ExecIntrStat ( } HaveInterrupt(); - - /* One reason we might be here is a timeout. If so longjump out to the - CallWithTimeLimit where we started */ - CheckAndRespondToAlarm(); - /* and now for something completely different */ SET_BRK_CURR_STAT( stat ); if ( SyStorOverrun != 0 ) { diff --git a/src/sysfiles.c b/src/sysfiles.c index 336fc5cff10..e11ca7ec731 100644 --- a/src/sysfiles.c +++ b/src/sysfiles.c @@ -3601,8 +3601,6 @@ static Int postRestore ( static Int InitKernel( StructInitInfo * module ) { - SyInitAlarm(); - /* init filters and functions */ InitHdlrFuncsFromTable( GVarFuncs ); diff --git a/src/sysfiles.h b/src/sysfiles.h index c08f55957ba..3da14d71ed8 100644 --- a/src/sysfiles.h +++ b/src/sysfiles.h @@ -336,14 +336,6 @@ extern void SyInstallAnswerIntr ( void ); extern UInt SyIsIntr ( void ); -extern int SyHaveAlarms; -extern volatile int SyAlarmRunning; -extern volatile int SyAlarmHasGoneOff; - -extern void SyInitAlarm( void ); -extern void SyInstallAlarm( UInt seconds, UInt nanoseconds); -extern void SyStopAlarm( UInt *seconds, UInt *nanoseconds); - /**************************************************************************** ** diff --git a/src/system.h b/src/system.h index 6f9bcb3481b..2da2803e5f2 100644 --- a/src/system.h +++ b/src/system.h @@ -1037,8 +1037,6 @@ typedef void (*voidfunc)(void); Int RegisterSyLongjmpObserver(voidfunc); -extern syJmp_buf AlarmJumpBuffer; - /**************************************************************************** diff --git a/src/systimers.c b/src/systimers.c deleted file mode 100644 index 545c17b66f8..00000000000 --- a/src/systimers.c +++ /dev/null @@ -1,235 +0,0 @@ -/**************************************************************************** -** -*W systimer.c -** -** -*Y Copyright (C) 1996, Lehrstuhl D für Mathematik, RWTH Aachen, Germany -*Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland -*Y Copyright (C) 2002 The GAP Group -** -** -** This file implements timers for CallWithTimeout. There are two options -** 1) Using the POSIX 2001 timer api -** 2) Using setitimer/getitimer -** -*/ - -#include -#include -#include -#include -#include -#include // for Pr() - -#include -#include -#include - -#include - -volatile int SyAlarmRunning = 0; -volatile int SyAlarmHasGoneOff = 0; - - -#if defined(HAVE_SIGNAL) && defined(HAVE_SIGACTION) && \ - defined(HAVE_TIMER_CREATE) && defined(CLOCK_REALTIME) - -/* This uses the POSIX 2001 API - which allows per-thread timing and minimises risk of - interference with other code using timers. - - Sadly it's not always available, so we have an alternative implementation - below using the odler setitimer interface */ - -/* Handler for the Alarm signal */ - -int SyHaveAlarms = 1; - -/* This API lets us pick wich signal to use */ -#define TIMER_SIGNAL SIGVTALRM - -/* For now anyway we create one timer at initialisation and use it */ -static timer_t syTimer = 0; - -#define MY_CLOCK CLOCK_REALTIME - -void SyInitAlarm( void ) { -/* Create the CPU timer used for timeouts */ - struct sigevent se; - se.sigev_notify = SIGEV_SIGNAL; - se.sigev_signo = TIMER_SIGNAL; - se.sigev_value.sival_int = 0x12345678; - if (timer_create( MY_CLOCK, &se, &syTimer)) { - Pr("#E Could not create interval timer. Timeouts will not be supported\n",0L,0L); - SyHaveAlarms = 0; - } -} - -static void syAnswerAlarm ( int signr, siginfo_t * si, void *context) -{ - /* interrupt the executor - Later we might want to do something cleverer with throwing an - exception or dealing better if this isn't our timer */ - assert( signr == TIMER_SIGNAL); - assert( si->si_signo == TIMER_SIGNAL); - assert( si->si_code == SI_TIMER); - assert( si->si_value.sival_int == 0x12345678 ); - SyAlarmRunning = 0; - SyAlarmHasGoneOff = 1; - InterruptExecStat(); -} - - -void SyInstallAlarm ( UInt seconds, UInt nanoseconds ) -{ - struct sigaction sa; - - sa.sa_handler = NULL; - sa.sa_sigaction = syAnswerAlarm; - sigemptyset(&(sa.sa_mask)); - sa.sa_flags = SA_RESETHAND | SA_SIGINFO | SA_RESTART; - - /* First install the handler */ - if (sigaction( TIMER_SIGNAL, &sa, NULL )) - { - ErrorReturnVoid("Could not set handler for alarm signal",0L,0L,"you can return to ignore"); - return; - } - - - struct itimerspec tv; - tv.it_value.tv_sec = (time_t)seconds; - tv.it_value.tv_nsec = (long)nanoseconds; - tv.it_interval.tv_sec = (time_t)0; - tv.it_interval.tv_nsec = 0L; - - SyAlarmRunning = 1; - SyAlarmHasGoneOff = 0; - if (timer_settime(syTimer, 0, &tv, NULL)) { - signal(TIMER_SIGNAL, SIG_DFL); - ErrorReturnVoid("Could not set interval timer", 0L, 0L, "you can return to ignore"); - } - return; -} - -void SyStopAlarm(UInt *seconds, UInt *nanoseconds) { - struct itimerspec tv, buf; - tv.it_value.tv_sec = (time_t)0; - tv.it_value.tv_nsec = 0L; - tv.it_interval.tv_sec = (time_t)0; - tv.it_interval.tv_nsec = 0L; - - timer_settime(syTimer, 0, &tv, &buf); - SyAlarmRunning = 0; - signal(TIMER_SIGNAL, SIG_IGN); - - if (seconds) - *seconds = (UInt)buf.it_value.tv_sec; - if (nanoseconds) - *nanoseconds = (UInt)buf.it_value.tv_nsec; - return; -} - -#elif defined(HAVE_SIGNAL) && defined(HAVE_SIGACTION) && \ - defined(HAVE_SETITIMER) && defined(HAVE_GETITIMER) - -/* Using setitimer and getitimer from sys/time.h */ -/* again sigaction could be replaced by signal if that was useful - sigaction is just a bit more robust */ - -/* Handler for the Alarm signal */ - -int SyHaveAlarms = 1; - -void SyInitAlarm( void ) { - /* No initialisation in this case */ - return; -} - -static void syAnswerAlarm ( int signr, siginfo_t * si, void *context) -{ - /* interrupt the executor - Later we might want to do something cleverer with throwing an - exception or dealing better if this isn't our timer */ - assert( signr == SIGVTALRM); - assert( si->si_signo == SIGVTALRM); - SyAlarmRunning = 0; - SyAlarmHasGoneOff = 1; - InterruptExecStat(); -} - -void SyInstallAlarm ( UInt seconds, UInt nanoseconds ) -{ - struct sigaction sa; - - sa.sa_handler = NULL; - sa.sa_sigaction = syAnswerAlarm; - sigemptyset(&(sa.sa_mask)); - sa.sa_flags = SA_RESETHAND | SA_SIGINFO | SA_RESTART; - - - /* First install the handler */ - if (sigaction( SIGVTALRM, &sa, NULL )) - { - ErrorReturnVoid("Could not set handler for alarm signal",0L,0L,"you can return to ignore"); - return; - } - - - struct itimerval tv; - tv.it_value.tv_sec = (time_t)seconds; - tv.it_value.tv_usec = (suseconds_t)(nanoseconds/1000); - tv.it_interval.tv_sec = (time_t)0; - tv.it_interval.tv_usec = (suseconds_t)0L; - - SyAlarmRunning = 1; - SyAlarmHasGoneOff = 0; - if (setitimer(ITIMER_VIRTUAL, &tv, NULL)) { - signal(SIGVTALRM, SIG_IGN); - ErrorReturnVoid("Could not set interval timer", 0L, 0L, "you can return to ignore"); - } - return; -} - -void SyStopAlarm(UInt *seconds, UInt *nanoseconds) { - struct itimerval tv, buf; - tv.it_value.tv_sec = (time_t)0; - tv.it_value.tv_usec = (suseconds_t)0L; - tv.it_interval.tv_sec = (time_t)0; - tv.it_interval.tv_usec = (suseconds_t)0L; - - setitimer(ITIMER_VIRTUAL, &tv, &buf); - SyAlarmRunning = 0; - signal(SIGVTALRM, SIG_IGN); - - if (seconds) - *seconds = (UInt)buf.it_value.tv_sec; - if (nanoseconds) - *nanoseconds = 1000*(UInt)buf.it_value.tv_usec; - return; -} - -#else - -int SyHaveAlarms = 0; - -/* stub implementations */ - -void SyInitAlarm( void ) -{ - /* No initialisation in this case */ - return; -} - -void SyInstallAlarm ( UInt seconds, UInt nanoseconds ) -{ - assert(0); - return; -} - -void SyStopAlarm(UInt *seconds, UInt *nanoseconds) { - assert(0); - return; -} - -#endif diff --git a/tst/testinstall/timeout.tst b/tst/testinstall/timeout.tst deleted file mode 100644 index 9443c7e7f0c..00000000000 --- a/tst/testinstall/timeout.tst +++ /dev/null @@ -1,23 +0,0 @@ -gap> START_TEST("timeout.tst"); -gap> spinFor := function(ms, arg...) local t; -> t := NanosecondsSinceEpoch() / 1000; -> while NanosecondsSinceEpoch() / 1000 < t + ms do od; -> if Length(arg) >= 1 -> then return arg[1]; else return; fi; end; -function( ms, arg... ) ... end -gap> spinFor(10); -gap> spinFor(10,0); -0 -gap> CallWithTimeout(50000,spinFor,1); -[ true ] -gap> CallWithTimeout(5000,spinFor,50000); -[ false ] -gap> CallWithTimeout(50000,spinFor,1,1); -[ true, 1 ] -gap> CallWithTimeoutList(50000,spinFor,[1,1]); -[ true, 1 ] -gap> CallWithTimeoutList(5000,spinFor,[50000,1]); -[ false ] -gap> CallWithTimeoutList(50000,spinFor,[1]); -[ true ] -gap> STOP_TEST( "timeout.tst", 1);