XTOS / OPEN SOURCE REAL-TIME SYSTEMOPEN SOURCE · VERSION 0.9.0 · BUILD FROM SOURCE
文档libxtos-rt

libxtos-rt

Linux 调度、亲和性、锁页内存和单生产者单消费者帧队列。

本页目录

策略与权限

xtos_rt_set_scheduler(policy, priority) 对调用线程执行 sched_setscheduler(0, ...)。

SCHED_OTHER 必须 priority=0;这不是 nice 值。

SCHED_FIFO/RR 通常为 1–99,数值越大静态优先级越高,实际范围用 sched_get_priority_min/max 查询。

不要用它配置 SCHED_DEADLINE;后者使用不同的 sched_setattr 契约。

策略语义前提与错误
SCHED_OTHER普通分时;适合无设备示例,不证明实时延迟。priority=0;仍受系统安全策略。
SCHED_FIFO同优先级不轮转;线程须阻塞或让出,避免占满 CPU。需 CAP_SYS_NICE 或符合 RLIMIT_RTPRIO;不足通常 EPERM。
SCHED_RR同优先级轮转,仍高于普通策略。权限同 FIFO;非法策略或优先级为 EINVAL。

成功返回 0,失败返回 -1。实现先查范围,越界设 EINVAL,再调用 sched_*;errno 也可来自系统调用。容器、CPU cgroup 和安全策略都可能限制配置,即使 uid=0 也要检查。示例用 SCHED_OTHER,不需实时权限。

亲和性与配置

c
struct xtos_rt_config {
    int policy;
    int priority;
    int cpu;
};

int xtos_rt_apply(const struct xtos_rt_config *config);
int xtos_rt_set_scheduler(int policy, int priority);
int xtos_rt_set_affinity(int cpu);
int xtos_rt_get_current(int *policy, int *priority);

cpu 是逻辑 CPU 编号,不是允许列表中的序号。XTOS_RT_NO_CPU(-1)只在 apply 中表示跳过亲和性;直接 set_affinity(-1) 返回 -1/EINVAL。set_affinity 接受 0≤cpu<CPU_SETSIZE,并设置单 CPU 掩码。CPU 离线、超出 cpuset 或无交集时内核可返回 EINVAL;CPU 0 不是可移植默认值。

apply 要求 config 非 NULL,先设调度,再设可选亲和性。

第二步失败时第一步已生效,不自动回滚;需要恢复时保存原策略和亲和性。

get_current 要求两个非 NULL 输出指针,只返回调用线程的策略和静态优先级,不返回亲和性;亲和性另用 sched_getaffinity 读回。

所有配置接口返回 0/-1,SDK 不保存调用方指针。

配置应在真正工作的线程内完成。

锁页内存

接口参数与所有权结果与错误
lock_memory(address,length)address 非 NULL,length 为正字节数且范围有效;调用方拥有内存。0/-1;NULL 或 0 为 EINVAL,其余来自 mlock。
alloc_locked(length)length>0;posix_memalign 页对齐后 mlock;内存未初始化。指针或 NULL;可为 EINVAL、ENOMEM、ENOSYS 或 mlock errno。
free_locked(address,length)只能传 alloc_locked 的原指针和原长度,不能传栈、子区间或已释放指针。先 munlock 后 free;munlock 失败仍释放,返回 -1 后不可重试释放。

mlock 受 RLIMIT_MEMLOCK;CAP_IPC_LOCK 改变权限条件。

超限、未映射或资源不足可为 ENOMEM,策略也可导致 EPERM/EAGAIN。

启动阶段完成分配、清零和访问。

lock_memory 的范围只能用 munlock 解锁;free_locked 不能释放任意地址。

队列内部、线程栈、临时数组和未来分配不会自动锁定。

SPSC 队列

c
struct xtos_sample_frame {
    uint64_t timestamp_ns;
    uint64_t sequence;
    uint32_t channels;
    uint32_t sample_rate_hz;
    uint32_t quality_flags;
    const int32_t *samples_nv;
};

struct xtos_spsc_queue *xtos_spsc_create(size_t capacity, uint32_t channels);
int xtos_spsc_push(struct xtos_spsc_queue *queue,
                   const struct xtos_sample_frame *frame);
int xtos_spsc_pop(struct xtos_spsc_queue *queue,
                  struct xtos_sample_frame *frame,
                  int32_t *samples_nv, size_t samples_capacity);
void xtos_spsc_destroy(struct xtos_spsc_queue *queue);

SPSC 严格要求一个生产者负责全部 push、一个消费者负责全部 pop;单线程顺序调用也合法。多个采集线程不能共用 push,多个处理线程不能共用 pop。head、tail 和槽内容用 acquire/release 发布,没有多生产者或多消费者仲裁。

create 要求 capacity>0、channels>0;capacity 是完整帧数,不是字节数,也不要求 2 的幂。每个槽在创建时分配通道数组;非法值为 EINVAL,分配失败通常为 ENOMEM。运行中的 push/pop 不分配。销毁前必须停止两个端点。push 检查指针非 NULL、channels 一致、timestamp_ns 非零,但不检查时间单调性、sequence 连续性、sample_rate_hz 非零或 quality_flags 含义;samples_nv 至少有 channels 个可读元素。

队列返回与生命周期

情况结果处理
push 成功0;元数据和样本复制进槽。返回后可复用源数组。
push 满-1/EAGAIN;拒绝新帧,不覆盖旧帧。记录丢弃和序号缺口,避免高优先级无限忙等。
push 参数错-1/EINVAL;有效 queue 的 rejected_invalid 增加。修正通道、时间戳或指针。
pop 成功0;samples_capacity≥channels,单位为元素。frame.samples_nv 指向调用方 output。
pop 空/参数错空为 -1/EAGAIN;NULL 或短数组为 -1/EINVAL。失败时不要使用未写入的 frame 或输出。

get_stats 独立读取 pushed、popped、rejected_full、rejected_invalid、overwritten 原子计数,不是跨字段一致快照;当前满队列拒绝实现不增加 overwritten。

NULL stats 静默返回;NULL queue 的 size/capacity 返回 0。

并发 size 不能用于预留槽或同步,以 push/pop 结果为准。

源码和测试为 sdk/libxtos-rt/include/xtos/{rt,spsc}.h、src/{rt,spsc}.c、tests/test_rt.c、tests/test_spsc.c。

C11 原子是否在目标平台无锁须单独确认。