Why golang clone syscall abi is diffent from linux kernel clone on x86-642019 Community Moderator ElectionWhat registers are preserved through a linux x86-64 function callDoes golang depend on c runtime?x86 paging in linux kernel with mmuLinux kernel module ABI (x86)Linux Kernel syscall compile errorLinux kernel file read debug syscallReplace linux kernel syscall : Unknown symbol current_kprobeHow to implement another variation of clone(2) syscall in linux kernel?what's the getpid work procedure in glibc?glibc time function implementationwhy golang chose syscall rather than libcAdd syscalls to linux kernel

Deletion of copy-ctor & copy-assignment - public, private or protected?

How can an organ that provides biological immortality be unable to regenerate?

Pronounciation of the combination "st" in spanish accents

How difficult is it to simply disable/disengage the MCAS on Boeing 737 Max 8 & 9 Aircraft?

Calculate the frequency of characters in a string

Probably overheated black color SMD pads

Asserting that Atheism and Theism are both faith based positions

Print a physical multiplication table

Light propagating through a sound wave

Are dual Irish/British citizens bound by the 90/180 day rule when travelling in the EU after Brexit?

How could an airship be repaired midflight?

Existence of a celestial body big enough for early civilization to be thought of as a second moon

Does .bashrc contain syntax errors?

Geography in 3D perspective

What is the term when voters “dishonestly” choose something that they do not want to choose?

Bash - pair each line of file

PTIJ What is the inyan of the Konami code in Uncle Moishy's song?

PTIJ: Why do we blow Shofar on Rosh Hashana and use a Lulav on Sukkos?

Help rendering a complicated sum/product formula

Violin - Can double stops be played when the strings are not next to each other?

Is it true that good novels will automatically sell themselves on Amazon (and so on) and there is no need for one to waste time promoting?

What does "Four-F." mean?

Question on point set topology

What does Jesus mean regarding "Raca," and "you fool?" - is he contrasting them?



Why golang clone syscall abi is diffent from linux kernel clone on x86-64



2019 Community Moderator ElectionWhat registers are preserved through a linux x86-64 function callDoes golang depend on c runtime?x86 paging in linux kernel with mmuLinux kernel module ABI (x86)Linux Kernel syscall compile errorLinux kernel file read debug syscallReplace linux kernel syscall : Unknown symbol current_kprobeHow to implement another variation of clone(2) syscall in linux kernel?what's the getpid work procedure in glibc?glibc time function implementationwhy golang chose syscall rather than libcAdd syscalls to linux kernel










5















The linux kernel clone abi definition at glibc/sysdeps/unix/sysv/linux/x86_64/clone.S:



The kernel expects:
rax: system call number
rdi: flags
rsi: child_stack
rdx: TID field in parent
r10: TID field in child
r8: thread pointer


And the golang clone syscall at go1.11.5/src/runtime/sys_linux_amd64.s:



// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVL flags+0(FP), DI
MOVQ stk+8(FP), SI
MOVQ $0, DX
MOVQ $0, R10

// Copy mp, gp, fn off parent stack for use by child.
// Careful: Linux system call clobbers CX and R11.
MOVQ mp+16(FP), R8
MOVQ gp+24(FP), R9
MOVQ fn+32(FP), R12

MOVL $SYS_clone, AX
SYSCALL


So why DX, R10, R8 do not keep to clone-syscall promise?
At the other hand, R9 and R12 seems to be needless.



Please help me.










share|improve this question



















  • 2





    What is your goal?

    – mkrieger1
    Feb 26 at 18:15











  • I want to know why runtime.clone traped successfully. It goes against "kernel expects" obviously.

    – api
    Feb 26 at 22:25











  • Go doesn't use glibc.

    – peterSO
    Feb 26 at 23:21











  • Yes, go runtime.clone invokes syscall as glibc.

    – api
    Feb 27 at 1:52






  • 1





    @peterSO It's more "yes or no—it depends" situation. OP included source code where dependencies to glibc are defined and asked why they were definded this way and not another

    – Alex Yu
    Mar 6 at 16:55















5















The linux kernel clone abi definition at glibc/sysdeps/unix/sysv/linux/x86_64/clone.S:



The kernel expects:
rax: system call number
rdi: flags
rsi: child_stack
rdx: TID field in parent
r10: TID field in child
r8: thread pointer


And the golang clone syscall at go1.11.5/src/runtime/sys_linux_amd64.s:



// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVL flags+0(FP), DI
MOVQ stk+8(FP), SI
MOVQ $0, DX
MOVQ $0, R10

// Copy mp, gp, fn off parent stack for use by child.
// Careful: Linux system call clobbers CX and R11.
MOVQ mp+16(FP), R8
MOVQ gp+24(FP), R9
MOVQ fn+32(FP), R12

MOVL $SYS_clone, AX
SYSCALL


So why DX, R10, R8 do not keep to clone-syscall promise?
At the other hand, R9 and R12 seems to be needless.



Please help me.










share|improve this question



















  • 2





    What is your goal?

    – mkrieger1
    Feb 26 at 18:15











  • I want to know why runtime.clone traped successfully. It goes against "kernel expects" obviously.

    – api
    Feb 26 at 22:25











  • Go doesn't use glibc.

    – peterSO
    Feb 26 at 23:21











  • Yes, go runtime.clone invokes syscall as glibc.

    – api
    Feb 27 at 1:52






  • 1





    @peterSO It's more "yes or no—it depends" situation. OP included source code where dependencies to glibc are defined and asked why they were definded this way and not another

    – Alex Yu
    Mar 6 at 16:55













5












5








5


3






The linux kernel clone abi definition at glibc/sysdeps/unix/sysv/linux/x86_64/clone.S:



The kernel expects:
rax: system call number
rdi: flags
rsi: child_stack
rdx: TID field in parent
r10: TID field in child
r8: thread pointer


And the golang clone syscall at go1.11.5/src/runtime/sys_linux_amd64.s:



// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVL flags+0(FP), DI
MOVQ stk+8(FP), SI
MOVQ $0, DX
MOVQ $0, R10

// Copy mp, gp, fn off parent stack for use by child.
// Careful: Linux system call clobbers CX and R11.
MOVQ mp+16(FP), R8
MOVQ gp+24(FP), R9
MOVQ fn+32(FP), R12

MOVL $SYS_clone, AX
SYSCALL


So why DX, R10, R8 do not keep to clone-syscall promise?
At the other hand, R9 and R12 seems to be needless.



Please help me.










share|improve this question
















The linux kernel clone abi definition at glibc/sysdeps/unix/sysv/linux/x86_64/clone.S:



The kernel expects:
rax: system call number
rdi: flags
rsi: child_stack
rdx: TID field in parent
r10: TID field in child
r8: thread pointer


And the golang clone syscall at go1.11.5/src/runtime/sys_linux_amd64.s:



// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVL flags+0(FP), DI
MOVQ stk+8(FP), SI
MOVQ $0, DX
MOVQ $0, R10

// Copy mp, gp, fn off parent stack for use by child.
// Careful: Linux system call clobbers CX and R11.
MOVQ mp+16(FP), R8
MOVQ gp+24(FP), R9
MOVQ fn+32(FP), R12

MOVL $SYS_clone, AX
SYSCALL


So why DX, R10, R8 do not keep to clone-syscall promise?
At the other hand, R9 and R12 seems to be needless.



Please help me.







linux go






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 2 at 16:27







api

















asked Feb 26 at 18:12









apiapi

504




504







  • 2





    What is your goal?

    – mkrieger1
    Feb 26 at 18:15











  • I want to know why runtime.clone traped successfully. It goes against "kernel expects" obviously.

    – api
    Feb 26 at 22:25











  • Go doesn't use glibc.

    – peterSO
    Feb 26 at 23:21











  • Yes, go runtime.clone invokes syscall as glibc.

    – api
    Feb 27 at 1:52






  • 1





    @peterSO It's more "yes or no—it depends" situation. OP included source code where dependencies to glibc are defined and asked why they were definded this way and not another

    – Alex Yu
    Mar 6 at 16:55












  • 2





    What is your goal?

    – mkrieger1
    Feb 26 at 18:15











  • I want to know why runtime.clone traped successfully. It goes against "kernel expects" obviously.

    – api
    Feb 26 at 22:25











  • Go doesn't use glibc.

    – peterSO
    Feb 26 at 23:21











  • Yes, go runtime.clone invokes syscall as glibc.

    – api
    Feb 27 at 1:52






  • 1





    @peterSO It's more "yes or no—it depends" situation. OP included source code where dependencies to glibc are defined and asked why they were definded this way and not another

    – Alex Yu
    Mar 6 at 16:55







2




2





What is your goal?

– mkrieger1
Feb 26 at 18:15





What is your goal?

– mkrieger1
Feb 26 at 18:15













I want to know why runtime.clone traped successfully. It goes against "kernel expects" obviously.

– api
Feb 26 at 22:25





I want to know why runtime.clone traped successfully. It goes against "kernel expects" obviously.

– api
Feb 26 at 22:25













Go doesn't use glibc.

– peterSO
Feb 26 at 23:21





Go doesn't use glibc.

– peterSO
Feb 26 at 23:21













Yes, go runtime.clone invokes syscall as glibc.

– api
Feb 27 at 1:52





Yes, go runtime.clone invokes syscall as glibc.

– api
Feb 27 at 1:52




1




1





@peterSO It's more "yes or no—it depends" situation. OP included source code where dependencies to glibc are defined and asked why they were definded this way and not another

– Alex Yu
Mar 6 at 16:55





@peterSO It's more "yes or no—it depends" situation. OP included source code where dependencies to glibc are defined and asked why they were definded this way and not another

– Alex Yu
Mar 6 at 16:55












1 Answer
1






active

oldest

votes


















5





+100









Reason why DX and R10 are zero



According to the manpage of clone, these are used only when CLONE_PARENT_SETTID, CLONE_CHILD_SETTID is set.




CLONE_PARENT_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ptid in the parent's
memory. (In Linux 2.5.32-2.5.48 there was a flag CLONE_SETTID
that did this.) The store operation completes before clone()
returns control to user space.



CLONE_CHILD_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ctid in the child's
memory. The store operation completes before clone() returns
control to user space.




DX and R10 corresponds to ptid and ctid in this manpage (Reference).



Actually, this flag is not set when calling runtime.clone() from os_linux.go: Source.



The reason they don't need tid is maybe because it's not a library such as pthread which user does something complicated using tid.



What R8, R9, and R12 are used for



In short, R8, R9 and R12 are not used by system call but used to construct the stack after it.



Note that R8 and R9 are passed as argument to system call, but not used by clone (see the reason below), and R12 is preserved after system call, it is safe to use these registers after system call. (Reference)



Let's see the detail.



internally runtime.clone is called as follows: Source



func newosproc(mp *m) 
stk := unsafe.Pointer(mp.g0.stack.hi)
....
ret := clone(cloneFlags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart)))
....



Reading Quick Guide to Go's Assembler, and the code OP posted, you can see that R8 is pointer to mp, and R9 is pointer to mp.g0 and R12 is pointer to some function which you want to call in the cloneed thread. (structure of m and g looks like this: Source and this: Source
).



R8 is argument to clone which indicates tls(thread local storage), but it is not used unless CLONE_SETTLS is set: Source



R9 is generally used as 6th argument to system call, but clone does not use it because it only uses 5 arguments(Source).



R12 is a register which is preserved after system call.



So finally let's see the source of runtime.clone. The important thing is after the SYSCALL. They are doing some stack setup using R8 and R9 in the child thread which is created, and finally calling R12.



// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVL flags+0(FP), DI
MOVQ stk+8(FP), SI
MOVQ $0, DX
MOVQ $0, R10

// Copy mp, gp, fn off parent stack for use by child.
// Careful: Linux system call clobbers CX and R11.
MOVQ mp+16(FP), R8
MOVQ gp+24(FP), R9
MOVQ fn+32(FP), R12

MOVL $SYS_clone, AX
SYSCALL

// In parent, return.
CMPQ AX, $0
JEQ 3(PC)
MOVL AX, ret+40(FP)
RET

// In child, on new stack.
MOVQ SI, SP

// If g or m are nil, skip Go-related setup.
CMPQ R8, $0 // m
JEQ nog
CMPQ R9, $0 // g
JEQ nog

// Initialize m->procid to Linux tid
MOVL $SYS_gettid, AX
SYSCALL
MOVQ AX, m_procid(R8)

// Set FS to point at m->tls.
LEAQ m_tls(R8), DI
CALL runtime·settls(SB)

// In child, set up new stack
get_tls(CX)
MOVQ R8, g_m(R9)
MOVQ R9, g(CX)
CALL runtime·stackcheck(SB)

nog:
// Call fn
CALL R12

//(omitted)





share|improve this answer

























  • I had a hope that OP will return. But we have only 2 days left and I think your answer is correct. So: reward for you!

    – Alex Yu
    Mar 12 at 3:18











  • I return, a little surprise, i thought nobody will care this post. Now i make it clear that R8, R9, R12 is not for raw clone syscall but for passing parameters to child. This also enhanced my understanding about "The raw clone() system call corresponds more closely to fork(2)". Thanks.

    – api
    Mar 13 at 18:30











  • @api I'm glad that you checked answer yourself and cleared my doubts, because I myself wrote asm many years ago. "i thought nobody will care this post" - there are people exists who thinks that this question is very good

    – Alex Yu
    Mar 14 at 15:35











  • @AlexYu stackoverflow is a marvelous place :)

    – api
    Mar 14 at 17:08










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54891678%2fwhy-golang-clone-syscall-abi-is-diffent-from-linux-kernel-clone-on-x86-64%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









5





+100









Reason why DX and R10 are zero



According to the manpage of clone, these are used only when CLONE_PARENT_SETTID, CLONE_CHILD_SETTID is set.




CLONE_PARENT_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ptid in the parent's
memory. (In Linux 2.5.32-2.5.48 there was a flag CLONE_SETTID
that did this.) The store operation completes before clone()
returns control to user space.



CLONE_CHILD_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ctid in the child's
memory. The store operation completes before clone() returns
control to user space.




DX and R10 corresponds to ptid and ctid in this manpage (Reference).



Actually, this flag is not set when calling runtime.clone() from os_linux.go: Source.



The reason they don't need tid is maybe because it's not a library such as pthread which user does something complicated using tid.



What R8, R9, and R12 are used for



In short, R8, R9 and R12 are not used by system call but used to construct the stack after it.



Note that R8 and R9 are passed as argument to system call, but not used by clone (see the reason below), and R12 is preserved after system call, it is safe to use these registers after system call. (Reference)



Let's see the detail.



internally runtime.clone is called as follows: Source



func newosproc(mp *m) 
stk := unsafe.Pointer(mp.g0.stack.hi)
....
ret := clone(cloneFlags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart)))
....



Reading Quick Guide to Go's Assembler, and the code OP posted, you can see that R8 is pointer to mp, and R9 is pointer to mp.g0 and R12 is pointer to some function which you want to call in the cloneed thread. (structure of m and g looks like this: Source and this: Source
).



R8 is argument to clone which indicates tls(thread local storage), but it is not used unless CLONE_SETTLS is set: Source



R9 is generally used as 6th argument to system call, but clone does not use it because it only uses 5 arguments(Source).



R12 is a register which is preserved after system call.



So finally let's see the source of runtime.clone. The important thing is after the SYSCALL. They are doing some stack setup using R8 and R9 in the child thread which is created, and finally calling R12.



// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVL flags+0(FP), DI
MOVQ stk+8(FP), SI
MOVQ $0, DX
MOVQ $0, R10

// Copy mp, gp, fn off parent stack for use by child.
// Careful: Linux system call clobbers CX and R11.
MOVQ mp+16(FP), R8
MOVQ gp+24(FP), R9
MOVQ fn+32(FP), R12

MOVL $SYS_clone, AX
SYSCALL

// In parent, return.
CMPQ AX, $0
JEQ 3(PC)
MOVL AX, ret+40(FP)
RET

// In child, on new stack.
MOVQ SI, SP

// If g or m are nil, skip Go-related setup.
CMPQ R8, $0 // m
JEQ nog
CMPQ R9, $0 // g
JEQ nog

// Initialize m->procid to Linux tid
MOVL $SYS_gettid, AX
SYSCALL
MOVQ AX, m_procid(R8)

// Set FS to point at m->tls.
LEAQ m_tls(R8), DI
CALL runtime·settls(SB)

// In child, set up new stack
get_tls(CX)
MOVQ R8, g_m(R9)
MOVQ R9, g(CX)
CALL runtime·stackcheck(SB)

nog:
// Call fn
CALL R12

//(omitted)





share|improve this answer

























  • I had a hope that OP will return. But we have only 2 days left and I think your answer is correct. So: reward for you!

    – Alex Yu
    Mar 12 at 3:18











  • I return, a little surprise, i thought nobody will care this post. Now i make it clear that R8, R9, R12 is not for raw clone syscall but for passing parameters to child. This also enhanced my understanding about "The raw clone() system call corresponds more closely to fork(2)". Thanks.

    – api
    Mar 13 at 18:30











  • @api I'm glad that you checked answer yourself and cleared my doubts, because I myself wrote asm many years ago. "i thought nobody will care this post" - there are people exists who thinks that this question is very good

    – Alex Yu
    Mar 14 at 15:35











  • @AlexYu stackoverflow is a marvelous place :)

    – api
    Mar 14 at 17:08















5





+100









Reason why DX and R10 are zero



According to the manpage of clone, these are used only when CLONE_PARENT_SETTID, CLONE_CHILD_SETTID is set.




CLONE_PARENT_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ptid in the parent's
memory. (In Linux 2.5.32-2.5.48 there was a flag CLONE_SETTID
that did this.) The store operation completes before clone()
returns control to user space.



CLONE_CHILD_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ctid in the child's
memory. The store operation completes before clone() returns
control to user space.




DX and R10 corresponds to ptid and ctid in this manpage (Reference).



Actually, this flag is not set when calling runtime.clone() from os_linux.go: Source.



The reason they don't need tid is maybe because it's not a library such as pthread which user does something complicated using tid.



What R8, R9, and R12 are used for



In short, R8, R9 and R12 are not used by system call but used to construct the stack after it.



Note that R8 and R9 are passed as argument to system call, but not used by clone (see the reason below), and R12 is preserved after system call, it is safe to use these registers after system call. (Reference)



Let's see the detail.



internally runtime.clone is called as follows: Source



func newosproc(mp *m) 
stk := unsafe.Pointer(mp.g0.stack.hi)
....
ret := clone(cloneFlags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart)))
....



Reading Quick Guide to Go's Assembler, and the code OP posted, you can see that R8 is pointer to mp, and R9 is pointer to mp.g0 and R12 is pointer to some function which you want to call in the cloneed thread. (structure of m and g looks like this: Source and this: Source
).



R8 is argument to clone which indicates tls(thread local storage), but it is not used unless CLONE_SETTLS is set: Source



R9 is generally used as 6th argument to system call, but clone does not use it because it only uses 5 arguments(Source).



R12 is a register which is preserved after system call.



So finally let's see the source of runtime.clone. The important thing is after the SYSCALL. They are doing some stack setup using R8 and R9 in the child thread which is created, and finally calling R12.



// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVL flags+0(FP), DI
MOVQ stk+8(FP), SI
MOVQ $0, DX
MOVQ $0, R10

// Copy mp, gp, fn off parent stack for use by child.
// Careful: Linux system call clobbers CX and R11.
MOVQ mp+16(FP), R8
MOVQ gp+24(FP), R9
MOVQ fn+32(FP), R12

MOVL $SYS_clone, AX
SYSCALL

// In parent, return.
CMPQ AX, $0
JEQ 3(PC)
MOVL AX, ret+40(FP)
RET

// In child, on new stack.
MOVQ SI, SP

// If g or m are nil, skip Go-related setup.
CMPQ R8, $0 // m
JEQ nog
CMPQ R9, $0 // g
JEQ nog

// Initialize m->procid to Linux tid
MOVL $SYS_gettid, AX
SYSCALL
MOVQ AX, m_procid(R8)

// Set FS to point at m->tls.
LEAQ m_tls(R8), DI
CALL runtime·settls(SB)

// In child, set up new stack
get_tls(CX)
MOVQ R8, g_m(R9)
MOVQ R9, g(CX)
CALL runtime·stackcheck(SB)

nog:
// Call fn
CALL R12

//(omitted)





share|improve this answer

























  • I had a hope that OP will return. But we have only 2 days left and I think your answer is correct. So: reward for you!

    – Alex Yu
    Mar 12 at 3:18











  • I return, a little surprise, i thought nobody will care this post. Now i make it clear that R8, R9, R12 is not for raw clone syscall but for passing parameters to child. This also enhanced my understanding about "The raw clone() system call corresponds more closely to fork(2)". Thanks.

    – api
    Mar 13 at 18:30











  • @api I'm glad that you checked answer yourself and cleared my doubts, because I myself wrote asm many years ago. "i thought nobody will care this post" - there are people exists who thinks that this question is very good

    – Alex Yu
    Mar 14 at 15:35











  • @AlexYu stackoverflow is a marvelous place :)

    – api
    Mar 14 at 17:08













5





+100







5





+100



5




+100





Reason why DX and R10 are zero



According to the manpage of clone, these are used only when CLONE_PARENT_SETTID, CLONE_CHILD_SETTID is set.




CLONE_PARENT_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ptid in the parent's
memory. (In Linux 2.5.32-2.5.48 there was a flag CLONE_SETTID
that did this.) The store operation completes before clone()
returns control to user space.



CLONE_CHILD_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ctid in the child's
memory. The store operation completes before clone() returns
control to user space.




DX and R10 corresponds to ptid and ctid in this manpage (Reference).



Actually, this flag is not set when calling runtime.clone() from os_linux.go: Source.



The reason they don't need tid is maybe because it's not a library such as pthread which user does something complicated using tid.



What R8, R9, and R12 are used for



In short, R8, R9 and R12 are not used by system call but used to construct the stack after it.



Note that R8 and R9 are passed as argument to system call, but not used by clone (see the reason below), and R12 is preserved after system call, it is safe to use these registers after system call. (Reference)



Let's see the detail.



internally runtime.clone is called as follows: Source



func newosproc(mp *m) 
stk := unsafe.Pointer(mp.g0.stack.hi)
....
ret := clone(cloneFlags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart)))
....



Reading Quick Guide to Go's Assembler, and the code OP posted, you can see that R8 is pointer to mp, and R9 is pointer to mp.g0 and R12 is pointer to some function which you want to call in the cloneed thread. (structure of m and g looks like this: Source and this: Source
).



R8 is argument to clone which indicates tls(thread local storage), but it is not used unless CLONE_SETTLS is set: Source



R9 is generally used as 6th argument to system call, but clone does not use it because it only uses 5 arguments(Source).



R12 is a register which is preserved after system call.



So finally let's see the source of runtime.clone. The important thing is after the SYSCALL. They are doing some stack setup using R8 and R9 in the child thread which is created, and finally calling R12.



// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVL flags+0(FP), DI
MOVQ stk+8(FP), SI
MOVQ $0, DX
MOVQ $0, R10

// Copy mp, gp, fn off parent stack for use by child.
// Careful: Linux system call clobbers CX and R11.
MOVQ mp+16(FP), R8
MOVQ gp+24(FP), R9
MOVQ fn+32(FP), R12

MOVL $SYS_clone, AX
SYSCALL

// In parent, return.
CMPQ AX, $0
JEQ 3(PC)
MOVL AX, ret+40(FP)
RET

// In child, on new stack.
MOVQ SI, SP

// If g or m are nil, skip Go-related setup.
CMPQ R8, $0 // m
JEQ nog
CMPQ R9, $0 // g
JEQ nog

// Initialize m->procid to Linux tid
MOVL $SYS_gettid, AX
SYSCALL
MOVQ AX, m_procid(R8)

// Set FS to point at m->tls.
LEAQ m_tls(R8), DI
CALL runtime·settls(SB)

// In child, set up new stack
get_tls(CX)
MOVQ R8, g_m(R9)
MOVQ R9, g(CX)
CALL runtime·stackcheck(SB)

nog:
// Call fn
CALL R12

//(omitted)





share|improve this answer















Reason why DX and R10 are zero



According to the manpage of clone, these are used only when CLONE_PARENT_SETTID, CLONE_CHILD_SETTID is set.




CLONE_PARENT_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ptid in the parent's
memory. (In Linux 2.5.32-2.5.48 there was a flag CLONE_SETTID
that did this.) The store operation completes before clone()
returns control to user space.



CLONE_CHILD_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ctid in the child's
memory. The store operation completes before clone() returns
control to user space.




DX and R10 corresponds to ptid and ctid in this manpage (Reference).



Actually, this flag is not set when calling runtime.clone() from os_linux.go: Source.



The reason they don't need tid is maybe because it's not a library such as pthread which user does something complicated using tid.



What R8, R9, and R12 are used for



In short, R8, R9 and R12 are not used by system call but used to construct the stack after it.



Note that R8 and R9 are passed as argument to system call, but not used by clone (see the reason below), and R12 is preserved after system call, it is safe to use these registers after system call. (Reference)



Let's see the detail.



internally runtime.clone is called as follows: Source



func newosproc(mp *m) 
stk := unsafe.Pointer(mp.g0.stack.hi)
....
ret := clone(cloneFlags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart)))
....



Reading Quick Guide to Go's Assembler, and the code OP posted, you can see that R8 is pointer to mp, and R9 is pointer to mp.g0 and R12 is pointer to some function which you want to call in the cloneed thread. (structure of m and g looks like this: Source and this: Source
).



R8 is argument to clone which indicates tls(thread local storage), but it is not used unless CLONE_SETTLS is set: Source



R9 is generally used as 6th argument to system call, but clone does not use it because it only uses 5 arguments(Source).



R12 is a register which is preserved after system call.



So finally let's see the source of runtime.clone. The important thing is after the SYSCALL. They are doing some stack setup using R8 and R9 in the child thread which is created, and finally calling R12.



// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVL flags+0(FP), DI
MOVQ stk+8(FP), SI
MOVQ $0, DX
MOVQ $0, R10

// Copy mp, gp, fn off parent stack for use by child.
// Careful: Linux system call clobbers CX and R11.
MOVQ mp+16(FP), R8
MOVQ gp+24(FP), R9
MOVQ fn+32(FP), R12

MOVL $SYS_clone, AX
SYSCALL

// In parent, return.
CMPQ AX, $0
JEQ 3(PC)
MOVL AX, ret+40(FP)
RET

// In child, on new stack.
MOVQ SI, SP

// If g or m are nil, skip Go-related setup.
CMPQ R8, $0 // m
JEQ nog
CMPQ R9, $0 // g
JEQ nog

// Initialize m->procid to Linux tid
MOVL $SYS_gettid, AX
SYSCALL
MOVQ AX, m_procid(R8)

// Set FS to point at m->tls.
LEAQ m_tls(R8), DI
CALL runtime·settls(SB)

// In child, set up new stack
get_tls(CX)
MOVQ R8, g_m(R9)
MOVQ R9, g(CX)
CALL runtime·stackcheck(SB)

nog:
// Call fn
CALL R12

//(omitted)






share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 6 at 22:09

























answered Mar 6 at 20:09









ymonadymonad

7,6261836




7,6261836












  • I had a hope that OP will return. But we have only 2 days left and I think your answer is correct. So: reward for you!

    – Alex Yu
    Mar 12 at 3:18











  • I return, a little surprise, i thought nobody will care this post. Now i make it clear that R8, R9, R12 is not for raw clone syscall but for passing parameters to child. This also enhanced my understanding about "The raw clone() system call corresponds more closely to fork(2)". Thanks.

    – api
    Mar 13 at 18:30











  • @api I'm glad that you checked answer yourself and cleared my doubts, because I myself wrote asm many years ago. "i thought nobody will care this post" - there are people exists who thinks that this question is very good

    – Alex Yu
    Mar 14 at 15:35











  • @AlexYu stackoverflow is a marvelous place :)

    – api
    Mar 14 at 17:08

















  • I had a hope that OP will return. But we have only 2 days left and I think your answer is correct. So: reward for you!

    – Alex Yu
    Mar 12 at 3:18











  • I return, a little surprise, i thought nobody will care this post. Now i make it clear that R8, R9, R12 is not for raw clone syscall but for passing parameters to child. This also enhanced my understanding about "The raw clone() system call corresponds more closely to fork(2)". Thanks.

    – api
    Mar 13 at 18:30











  • @api I'm glad that you checked answer yourself and cleared my doubts, because I myself wrote asm many years ago. "i thought nobody will care this post" - there are people exists who thinks that this question is very good

    – Alex Yu
    Mar 14 at 15:35











  • @AlexYu stackoverflow is a marvelous place :)

    – api
    Mar 14 at 17:08
















I had a hope that OP will return. But we have only 2 days left and I think your answer is correct. So: reward for you!

– Alex Yu
Mar 12 at 3:18





I had a hope that OP will return. But we have only 2 days left and I think your answer is correct. So: reward for you!

– Alex Yu
Mar 12 at 3:18













I return, a little surprise, i thought nobody will care this post. Now i make it clear that R8, R9, R12 is not for raw clone syscall but for passing parameters to child. This also enhanced my understanding about "The raw clone() system call corresponds more closely to fork(2)". Thanks.

– api
Mar 13 at 18:30





I return, a little surprise, i thought nobody will care this post. Now i make it clear that R8, R9, R12 is not for raw clone syscall but for passing parameters to child. This also enhanced my understanding about "The raw clone() system call corresponds more closely to fork(2)". Thanks.

– api
Mar 13 at 18:30













@api I'm glad that you checked answer yourself and cleared my doubts, because I myself wrote asm many years ago. "i thought nobody will care this post" - there are people exists who thinks that this question is very good

– Alex Yu
Mar 14 at 15:35





@api I'm glad that you checked answer yourself and cleared my doubts, because I myself wrote asm many years ago. "i thought nobody will care this post" - there are people exists who thinks that this question is very good

– Alex Yu
Mar 14 at 15:35













@AlexYu stackoverflow is a marvelous place :)

– api
Mar 14 at 17:08





@AlexYu stackoverflow is a marvelous place :)

– api
Mar 14 at 17:08



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54891678%2fwhy-golang-clone-syscall-abi-is-diffent-from-linux-kernel-clone-on-x86-64%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

1928 у кіно

Захаров Федір Захарович

Ель Греко