Page 1 of 2

fork()

Posted: Sun Jan 09, 2005 7:37 pm
by PolyVector
Code updated For 5.20+

I was just playing around with the idea of creating a fork() function and I came up with this:...

Code: Select all

Global _ForkRet.l
EnableASM
Procedure _fork(RetAddy.l)
  MOV eax,#True
  CALL RetAddy
  ProcedureReturn #False
EndProcedure
Procedure fork()
  !MOV eax,[esp+20]
  !MOV [v__ForkRet],eax
  CreateThread(@_fork(),_ForkRet)
  ProcedureReturn #False
EndProcedure


;/Example:

If fork()
  Debug "FORKED"
  MessageRequester("Fork()","Forked :)")
  !RET
EndIf

MessageRequester("","We're Done...")
Tell me if it works... I'm not so sure with this [esp+20] thing but if PB doesn't change too much i'm sure it'll be fine... It works on 3.91 at least :)

Posted: Sun Jan 09, 2005 7:44 pm
by GPI
What do this function?

Posted: Sun Jan 09, 2005 7:48 pm
by PolyVector
it forks the running process into two...
the code that executes when fork() is true is in a newly created thread (it is executed asyncronously...)
you MUST "!RET" to kill the newly created thread!

This should be built into PB....Fred? :)

Posted: Sun Jan 09, 2005 7:48 pm
by Bonne_den_kule
What is this good for? what can it do?

Posted: Sun Jan 09, 2005 7:50 pm
by PolyVector
it's a simple way of creating a thread...
if there's a function that blocks input you can simply call it within an "if fork()" and it will no longer block input... this is pretty standard on linux... read up on it :)

I'll try to think of a better example...

Posted: Sun Jan 09, 2005 8:19 pm
by venom
In what cases would it return false?

Posted: Sun Jan 09, 2005 8:26 pm
by PolyVector
Here's a break-down of how it works...

1) It creates a new thread... Let's call this "Thread B" (The original is "Thread A")
2) Inside of Thread B it returns #True
3) Inside of Thread A it returns #False

Thread B must "!RET" when it's finished to destroy the new thread...

The simple way to think of it is this....

Code: Select all

If fork()
  ;/We're in a new thread...
  !RET
EndIf
;/Continue as usual...

It could very easily be modified to return the ThreadID to "Thread A" and #False to "Thread B"... this would be more like the real version of fork()... but I figured this syntax would be easier to understand for beginners...

Posted: Sun Jan 09, 2005 10:53 pm
by Psychophanta
What is the value you think you are getting with: !MOV eax,[esp+20] ??

Posted: Mon Jan 10, 2005 12:25 am
by Pupil
Psychophanta wrote:What is the value you think you are getting with: !MOV eax,[esp+20] ??
I think it's the return address from where the procedure was called.

Posted: Mon Jan 10, 2005 6:37 am
by PolyVector
yup, it's the return address... I asked about this in a thread a few months ago... PB pushes a few registers onto the stack so it's further up than usual...

If pb ever changes it's behavior, then "!MOV eax,[esp+20]" will have to have a different offset...

Posted: Mon Jan 10, 2005 4:14 pm
by Psychophanta
PolyVector wrote:yup, it's the return address... I asked about this in a thread a few months ago... PB pushes a few registers onto the stack so it's further up than usual...

If pb ever changes it's behavior, then "!MOV eax,[esp+20]" will have to have a different offset...
I see.
Sorry, i didn't see the other thread months ago 8)

Posted: Mon Jan 10, 2005 4:57 pm
by PolyVector
you have been forgiven :D

Try this out... (I'm not sure why this amuses me)

Code: Select all

If fork() Or fork() Or fork()
  Debug "FORKED"
  MessageRequester("Fork()","Forked :)")
  !RET
EndIf

MessageRequester("","We're Done...")

Posted: Mon Jan 10, 2005 5:05 pm
by Psychophanta
Look at this:

Code: Select all

Global _ForkRet.l 
Procedure _fork(RetAddy.l) 
  !MOV eax,1 
  !CALL dword[esp] 
  ProcedureReturn 0 
EndProcedure 
Procedure fork() 
  !MOV eax,[esp+20] 
  !MOV [v__ForkRet],eax 
  CreateThread(@_fork(),_ForkRet) 
  ProcedureReturn 0
EndProcedure 

;/Example: 

If fork() 
  Debug "FORKED" 
  !RET 
Else
  Debug "NOT FORKED" 
EndIf 
In fact, the condition is False, but the True routine is executed by the CALL asm command in _fork() function (the secondary threat).
So then, the main thread is the stuff after the "Else" command, and the secondary thread is the one after the "If" command.

Posted: Mon Jan 10, 2005 5:21 pm
by Psychophanta
PolyVector wrote:Try this out... (I'm not sure why this amuses me)

Code: Select all

If fork() Or fork() Or fork()
  Debug "FORKED"
  MessageRequester("Fork()","Forked :)")
  !RET
EndIf

MessageRequester("","We're Done...")
Yes, the first call to fork() (in the "If" line) returns as #False, but is is executed, which means that all stuff after the "If" line is made (coz the CALL command inside _fork() function). Then, since there are an "Or" statement, the 2nd fork() call is executed too, which means the all stuff after "If" statement is made too. Then the 3rd. fork() call is made too (with a return result o #False too), and once again, the stuff is executed.

Posted: Mon Jan 10, 2005 5:37 pm
by Psychophanta
PolyVector, could be this a final version?

Code: Select all

Global _ForkRet.l
Procedure _fork(RetAddy.l)
  !CALL dword[esp]
EndProcedure
Procedure fork()
  !MOV eax,dword[esp+20]
  !MOV dword[v__ForkRet],eax
  CreateThread(@_fork(),_ForkRet)
  ProcedureReturn 0
EndProcedure

;/Example:

If fork()
;Put here the 2ndary thread code:
  Debug "FORKED"
;End of 2ndary thread code
  !RET
Else
;and here de 1ary thread code:
  Debug "NOT FORKED"
;End of 1ary thread code.
EndIf