• More of my philosophy about timesharing that is a Solution to Computer

    From Amine Moulay Ramdane@21:1/5 to All on Thu Nov 25 14:18:55 2021
    Hello,


    More of my philosophy about timesharing that is a Solution to Computer Bottlenecks..

    I am a white arab from Morocco, and i think i am smart since i have also invented many scalable algorithms and algorithms..

    I invite you to look at the following very interesting video about timesharing that is a Solution to Computer Bottlenecks:

    https://www.youtube.com/watch?v=Q07PhW5sCEk

    I think i am smart, and you have to understand one important thing
    and it is: What is the difference between a software architect and
    a software engineer?, i think there is an important difference and it
    is also like abstracted in the following question:

    "How it is made?"

    So i think that software engineering works at a higher level than
    a software architect, this is why you will notice that i am
    quickly implementing a sophisticated stackful coroutines
    Library and i am quickly implementing setjmp() and longjmp() with
    x64 assembler or code machine, read my below thoughts about them, but you have to know that my sophisticated stackful coroutines Library
    does a kind of timesharing as in the above video, but i think that there is two kinds of timesharing: the preemptive one, and the non-preemptive one, but the difference is that the preemptive one does interrupt with a timer the coroutines from an
    external scheduler in
    a form of function, but notice below that i am implementing the non-preemptive timesharing in my sophisticated coroutines Library, but you have to be smart and notice that my way of doing is like the software architect way, since i am implementing it
    from the lowest level with x64 assembler routines that are part of the non-preemptive scheduler, but not only that, but you have also to look at how i am also implementing a
    sophisticated and much more rich interface in my stackful coroutines Library, so it is like both software achitecting and software engineering, so here is all my below thoughts that shows how i am implementing it quickly, so read it carefully since you
    have also to know what's the problem with the stack frames when architecturing and using the setjmp() and longjmp() so that to implement coroutines:

    More of my philosophy and precision about the link of the article and more..

    And notice that the link below of the article that shows the problem
    of implementing coroutines with just setjmp() and longjmp()
    is from the last semester of the second year of the course
    called "CS4411 Operating Systems" from Michigan Technological University, but i think i am smart and those courses are easy
    for me, so i invite you to read about this course that requires
    both the course of "CS3331 Concurrent Computing" and "CS3421 Computer Organization", and here it is:

    http://www.csl.mtu.edu/cs4411.ck/www/Home.html

    More of my philosophy about coroutines and about setjmp() and longjmp()..

    I think i am smart, and i will say that with setjmp() and longjmp()
    you can implement a generator or the like, but you can not implement coroutines with just setjmp() and longjmp(), and so that to understand it, i invite you to read the following article that shows how when you yield from a first function with a longjmp()
    to the main body of a program and when you call another functions with longjmp(), it can make the stack frames not work correctly, and when you understand it you will not use setjmp() and longjmp() alone so that to implement coroutines, so read the
    following article so that to understand the problem with
    the stack frames, and i am understanding it easily:

    https://www.csl.mtu.edu/cs4411.ck/www/NOTES/non-local-goto/coroutine.html

    So this is why i have also implemented my sophisticated stackful coroutines library so that to solve this problem, and here is my sophisticated coroutines library and read about it and download it from here:

    https://sites.google.com/site/scalable68/object-oriented-stackful-coroutines-library-for-delphi-and-freepascal

    More of my philosophy about setjmp() and longjmp() and generators and coroutines..

    I have just quickly implemented setjmp() and longjmp() in x64 assembler,
    and after that i have just implemented quickly a good example of a generator with my setjmp() and longjmp(), look at it below, and in computer science, a generator is a routine that can be used to control the iteration behaviour of a loop. All generators
    are also iterators. A generator is very similar to a function that returns an array, in that a generator has parameters, can be called, and generates a sequence of values. However, instead of building an array containing all the values and returning them
    all at once, a generator yields the values one at a time, which requires less memory and allows the caller to get started processing the first few values immediately. In short, a generator looks like a function but behaves like an iterator. So here is my
    implementations in freepascal and delphi and they are working perfectly:

    Here is my first unit that implements longjmp() and setjmp() and notice
    how i am saving the non-volatile registers and how i am coding it in
    x64 assembler:

    ======


    { Volatile registers: The calling program assumes registers
    RAX, RCX, RDX, and R8 through R11 are volatile.
    The contents of registers RBX, RSI, RDI, RBP, RSP, and
    R12 through R15 are considered non-volatile. Functions return
    values in RAX. }



    unit JmpLib64;

    {$IFDEF FPC}
    {$ASMMODE intel}
    {$ENDIF}
    interface

    type
    jmp_buf = record
    RBX,
    RSI,
    RDI,
    RSP,
    RBP,
    RIP,
    R12,
    R13,
    R14,
    R15: UInt64;
    end;

    { setjmp captures the complete task state which can later be used to perform a non-local goto using longjmp. setjmp returns 0 when it is initially called, and a non-zero value when it is returning from a call to longjmp. setjmp must be called before
    longjmp. }

    function setjmp(out jmpb: jmp_buf): UInt64;

    { longjmp restores the task state captured by setjmp (and passed in jmpb). It then returns in such a way that setjmp appears to have returned with the value retval. setjmp must be called before longjmp. }

    procedure longjmp(const jmpb: jmp_buf; retval: UInt64);
    implementation

    function setjmp(out jmpb: jmp_buf): UInt64; assembler;{$IFDEF FPC} nostackframe; {$ENDIF}register;
    asm
    { -> RCX jmpb }
    { <- RAX Result }
    MOV RDX, [RSP] // Fetch return address (RIP)
    // Save task state
    MOV [RCX+jmp_buf.&RBX], RBX
    MOV [RCX+jmp_buf.&RSI], RSI
    MOV [RCX+jmp_buf.&RDI], RDI
    MOV [RCX+jmp_buf.&RSP], RSP
    MOV [RCX+jmp_buf.&RBP], RBP
    MOV [RCX+jmp_buf.&RIP], RDX
    MOV [RCX+jmp_buf.&R12], R12
    MOV [RCX+jmp_buf.&R13], R13
    MOV [RCX+jmp_buf.&R14], R14
    MOV [RCX+jmp_buf.&R15], R15


    SUB RAX, RAX
    @@1:
    end;

    procedure longjmp(const jmpb: jmp_buf; retval: UInt64);assembler;{$IFDEF FPC} nostackframe; {$ENDIF}register;
    asm
    { -> RCX jmpb }
    { RDX retval }
    { <- RAX Result }
    XCHG RDX, RCX
    MOV RAX,RCX
    MOV RCX, [RDX+jmp_buf.&RIP]
    // Restore task state
    MOV RBX, [RDX+jmp_buf.&RBX]
    MOV RSI, [RDX+jmp_buf.&RSI]
    MOV RDI, [RDX+jmp_buf.&RDI]
    MOV RSP, [RDX+jmp_buf.&RSP]
    MOV RBP, [RDX+jmp_buf.&RBP]
    MOV R12, [RDX+jmp_buf.&R12]
    MOV R13, [RDX+jmp_buf.&R13]
    MOV R14, [RDX+jmp_buf.&R14]
    MOV R15, [RDX+jmp_buf.&R15]
    MOV [RSP], RCX // Restore return address (RIP)

    TEST RAX, RAX // Ensure retval is <> 0
    JNZ @@1
    MOV RAX, 1
    @@1:
    end;

    end.

    ================

    And here is my example of a generator with my longjmp() and setjmp():


    { In computer science, a generator is a routine that can be used to control the iteration behaviour of a loop. All generators are also iterators. A generator is very similar to a function that returns an array, in that a generator has parameters, can be
    called, and generates a sequence of values. However, instead of building an array containing all the values and returning them all at once, a generator yields the values one at a time, which requires less memory and allows the caller to get started
    processing the first few values immediately. In short, a generator looks like a function but behaves like an iterator. }

    program test_generator;

    {$APPTYPE CONSOLE}

    uses
    JmpLib64;

    type PtrInt = ^Integer;

    var
    childtask,maintask: jmp_buf;
    myarr1: array of integer;
    i,a:integer;
    Ptr1:PtrInt;

    function generator(var myarr:array of integer):integer;

    var i1:integer;
    val:integer;
    ptr:PtrInt;
    begin


    i1:=0;

    val:= setjmp(childtask);

    i1:=val-1;

    if val=0 then
    begin
    new(ptr);
    ptr^:=myarr1[i1];
    longjmp(maintask,uint64(ptr));
    end;

    if val=10
    then
    begin
    writeln('Exiting child..');
    exit;
    end;

    inc(i1);
    new(ptr);
    ptr^:=myarr1[i1];
    longjmp(maintask,uint64(ptr));
    end;

    begin

    setlength(myarr1,10);

    for i:=0 to 9
    do myarr1[i]:=i;

    uint64(ptr1):=setjmp(maintask);

    if ptr1=nil then generator(myarr1);

    a:=ptr1^;
    dispose(ptr1);

    if (a<=length(myarr1))
    then
    begin
    if a=length(myarr1)
    then longjmp(childtask,a+1)
    else
    begin
    writeln('Value retuned by generator is: ',a);
    longjmp(childtask,a+1);
    end;
    end;

    setlength(myarr1,0);

    end.

    ====


    Thank you,
    Amine Moulay Ramdane.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)