1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#![no_std]

extern crate alloc;

pub mod application;
pub mod schedulers;

#[macro_export]
macro_rules! kernel
{
  (
    name: $kernel_name:ident,
    instance: $kernel_instance:ident,
    main_arguments: ( $($main_arg_name:ident : $main_arg_type:ty),+ $(,)? ),
    devices: { $($dev_name:ident : $dev_type:ty => ($($dev_create_arg:tt)*) / ($($dev_init_arg:tt)*)),+ $(,)? },
    stdout: $stdout_name:expr,
    scheduler: $scheduler_type:ty => ($($scheduler_args:tt)*),
    applications: { $($app_name:ident : $app_type:ty => ($($app_create_arg:tt)*)),+ $(,)? }
  ) => (
    pub struct Kernel
    {
      $(pub $dev_name: spin::Mutex<$dev_type>,)+
      pub scheduler: spin::Mutex<$scheduler_type>,
    }

    lazy_static! {
      pub static ref $kernel_instance: Kernel = Kernel {
        $($dev_name: spin::Mutex::new(<$dev_type>::new($($dev_create_arg)*)),)+
        scheduler: spin::Mutex::new(<$scheduler_type>::new($($scheduler_args)*)),
      };
    }

    fn $kernel_name($($main_arg_name: $main_arg_type,)+) -> !
    {
      $($kernel_instance.$dev_name.lock().initialise($($dev_init_arg)*);)+
      $kernel_instance.scheduler.lock().initialise();
      mango_hal::io::STDOUT.lock().set_device(
        |x| {
          if let Some(dev) = $stdout_name
          {
            dev.lock().write_str(x)
          } else {
            Ok(())
          }
        });
      $(let mut $app_name = <$app_type>::new($($app_create_arg)*);)+
      $($app_name.start();)+

      $kernel_instance.scheduler.lock().run();
    }
  );
}