eebef2a157f535a88e6e8b28d61cd539ebdf99ff
[dragonfly.git] / lib / libc / amd64 / gen / rfork_thread.S
1 /*-
2  * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org>
3  * Copyright (c) 2003 Alan L. Cox <alc@cs.rice.edu>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: src/lib/libc/amd64/gen/rfork_thread.S,v 1.2 2008/11/02 01:10:54 peter Exp $
28  * $DragonFly: src/lib/libc/amd64/gen/rfork_thread.S,v 1.1 2004/02/02 05:43:14 dillon Exp $
29  */
30
31 #include <machine/asm.h>
32
33 /*
34  * With thanks to John Dyson for the original version of this.
35  */
36
37 #include <SYS.h>
38
39 /*
40  *              %edi   %rsi        %rdx       %rcx
41  * rfork_thread(flags, stack_addr, start_fnc, start_arg);
42  *
43  * flags:               Flags to rfork system call.  See rfork(2).
44  * stack_addr:          Top of stack for thread.
45  * start_fnc:           Address of thread function to call in child.
46  * start_arg:           Argument to pass to the thread function in child.
47  */
48
49 ENTRY(rfork_thread)
50         pushq   %rbx
51         pushq   %r12
52         movq    %rdx, %rbx
53         movq    %rcx, %r12
54
55         /*
56          * Prepare and execute the thread creation syscall
57          */
58         movq    $SYS_rfork, %rax
59         KERNCALL
60         jb      2f
61
62         /*
63          * Check to see if we are in the parent or child
64          */
65         cmpl    $0, %edx
66         jnz     1f
67         popq    %r12
68         popq    %rbx
69         ret
70
71         /*
72          * If we are in the child (new thread), then
73          * set-up the call to the internal subroutine.  If it
74          * returns, then call __exit.
75          */
76 1:
77         movq    %rsi, %rsp
78         movq    %r12, %rdi 
79         call    *%rbx
80         movl    %eax, %edi
81
82         /*
83          * Exit system call
84          */
85 #ifdef SYS_exit
86         movq    $SYS_exit, %rax
87 #else
88         movq    $SYS_sys_exit, %rax
89 #endif
90         KERNCALL
91
92         /*
93          * Branch here if the thread creation fails:
94          */
95 2:
96         popq    %r12
97         popq    %rbx
98 #ifdef PIC
99         movq    PIC_GOT(HIDENAME(cerror)), %rdx
100         jmp     *%rdx
101 #else
102         jmp     HIDENAME(cerror)
103 #endif
104 END(rfork_thread)