Repository: raspberrypi/pico-sdk
File: src/rp2_common/pico_multicore/multicore.c (C)

Code before:
    do {
        int64_t next_timeout_us = absolute_time_diff_us(get_absolute_time(), until);
        if (next_timeout_us < 0) {
            break;
        }
        multicore_fifo_push_timeout_us(request_id, (uint64_t)next_timeout_us);
        next_timeout_us = absolute_time_diff_us(get_absolute_time(), until);
        if (next_timeout_us < 0) {
            break;
        }
        uint32_t word = 0;
        if (!multicore_fifo_pop_timeout_us((uint64_t)next_timeout_us, &word)) {
            break;
        }
        if (word == request_id) {
            rc = true;
        }
    } while (!rc);
    if (enabled) irq_set_enabled(irq_num, true);
    return rc;
}

static uint32_t update_lockout_request_id() {
    // generate new number and then update shared variable
    uint32_t new_request_id = lockout_request_id + 1;
    lockout_request_id = new_request_id;
    // notify other core
    __sev();
    return new_request_id;
}

static bool multicore_lockout_start_block_until(absolute_time_t until) {
    check_lockout_mutex_init();
    if (!mutex_enter_block_until(&lockout_mutex, until)) {
        return false;
    }
    // generate a new request_id number
    uint32_t request_id = update_lockout_request_id();
    // attempt to lock out
    bool rc = multicore_lockout_handshake(request_id, until);
    if (!rc) {
        // lockout failed - cancel it
        update_lockout_request_id();
    }
    mutex_exit(&lockout_mutex);
    return rc;
}

bool multicore_lockout_start_timeout_us(uint64_t timeout_us) {
    return multicore_lockout_start_block_until(make_timeout_time_us(timeout_us));
}

Review comment (bug):
AFAICT it looks like `lockout_request_id` only gets incremented and never gets decremented - does that mean that theoretically it might eventually overflow?

Code after:
    do {
        int64_t next_timeout_us = absolute_time_diff_us(get_absolute_time(), until);
        if (next_timeout_us < 0) {
            break;
        }
        multicore_fifo_push_timeout_us(request_id, (uint64_t)next_timeout_us);
        next_timeout_us = absolute_time_diff_us(get_absolute_time(), until);
        if (next_timeout_us < 0) {
            break;
        }
        uint32_t word = 0;
        if (!multicore_fifo_pop_timeout_us((uint64_t)next_timeout_us, &word)) {
            break;
        }
        if (word == request_id) {
            rc = true;
        }
    } while (!rc);
    if (enabled) irq_set_enabled(irq_num, true);
    return rc;
}

static uint32_t update_lockout_request_id(void) {
    // generate new number and then update shared variable
    uint32_t new_request_id = lockout_request_id + 1;
    lockout_request_id = new_request_id;
    // notify other core
    __sev();
    return new_request_id;
}

static bool multicore_lockout_start_block_until(absolute_time_t until) {
    check_lockout_mutex_init();
    if (!mutex_enter_block_until(&lockout_mutex, until)) {
        return false;
    }
    // generate a new request_id number
    uint32_t request_id = update_lockout_request_id();
    // attempt to lock out
    bool rc = multicore_lockout_handshake(request_id, until);
    if (!rc) {
        // lockout failed - cancel it
        update_lockout_request_id();
    }
    mutex_exit(&lockout_mutex);
    return rc;
}

bool multicore_lockout_start_timeout_us(uint64_t timeout_us) {
    return multicore_lockout_start_block_until(make_timeout_time_us(timeout_us));
}