Skip to content

Commit f9f8942

Browse files
alexrpandrewrk
authored andcommitted
std.os.linux: Move clone() here and stop exporting it.
1 parent 75f78bf commit f9f8942

13 files changed

+414
-441
lines changed

lib/c.zig

Lines changed: 0 additions & 402 deletions
Large diffs are not rendered by default.

lib/std/os/linux.zig

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,27 @@ pub const socketcall = syscall_bits.socketcall;
6565
pub const syscall_pipe = syscall_bits.syscall_pipe;
6666
pub const syscall_fork = syscall_bits.syscall_fork;
6767

68+
pub fn clone(
69+
func: *const fn (arg: usize) callconv(.C) u8,
70+
stack: usize,
71+
flags: u32,
72+
arg: usize,
73+
ptid: *i32,
74+
tp: usize, // aka tls
75+
ctid: *i32,
76+
) usize {
77+
// Can't directly call a naked function; cast to C calling convention first.
78+
return @as(*const fn (
79+
*const fn (arg: usize) callconv(.C) u8,
80+
usize,
81+
u32,
82+
usize,
83+
*i32,
84+
usize,
85+
*i32,
86+
) callconv(.C) usize, @ptrCast(&syscall_bits.clone))(func, stack, flags, arg, ptid, tp, ctid);
87+
}
88+
6889
pub const ARCH = arch_bits.ARCH;
6990
pub const Elf_Symndx = arch_bits.Elf_Symndx;
7091
pub const F = arch_bits.F;
@@ -77,7 +98,6 @@ pub const Stat = arch_bits.Stat;
7798
pub const VDSO = arch_bits.VDSO;
7899
pub const blkcnt_t = arch_bits.blkcnt_t;
79100
pub const blksize_t = arch_bits.blksize_t;
80-
pub const clone = arch_bits.clone;
81101
pub const dev_t = arch_bits.dev_t;
82102
pub const ino_t = arch_bits.ino_t;
83103
pub const mcontext_t = arch_bits.mcontext_t;

lib/std/os/linux/arm-eabi.zig

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,36 @@ pub fn syscall6(
9898
);
9999
}
100100

101-
const CloneFn = *const fn (arg: usize) callconv(.C) u8;
102-
103-
/// This matches the libc clone function.
104-
pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
101+
pub fn clone() callconv(.Naked) usize {
102+
// __clone(func, stack, flags, arg, ptid, tls, ctid)
103+
// r0, r1, r2, r3, +0, +4, +8
104+
//
105+
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
106+
// r7 r0, r1, r2, r3, r4
107+
asm volatile (
108+
\\ stmfd sp!,{r4,r5,r6,r7}
109+
\\ mov r7,#120 // SYS_clone
110+
\\ mov r6,r3
111+
\\ mov r5,r0
112+
\\ mov r0,r2
113+
\\ and r1,r1,#-16
114+
\\ ldr r2,[sp,#16]
115+
\\ ldr r3,[sp,#20]
116+
\\ ldr r4,[sp,#24]
117+
\\ svc 0
118+
\\ tst r0,r0
119+
\\ beq 1f
120+
\\ ldmfd sp!,{r4,r5,r6,r7}
121+
\\ bx lr
122+
\\
123+
\\1: mov r0,r6
124+
\\ bl 3f
125+
\\2: mov r7,#1 // SYS_exit
126+
\\ svc 0
127+
\\ b 2b
128+
\\3: bx r5
129+
);
130+
}
105131

106132
pub fn restore() callconv(.Naked) noreturn {
107133
switch (@import("builtin").zig_backend) {

lib/std/os/linux/arm64.zig

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,35 @@ pub fn syscall6(
9898
);
9999
}
100100

101-
const CloneFn = *const fn (arg: usize) callconv(.C) u8;
102-
103-
/// This matches the libc clone function.
104-
pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
101+
pub fn clone() callconv(.Naked) usize {
102+
// __clone(func, stack, flags, arg, ptid, tls, ctid)
103+
// x0, x1, w2, x3, x4, x5, x6
104+
//
105+
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
106+
// x8, x0, x1, x2, x3, x4
107+
asm volatile (
108+
\\ // align stack and save func,arg
109+
\\ and x1,x1,#-16
110+
\\ stp x0,x3,[x1,#-16]!
111+
\\
112+
\\ // syscall
113+
\\ uxtw x0,w2
114+
\\ mov x2,x4
115+
\\ mov x3,x5
116+
\\ mov x4,x6
117+
\\ mov x8,#220 // SYS_clone
118+
\\ svc #0
119+
\\
120+
\\ cbz x0,1f
121+
\\ // parent
122+
\\ ret
123+
\\ // child
124+
\\1: ldp x1,x0,[sp],#16
125+
\\ blr x1
126+
\\ mov x8,#93 // SYS_exit
127+
\\ svc #0
128+
);
129+
}
105130

106131
pub const restore = restore_rt;
107132

lib/std/os/linux/mips.zig

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,48 @@ pub fn syscall7(
190190
);
191191
}
192192

193-
const CloneFn = *const fn (arg: usize) callconv(.C) u8;
194-
195-
/// This matches the libc clone function.
196-
pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
193+
pub fn clone() callconv(.Naked) usize {
194+
// __clone(func, stack, flags, arg, ptid, tls, ctid)
195+
// 3, 4, 5, 6, 7, 8, 9
196+
//
197+
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
198+
// 2 4, 5, 6, 7, 8
199+
asm volatile (
200+
\\ # Save function pointer and argument pointer on new thread stack
201+
\\ and $5, $5, -8
202+
\\ subu $5, $5, 16
203+
\\ sw $4, 0($5)
204+
\\ sw $7, 4($5)
205+
\\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid)
206+
\\ move $4, $6
207+
\\ lw $6, 16($sp)
208+
\\ lw $7, 20($sp)
209+
\\ lw $9, 24($sp)
210+
\\ subu $sp, $sp, 16
211+
\\ sw $9, 16($sp)
212+
\\ li $2, 4120 # SYS_clone
213+
\\ syscall
214+
\\ beq $7, $0, 1f
215+
\\ nop
216+
\\ addu $sp, $sp, 16
217+
\\ jr $ra
218+
\\ subu $2, $0, $2
219+
\\1:
220+
\\ beq $2, $0, 1f
221+
\\ nop
222+
\\ addu $sp, $sp, 16
223+
\\ jr $ra
224+
\\ nop
225+
\\1:
226+
\\ lw $25, 0($sp)
227+
\\ lw $4, 4($sp)
228+
\\ jalr $25
229+
\\ nop
230+
\\ move $4, $2
231+
\\ li $2, 4001 # SYS_exit
232+
\\ syscall
233+
);
234+
}
197235

198236
pub fn restore() callconv(.Naked) noreturn {
199237
asm volatile (

lib/std/os/linux/powerpc.zig

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,71 @@ pub fn syscall6(
126126
);
127127
}
128128

129-
const CloneFn = *const fn (arg: usize) callconv(.C) u8;
130-
131-
/// This matches the libc clone function.
132-
pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
129+
pub fn clone() callconv(.Naked) usize {
130+
// __clone(func, stack, flags, arg, ptid, tls, ctid)
131+
// 3, 4, 5, 6, 7, 8, 9
132+
//
133+
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
134+
// 0 3, 4, 5, 6, 7
135+
asm volatile (
136+
\\ # store non-volatile regs r30, r31 on stack in order to put our
137+
\\ # start func and its arg there
138+
\\ stwu 30, -16(1)
139+
\\ stw 31, 4(1)
140+
\\
141+
\\ # save r3 (func) into r30, and r6(arg) into r31
142+
\\ mr 30, 3
143+
\\ mr 31, 6
144+
\\
145+
\\ # create initial stack frame for new thread
146+
\\ clrrwi 4, 4, 4
147+
\\ li 0, 0
148+
\\ stwu 0, -16(4)
149+
\\
150+
\\ #move c into first arg
151+
\\ mr 3, 5
152+
\\ #mr 4, 4
153+
\\ mr 5, 7
154+
\\ mr 6, 8
155+
\\ mr 7, 9
156+
\\
157+
\\ # move syscall number into r0
158+
\\ li 0, 120 # SYS_clone
159+
\\
160+
\\ sc
161+
\\
162+
\\ # check for syscall error
163+
\\ bns+ 1f # jump to label 1 if no summary overflow.
164+
\\ #else
165+
\\ neg 3, 3 #negate the result (errno)
166+
\\ 1:
167+
\\ # compare sc result with 0
168+
\\ cmpwi cr7, 3, 0
169+
\\
170+
\\ # if not 0, jump to end
171+
\\ bne cr7, 2f
172+
\\
173+
\\ #else: we're the child
174+
\\ #call funcptr: move arg (d) into r3
175+
\\ mr 3, 31
176+
\\ #move r30 (funcptr) into CTR reg
177+
\\ mtctr 30
178+
\\ # call CTR reg
179+
\\ bctrl
180+
\\ # mov SYS_exit into r0 (the exit param is already in r3)
181+
\\ li 0, 1
182+
\\ sc
183+
\\
184+
\\ 2:
185+
\\
186+
\\ # restore stack
187+
\\ lwz 30, 0(1)
188+
\\ lwz 31, 4(1)
189+
\\ addi 1, 1, 16
190+
\\
191+
\\ blr
192+
);
193+
}
133194

134195
pub const restore = restore_rt;
135196

lib/std/os/linux/powerpc64.zig

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,51 @@ pub fn syscall6(
126126
);
127127
}
128128

129-
const CloneFn = *const fn (arg: usize) callconv(.C) u8;
130-
131-
/// This matches the libc clone function.
132-
pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
129+
pub fn clone() callconv(.Naked) usize {
130+
// __clone(func, stack, flags, arg, ptid, tls, ctid)
131+
// 3, 4, 5, 6, 7, 8, 9
132+
//
133+
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
134+
// 0 3, 4, 5, 6, 7
135+
asm volatile (
136+
\\ # create initial stack frame for new thread
137+
\\ clrrdi 4, 4, 4
138+
\\ li 0, 0
139+
\\ stdu 0,-32(4)
140+
\\
141+
\\ # save fn and arg to child stack
142+
\\ std 3, 8(4)
143+
\\ std 6, 16(4)
144+
\\
145+
\\ # shuffle args into correct registers and call SYS_clone
146+
\\ mr 3, 5
147+
\\ #mr 4, 4
148+
\\ mr 5, 7
149+
\\ mr 6, 8
150+
\\ mr 7, 9
151+
\\ li 0, 120 # SYS_clone = 120
152+
\\ sc
153+
\\
154+
\\ # if error, negate return (errno)
155+
\\ bns+ 1f
156+
\\ neg 3, 3
157+
\\
158+
\\1:
159+
\\ # if we're the parent, return
160+
\\ cmpwi cr7, 3, 0
161+
\\ bnelr cr7
162+
\\
163+
\\ # we're the child. call fn(arg)
164+
\\ ld 3, 16(1)
165+
\\ ld 12, 8(1)
166+
\\ mtctr 12
167+
\\ bctrl
168+
\\
169+
\\ # call SYS_exit. exit code is already in r3 from fn return value
170+
\\ li 0, 1 # SYS_exit = 1
171+
\\ sc
172+
);
173+
}
133174

134175
pub const restore = restore_rt;
135176

lib/std/os/linux/riscv32.zig

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,40 @@ pub fn syscall6(
9595
);
9696
}
9797

98-
const CloneFn = *const fn (arg: usize) callconv(.C) u8;
99-
100-
pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
98+
pub fn clone() callconv(.Naked) usize {
99+
// __clone(func, stack, flags, arg, ptid, tls, ctid)
100+
// a0, a1, a2, a3, a4, a5, a6
101+
//
102+
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
103+
// a7 a0, a1, a2, a3, a4
104+
asm volatile (
105+
\\ # Save func and arg to stack
106+
\\ addi a1, a1, -8
107+
\\ sw a0, 0(a1)
108+
\\ sw a3, 4(a1)
109+
\\
110+
\\ # Call SYS_clone
111+
\\ mv a0, a2
112+
\\ mv a2, a4
113+
\\ mv a3, a5
114+
\\ mv a4, a6
115+
\\ li a7, 220 # SYS_clone
116+
\\ ecall
117+
\\
118+
\\ beqz a0, 1f
119+
\\ # Parent
120+
\\ ret
121+
\\
122+
\\ # Child
123+
\\1: lw a1, 0(sp)
124+
\\ lw a0, 4(sp)
125+
\\ jalr a1
126+
\\
127+
\\ # Exit
128+
\\ li a7, 93 # SYS_exit
129+
\\ ecall
130+
);
131+
}
101132

102133
pub const restore = restore_rt;
103134

lib/std/os/linux/riscv64.zig

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,40 @@ pub fn syscall6(
9595
);
9696
}
9797

98-
const CloneFn = *const fn (arg: usize) callconv(.C) u8;
99-
100-
pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
98+
pub fn clone() callconv(.Naked) usize {
99+
// __clone(func, stack, flags, arg, ptid, tls, ctid)
100+
// a0, a1, a2, a3, a4, a5, a6
101+
//
102+
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
103+
// a7 a0, a1, a2, a3, a4
104+
asm volatile (
105+
\\ # Save func and arg to stack
106+
\\ addi a1, a1, -16
107+
\\ sd a0, 0(a1)
108+
\\ sd a3, 8(a1)
109+
\\
110+
\\ # Call SYS_clone
111+
\\ mv a0, a2
112+
\\ mv a2, a4
113+
\\ mv a3, a5
114+
\\ mv a4, a6
115+
\\ li a7, 220 # SYS_clone
116+
\\ ecall
117+
\\
118+
\\ beqz a0, 1f
119+
\\ # Parent
120+
\\ ret
121+
\\
122+
\\ # Child
123+
\\1: ld a1, 0(sp)
124+
\\ ld a0, 8(sp)
125+
\\ jalr a1
126+
\\
127+
\\ # Exit
128+
\\ li a7, 93 # SYS_exit
129+
\\ ecall
130+
);
131+
}
101132

102133
pub const restore = restore_rt;
103134

0 commit comments

Comments
 (0)