Repository: raspberrypi/pico-sdk
File: src/rp2_common/pico_stdio_usb/stdio_usb.c (C)

Code before:
    int64_t repeat_time;
    if (critical_section_is_initialized(&one_shot_timer_crit_sec)) {
        critical_section_enter_blocking(&one_shot_timer_crit_sec);
        one_shot_timer_pending = false;
        critical_section_exit(&one_shot_timer_crit_sec);
        repeat_time = 0; // don't repeat
    } else {
        repeat_time = PICO_STDIO_USB_TASK_INTERVAL_US;
    }
    if (irq_is_enabled(low_priority_irq_num)) {
        irq_set_pending(low_priority_irq_num);
        return repeat_time;
    } else {
        return 0; // don't repeat
    }
}

static void low_priority_worker_irq(void) {
    if (mutex_try_enter(&stdio_usb_mutex, NULL)) {
        tud_task();
#if PICO_STDIO_USB_SUPPORT_CHARS_AVAILABLE_CALLBACK
        uint32_t chars_avail = tud_cdc_available();
#endif
        mutex_exit(&stdio_usb_mutex);
#if PICO_STDIO_USB_SUPPORT_CHARS_AVAILABLE_CALLBACK
        if (chars_avail && chars_available_callback) stdio_usb_run_chars_available_callback();
#endif
    } else {
        // if the mutex is already owned, then we are in non IRQ code in this file.
        //
        // it would seem simplest to just let that code call tud_task() at the end, however this
        // code might run during the call to tud_task() and we might miss a necessary tud_task() call
        //
        // if we are using a periodic timer (crit_sec is not initialized in this case),
        // then we are happy just to wait until the next tick, however when we are not using a periodic timer,
        // we must kick off a one-shot timer to make sure the tud_task() DOES run (this method
        // will be called again as a result, and will try the mutex_try_enter again, and if that fails
        // create another one shot timer again, and so on).
        if (critical_section_is_initialized(&one_shot_timer_crit_sec)) {
            bool need_timer;
            critical_section_enter_blocking(&one_shot_timer_crit_sec);
            need_timer = !one_shot_timer_pending;
            one_shot_timer_pending = true;
            critical_section_exit(&one_shot_timer_crit_sec);
            if (need_timer) {
                add_alarm_in_us(PICO_STDIO_USB_TASK_INTERVAL_US, timer_task, NULL, true);
            }
        }
    }
}


Review comment (suggestion):
I think i'd revert this line... no point in calling another method here (which also checks `chars_avail_callback` - id just call it directly to save introduction of the new function (which likely isn't otherwise called when this code is included

Code after:
    int64_t repeat_time;
    if (critical_section_is_initialized(&one_shot_timer_crit_sec)) {
        critical_section_enter_blocking(&one_shot_timer_crit_sec);
        one_shot_timer_pending = false;
        critical_section_exit(&one_shot_timer_crit_sec);
        repeat_time = 0; // don't repeat
    } else {
        repeat_time = PICO_STDIO_USB_TASK_INTERVAL_US;
    }
    if (irq_is_enabled(low_priority_irq_num)) {
        irq_set_pending(low_priority_irq_num);
        return repeat_time;
    } else {
        return 0; // don't repeat
    }
}

static void low_priority_worker_irq(void) {
    if (mutex_try_enter(&stdio_usb_mutex, NULL)) {
        tud_task();
#if PICO_STDIO_USB_SUPPORT_CHARS_AVAILABLE_CALLBACK
        uint32_t chars_avail = tud_cdc_available();
#endif
        mutex_exit(&stdio_usb_mutex);
#if PICO_STDIO_USB_SUPPORT_CHARS_AVAILABLE_CALLBACK
        if (chars_avail && chars_available_callback) chars_available_callback(chars_available_param);
#endif
    } else {
        // if the mutex is already owned, then we are in non IRQ code in this file.
        //
        // it would seem simplest to just let that code call tud_task() at the end, however this
        // code might run during the call to tud_task() and we might miss a necessary tud_task() call
        //
        // if we are using a periodic timer (crit_sec is not initialized in this case),
        // then we are happy just to wait until the next tick, however when we are not using a periodic timer,
        // we must kick off a one-shot timer to make sure the tud_task() DOES run (this method
        // will be called again as a result, and will try the mutex_try_enter again, and if that fails
        // create another one shot timer again, and so on).
        if (critical_section_is_initialized(&one_shot_timer_crit_sec)) {
            bool need_timer;
            critical_section_enter_blocking(&one_shot_timer_crit_sec);
            need_timer = !one_shot_timer_pending;
            one_shot_timer_pending = true;
            critical_section_exit(&one_shot_timer_crit_sec);
            if (need_timer) {
                add_alarm_in_us(PICO_STDIO_USB_TASK_INTERVAL_US, timer_task, NULL, true);
            }
        }
    }
}