On Sun, Mar 21, 1999 at 12:48:07AM -0800, Matthew Dillon wrote:
>     This is an example only.  It takes a *BUNCH* of arcane assembly to make
>     it work.
> 
>     I would suggest *EXTREME* caution when using a completely cloned address
>     space such as RFPROC|RFMEM generate.  Normal library calls cannot be made
>     by the child safely.   Thread libraries will also not work since they
>     expect the pthread model.
> 
>     This is not portable.  The assembly is designed for ELF libraries.

The linux threads "port" at http://lt.tar.com/linuxthreads.tar.gz contains an
implementation of a linux clone call using rfork.  An alternative assembly
language interface to rfork, originally posted to -hackers by John Dyson
last summer, is attached.  This was part of a larger posting of some kthread
code.  Check the mail archives for the complete posting by John on August
20, titled "rfork stuff", which includes an example using thr_fork.

No reason I can see that thr_fork and/or "clone" couldn't be added to
libc. 

-- 
Richard Seaman, Jr.           email: d...@tar.com
5182 N. Maple Lane            phone: 414-367-5450
Chenequa WI 53058             fax:   414-367-5852
        .file   "rf.S"
#include <sys/syscall.h>
#include "DEFS.h"
#include "SYS.h"
#define KERNEL
#include <sys/errno.h>
#undef KERNEL

#undef DEBUG

/*
 *        8      12     16        20        24       28
 * thr_fork(flags, stack, startrtn, startarg, userrtn, arg);
 *
 * flags: RF* flags for rfork in unistd.h.
 * subr:  subroutine to run as a thread.
 * stack: top of stack for thread.
 * arg:   argument to thread.
 */
.stabs "rf.S",100,0,0,Ltext0
        .text
Ltext0:
        .type   CNAME(thrfork),@function
        .stabd 68,0,1
ENTRY(thrfork)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %esi

        /*
         * Push thread info onto the new thread's stack
         */
        movl    12(%ebp), %esi  / get stack addr

        subl    $4, %esi
        movl    28(%ebp), %eax  / get user argument
        movl    %eax, (%esi)

        subl    $4, %esi
        movl    24(%ebp), %eax  / get user thread address
        movl    %eax, (%esi)

        subl    $4, %esi
        movl    20(%ebp), %eax  / get internal argument
        movl    %eax, (%esi)

        subl    $4, %esi
        movl    16(%ebp), %eax  / get internal subroutine
        movl    %eax, (%esi)

        .stabd 68,0,2
        /*
         * Prepare and execute rfork
         */
        pushl   8(%ebp)
        pushl   %esi

        leal    SYS_rfork, %eax
        KERNCALL
        jb      2f

        .stabd 68,0,3
        /*
         * Check to see if we are in the parent or child
         */
        cmpl    $0, %edx
        jnz     1f
        addl    $8, %esp
        popl    %esi
        movl    %ebp, %esp
        popl    %ebp
        ret
        .p2align 2

        /*
         * If we are in the child (new thread), then
         * set-up the call to the internal subroutine.  If it
         * returns, then call _exit.
         */
        .stabd 68,0,4
1:
        movl    %esi,%esp
#ifdef DEBUG
        movl    %esp, _stackaddr
        movl    (%esp), %eax
        movl    %eax, _stack
        movl    4(%esp), %eax
        movl    %eax,_stack+4
        movl    8(%esp), %eax
        movl    %eax,_stack+8
        movl    12(%esp), %eax
        movl    %eax,_stack+12
#endif
        popl    %eax 
#ifdef DEBUG
        movl    %eax,_fcn
#endif
        call    %eax
        addl    $12, %esp

        /*
         * Exit system call
         */
        call    PIC_PLT(_exit)

        .stabd 68,0,5
2:      addl    $8, %esp
        popl    %esi
        movl    %ebp, %esp
        popl    %ebp
        jmp     PIC_PLT(HIDENAME(cerror))

.stabs "thrfork:f67",36,0,6,CNAME(thrfork)
Lfe1:
        .size    CNAME(thrfork),Lfe1-CNAME(thrfork)

#ifdef DEBUG
        .data
        .globl  _stack
_stack: .long   0
        .long   0
        .long   0
        .long   0
        .long   0
        .globl  _stackaddr
_stackaddr:     .long   0
        .globl  _fcn
_fcn:   .long   0
#endif
#include <sys/types.h>

extern pid_t thrfork(int flags, caddr_t stack_top,
                     void (*internal_fn)(void *, int (*)(void *), void*), void 
*internal_arg,
                     int  (*user_fn)(void *), void * user_arg);

Reply via email to