Project

General

Profile

Statistics
| Branch: | Revision:

root / prex-0.9.0 / usr / lib / posix / process / fork_nommu.c @ 03e9c04a

History | View | Annotate | Download (4.69 KB)

1 03e9c04a Brad Neuman
/*
2
 * Copyright (c) 2006, Kohsuke Ohtani
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. Neither the name of the author nor the names of any co-contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
#include <sys/prex.h>
31
#include <sys/posix.h>
32
#include <sys/signal.h>
33
#include <ipc/proc.h>
34
#include <ipc/fs.h>
35
#include <ipc/ipc.h>
36
37
#include <stddef.h>
38
#include <setjmp.h>
39
#include <errno.h>
40
41
static void __parent_entry(void);
42
static void __child_entry(void);
43
44
static jmp_buf __fork_env;
45
static pid_t __child_pid;
46
static thread_t __parent_thread;
47
48
/*
49
 * vfork() - vfork for No-MMU system.
50
 *
51
 * RETURN VALUE:
52
 *
53
 *  vfork() returns 0 to the child process and return the process
54
 *  ID of the child process to the parent process. Or, -1 will be
55
 *  returned to the parent process if error.
56
 *
57
 * ERRORS:
58
 *
59
 *  EAGAIN
60
 *  ENOMEM
61
 *
62
 * NOTE:
63
 *
64
 *  Since no thread is created by task_create(), thread_create()
65
 *  must be called follwing task_crate(). But, when new thread is
66
 *  created by thread_create(), the stack pointer of new thread is
67
 *  used at thread_create() although the stack image is copied at
68
 *  task_create(). So, the stack pointer must be reset to same
69
 *  address of thread_create() before calling task_create();
70
 *  This is a little tricky...
71
 *
72
 * The new process is an exact copy of the calling process
73
 * except as detailed below:
74
 * - Process IDs are different.
75
 * - tms_* is set to 0.
76
 * - Alarm clock is set to 0.
77
 * - Opend semaphore is inherited.
78
 * - Pending signals are cleared.
79
 *
80
 * - File lock is not inherited.
81
 * - File descriptor is shared.
82
 * - Directory stream is shared.
83
 */
84
pid_t
85
vfork(void)
86
{
87
        struct msg m;
88
        task_t tsk;
89
        thread_t t;
90
        int error, sts, pri;
91
92
        /* Save current stack pointer */
93
        sts = setjmp(__fork_env);
94
        if (sts == 0) {
95
                /*
96
                 * Create new task
97
                 */
98
                if ((error = task_create(task_self(), VM_SHARE, &tsk)) != 0) {
99
                        errno = error;
100
                        return -1;
101
                }
102
                if ((error = thread_create(tsk, &t)) != 0) {
103
                        task_terminate(tsk);
104
                        errno = error;
105
                        return -1;
106
                }
107
                /*
108
                 * Notify to file system server
109
                 */
110
                m.hdr.code = FS_FORK;
111
                m.data[0] = tsk;                /* child task */
112
                if (__posix_call(__fs_obj, &m, sizeof(m), 1) != 0)
113
                        return -1;
114
115
                /*
116
                 * Notify to process server
117
                 */
118
                m.hdr.code = PS_FORK;
119
                m.data[0] = tsk;                /* child task */
120
                m.data[1] = 1;                        /* fork type */
121
                if (__posix_call(__proc_obj, &m, sizeof(m), 1) != 0)
122
                        return -1;
123
                __child_pid = m.data[0];
124
125
                /*
126
                 * Start child task.
127
                 *
128
                 * TODO:
129
                 * In order to synchronize the execution, we change
130
                 * the child's priority to lower value. This ugly hack
131
                 * will be replaced by some other methods...
132
                 */
133
                thread_load(t, __child_entry, NULL);
134
                thread_getpri(t, &pri);
135
                thread_setpri(t, pri + 1);
136
                thread_resume(t);
137
138
                /*
139
                 * Suspend until child process calls exec() or exit()
140
                 */
141
                __parent_thread = thread_self();
142
                task_suspend(task_self());
143
144
        } else if (sts == 1) {
145
                /*
146
                 * Child task
147
                 */
148
                thread_load(__parent_thread, __parent_entry, NULL);
149
                t = thread_self();
150
                thread_getpri(t, &pri);
151
                thread_setpri(t, pri - 1);
152
153
#ifdef _REENTRANT
154
                error = mutex_init(&__sig_lock);
155
#endif
156
                __sig_pending = 0;
157
                thread_yield();
158
                return 0;
159
        }
160
        return __child_pid;
161
}
162
163
static void
164
__parent_entry(void)
165
{
166
167
        longjmp(__fork_env, 2);
168
        /* NOTREACHED */
169
}
170
171
static void
172
__child_entry(void)
173
{
174
175
        longjmp(__fork_env, 1);
176
        /* NOTREACHED */
177
}
178
179
/*
180
 * fork() is not supported on NOMMU system.
181
 */
182
pid_t
183
fork(void)
184
{
185
186
        return ENOSYS;
187
}