diff options
author | Matheus Castanho <msc@linux.ibm.com> | 2020-12-03 14:15:28 -0300 |
---|---|---|
committer | Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> | 2020-12-30 18:26:33 -0300 |
commit | 41f013cef24884604c303435dd1915be2ea5c0e0 (patch) | |
tree | ecbca383796ba7121e14a33f91ec6a5060d5a34d /sysdeps/unix | |
parent | 68ab82f56690ada86ac1e0c46bad06ba189a10ef (diff) | |
download | glibc-41f013cef24884604c303435dd1915be2ea5c0e0.tar.gz glibc-41f013cef24884604c303435dd1915be2ea5c0e0.tar.xz glibc-41f013cef24884604c303435dd1915be2ea5c0e0.zip |
powerpc: Use scv instruction on clone when available
clone already uses r31 to temporarily save input arguments before doing the syscall, so we use a different register to read from the TCB. We can also avoid allocating another stack frame, which is not needed since we can simply extend the usage of the red zone. Tested-by: Lucas A. M. Magalhães <lamm@linux.ibm.com> Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Diffstat (limited to 'sysdeps/unix')
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S index fc496fa671..247e0de68c 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S @@ -38,9 +38,11 @@ ENTRY (__clone) beq- cr0,L(badargs) /* Save some regs in the "red zone". */ + std r28,-32(r1) std r29,-24(r1) std r30,-16(r1) std r31,-8(r1) + cfi_offset(r28,-32) cfi_offset(r29,-24) cfi_offset(r30,-16) cfi_offset(r31,-8) @@ -69,11 +71,26 @@ ENTRY (__clone) /* Do the call. */ li r0,SYS_ify(clone) - DO_CALL_SC + CHECK_SCV_SUPPORT r28 0f + /* This is equivalent to DO_CALL_SCV, but we cannot use the macro here + because it uses CFI directives and we just called cfi_endproc. */ + mflr r9 + std r9,FRAME_LR_SAVE(r1) + scv 0 + ld r9,FRAME_LR_SAVE(r1) + mtlr r9 + + /* Check for child process. */ + /* When using scv, error is indicated by negative r3. */ + cmpdi cr1,r3,0 + b 1f +0: DO_CALL_SC /* Check for child process. */ + /* With sc, error is indicated by cr0.SO. */ cmpdi cr1,r3,0 crandc cr1*4+eq,cr1*4+eq,cr0*4+so +1: bne- cr1,L(parent) /* The '-' is to minimise the race. */ std r2,FRAME_TOC_SAVE(r1) @@ -95,19 +112,29 @@ L(badargs): TAIL_CALL_SYSCALL_ERROR L(parent): + /* Check if scv is available. */ + cmpdi cr1,r28,0 + /* Parent. Restore registers & return. */ + cfi_offset(r28,-32) cfi_offset(r29,-24) cfi_offset(r30,-16) cfi_offset(r31,-8) + ld r28,-32(r1) ld r29,-24(r1) ld r30,-16(r1) ld r31,-8(r1) + cfi_restore(r28) cfi_restore(r29) cfi_restore(r30) cfi_restore(r31) - RET_SC - TAIL_CALL_SYSCALL_ERROR + beq cr1,0f + RET_SCV + b 1f +0: RET_SC +1: TAIL_CALL_SYSCALL_ERROR + END (__clone) |