Questions about Minix - Minix

This is a discussion on Questions about Minix - Minix ; > One could still implement copy-on-write using segmentation. > Only, instead of duplicating the pages as they are written, the data > segment needed to be duplicated all at once. > The only problem would be if the parent process ...

+ Reply to Thread
Page 2 of 2 FirstFirst 1 2
Results 21 to 26 of 26

Thread: Questions about Minix

  1. Re: Questions about Minix

    > One could still implement copy-on-write using segmentation.
    > Only, instead of duplicating the pages as they are written, the data
    > segment needed to be duplicated all at once.
    > The only problem would be if the parent process wrote something in the
    > memory immediately after the fork().
    > (now, thinking about that, it's pretty likely that the parent does
    > that)


    In fact, it is absolutely certain that both processes will modify their
    memory. At some point they will call either exec or exit, which causes
    the return address to be pushed on the stack which would trigger a copy.

    --
    With kind regards,
    Erik van der Kouwe

  2. Re: Questions about Minix

    "Erik van der Kouwe" few.vu.nl> wrote:
    >> One could still implement copy-on-write using segmentation.
    >> Only, instead of duplicating the pages as they are written, the data
    >> segment needed to be duplicated all at once.
    >> The only problem would be if the parent process wrote something in the
    >> memory immediately after the fork().
    >> (now, thinking about that, it's pretty likely that the parent does
    >> that)


    > In fact, it is absolutely certain that both processes will modify their
    > memory. At some point they will call either exec or exit, which causes
    > the return address to be pushed on the stack which would trigger a copy.


    It is also very common for a program to store the result of fork() in a
    variable, because you have to do two checks against the value: check for
    error and check for parent/child status. The only time I have ever seen a
    program that used an "if (fork()) {....} else {....}" construction (thus
    not using a variable) it caused incorrect program behaviour: the fork
    _did_ fail occasionally and the program could not detect it.... So, I
    think it is safe to say that copy-on-write for the data/stack segment is a
    nice idea but in practice not very useful

    Regards,

    Jens

    --
    Jens de Smit
    Student Computer Science | Vrije Universiteit Amsterdam
    jfdsmit@few.vu.nl | http://www.few.vu.nl/~jfdsmit
    "[In the end, people] get furious at IT that the goddamn magic isn't working"
    -- Stewart Dean

  3. Re: Questions about Minix

    > It is also very common for a program to store the result of fork() in
    > a variable, because you have to do two checks against the value:
    > check for error and check for parent/child status. The only time I
    > have ever seen a program that used an "if (fork()) {....} else
    > {....}" construction (thus not using a variable) it caused incorrect
    > program behaviour: the fork did fail occasionally and the program
    > could not detect it.... So, I think it is safe to say that
    > copy-on-write for the data/stack segment is a nice idea but in
    > practice not very useful


    Storing in a variable is not the same thing as storing in memory. With
    a good compiler and optimization enabled it would be stored in a
    register:



    int run_script()
    {
    pid_t pid;

    if ((pid = fork()) < 0)
    return -1;

    if (!pid)
    {
    execl("/bin/sh", "myscript.sh", NULL);
    exit(1);
    }

    return 0;
    }



    This should produce something like this:



    _run_script:
    call _fork
    test eax, eax
    jns 0f
    mov eax, 0xffffffff
    ret

    0: jnz 1f
    push 0
    push param2
    push param1
    call _execl
    add esp, 12
    push 1
    call _exit
    add esp, 4

    1: xor eax, eax
    ret



    The only time memory writes are needed is to push the parameters and to
    perform the call.

    This suggests, by the way, that it might work if the data and stack
    segments are separate. There may be a good chance that the data segment
    does not get written to by the child.

    --
    With kind regards,
    Erik van der Kouwe

  4. Re: Questions about Minix

    In article <48ae7b6a$0$6019$ba620dc5@text.nova.planet.nl>,
    Erik van der Kouwe wrote:
    >This suggests, by the way, that it might work if the data and stack
    >segments are separate. There may be a good chance that the data segment
    >does not get written to by the child.


    The data segment and the stack segment have to be the same (or you need a
    C compiler that is segment-aware).

    The parent and the child receive different reply messages, so the child's
    data segment is already dirty before fork even returns.


    --
    That was it. Done. The faulty Monk was turned out into the desert where it
    could believe what it liked, including the idea that it had been hard done
    by. It was allowed to keep its horse, since horses were so cheap to make.
    -- Douglas Adams in Dirk Gently's Holistic Detective Agency

  5. Re: Questions about Minix

    "Erik van der Kouwe" few.vu.nl> wrote:
    > Storing in a variable is not the same thing as storing in memory. With
    > a good compiler and optimization enabled it would be stored in a
    > register:




    > This should produce something like this:




    Your statement holds theoretical merit, as it is indeed possible to
    optimize away the memory access by keeping variable pid in a register.
    However, gcc -S produces this assembly code:

    run_script:
    pushl %ebp
    movl %esp, %ebp
    subl $40, %esp
    call fork
    movl %eax, -4(%ebp)
    cmpl $0, -4(%ebp)
    jns .L2
    movl $-1, -20(%ebp)
    jmp .L4
    ..L2:
    cmpl $0, -4(%ebp)
    jne .L5
    movl $0, 8(%esp)
    movl $.LC0, 4(%esp)
    movl $.LC1, (%esp)
    call execl
    movl $1, (%esp)
    call exit
    ..L5:
    movl $0, -20(%ebp)
    ..L4:
    movl -20(%ebp), %eax
    leave
    ret

    You can see right after the "call fork" that the contents of eax (return
    register) are stored 4 bytes under the base pointer, i.e. on the stack.
    I don't have access to a Minix box right here, but I would be highly
    surprised if ACK does this optimization when GCC does not. So, it could be
    done, but you'd need compiler support for it. I still say we go for the
    paging, if we're going to do anything

    Regards,

    Jens

    --
    Jens de Smit
    Student Computer Science | Vrije Universiteit Amsterdam
    jfdsmit@few.vu.nl | http://www.few.vu.nl/~jfdsmit
    "[In the end, people] get furious at IT that the goddamn magic isn't working"
    -- Stewart Dean

  6. Re: Questions about Minix

    > You can see right after the "call fork" that the contents of eax
    > (return register) are stored 4 bytes under the base pointer, i.e. on
    > the stack. I don't have access to a Minix box right here, but I
    > would be highly surprised if ACK does this optimization when GCC does
    > not. So, it could be done, but you'd need compiler support for it.


    Enable optimization (O2) and you'll find that GCC (3.4.3 on Minix)
    output is nearly identical to what I made up:

    _run_script:
    pushl %ebp
    movl %esp, %ebp
    subl $8, %esp
    call _fork
    testl %eax, %eax
    movl $-1, %edx
    jl L1
    je L5
    xorl %edx, %edx
    L1:
    movl %edx, %eax
    leave
    ret
    L5:
    pushl %eax
    pushl $0
    pushl $LC0
    pushl $LC1
    call _execl
    movl $1, (%esp)
    call _exit

    The guest only performs memory accesses to call execl and exit
    (although, as Phillip correctly stated, the implementation of fork
    itself is a problem).

    ACK (also with O2) does indeed do much worse:

    _run_script:
    push ebp
    mov ebp,esp
    sub esp,4
    call _fork
    mov -4(ebp),eax
    test eax,eax
    jns I1_1
    mov eax,-1
    jmp I1_2
    I1_1:
    cmp -4(ebp),0
    jne I1_3
    push 0
    push __II0
    push __II1
    call _execl
    push 1
    call _exit
    add esp,16
    I1_3:
    xor eax,eax
    I1_2:
    leave
    ret

    > I still say we go for the paging, if we're going to do anything


    Yes, I can't wait

    --
    With kind regards,
    Erik van der Kouwe

+ Reply to Thread
Page 2 of 2 FirstFirst 1 2