pub(crate) unsafe fn allocate_alarm(&self, priority: Priority) -> Option<AlarmHandle> {
        unsafe {
            for (i, alarm) in self.alarms.iter().enumerate() {
                let handle = alarm.inner.with(|alarm| {
                    let AlarmState::Created(interrupt_handler) = alarm.state else {
                        return None;
                    };

                    let timer = self.available_timers.with(|available_timers| {
                        if let Some(timers) = available_timers.take() {
                            // If the driver is initialized, we can allocate a timer.
                            // If this fails, we can't do anything about it.
                            let Some((timer, rest)) = timers.split_first_mut() else {
                                not_enough_timers();
                            };
                            *available_timers = Some(rest);
                            timer
                        } else {
                            panic!("schedule_wake called before esp_hal_embassy::init()")
                        }
                    });

                    alarm.state = AlarmState::initialize(
                        timer,
                        InterruptHandler::new(interrupt_handler, priority),
                    );

                    Some(AlarmHandle::new(i))
                });

                if handle.is_some() {
                    return handle;
                }
            }

            None
        }
    }
Allocate an alarm, if possible.

Returns `None` if there are no available alarms.

When using multiple timer queues, the `priority` parameter indicates the
priority of the interrupt handler. It is 1 for thread-mode
executors, or equals to the priority of an interrupt executor.

When using a single timer queue, the `priority` parameter is always the
highest value possible.
esp-hal-embassy/src/time_driver.rs