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.
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.
13 A single runtime instance.
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.
20 The kernel runs until there are no live schedulers.
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
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.
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).
43 #include "rust_globals.h"
48 #include "rust_exchange_alloc.h"
50 #include "rust_sched_reaper.h"
51 #include "rust_type.h"
52 #include "sync/lock_and_signal.h"
55 class rust_sched_driver;
56 class rust_sched_launcher_factory;
57 struct rust_task_thread;
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;
64 typedef std::map<rust_sched_id, rust_scheduler*> sched_map;
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 {
74 rust_exchange_alloc exchange_alloc;
78 rust_task_id max_task_id;
80 lock_and_signal rval_lock;
83 // Protects max_sched_id and sched_table, join_list, killed,
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.
100 rust_sched_reaper sched_reaper;
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;
110 // An atomically updated count of the live, 'non-weak' tasks
111 uintptr_t non_weak_tasks;
113 rust_scheduler* get_scheduler_by_id_nolock(rust_sched_id id);
114 void allow_scheduler_exit();
115 void begin_shutdown();
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;
123 void run_exit_functions();
126 struct rust_env *env;
128 rust_kernel(rust_env *env);
130 void log(uint32_t level, char const *fmt, ...);
131 void fatal(char const *fmt, ...);
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; }
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();
149 rust_task_id generate_task_id();
151 void set_exit_status(int code);
153 rust_sched_id main_sched_id() { return main_scheduler; }
154 rust_sched_id osmain_sched_id() { return osmain_scheduler; }
156 void inc_live_count();
157 void dec_live_count();
159 void register_exit_function(spawn_fn runner, fn_env_pair *f);
162 template <typename T> struct kernel_owned {
163 inline void *operator new(size_t size, rust_kernel *kernel,
165 return kernel->malloc(size, tag);
168 void operator delete(void *ptr) {
169 ((T *)ptr)->kernel->free(ptr);
173 #endif /* RUST_KERNEL_H */
179 // indent-tabs-mode: nil
181 // buffer-file-coding-system: utf-8-unix