File: clone.S

package info (click to toggle)
dietlibc 0.34~cvs20160606-10
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 11,336 kB
  • sloc: ansic: 71,631; asm: 13,006; cpp: 1,860; makefile: 799; sh: 292; perl: 62
file content (103 lines) | stat: -rw-r--r-- 2,304 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <errno.h>
#include "syscalls.h"
#include "arm-features.h"

@
@ Some slightly tricky stuff here... edit with care :-)
@


#ifdef __ARM_EABI__

#define CLONE_VM      0x00000100
#define CLONE_THREAD  0x00010000

@ ;  don't do this yet
@#define RESET_PID

FUNC_START_WEAK	clone
FUNC_START	__clone
	@ ; start with a sanity check
	cmp	r0, #0
	cmpne	r1, #0
	mvneq	r0, #-EINVAL
	beq	__unified_syscall	@ handle as if error was returned by the syscall

	@ ; insert args into stack
	str	r3, [r1, #-4]!
	str	r0, [r1, #-4]!

	@ ; do the system call
	@ ; get the flags
	mov	r0, r2
#ifdef RESET_PID
	mov	ip, r2
#endif
	@ ; child sp is already in r1
	stmfd	sp!, {r4, r7}
	@stmdb	sp!, {r4, r7}
	ldr	r2, [sp, #8]
	ldr	r3, [sp, #12]
	ldr	r4, [sp, #16]
        ldr     r7, =__NR_clone
	swi	0

	cmp	r0, #0
	beq	1f
	ldmfd	sp!, {r4, r7}
	blt	__unified_syscall	@ (return code < 0): handle as an error
	RET
1:
#ifdef RESET_PID
	tst	ip, #CLONE_THREAD
	bne	3f

	mov	r0, #0xffff0fff
	mov	lr, pc
	sub	pc, r0, #31
	mov	r1, r0
	tst	ip, #CLONE_VM
	movne	r0, #-1
        ldr     r7, =__NR_getpid
	swi	0
	str	r0, [r1, #PID_OFFSET] @	; not defined yet ??
	str	r0, [r1, #TID_OFFSET] @	; not defined yet ??
3:
#endif
	@ ; pick the function arg and call address off the stack and execute
	ldr	r0, [sp, #4]
	mov	lr, pc
	ldr	pc, [sp], #8

	@ ; and we're done, passing return value through r0
	b	_exit			@ branch to _exit (PIC safe)
FUNC_END	__clone
FUNC_END	clone

#else

FUNC_START_WEAK	clone
FUNC_START	__clone
	movs	r12, r0			@ check function pointer
	cmpne	r1, #0			@ if function check for stack pointer
	moveq	r0, #-EINVAL		@ if one is not available set errno value
	beq	__unified_syscall	@ handle as if error was returned by the syscall

	stmdb	r1!, { r3, r12 } 	@ store function param (r3) and function ptr (r12)
					@ into what will become the childs stack.

	mov	r0, r2			@ move flags argument to r0
	swi	__NR_clone		@ call the syscall
	movs	r0, r0			@ set condition codes
	blt	__unified_syscall	@ (return code < 0): handle as an error
	movne	pc, lr			@ (return code > 0): return to parent

	mov	fp, #0			@ clear the frame pointer
	adr	lr, 1f			@ setup return address
	ldmia	sp!, { r0, pc } 	@ load function param and jump to thread function

1:	b	_exit			@ branch to _exit (PIC safe)
FUNC_END	__clone
FUNC_END	clone

#endif