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,不需实时权限。
亲和性与配置
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 队列
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 原子是否在目标平台无锁须单独确认。