]> git.lizzy.rs Git - rust.git/blob - src/rt/rust_kernel.h
91f49662f46f07101e4fe6846d3b812aa179c33b
[rust.git] / src / rt / rust_kernel.h
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11
12 /**
13    A single runtime instance.
14
15    The kernel is primarily responsible for managing the lifetime of
16    schedulers, which in turn run rust tasks. It provides a memory
17    allocator and logging service for use by other runtime components,
18    it creates unique task ids.
19
20    The kernel runs until there are no live schedulers.
21
22    The kernel internally runs an additional, special scheduler called
23    the 'osmain' (or platform) scheduler, which schedules tasks on the
24    thread that is running the kernel (normally the thread on which the
25    C main function was called). This scheduler may be used by Rust
26    code for interacting with platform APIs that insist on being called
27    from the main thread.
28
29    The requirements of the osmain scheduler has resulted in a complex
30    process for creating and running scheduler loops that involves
31    a thing called a 'rust_sched_launcher_factory' whose function I've
32    already forgotten. rust_scheduler is the main scheduler class,
33    and tasks are scheduled on individual threads by rust_sched_loop.
34
35    Ideally all the in-memory Rust state is encapsulated by a kernel
36    instance, but there is still some truly global data in the runtime
37    (like the check claims flag).
38  */
39
40 #ifndef RUST_KERNEL_H
41 #define RUST_KERNEL_H
42
43 #include "rust_globals.h"
44
45 #include <map>
46 #include <vector>
47
48 #include "rust_exchange_alloc.h"
49 #include "rust_log.h"
50 #include "rust_sched_reaper.h"
51 #include "rust_type.h"
52 #include "sync/lock_and_signal.h"
53
54 class rust_scheduler;
55 class rust_sched_driver;
56 class rust_sched_launcher_factory;
57 struct rust_task_thread;
58
59 // Scheduler, task handles. These uniquely identify within a
60 // single kernel instance the objects they represent.
61 typedef intptr_t rust_sched_id;
62 typedef intptr_t rust_task_id;
63
64 typedef std::map<rust_sched_id, rust_scheduler*> sched_map;
65
66 // This is defined as a struct only because we need a single pointer to pass
67 // to the Rust function that runs the at_exit functions
68 struct exit_functions {
69     size_t count;
70     fn_env_pair **start;
71 };
72
73 class rust_kernel {
74     rust_exchange_alloc exchange_alloc;
75     rust_log _log;
76
77     // The next task id
78     rust_task_id max_task_id;
79
80     lock_and_signal rval_lock;
81     int rval;
82
83     // Protects max_sched_id and sched_table, join_list, killed,
84     // already_exiting
85     lock_and_signal sched_lock;
86     // The next scheduler id
87     rust_sched_id max_sched_id;
88     // A map from scheduler ids to schedulers. When this is empty
89     // the kernel terminates
90     sched_map sched_table;
91     // A list of scheduler ids that are ready to exit
92     std::vector<rust_sched_id> join_list;
93     // Whether or not the runtime has to die (triggered when the root/main
94     // task group fails). This propagates to all new schedulers and tasks
95     // created after it is set.
96     bool killed;
97     bool already_exiting;
98
99
100     rust_sched_reaper sched_reaper;
101
102     // The primary scheduler
103     rust_sched_id main_scheduler;
104     // The single-threaded scheduler that uses the main thread
105     rust_sched_id osmain_scheduler;
106     // Runs the single-threaded scheduler that executes tasks
107     // on the main thread
108     rust_sched_driver *osmain_driver;
109
110     // An atomically updated count of the live, 'non-weak' tasks
111     uintptr_t non_weak_tasks;
112
113     rust_scheduler* get_scheduler_by_id_nolock(rust_sched_id id);
114     void allow_scheduler_exit();
115     void begin_shutdown();
116
117     lock_and_signal at_exit_lock;
118     spawn_fn at_exit_runner;
119     bool at_exit_started;
120     std::vector<fn_env_pair*> at_exit_fns;
121     exit_functions final_exit_fns;
122
123     void run_exit_functions();
124
125 public:
126     struct rust_env *env;
127
128     rust_kernel(rust_env *env);
129
130     void log(uint32_t level, char const *fmt, ...);
131     void fatal(char const *fmt, ...);
132
133     void *malloc(size_t size, const char *tag);
134     void *realloc(void *mem, size_t size);
135     void free(void *mem);
136     rust_exchange_alloc *region() { return &exchange_alloc; }
137
138     void fail();
139
140     rust_sched_id create_scheduler(size_t num_threads);
141     rust_sched_id create_scheduler(rust_sched_launcher_factory *launchfac,
142                                    size_t num_threads, bool allow_exit);
143     rust_scheduler* get_scheduler_by_id(rust_sched_id id);
144     // Called by a scheduler to indicate that it is terminating
145     void release_scheduler_id(rust_sched_id id);
146     void wait_for_schedulers();
147     int run();
148
149     rust_task_id generate_task_id();
150
151     void set_exit_status(int code);
152
153     rust_sched_id main_sched_id() { return main_scheduler; }
154     rust_sched_id osmain_sched_id() { return osmain_scheduler; }
155
156     void inc_live_count();
157     void dec_live_count();
158
159     void register_exit_function(spawn_fn runner, fn_env_pair *f);
160 };
161
162 template <typename T> struct kernel_owned {
163     inline void *operator new(size_t size, rust_kernel *kernel,
164                               const char *tag) {
165         return kernel->malloc(size, tag);
166     }
167
168     void operator delete(void *ptr) {
169         ((T *)ptr)->kernel->free(ptr);
170     }
171 };
172
173 #endif /* RUST_KERNEL_H */
174
175 //
176 // Local Variables:
177 // mode: C++
178 // fill-column: 78;
179 // indent-tabs-mode: nil
180 // c-basic-offset: 4
181 // buffer-file-coding-system: utf-8-unix
182 // End:
183 //