From 36a42cf251672481da028bb30eea1b16779b5f05 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Sun, 27 Nov 2022 14:01:46 -0800 Subject: [PATCH 1/1] Implement (MSEC) using usleep() (#125) Use Sleep() on Windows. Need platform specific code for embedded systems. Check to see is (SLEEP) is implemented. If not then use old busy loop code. Fixes #112 --- csrc/pf_guts.h | 8 ++++---- csrc/pf_inner.c | 4 ++++ csrc/pf_io.h | 1 + csrc/pf_io_none.c | 6 ++++++ csrc/pfcompil.c | 1 + csrc/posix/pf_io_posix.c | 20 ++++++++++++++++++++ csrc/win32/pf_io_win32.c | 9 +++++++++ fth/loadp4th.fth | 2 +- fth/misc2.fth | 32 +++++++++++++++++++++++++++----- platforms/unix/Makefile | 1 - 10 files changed, 73 insertions(+), 11 deletions(-) diff --git a/csrc/pf_guts.h b/csrc/pf_guts.h index 5b10ac8..6092bf3 100644 --- a/csrc/pf_guts.h +++ b/csrc/pf_guts.h @@ -285,9 +285,10 @@ enum cforth_primitive_ids ID_CELLS, /* DELETE-FILE */ ID_FILE_DELETE, - ID_FILE_FLUSH, /* FLUSH-FILE */ - ID_FILE_RENAME, /* (RENAME-FILE) */ - ID_FILE_RESIZE, /* RESIZE-FILE */ + ID_FILE_FLUSH, /* FLUSH-FILE */ + ID_FILE_RENAME, /* (RENAME-FILE) */ + ID_FILE_RESIZE, /* RESIZE-FILE */ + ID_SLEEP_P, /* (SLEEP) V2.0.0 */ /* If you add a word here, take away one reserved word below. */ #ifdef PF_SUPPORT_FP /* Only reserve space if we are adding FP so that we can detect @@ -302,7 +303,6 @@ enum cforth_primitive_ids ID_RESERVED07, ID_RESERVED08, ID_RESERVED09, - ID_RESERVED10, ID_FP_D_TO_F, ID_FP_FSTORE, ID_FP_FTIMES, diff --git a/csrc/pf_inner.c b/csrc/pf_inner.c index b23974d..b7c8ae1 100644 --- a/csrc/pf_inner.c +++ b/csrc/pf_inner.c @@ -1635,6 +1635,10 @@ DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql )); endcase; #endif + case ID_SLEEP_P: + TOS = sdSleepMillis(TOS); + endcase; + case ID_SP_FETCH: /* ( -- sp , address of top of stack, sorta ) */ PUSH_TOS; TOS = (cell_t)STKPTR; diff --git a/csrc/pf_io.h b/csrc/pf_io.h index 56cc905..4db8faf 100644 --- a/csrc/pf_io.h +++ b/csrc/pf_io.h @@ -37,6 +37,7 @@ int sdTerminalIn( void ); int sdQueryTerminal( void ); void sdTerminalInit( void ); void sdTerminalTerm( void ); +cell_t sdSleepMillis( cell_t msec ); #ifdef __cplusplus } #endif diff --git a/csrc/pf_io_none.c b/csrc/pf_io_none.c index 52f92b0..2aa0f73 100644 --- a/csrc/pf_io_none.c +++ b/csrc/pf_io_none.c @@ -49,4 +49,10 @@ void sdTerminalInit( void ) void sdTerminalTerm( void ) { } + +void sdSleepMillis(cell_t /* msec */) +{ + // TODO Call some platform specific sleep function here. + return PF_ERR_NOT_SUPPORTED; +} #endif diff --git a/csrc/pfcompil.c b/csrc/pfcompil.c index 00c1540..3b54284 100644 --- a/csrc/pfcompil.c +++ b/csrc/pfcompil.c @@ -344,6 +344,7 @@ PForthDictionary pfBuildDictionary( cell_t HeaderSize, cell_t CodeSize ) CreateDicEntryC( ID_SAVE_FORTH_P, "(SAVE-FORTH)", 0 ); CreateDicEntryC( ID_SCAN, "SCAN", 0 ); CreateDicEntryC( ID_SKIP, "SKIP", 0 ); + CreateDicEntryC( ID_SLEEP_P, "(SLEEP)", 0 ); CreateDicEntryC( ID_SOURCE, "SOURCE", 0 ); CreateDicEntryC( ID_SOURCE_SET, "SET-SOURCE", 0 ); CreateDicEntryC( ID_SOURCE_ID, "SOURCE-ID", 0 ); diff --git a/csrc/posix/pf_io_posix.c b/csrc/posix/pf_io_posix.c index 156e860..c66ebea 100644 --- a/csrc/posix/pf_io_posix.c +++ b/csrc/posix/pf_io_posix.c @@ -146,3 +146,23 @@ void sdTerminalTerm(void) tcsetattr(STDIN_FILENO, TCSANOW, &save_termios); } } + +cell_t sdSleepMillis(cell_t msec) +{ + const cell_t kMaxMicros = 500000; /* to be safe, usleep() limit is 1000000 */ + cell_t micros; + cell_t napTime; + if (msec < 0) return 0; + micros = msec * 1000; + while (micros > 0) + { + napTime = (micros > kMaxMicros) ? kMaxMicros : micros; + if (usleep(napTime)) + { + perror("sdSleepMillis: usleep failed"); + return -1; + } + micros -= napTime; + } + return 0; +} diff --git a/csrc/win32/pf_io_win32.c b/csrc/win32/pf_io_win32.c index ea21508..89b6fd9 100644 --- a/csrc/win32/pf_io_win32.c +++ b/csrc/win32/pf_io_win32.c @@ -24,6 +24,7 @@ #include "../pf_all.h" #include +#include /* for Sleep() */ /* Use console mode I/O so that KEY and ?TERMINAL will work. */ #if defined(WIN32) || defined(__NT__) @@ -72,4 +73,12 @@ void sdTerminalInit( void ) void sdTerminalTerm( void ) { } + +cell_t sdSleepMillis(cell_t msec) +{ + if (msec < 0) return 0; + Sleep((DWORD)msec); + return 0; +} + #endif diff --git a/fth/loadp4th.fth b/fth/loadp4th.fth index e794c60..8afa2d9 100644 --- a/fth/loadp4th.fth +++ b/fth/loadp4th.fth @@ -25,8 +25,8 @@ include? privatize private.fth include? (local) ansilocs.fth include? { locals.fth include? fm/mod math.fth -include? task-misc2.fth misc2.fth include? [if] condcomp.fth +include? task-misc2.fth misc2.fth include? save-input save-input.fth include? read-line file.fth include? require require.fth diff --git a/fth/misc2.fth b/fth/misc2.fth index f5f9f34..b1ae8ea 100644 --- a/fth/misc2.fth +++ b/fth/misc2.fth @@ -49,16 +49,39 @@ variable if-debug ; decimal -create msec-delay 10000 , ( default for SUN ) -: (MSEC) ( #msecs -- ) +create MSEC-DELAY 100000 , \ calibrate this for your system +: (MSEC.SPIN) ( #msecs -- , busy wait, not accurate ) + 0 max \ avoid endless loop 0 - do msec-delay @ 0 + ?do msec-delay @ 0 do loop loop ; +: (MSEC) ( millis -- ) + dup (sleep) \ call system sleep in kernel + IF + ." (SLEEP) failed or not implemented! Using (MSEC.SPIN)" CR + (msec.spin) + ELSE + drop + THEN +; + defer msec -' (msec) is msec + +\ (SLEEP) uses system sleep functions to actually sleep. +\ Use (MSEC.SPIN) on embedded systems that do not support Win32 Sleep() posix usleep(). +1 (SLEEP) [IF] + ." (SLEEP) failed or not implemented! Use (MSEC.SPIN) for MSEC" CR + ' (msec.spin) is msec +[ELSE] + ' (msec) is msec +[THEN] + +: MS ( msec -- , sleep, ANS standard ) + msec +; : SHIFT ( val n -- val<