1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dalvik.system;
18 
19 import java.io.File;
20 
21 /**
22  * Provides hooks for the zygote to call back into the runtime to perform
23  * parent or child specific initialization..
24  *
25  * @hide
26  */
27 public final class ZygoteHooks {
28     private long token;
29 
30     /**
31      * Called by the zygote when starting up. It marks the point when any thread
32      * start should be an error, as only internal daemon threads are allowed there.
33      */
startZygoteNoThreadCreation()34     public static native void startZygoteNoThreadCreation();
35 
36     /**
37      * Called by the zygote when startup is finished. It marks the point when it is
38      * conceivable that threads would be started again, e.g., restarting daemons.
39      */
stopZygoteNoThreadCreation()40     public static native void stopZygoteNoThreadCreation();
41 
42     /**
43      * Called by the zygote prior to every fork. Each call to {@code preFork}
44      * is followed by a matching call to {@link #postForkChild(int, String)} on the child
45      * process and {@link #postForkCommon()} on both the parent and the child
46      * process. {@code postForkCommon} is called after {@code postForkChild} in
47      * the child process.
48      */
preFork()49     public void preFork() {
50         Daemons.stop();
51         waitUntilAllThreadsStopped();
52         token = nativePreFork();
53     }
54 
55     /**
56      * Called by the zygote in the child process after every fork. The debug
57      * flags from {@code debugFlags} are applied to the child process. The string
58      * {@code instructionSet} determines whether to use a native bridge.
59      */
postForkChild(int debugFlags, boolean isSystemServer, String instructionSet)60     public void postForkChild(int debugFlags, boolean isSystemServer, String instructionSet) {
61         nativePostForkChild(token, debugFlags, isSystemServer, instructionSet);
62 
63         Math.setRandomSeedInternal(System.currentTimeMillis());
64     }
65 
66     /**
67      * Called by the zygote in both the parent and child processes after
68      * every fork. In the child process, this method is called after
69      * {@code postForkChild}.
70      */
postForkCommon()71     public void postForkCommon() {
72         Daemons.start();
73     }
74 
nativePreFork()75     private static native long nativePreFork();
nativePostForkChild(long token, int debugFlags, boolean isSystemServer, String instructionSet)76     private static native void nativePostForkChild(long token, int debugFlags,
77                                                    boolean isSystemServer, String instructionSet);
78 
79     /**
80      * We must not fork until we're single-threaded again. Wait until /proc shows we're
81      * down to just one thread.
82      */
waitUntilAllThreadsStopped()83     private static void waitUntilAllThreadsStopped() {
84         File tasks = new File("/proc/self/task");
85         // All Java daemons are stopped already. We're just waiting for their OS counterparts to
86         // finish as well. This shouldn't take much time so spinning is ok here.
87         while (tasks.list().length > 1) {
88           Thread.yield();
89         }
90     }
91 }
92