Sched Handler (WIP)

If you have questions about any aspect of QBasic programming, or would like to help fellow programmers solve their problems, check out this board!

Moderators: Pete, Mods

Post Reply
SMcClouth
Coder
Posts: 32
Joined: Wed Jun 06, 2012 11:45 am

Sched Handler (WIP)

Post by SMcClouth »

For a w.i.p. (work in process) schedule handler,

I've the following code:

Code: Select all

DIM SHARED task(100) AS INTEGER

CONST NR.TASKS = 64

SUB sched.init
FOR i = 1 TO NR.TASKS
     task(i) = 0
NEXT
END SUB
Now the thing is, that it doesn't walk through till the 64.
When trying to debug, I REMarked

Code: Select all

task(i) = 0
and added

Code: Select all

PRINT task(i)
which then gives diffrent values. When adjusting this to:

Code: Select all

task(i) = 0
PRINT i; "-"; task(i)
it gets to 32 - 0 and hangs there. Does anyone have a clue why this could be and how to fix this?
Last edited by SMcClouth on Mon Apr 08, 2013 3:05 am, edited 1 time in total.
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

1) post code that actually runs! Good or bad, you have to care before we do. NEX? USB?

2) all the elements of an array are zero already

3) use dot names after you know how the code works. Dot names do not make a program or the programmer any better!
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
SMcClouth
Coder
Posts: 32
Joined: Wed Jun 06, 2012 11:45 am

Post by SMcClouth »

burger2227 wrote:1) post code that actually runs! Good or bad, you have to care before we do. NEX? USB?
My bad, sorry. Fixed it.
burger2227 wrote:2) all the elements of an array are zero already
Apparently for some reason, because it runs in modules, it isn't. But you're right though, they should be zero.[/quote]
burger2227 wrote:3) use dot names after you know how the code works. Dot names do not make a program or the programmer any better!
Thanks for the tip.

Alright, I'll put up the source in which in runs, and perhaps that will explain some more.
I use PDS 7.1
SMcClouth
Coder
Posts: 32
Joined: Wed Jun 06, 2012 11:45 am

Post by SMcClouth »

PART 1

kernel/include/qbinux.bi:

Code: Select all

DEFINT A-Z
'$DYNAMIC

TYPE RegTypeX
AX AS INTEGER
BX AS INTEGER
CX AS INTEGER
DX AS INTEGER
BP AS INTEGER
SI AS INTEGER
DI AS INTEGER
flags AS INTEGER
DS AS INTEGER
ES AS INTEGER
END TYPE

TYPE tm
sec AS INTEGER
min AS INTEGER
hour AS INTEGER
mday AS INTEGER
mon AS INTEGER
year AS INTEGER
wday AS INTEGER
yday AS INTEGER
isdst AS INTEGER
END TYPE

DECLARE FUNCTION BCD2BIN (Value AS INTEGER)
DECLARE FUNCTION BITS2NUM& (bits AS STRING)
DECLARE FUNCTION BitShift (Value%, way$, count%)
DECLARE SUB bufferinit ()
DECLARE FUNCTION CMOS.Read (Addr)
DECLARE FUNCTION CreateArray$ (slots&, bytes%)
DECLARE FUNCTION Day! ()
DECLARE FUNCTION FindFATFile% (fil AS STRING)
DECLARE SUB hdinit ()
DECLARE SUB head ()
DECLARE SUB InterruptX (intnm AS INTEGER, inreg AS RegTypeX, outreg AS RegTypeX)
DECLARE FUNCTION Kernel.MkTime (tmx AS tm)
DECLARE SUB main ()
DECLARE SUB MakDir (dir AS STRING)
DECLARE FUNCTION Month! (mont%)
DECLARE SUB movetousermode ()
DECLARE FUNCTION NUM2BITS$ (num AS INTEGER, bits AS INTEGER)
DECLARE FUNCTION RHEX$ (lenght AS INTEGER)
DECLARE SUB sched.init ()
DECLARE SUB SetDir (DirID AS LONG)
DECLARE SUB SetDrv (DrvID AS LONG)
DECLARE SUB setup ()
DECLARE SUB TimeInit ()
DECLARE FUNCTION WorkPath$ (file AS STRING)
DECLARE FUNCTION Year! ()

'Shared variables
COMMON SHARED CurDir AS STRING * 4, CurDrive AS STRING * 4, CurUser AS STRING * 1
COMMON SHARED FileFound AS STRING * 1, PriPub AS STRING * 1, IsSystem AS STRING * 1
COMMON SHARED DirFound AS STRING * 1, PathAccess AS STRING * 1
COMMON SHARED EditArr AS STRING * 8, cTask AS STRING
COMMON SHARED PMode

'Shared dims
DIM SHARED curpos       AS INTEGER
DIM SHARED msg1         AS STRING
DIM SHARED RegsX        AS RegTypeX
DIM SHARED startuptime  AS LONG
DIM SHARED task(100)     AS INTEGER
DIM SHARED tme          AS tm

CONST MINUTE = 60
CONST NR.TASKS = 64

ON ERROR RESUME NEXT
kernel/boot/boot.bas:

Code: Select all

'
'       boot.bas
'

'$INCLUDE:'include/qbinux.bi'

msg1 = "Loading system ..." + CHR$(13) + CHR$(10)

start:
        RegsX.AX = &H300                        ' read cursor pos
        RegsX.BX = &H10
        InterruptX &H10, RegsX, RegsX

        FOR ascii = 1 TO LEN(msg1)
        RegsX. AX = &HE00 + ASC(MID$(msg1, ascii))
        RegsX. BX = 0
        InterruptX &H10, RegsX, RegsX           ' write string, move cursor
        NEXT

' ok, we've written the message, now
' we get the current cursor position and save it for
' posterity.

        RegsX.AX = &H300                        ' read cursor pos
        RegsX.BX = &H10
        InterruptX &H10, RegsX, RegsX           ' save it in known place, con_init fetches
        CurPos = RegsX.DX                       ' it from CurPos.

' that was painless, now we see if A20 is enabled
        DEF SEG = 0: a% = PEEK(&H4F0): POKE &H4F0, &HE7
        DEF SEG = &HFFFF: b% = PEEK(&H500) '&H4F0+&H10
        DEF SEG = 0: POKE &H4F0, a%
        IF b% <> &HE7 THEN
                GOTO empty8042
        ELSE
                PRINT "A20 not enabled": SYSTEM
        END IF

' This routine checks that the keyboard command queue is empty
' No timeout is used - if this hangs there is something wrong with
' the machine, and we probably couldn't proceed anyway.
empty8042:
        RegsX.AX = &HB00
        InterruptX &H21, RegsX, RegsX           ' 8042 status port
        IF (RegsX.AX AND &HFF) <> 0 THEN        ' is input buffer full?
        goto empty8042                          ' yes - loop
        END IF

        head
kernel/boot/head.bas:

Code: Select all

'
'       head.bas
'

'$INCLUDE:'include/qbinux.bi'

SUB head
startup32:
        DEF SEG = 0: a% = PEEK(&H4F0): POKE &H4F0, &HE7 ' check that A20 really IS enabled
        DEF SEG = &HFFFF: b%  = PEEK(&H500)
        DEF SEG = 0: POKE &H4F0, a%
        InterruptX &H11, RegsX, RegsX                   ' check math chip
        SHARED ax2 AS LONG
        ax2 = CVL(MKI$(RegsX.AX) + CHR$(0) + CHR$(0))
        IF ((ax2 AND 2) \ 2) = 1 THEN
        ET = 1                                          ' ET is set - 387 is present
        END IF
        GOTO afterpagetables

afterpagetables:
        goto setuppaging

setuppaging:   'will be added later
'        IF b4ginit THEN
'                PMode = 0
'        ELSE
'                PMode = 1
'        END IF

main
END SUB
SMcClouth
Coder
Posts: 32
Joined: Wed Jun 06, 2012 11:45 am

Post by SMcClouth »

Part 2

kernel/fs/fs.bas:

Code: Select all

'
'       fs.bas
'

'$INCLUDE:'include/qbinux.bi'

SUB AscendDir
END SUB

SUB bufferinit
        EditArr = CreateArray(131074, 80)
        IF EditArr = STRING$(8, 0) THEN
                PRINT "Failed..."
        END IF
END SUB

FUNCTION CreateArray$ (slots&, bytes%)
IF bytes > 8192 THEN EXIT FUNCTION
DO
        arrn$ = RHEX(8)
LOOP WHILE FindFATFILE("ARR\" + arrn$ + ".Arr")
ff = FREEFILE
OPEN "ARR\" + arrn$ + ".Arr" FOR OUTPUT AS #FF
t$ = MKL$(slots&) + MKI$(bytes)
PRINT #ff, t$
FOR a = 8193 TO bytes STEP - 1
        i! = a / bytes
        n! = slots& / ( a / bytes)
        IF i! = INT(a / bytes) AND n! = INT(n!) THEN EXIT FOR
NEXT
END FUNCTION

FUNCTION FindFATFile (fil AS STRING)
spec$ = fil + CHR$(0)
RegsX.AX = &H4E00
RegsX.CX = 39
RegsX.DX = SADD(Spec$)
RegsX.DS = SSEG(Spec$)
InterruptX &H21, RegsX, RegsX
IF RegsX.flags AND 1 THEN
        FindFATFile = VAL("0")
ELSE
        FindFATFile = VAL("1")
END IF
END FUNCTION

FUNCTION GetID& (filedir AS STRING, typ AS INTEGER)
IF filedir = "" THEN EXIT FUNCTION
ff = FREEFILE
IF typ = 0 THEN         'file
        IF FindFATFile("NVXFS/FileList.nff") = 0 THEN GetID = 0: EXIT FUNCTION
        OPEN "NVXFS/FileList.nff" FOR BINARY AS #ff
        mt$ = "  "
        GET #ff, 1, mt$
        k = CVI(mt$)
        FOR a = 0 TO k
                offs& = a * 272& + 3
                t$ = SPACE$(271)
                GET #ff, offs&, t$
                dnam$ = MID$(t$, 2, ASC(MID$(t$, 1, 1)))
                ddrive$ = MID$(t$, 257, 4)
                ddir$ = MID$(t$, 261, 4)
                ID$ = MID$(t$, 265, 4)
                IF dnam$ = filedir THEN
                        IF ddrive$ = CurDrive THEN
                                IF ddir$ = CurDir THEN
                                        GetID& = CVL(ID$)
                                        CLOSE #ff
                                        EXIT FUNCTION
                                END IF
                        END IF
                 END IF
          NEXT
          CLOSE #FF
ELSEIF typ = 1 THEN     'directory
        IF FindFATFile("NVXFS/DirList.nfd") = 0 THEN GetID = 0: EXIT FUNCTION
        OPEN "NVXFS/DirList.nfd" FOR BINARY AS #FF
        mt$ = "  "
        GET #ff, 1, mt$
        k = CVI(mt$)
        FOR a = 0 TO k
                offs& = a * 272& + 3
                t$ = SPACE$(271)
                GET #ff, offs&, t$
                dnam$ = MID$(t$, 2, ASC(MID$(t$, 1, 1)))
                ddrive$ = MID$(t$, 257, 4)
                ddir$ = MID$(t$, 261, 4)
                ID$ = MID$(t$, 265, 4)
                IF dnam$ = filedir THEN
                        IF ddrive$ = CurDrive THEN
                                IF ddir$ = CurDir THEN
                                        GetID& = CVL(ID$)
                                        CLOSE #ff
                                        EXIT FUNCTION
                                 END IF
                         END IF
                 END IF
         NEXT
         CLOSE #ff
ELSE                    'drive
        IF FindFATFile("NVXFS/DrvList.drv") = 0 THEN GetID = 0: EXIT FUNCTION

END IF
END FUNCTION

SUB MakDir (dir AS STRING)
odir$ = CurDir
dirn$ = WorkPath(dir)
END SUB

FUNCTION RHEX$ (lenght AS INTEGER)
FOR A = 1 to lenght
        s$ = s$ + HEX$(INT(16 * RND))
NEXT
RHEX$ = s$
END FUNCTION

SUB SetDir (DirID AS LONG)
CurDir = MKL$(DirID)
END SUB

SUB SetDrv (DrvID AS LONG)
CurDrive = MKL$(DrvID)
END SUB

FUNCTION WorkPath$ (file AS STRING)
h$ = file
Ompa$ = CurDir
IF INSTR(file, "/") THEN
        DO
                t$ = LEFT$(h$, INSTR(h$, "/") - 1)
                IF t$ = "..." THEN
                        SetDir 0
                ELSEIF t$ = ".." THEN
                        AscendDir
                ELSE
                        IF GetID(t$, 1) <> 0 THEN
                                SetDir GetID(t$, 1)
                        ELSE
                                WorkPath$ = "DNF"
                                CurDir = Ompa$
                                EXIT FUNCTION
                        END IF
                END IF
                h$ = RIGHT$(h$, LEN(h$) - (LEN(t$) + 1))
         LOOP WHILE INSTR(h$, "/")
END IF
WorkPath$ = h$
END FUNCTION
kernel/init/main.bas:

Code: Select all

'
'       main.bas
'

'$INCLUDE:'include/qbinux.bi'

'
' Yeah, yeah, it's ugly, but I cannot find how to do this correctly
' and this seems to work. If anybody has more info on the real-time
' clock I'd be interested. Most of this was trial and error, and some
' bios-listing reading. Urghh.
'
REM $STATIC
FUNCTION BCD2BIN (Value AS INTEGER)
BCD2BIN = ((Value) AND 15) + (BitShift(Value, ">>", 4) * 10)
END FUNCTION

'Needs to be moved to proper library
REM $DYNAMIC
FUNCTION BitShift (Value%, way$, count%)
IF way$ = "<<" THEN
        X = Value% * (2 ^ count%)
        temp& = x%
        temp& = (temp% * (X ^ count%)) AND &HFFFF
        BitShift = temp&
ELSEIF way$ = ">>" THEN
        BitShift = INT(Value% / 2 ^ count%)
END IF
END FUNCTION

FUNCTION CMOS.Read (Addr)
OUT &H70, Addr
CMOS.Read = INP(&H71)
END FUNCTION

SUB init

        setup
END SUB

SUB main
timeinit
sched.init
bufferinit
hdinit
movetousermode
rem        init
END SUB

SUB movetousermode
PriPub = CHR$(BITS2NUM("11000000"))
IsSystem = CHR$(BITS2NUM("00000000"))
END SUB

SUB timeinit
DO
        tme.sec = CMOS.READ(0)
        tme.min = CMOS.READ(2)
        tme.hour = CMOS.READ(4)
        tme.mday = CMOS.READ(7)
        tme.mon = CMOS.READ(8)
        tme.year = CMOS.READ(9)
LOOP WHILE (tme.sec = CMOS.READ(0))
x% = BCD2BIN(tme.sec): tme.sec = x%
x% = BCD2BIN(tme.min): tme.min = x%
x% = BCD2BIN(tme.hour): tme.hour = x%
x% = BCD2BIN(tme.mday): tme.mday = x%
x% = BCD2BIN(tme.mon): tme.mon = x%
x% = BCD2BIN(tme.year): tme.year = x%
startuptime = Kernel.MkTime(tme)
END SUB
SMcClouth
Coder
Posts: 32
Joined: Wed Jun 06, 2012 11:45 am

Post by SMcClouth »

PART 3

kernel/kernel/kernel.bas:

Code: Select all

'
'       kernel.bas
'

'$INCLUDE:'include/qbinux.bi'

REM $STATIC
FUNCTION Day!
Day! = 24 * hour!
END FUNCTION

SUB hdinit
ff = FREEFILE
OPEN "TEMP\WPM.chk" FOR OUTPUT AS #ff: CLOSE #ff
IF FindFATFile("TEMP\WPM.CHK") = 0 THEN
        'COLOR 4
        PRINT " ---ERROR: Running on write protected medium."
        PRINT
        'COLOR 1
        'PRINT
        'PRINT "This means that there is really not much use starting QBinux at all."
END IF

PriPub = CHR$(BITS2NUM("11010000"))
CurUser = CHR$(BITS2NUM("00000000"))
IsSystem = CHR$(BITS2NUM("10000000"))
SetDir 0
SetDrv 0
END SUB

FUNCTION Kernel.MkTime (tmx AS tm)
DIM res AS DOUBLE
DIM year2 AS DOUBLE
year2 = tmx.year - 70 ' magic offset (y+1) needed to get leapyears right
res = year * year2 + day * ((year2 + 1) / 4)
res = res + month(tmx.mon) ' and (y+2) here. If it wasn't a leap-year, we have to adjust
IF tmx.mon > 1 AND ((year2 + 2) \ 4) THEN
        res = res - day
END IF
res = res + day * (tmx.mday - 1)
res = res + hour * tmx.hour
res = res + MINUTE * tmx.min
res = res + tmx.sec
Kernel.MkTime = res
END FUNCTION

FUNCTION Month! (mont%)
IF mont% = 1 THEN month! = 0
IF mont% = 2 THEN mont! = day! * 31
IF mont% = 3 THEN mont! = day! * (31 + 29)
IF mont% = 4 THEN mont! = day! * (31 + 29 + 31)
IF mont% = 5 THEN mont! = day! * (31 + 29 + 31 + 30)
IF mont% = 6 THEN mont! = day! * (31 + 29 + 31 + 30 + 31)
IF mont% = 7 THEN mont! = day! * (31 + 29 + 31 + 30 + 31 + 30)
IF mont% = 8 THEN mont! = day! * (31 + 29 + 31 + 30 + 31 + 30 + 31)
IF mont% = 9 THEN mont! = day! * (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31)
IF mont% = 10 THEN mont! = day! * (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30)
IF mont% = 11 THEN mont! = day! * (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31)
IF mont% = 12 THEN mont! = day! * (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30)
END FUNCTION

SUB sched.init
        FOR i = 1 to NR.TASKS
                task(i) = 0
        NEXT
END SUB

SUB setup
        CurUser = CHR$(BITS2NUM("00000000"))
        IsSystem = CHR$(BITS2NUM("00000000"))
        PathAccess = "1"
        SetDir 0
        SetDrv 0
END SUB

REM $STATIC
FUNCTION year!
year! = 365 * day!
END FUNCTION
kernel/lib/lib.bas:

Code: Select all

'
'       lib.bas
'

'$INCLUDE:'include/b4g.bi'

FUNCTION BITS2NUM& (bits AS STRING)
IF LEN(bits) > 16 THEN bits = LEFT$(bits, 16)
FOR a = LEN(bits) TO 1 STEP - 1
        IF MID$(bits, a, 1) = "1" THEN n& = n& + (2 ^ (a - 1))
NEXT
BITS2NUM& = n&
END FUNCTION
kernel/compile.bat:

Code: Select all

@ECHO OFF
del testrun.exe

REM build Image: boot/boot tools/system

REM build boot/boot
bc /o /Ot /Fs /G2 /Fpi /E /X boot\boot.bas;

REM build tools/system
bc /o /Ot /Fs /G2 /Fpi /E /X boot\head.bas;
bc /o /Ot /Fs /G2 /Fpi /E /X init\main.bas;

REM build ARCHIVES = kernel/kernel.bas mm/mm.bas fs/fs.bas
bc /o /Ot /Fs /G2 /Fpi /E /X kernel\kernel.bas;
bc /o /Ot /Fs /G2 /Fpi /E /X fs\fs.bas;

REM build lib/lib.bas
bc /o /Ot /Fs /G2 /Fpi /E /X lib\lib.bas;

ren boot.obj a.obj
ren head.obj b.obj
ren main.obj c.obj
ren kernel.obj d.obj
ren fs.obj f.obj
ren lib.obj g.obj

link a+b+c++d+f+g,,nul,lib\bcl71efr.lib+lib\qbx.lib;

ren a.exe testrun.exe
del *.obj
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

This works fine in QB64:

Code: Select all

DIM SHARED task(100) AS INTEGER

CONST NR.TASKS = 64

sched.init

END

SUB sched.init
FOR i = 1 TO NR.TASKS
  task(i) = 0
  PRINT i; "-"; task(i);
NEXT
END SUB
I did not notice a call to the SUB in your original posted code.
Last edited by burger2227 on Mon Apr 08, 2013 9:54 am, edited 1 time in total.
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
SMcClouth
Coder
Posts: 32
Joined: Wed Jun 06, 2012 11:45 am

Post by SMcClouth »

Thx for bearing with me!

Yes that way it does. But when running it in QBinux, it crashes when during the FOR-NEXT-loop in sched.init.

When I REMarked the task(i)= 0 and I still used the PRINT i; "-"; task(i), it displays diffrent values (not zero). When I unREMark the task(i) = 0, it crashes at either i = 20, or 25, or 32.

Grtz
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

CONST values should be shared globally too.
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
SMcClouth
Coder
Posts: 32
Joined: Wed Jun 06, 2012 11:45 am

Post by SMcClouth »

burger2227 wrote:CONST values should be shared globally too.
edit: You mean that I should use:

Code: Select all

DIM SHARED NR.TASKS AS INTEGER

NR.TASKS = 64
Follow up:

I changed it to the above, with the result that NR.TASKS = 0, on checking in the routine.
When chancing DIM SHARED to COMMON SHARED, NR.TASKS results in 64, but the after check, when the FOR-NEXT-loop is done, states that i = 65, which shouldn't be possible as i = 1 TO NR.TASKS (=64). and then crashes again.

Grtz
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

NEXT will do that at the end of a FOR loop every time. It goes to the next STEP interval value. Without STEP it always goes up one by default.

Code: Select all

FOR i = 1 TO 10
NEXT
PRINT i
11

If you read an invalid array element(index) it will cause an error too.
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
SMcClouth
Coder
Posts: 32
Joined: Wed Jun 06, 2012 11:45 am

Post by SMcClouth »

Thanks for clear that out burger2227.

edit: I added DEFINT A-Z to the kernel.bas file, on top.
When running the code now, it states in the debug check that NR.TASKS = 64 and ends with i= 64.
But still a crash.

edit2: after removing the debug checks (PRINT NR.TASKS, and PRINT i) it continues to print the next debug check (PRINT sched.init), but then crashes. It a very special way, (since I run this now in VirtualBox for a real DOS-experience) randomly the screens get filled with ASCII-code 219 and turns white...

grtz
Post Reply