Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.programming.threads > #7064

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

Newsgroups comp.programming.threads
Date 2021-11-23 12:24 -0800
Message-ID <cbbc9ee5-9220-4b71-99ae-e8341e123311n@googlegroups.com> (permalink)
Subject More of my philosophy about setjmp() and longjmp() and generators and coroutines..
From Amine Moulay Ramdane <aminer68@gmail.com>

Show all headers | View raw


Hello,


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

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

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 implement 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.

Back to comp.programming.threads | Previous | Next | Find similar | Unroll thread


Thread

More of my philosophy about setjmp() and longjmp() and generators and coroutines.. Amine Moulay Ramdane <aminer68@gmail.com> - 2021-11-23 12:24 -0800

csiph-web