菜单

Cobalt/Task management services

详细描述

处理抢占式多任务的服务。

每个 Alchemy 任务都是整体应用代码的独立部分,体现为一个 C 过程,在其自己的堆栈上下文中执行。


函数文档

rt_task_bind

int rt_task_bind (RT_TASK *task, const char *name, RTIME timeout);

绑定到任务。

此例程创建一个新的描述符,以引用由其符号名称标识的现有 Alchemy 任务。如果在进入时对象不存在,调用者可能会阻塞,直到创建具有给定名称的任务。

参数

  • task: 由操作填充的任务描述符的地址。失败时此内存的内容未定义。
  • name: 一个有效的以 NULL 结尾的名称,用于标识要绑定的任务。此字符串应与传递给 rt_task_create() 或 rt_task_shadow() 的对象名称参数匹配。
  • timeout: 等待注册发生的时钟滴答数(参见注释)。传递 TM_INFINITE 会导致调用者无限期阻塞,直到对象注册。传递 TM_NONBLOCK 会导致服务在进入时对象未注册的情况下立即返回而不等待。

返回值

成功时返回零。否则:

  • 如果在检索完成之前为当前任务调用了 rt_task_unblock(),则返回 -EINTR
  • 如果 timeout 等于 TM_NONBLOCK 且在进入时未注册搜索的对象,则返回 -EWOULDBLOCK
  • 如果在指定时间内无法检索到对象,则返回 -ETIMEDOUT
  • 如果此服务应阻塞,但不是从 Xenomai 线程调用的,则返回 -EPERM

标签

xthread-nowait, switch-primary

注释

超时值被解释为 Alchemy 时钟分辨率的倍数(参见 --alchemy-clock-resolution 选项,默认为 1 纳秒)。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    RT_TASK current_task;
    RT_TASK_INFO info;

    printf("This is a Demo Task\n");

    // 通过TASK_NAME绑定到描述符
    if (rt_task_bind(&current_task, TASK_NAME, TM_INFINITE)) {
        printf("Error creating sender task\n");
        return;
    }

    // 使用描述符
    int ret = rt_task_inquire(&current_task,&info);
    if(ret == 0){
        printf("Get task info:\n");
        printf("    name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
    }else{
        printf("Error while inquire task: %d\n", ret);
    }

    // 解除绑定
    rt_task_unbind(&current_task);
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_create

int rt_task_create (RT_TASK *task, const char *name, int stksize, int prio, int mode);

创建具有 Alchemy 特性的任务。

此服务创建一个可以访问完整 Alchemy 服务集的任务。如果 prio 非零,新任务属于 Xenomai 的实时 FIFO 调度类,即 SCHED_FIFO。如果 prio 为零,任务属于常规的 SCHED_OTHER 类。

创建优先级为零的任务对于运行可能调用阻塞实时服务的非实时进程非常有用,例如等待信号量、从消息队列或缓冲区读取等。

一旦创建,任务将保持休眠状态,直到通过 rt_task_start() 实际启动。

参数

  • task: 任务描述符的地址,成功调用后可用于唯一标识创建的对象。
  • name: 代表任务符号名称的 ASCII 字符串。当非 NULL 且非空时,此字符串的副本将用于将创建的任务索引到对象注册表中。
  • stksize: 新任务的堆栈大小(以字节为单位)。如果传递零,将替换为系统依赖的默认大小。
  • prio: 新任务的基本优先级。此值必须在 [0 .. 99] 范围内,其中 0 是最低有效优先级。
  • mode: 任务创建模式。以下标志可以 OR 进此位掩码:
    • T_JOINABLE 允许另一个任务等待新任务的终止。rt_task_join() 应在此任务终止后调用以清理任何资源。
    • T_LOCK 使新任务在进入由 rt_task_start() 指定的用户例程之前锁定调度程序。需要从新任务调用 rt_task_set_mode() 以解除此锁定。
    • 在 Cobalt 核心上运行时,T_WARNSW 使当前任务每次切换到次级模式时发送 SIGDEBUG 信号。此功能对于检测不希望的迁移到 Linux 域非常有用。此标志在 Mercury 核心上无效。

返回值

成功时返回零。否则:

  • 如果 prio、mode 或 stksize 无效,则返回 -EINVAL
  • 如果系统无法从主堆中获取内存以创建任务,则返回 -ENOMEM
  • 如果名称与已注册的任务冲突,则返回 -EEXIST
  • 如果从无效上下文(例如中断或非 Xenomai 线程)调用此服务,则返回 -EPERM

标签

xthread-only, mode-unrestricted, switch-secondary

副作用

  • 在 Cobalt 核心上运行时:
    • 调用 rt_task_create() 会导致 SCHED_FIFO 任务切换到次级模式。
    • 在主域中运行的 Xenomai 的 SCHED_FIFO 类成员在系统中具有最高优先级,优先于所有 Linux 活动,包括 Linux 中断处理程序。
  • 在 Mercury 核心上运行时,新任务属于常规 POSIX SCHED_FIFO 类。

注意

多个属于同一 Xenomai 会话的进程可以引用任务。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    printf("This is a Demo Task\n");
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_delete

int rt_task_delete (RT_TASK *task);

删除实时任务。

此调用终止先前由 rt_task_create() 创建的任务。

使用 T_JOINABLE 标志创建的任务在成功删除后应通过后续调用 rt_task_join() 来回收所有资源。

参数

  • task: 任务描述符。

返回值

成功时返回零。否则:

  • 如果 task 不是有效的任务描述符,则返回 -EINVAL
  • 如果 task 为 NULL 且此服务从无效上下文调用,则返回 -EPERM。此外,当此服务从异步上下文(例如定时器/报警处理程序)调用时,总是会引发此错误。

标签

mode-unrestricted, switch-secondary

注意

如果 task 为 NULL,则调用者必须是 Alchemy 任务。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    printf("This is a Demo Task\n");
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_inquire

int rt_task_inquire (RT_TASK *task, RT_TASK_INFO *info);

检索实时任务的信息。

返回有关 Alchemy 任务的各种信息。此服务也可用于探测任务是否存在。

参数

  • task: 任务描述符。如果 task 为 NULL,则返回当前任务的信息。
  • info: 将写入任务信息的结构体地址。传递 NULL 是有效的,在这种情况下,系统仅探测指定任务的存在性。

返回值

如果任务存在,则返回零。此外,如果 info 非 NULL,则填充任务信息。否则:

  • 如果 task 不是有效的任务描述符,或 prio 无效,则返回 -EINVAL
  • 如果 task 为 NULL 且此服务从无效上下文调用,则返回 -EPERM

标签

mode-unrestricted, switch-primary

注意

如果 task 为 NULL,则调用者必须是 Alchemy 任务。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    int ret;
    RT_TASK_INFO info;

    printf("This is a Demo Task\n");
    ret = rt_task_inquire(&demo_task_desc,&info);
    if(ret == 0){
        printf("Get task info:\n");
        printf("    name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
    }else{
        printf("Error while inquire task: %d\n", ret);
    }

}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_join

int rt_task_join (RT_TASK *task);

等待实时任务的终止。

此服务在非实时上下文中阻塞调用者,直到任务终止。成功完成此服务后,所有资源将被释放。

指定的任务必须由希望加入它的同一进程创建,并且在调用 rt_task_create() 时必须设置 T_JOINABLE 模式标志。

使用 T_JOINABLE 标志创建的任务在成功删除后应通过后续调用 rt_task_join() 来回收所有资源。

参数

  • task: 任务描述符。

返回值

成功时返回零。否则:

  • 如果 task 不是有效的任务描述符,则返回 -EINVAL
  • 如果任务在创建时未设置 T_JOINABLE 或其他任务已在等待其终止,则返回 -EINVAL
  • 如果 task 引用调用者自身,则返回 -EDEADLK
  • 如果 task 不再存在或引用由不同进程创建的任务,则返回 -ESRCH

标签

mode-unrestricted, switch-primary

注意

成功完成此服务后,不需要也不应再对同一任务调用 rt_task_delete()。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    printf("This is a Demo Task\n");
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_receive

ssize_t rt_task_receive (RT_TASK_MCB *mcb_r, RTIME timeout);

从实时任务接收消息(具有相对标量超时)。

此例程是 rt_task_receive_timed() 的变体,接受以标量值表示的相对超时规范。

参数

  • mcb_r: 指向消息控制块的地址,该块引用接收消息区域。
  • timeout: 以时钟滴答表示的延迟。传递 TM_INFINITE 会导致调用者无限期阻塞,直到远程任务最终发送消息。传递 TM_NONBLOCK 会导致服务在没有远程任务等待发送消息时立即返回而不等待。

标签

xthread-only, switch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"

RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;

void receiver_task(void *arg)
{
    RT_TASK_MCB mcb_r;
    char buffer[100];
    int ret;

    mcb_r.data = buffer;
    mcb_r.size = sizeof(buffer);

    while (cycle_time) {
        printf("Receiver: Waiting for a message...\n");
        ret = rt_task_receive(&mcb_r, TM_INFINITE);
        if (ret > 0) {
            printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
            rt_task_reply(ret, NULL);  // 发送空回复
        } else {
            printf("Receiver: Error receiving message, code: %d\n", ret);
        }
    }
}

void sender_task(void *arg)
{
    RT_TASK_MCB mcb_s;
    char message[] = "Hello from sender!";
    int ret;

    while (cycle_time--) {
        rt_task_sleep(1000000000);  // 睡眠1秒

        mcb_s.data = message;
        mcb_s.size = sizeof(message);

        printf("Sender: Sending message...\n");
        ret = rt_task_send(&receiver_task_desc, &mcb_s, NULL, TM_INFINITE);
        if (ret >= 0) {
            printf("Sender: Message sent successfully\n");
        } else {
            printf("Sender: Error sending message, code: %d\n", ret);
        }
    }
}

int main(int argc, char *argv[])
{
    // 创建接受任务
    if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating receiver task\n");
        return 1;
    }

    // 创建发送任务
    if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&receiver_task_desc, &receiver_task, NULL);
    rt_task_start(&sender_task_desc, &sender_task, NULL);

    // 等待任务结束
    rt_task_join(&receiver_task_desc);
    rt_task_join(&sender_task_desc);

    // 清理
    rt_task_delete(&receiver_task_desc);
    rt_task_delete(&sender_task_desc);

    return 0;
}

rt_task_receive_timed

int rt_task_receive_timed (RT_TASK_MCB *mcb_r, const struct timespec *abs_timeout);

从实时任务接收消息。

此服务是 Alchemy 任务可用的同步消息传递支持的一部分。调用者从另一个任务接收可变大小的消息。发送方被阻塞,直到调用者调用 rt_task_reply() 完成事务。

基本消息控制块用于存储从客户端接收数据区域的位置和大小,以及用户定义的操作码。

参数

  • mcb_r: 指向消息控制块的地址,该块引用接收消息区域。此控制块的字段应设置如下:

    • mcb_r->data 应包含足够大的缓冲区地址,以收集远程任务发送的数据;
    • mcb_r->size 应包含 mcb_r->data 指向的缓冲区空间的字节大小。如果 mcb_r->size 小于接收消息的实际大小,则不会进行数据复制,并返回 -ENOBUFS 给调用者。参见注意事项。
    • 返回时,mcb_r->opcode 将包含远程任务使用 rt_task_send() 发送的操作码。
  • abs_timeout: 基于 Alchemy 时钟,以秒/纳秒表示的绝对时间,指定等待接收消息的时间限制。传递 NULL 会导致调用者无限期阻塞,直到远程任务最终发送消息。传递 {.tv_sec = 0, .tv_nsec = 0} 会导致服务立即返回而不等待,如果当前没有远程任务等待发送消息。

返回值

成功时返回一个严格正值,表示打开事务的流标识符;此令牌应传递给 rt_task_reply(),以便发送回复并适当地解除远程任务的阻塞。否则:

  • 如果从无效上下文调用此服务,则返回 -EPERM
  • 如果在接收消息之前调用了 rt_task_unblock(),则返回 -EINTR
  • 如果 mcb_r 不指向足够大的消息区域以收集远程任务的消息,则返回 -ENOBUFS
  • 如果 abs_timeout 为 {.tv_sec = 0, .tv_nsec = 0} 且当前没有远程任务等待发送消息给调用者,则返回 -EWOULDBLOCK
  • 如果在超时时间内未收到消息,则返回 -ETIMEDOUT

标签

xthread-only, switch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"

RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;

void receiver_task(void *arg)
{
    RT_TASK_MCB mcb_r;
    char buffer[100];
    int ret;
    struct timespec ts;

    mcb_r.data = buffer;
    mcb_r.size = sizeof(buffer);

    while (cycle_time) {
        printf("Receiver: Waiting for a message...\n");
        clock_gettime(CLOCK_MONOTONIC, &ts);
        ts.tv_sec += 2;  // 超时时间 2 秒
        ret = rt_task_receive_timed(&mcb_r, &ts);
        if (ret > 0) {
            printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
            rt_task_reply(ret, NULL);  // 发送空回复
        } else if(ret == -ETIMEDOUT) {
            printf("Receiver: Timeout while waiting for message.\n");
        } else {
            printf("Receiver: Error receiving message, code: %d\n", ret);
        }
    }
}

void sender_task(void *arg)
{
    RT_TASK_MCB mcb_s;
    char message[] = "Hello from sender!";
    int ret;
    struct timespec ts;

    while (cycle_time--) {
        if(cycle_time == 2)
        {
            rt_task_sleep(2000000000);  // 睡眠2秒,触发接受超时
        }
        rt_task_sleep(1000000000);  // 睡眠1秒

        mcb_s.data = message;
        mcb_s.size = sizeof(message);

        printf("Sender: Sending message...\n");
        clock_gettime(CLOCK_MONOTONIC, &ts);
        ts.tv_sec += 2;  // 超时时间 2 秒
        ret = rt_task_send_timed(&receiver_task_desc, &mcb_s, NULL, &ts);
        if (ret >= 0) {
            printf("Sender: Message sent successfully\n");
        } else if(ret == -ETIMEDOUT) {
            printf("Sender: Timeout while waiting for Reply.\n");
        } else {
            printf("Sender: Error sending message, code: %d\n", ret);
        }
    }
}

int main(int argc, char *argv[])
{
    // 创建接受任务
    if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating receiver task\n");
        return 1;
    }

    // 创建发送任务
    if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&receiver_task_desc, &receiver_task, NULL);
    rt_task_start(&sender_task_desc, &sender_task, NULL);

    // 等待任务结束
    rt_task_join(&receiver_task_desc);
    rt_task_join(&sender_task_desc);

    // 清理
    rt_task_delete(&receiver_task_desc);
    rt_task_delete(&sender_task_desc);

    return 0;
}

rt_task_receive_until

ssize_t rt_task_receive_until (RT_TASK_MCB *mcb_r, RTIME abs_timeout);

从实时任务接收消息(具有绝对标量超时)。

此例程是 rt_task_receive_timed() 的变体,接受以标量值表示的绝对超时规范。

参数

  • mcb_r: 指向消息控制块的地址,该块引用接收消息区域。
  • abs_timeout: 以时钟滴答表示的绝对时间。传递 TM_INFINITE 会导致调用者无限期阻塞,直到远程任务最终发送消息。传递 TM_NONBLOCK 会导致服务在没有远程任务等待发送消息时立即返回而不等待。

标签

xthread-only, switch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"

RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;

void receiver_task(void *arg)
{
    RT_TASK_MCB mcb_r;
    char buffer[100];
    int ret;
    RTIME timeout;

    mcb_r.data = buffer;
    mcb_r.size = sizeof(buffer);

    while (cycle_time) {
        printf("Receiver: Waiting for a message...\n");
        timeout = rt_timer_read() + 2000000000;  // 超时时间 2 秒
        ret = rt_task_receive_until(&mcb_r, timeout);
        if (ret > 0) {
            printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
            rt_task_reply(ret, NULL);  // 发送空回复
        } else if(ret == -ETIMEDOUT) {
            printf("Receiver: Timeout while waiting for message.\n");
        } else {
            printf("Receiver: Error receiving message, code: %d\n", ret);
        }
    }
}

void sender_task(void *arg)
{
    RT_TASK_MCB mcb_s;
    char message[] = "Hello from sender!";
    int ret;
    RTIME timeout;

    while (cycle_time--) {
        if(cycle_time == 2)
        {
            rt_task_sleep(2000000000);  // 睡眠2秒,触发接受超时
        }
        rt_task_sleep(1000000000);  // 睡眠1秒

        mcb_s.data = message;
        mcb_s.size = sizeof(message);

        printf("Sender: Sending message...\n");
        timeout = rt_timer_read() + 2000000000;  // 超时时间 2 秒
        ret = rt_task_send_until(&receiver_task_desc, &mcb_s, NULL, timeout);
        if (ret >= 0) {
            printf("Sender: Message sent successfully\n");
        } else if(ret == -ETIMEDOUT) {
            printf("Sender: Timeout while waiting for Reply.\n");
        } else {
            printf("Sender: Error sending message, code: %d\n", ret);
        }
    }
}

int main(int argc, char *argv[])
{
    // 创建接受任务
    if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating receiver task\n");
        return 1;
    }

    // 创建发送任务
    if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&receiver_task_desc, &receiver_task, NULL);
    rt_task_start(&sender_task_desc, &sender_task, NULL);

    // 等待任务结束
    rt_task_join(&receiver_task_desc);
    rt_task_join(&sender_task_desc);

    // 清理
    rt_task_delete(&receiver_task_desc);
    rt_task_delete(&sender_task_desc);

    return 0;
}

rt_task_reply

int rt_task_reply (int flowid, RT_TASK_MCB *mcb_s);

回复远程任务消息。

此服务是 Alchemy 任务可用的同步消息传递支持的一部分。调用者将可变大小的消息发送回远程任务,以响应通过调用 rt_task_receive() 接收到的初始消息。调用 rt_task_reply() 的结果是,远程任务将从 rt_task_send() 服务中解除阻塞。

基本消息控制块用于存储要发送回的数据区域的位置和大小,以及用户定义的状态码。

参数

  • flowid: 由先前调用 rt_task_receive() 返回的流标识符,唯一标识当前事务。
  • mcb_s: 指向可选消息控制块的地址,该块引用要发送回的消息。如果 mcb_s 为 NULL,远程任务将被解除阻塞而不会收到任何回复数据。当 mcb_s 有效时,此控制块的字段应设置如下:
    • mcb_s->data: 应包含要发送到远程任务的有效负载数据的地址。
    • mcb_s->size: 应包含 mcb_s->data 指向的有效负载数据的字节大小。零是合法值,表示不会传输任何有效负载数据。
    • mcb_s->opcode: 是在消息传输过程中携带的不透明状态码,调用者可以填充任何适当的值。它将通过 rt_task_send() 服务按原样提供给远程任务的状态码字段。如果 mcb_s 为 NULL,零将返回给远程任务的状态码字段。

返回值

成功时返回零。否则:

  • 如果 flowid 无效,则返回 -EINVAL
  • 如果 flowid 与当前任务最近一次调用 rt_task_receive() 返回的标识符不匹配,或者远程任务在此期间停止等待回复(例如,远程任务可能已被删除或被强制解除阻塞),则返回 -ENXIO
  • 如果 mcb_s 引用的回复数据大于远程任务调用 rt_task_send() 时提到的回复区域,则返回 -ENOBUFS。在这种情况下,远程任务在从 rt_task_send() 返回时也会收到 -ENOBUFS
  • 如果从无效上下文调用此服务,则返回 -EPERM

标签

xthread-only, switch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"

RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;

void receiver_task(void *arg)
{
    RT_TASK_MCB mcb_r;
    char buffer[100];
    int ret;

    mcb_r.data = buffer;
    mcb_r.size = sizeof(buffer);

    while (cycle_time) {
        printf("Receiver: Waiting for a message...\n");
        ret = rt_task_receive(&mcb_r, TM_INFINITE);
        if (ret > 0) {
            printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
            rt_task_reply(ret, NULL);  // 发送空回复
        } else {
            printf("Receiver: Error receiving message, code: %d\n", ret);
        }
    }
}

void sender_task(void *arg)
{
    RT_TASK_MCB mcb_s;
    char message[] = "Hello from sender!";
    int ret;

    while (cycle_time--) {
        rt_task_sleep(1000000000);  // 睡眠1秒

        mcb_s.data = message;
        mcb_s.size = sizeof(message);

        printf("Sender: Sending message...\n");
        ret = rt_task_send(&receiver_task_desc, &mcb_s, NULL, TM_INFINITE);
        if (ret >= 0) {
            printf("Sender: Message sent successfully\n");
        } else {
            printf("Sender: Error sending message, code: %d\n", ret);
        }
    }
}

int main(int argc, char *argv[])
{
    // 创建接受任务
    if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating receiver task\n");
        return 1;
    }

    // 创建发送任务
    if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&receiver_task_desc, &receiver_task, NULL);
    rt_task_start(&sender_task_desc, &sender_task, NULL);

    // 等待任务结束
    rt_task_join(&receiver_task_desc);
    rt_task_join(&sender_task_desc);

    // 清理
    rt_task_delete(&receiver_task_desc);
    rt_task_delete(&sender_task_desc);

    return 0;
}

rt_task_resume

int rt_task_resume (RT_TASK *task);

恢复实时任务。

强制恢复先前通过调用 rt_task_suspend() 挂起的任务的执行,如果挂起嵌套计数递减到零。

参数

  • task: 任务描述符。

返回值

成功时返回零。否则:

  • 如果 task 不是有效的任务描述符,则返回 -EINVAL

标签

unrestricted, switch-primary

注意

阻塞和挂起的任务状态是累积的。因此,恢复当前正在等待同步对象(例如信号量、队列)的任务不会使其有资格进行调度,直到最终获取到等待的资源或超时。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    printf("This is a Demo Task\n");
    rt_task_suspend(&demo_task_desc);
    printf("Demo Task Continue to run\n");
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务运行
    rt_task_sleep(1000000000); // 1 秒
    rt_task_resume(&demo_task_desc);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_same

int rt_task_same (RT_TASK *task1, RT_TASK *task2);

比较实时任务描述符。

如果 task1 和 task2 引用相同的任务,则此谓词返回 true。

参数

  • task1: 要比较的第一个任务描述符。
  • task2: 要比较的第二个任务描述符。

返回值

如果两个描述符引用相同的任务,则返回非零值,否则返回零。

标签

unrestricted

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME_1 "Demo1"
#define TASK_NAME_2 "Demo2"

RT_TASK demo_task_desc_1, demo_task_desc_2;

void demo_task(void *arg)
{
    printf("This is a Demo Task\n");
    rt_task_sleep(1000000000);
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc_1, TASK_NAME_1, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }
    if (rt_task_create(&demo_task_desc_2, TASK_NAME_2, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc_1, &demo_task, NULL);
    rt_task_start(&demo_task_desc_2, &demo_task, NULL);

    if(rt_task_same(&demo_task_desc_1,&demo_task_desc_2))
    {
        printf("Both tasks are the same\n");
    }else{
        printf("The two tasks are different\n");
    }

    RT_TASK same_of_desc_1;
    if (rt_task_bind(&same_of_desc_1,TASK_NAME_1,TM_INFINITE)) {
        printf("Error bind to TASK_NAME_1\n");
        return 1;
    }
    if(rt_task_same(&demo_task_desc_1,&same_of_desc_1))
    {
        printf("Both tasks are the same\n");
    }else{
        printf("The two tasks are different\n");
    }

    // 等待任务结束
    rt_task_join(&demo_task_desc_1);
    rt_task_join(&demo_task_desc_2);

    // 清理
    rt_task_delete(&demo_task_desc_1);
    rt_task_delete(&demo_task_desc_2);
    return 0;
}

rt_task_self

RT_TASK* rt_task_self (void);

检索当前任务描述符。

返回当前 Alchemy 任务描述符的地址。

返回值

成功时返回引用当前 Alchemy 任务的任务描述符地址,如果不是从有效的 Alchemy 任务上下文调用,则返回 NULL。

标签

xthread-only

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    int ret;
    RT_TASK_INFO info;
    RT_TASK* current_task;

    printf("This is a Demo Task\n");
    current_task = rt_task_self();

    ret = rt_task_inquire(current_task,&info);
    if(ret == 0){
        printf("Get task info:\n");
        printf("    name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
    }else{
        printf("Error while inquire task: %d\n", ret);
    }

}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_send

ssize_t rt_task_send (RT_TASK *task, RT_TASK_MCB *mcb_s, RT_TASK_MCB *mcb_r, RTIME timeout);

向实时任务发送消息(具有相对标量超时)。

此例程是 rt_task_send_timed() 的变体,接受以标量值表示的相对超时规范。

参数

  • task: 任务描述符。
  • mcb_s: 指向消息控制块的地址,该块引用要发送的消息。
  • mcb_r: 指向可选消息控制块的地址,该块引用回复消息区域。
  • timeout: 以时钟滴答表示的延迟。传递 TM_INFINITE 会导致调用者无限期阻塞,直到收到回复。传递 TM_NONBLOCK 会导致服务在接收任务在调用时不等待消息的情况下立即返回而不阻塞。

标签

xthread-only, switch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"

RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;

void receiver_task(void *arg)
{
    RT_TASK_MCB mcb_r;
    char buffer[100];
    int ret;

    mcb_r.data = buffer;
    mcb_r.size = sizeof(buffer);

    while (cycle_time) {
        printf("Receiver: Waiting for a message...\n");
        ret = rt_task_receive(&mcb_r, TM_INFINITE);
        if (ret > 0) {
            printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
            rt_task_reply(ret, NULL);  // 发送空回复
        } else {
            printf("Receiver: Error receiving message, code: %d\n", ret);
        }
    }
}

void sender_task(void *arg)
{
    RT_TASK_MCB mcb_s;
    char message[] = "Hello from sender!";
    int ret;

    while (cycle_time--) {
        rt_task_sleep(1000000000);  // 睡眠1秒

        mcb_s.data = message;
        mcb_s.size = sizeof(message);

        printf("Sender: Sending message...\n");
        ret = rt_task_send(&receiver_task_desc, &mcb_s, NULL, TM_INFINITE);
        if (ret >= 0) {
            printf("Sender: Message sent successfully\n");
        } else {
            printf("Sender: Error sending message, code: %d\n", ret);
        }
    }
}

int main(int argc, char *argv[])
{
    // 创建接受任务
    if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating receiver task\n");
        return 1;
    }

    // 创建发送任务
    if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&receiver_task_desc, &receiver_task, NULL);
    rt_task_start(&sender_task_desc, &sender_task, NULL);

    // 等待任务结束
    rt_task_join(&receiver_task_desc);
    rt_task_join(&sender_task_desc);

    // 清理
    rt_task_delete(&receiver_task_desc);
    rt_task_delete(&sender_task_desc);

    return 0;
}

rt_task_send_timed

ssize_t rt_task_send_timed (RT_TASK *task, RT_TASK_MCB *mcb_s, RT_TASK_MCB *mcb_r, const struct timespec *abs_timeout);

向实时任务发送消息。

此服务是 Alchemy 任务可用的同步消息传递支持的一部分。调用者将可变大小的消息发送到另一个任务,等待远程任务通过调用 rt_task_receive() 接收初始消息,然后使用 rt_task_reply() 回复。

基本消息控制块用于存储要发送或在回复时检索的数据区域的位置和大小,以及用户定义的操作码。

参数

  • task
    任务描述符。

  • mcb_s
    指向消息控制块的地址,该块引用要发送的消息。此控制块的字段应设置如下:

    • mcb_s->data 应包含要发送到远程任务的有效负载数据的地址。

    • mcb_s->size 应包含 mcb_s->data 指向的有效负载数据的字节大小。零是合法值,表示不会传输任何有效负载数据。

    • mcb_s->opcode 是在消息传输过程中携带的不透明操作码,调用者可以填充任何适当的值。它将通过 rt_task_receive() 服务按原样提供给远程任务的操作码字段。

  • mcb_r
    指向可选消息控制块的地址,该块引用回复消息区域。如果 mcb_r 为 NULL 且远程任务发送了回复,回复消息将被丢弃,并返回 -ENOBUFS 给调用者。当 mcb_r 有效时,此控制块的字段应设置如下:

    • mcb_r->data 应包含足够大的缓冲区地址,以收集来自远程任务的回复数据。

    • mcb_r->size 应包含 mcb_r->data 指向的缓冲区空间的字节大小。如果 mcb_r->size 小于实际回复消息的大小,则不会进行数据复制,并返回 -ENOBUFS 给调用者。

    返回时,mcb_r->opcode 将包含远程任务使用 rt_task_reply() 发送回的状态码,或零(如果未指定)。

  • abs_timeout
    以秒/纳秒表示的绝对时间,基于 Alchemy 时钟,指定等待接收任务回复初始消息的时间限制。传递 NULL 会导致调用者无限期阻塞,直到收到回复。传递 {.tv_sec = 0, .tv_nsec = 0} 会导致服务在接收任务在调用时不等待消息的情况下立即返回而不阻塞。

返回值

成功时返回正值,表示远程任务返回的回复消息的长度(以字节为单位)。零表示成功状态,意味着 mcb_r 在输入时为 NULL,或者没有实际消息传递给远程调用 rt_task_reply()。否则:

  • 如果 task 不是有效的任务描述符,则返回 EINVAL

  • 如果从无效上下文调用此服务,则返回 EPERM

  • 如果 mcb_r 未指向足够大的消息区域以收集远程任务的回复,则返回 ENOBUFS。这包括 mcb_r 在输入时为 NULL,且远程任务试图发送回复消息的情况。

  • 如果 abs_timeout 为 {.tv_sec = 0, .tv_nsec = 0} 且接收任务当前未等待 rt_task_receive() 服务上的消息,则返回 EWOUDBLOCK

  • 如果 task 在等待回复时被删除,则返回 EIDRM

  • 如果在收到接收任务的任何回复之前调用了 rt_task_unblock(),则返回 EINTR

标签

xthread-only, switch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"

RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;

void receiver_task(void *arg)
{
    RT_TASK_MCB mcb_r;
    char buffer[100];
    int ret;
    struct timespec ts;

    mcb_r.data = buffer;
    mcb_r.size = sizeof(buffer);

    while (cycle_time) {
        printf("Receiver: Waiting for a message...\n");
        clock_gettime(CLOCK_MONOTONIC, &ts);
        ts.tv_sec += 2;  // 超时时间 2 秒
        ret = rt_task_receive_timed(&mcb_r, &ts);
        if (ret > 0) {
            printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
            if(cycle_time == 2)
            {
                rt_task_sleep(2000000000);  // 睡眠2秒,触发接受超时
            }else{
                rt_task_reply(ret, NULL);  // 发送空回复
            }
        } else if(ret == -ETIMEDOUT) {
            printf("Receiver: Timeout while waiting for message.\n");
        } else {
            printf("Receiver: Error receiving message, code: %d\n", ret);
        }
    }
}

void sender_task(void *arg)
{
    RT_TASK_MCB mcb_s;
    char message[] = "Hello from sender!";
    int ret;
    struct timespec ts;

    while (cycle_time--) {
        rt_task_sleep(1000000000);  // 睡眠1秒

        mcb_s.data = message;
        mcb_s.size = sizeof(message);

        printf("Sender: Sending message...\n");
        clock_gettime(CLOCK_MONOTONIC, &ts);
        ts.tv_sec += 2;  // 超时时间 2 秒
        ret = rt_task_send_timed(&receiver_task_desc, &mcb_s, NULL, &ts);
        if (ret >= 0) {
            printf("Sender: Message sent successfully\n");
        } else if(ret == -ETIMEDOUT) {
            printf("Sender: Timeout while waiting for Reply.\n");
        } else {
            printf("Sender: Error sending message, code: %d\n", ret);
        }
    }
}

int main(int argc, char *argv[])
{
    // 创建接受任务
    if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating receiver task\n");
        return 1;
    }

    // 创建发送任务
    if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&receiver_task_desc, &receiver_task, NULL);
    rt_task_start(&sender_task_desc, &sender_task, NULL);

    // 等待任务结束
    rt_task_join(&receiver_task_desc);
    rt_task_join(&sender_task_desc);

    // 清理
    rt_task_delete(&receiver_task_desc);
    rt_task_delete(&sender_task_desc);

    return 0;
}

rt_task_send_until

ssize_t rt_task_send_until (RT_TASK *task, RT_TASK_MCB *mcb_s, RT_TASK_MCB *mcb_r, RTIME abs_timeout);

向实时任务发送消息(具有绝对标量超时)。

此例程是 rt_task_send_timed() 的变体,接受以标量值表示的绝对超时规范。

参数

  • task
    任务描述符。

  • mcb_s
    指向消息控制块的地址,该块引用要发送的消息。

  • mcb_r
    指向可选消息控制块的地址,该块引用回复消息区域。

  • abs_timeout
    以时钟滴答表示的绝对时间。传递 TM_INFINITE 会导致调用者无限期阻塞,直到收到回复。传递 TM_NONBLOCK 会导致服务在接收任务在调用时不等待消息的情况下立即返回而不阻塞。

标签

xthread-only, switch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"

RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;

void receiver_task(void *arg)
{
    RT_TASK_MCB mcb_r;
    char buffer[100];
    int ret;
    RTIME timeout;

    mcb_r.data = buffer;
    mcb_r.size = sizeof(buffer);

    while (cycle_time) {
        printf("Receiver: Waiting for a message...\n");
        timeout = rt_timer_read() + 2000000000;  // 超时时间 2 秒
        ret = rt_task_receive_until(&mcb_r, timeout);
        if (ret > 0) {
            printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
            if(cycle_time == 2)
            {
                rt_task_sleep(2000000000);  // 睡眠2秒,触发接受超时
            }else{
                rt_task_reply(ret, NULL);  // 发送空回复
            }
        } else if(ret == -ETIMEDOUT) {
            printf("Receiver: Timeout while waiting for message.\n");
        } else {
            printf("Receiver: Error receiving message, code: %d\n", ret);
        }
    }
}

void sender_task(void *arg)
{
    RT_TASK_MCB mcb_s;
    char message[] = "Hello from sender!";
    int ret;
    RTIME timeout;

    while (cycle_time--) {
        rt_task_sleep(1000000000);  // 睡眠1秒

        mcb_s.data = message;
        mcb_s.size = sizeof(message);

        printf("Sender: Sending message...\n");
        timeout = rt_timer_read() + 2000000000;  // 超时时间 2 秒
        ret = rt_task_send_until(&receiver_task_desc, &mcb_s, NULL, timeout);
        if (ret >= 0) {
            printf("Sender: Message sent successfully\n");
        } else if(ret == -ETIMEDOUT) {
            printf("Sender: Timeout while waiting for Reply.\n");
        } else {
            printf("Sender: Error sending message, code: %d\n", ret);
        }
    }
}

int main(int argc, char *argv[])
{
    // 创建接受任务
    if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating receiver task\n");
        return 1;
    }

    // 创建发送任务
    if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&receiver_task_desc, &receiver_task, NULL);
    rt_task_start(&sender_task_desc, &sender_task, NULL);

    // 等待任务结束
    rt_task_join(&receiver_task_desc);
    rt_task_join(&sender_task_desc);

    // 清理
    rt_task_delete(&receiver_task_desc);
    rt_task_delete(&sender_task_desc);

    return 0;
}

rt_task_set_affinity

int rt_task_set_affinity (RT_TASK *task, const cpu_set_t *cpus);

设置实时任务的 CPU 亲和性。

此调用使 task 亲和于由 cpus 定义的 CPU 集。

参数

  • task
    任务描述符。如果 task 为 NULL,则更改当前任务的 CPU 亲和性。

  • cpus
    task 应该亲和的 CPU 集。

返回值

成功时返回零。否则:

  • 如果 task 为 NULL 但调用者不是 Xenomai 任务,或者 task 非 NULL 但不是有效的任务描述符,则返回 -EINVAL
  • 如果 cpus 不包含当前系统上物理存在且根据 cpuset(7) 中描述的 cpuset 机制允许进程使用的处理器,则返回 -EINVAL

标签

mode-unrestricted, switch-secondary

注意

如果 task 为 NULL,则调用者必须是 Alchemy 任务。

示例代码

c{filename="app.c"} 复制代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#include <sched.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    int ret;
    RT_TASK_INFO info;
    cpu_set_t cpu;
    
    rt_task_set_mode(0,TASK_MODE,NULL);

    printf("This is a Demo Task\n");
    ret = rt_task_inquire(&demo_task_desc,&info);
    if(ret != 0){
       printf("Error while inquire task: %d\n", ret);
       return;
    }
    printf("Get task info:\n");
    printf("    name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);

    CPU_ZERO(&cpu);
    CPU_SET(1, &cpu); // 设置到cpu1
    rt_task_set_affinity(&demo_task_desc,&cpu);
    rt_task_set_priority(&demo_task_desc,TASK_PRIO+10);
    
    ret = rt_task_inquire(&demo_task_desc,&info);
    if(ret != 0){
       printf("Error while inquire task: %d\n", ret);
       return;
    }
    printf("Get New task info:\n");
    printf("    name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, 0)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, 0);

    rt_task_sleep(1000000000); // 等待 1 秒
    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_set_mode()

int rt_task_set_mode(int clrmask, int setmask, int *mode_r);

更改当前任务模式。

每个 Alchemy 任务都有一组内部标志,用于确定若干操作条件。rt_task_set_mode() 接受一个位掩码,用于清除当前任务的相应模式位以禁用这些模式,并接受另一个位掩码,用于设置相应模式位以启用这些模式。可以根据需要返回更改前生效的模式位。

模式位

  • T_LOCK 使当前任务锁定当前 CPU 上的调度器,防止该 CPU 上的所有进一步的非自愿任务切换。清除此位将解锁调度器。
  • T_WARNSW 使当前任务每次切换到次级模式时发送 SIGDEBUG 信号。此功能对于检测到 Linux 域的不必要迁移非常有用。
  • T_CONFORMING 可以在 setmask 中传递,以将当前 Alchemy 任务切换到其首选的运行时模式。此开关的唯一有意义的用途是将实时任务强制切换回主模式。

参数

  • clrmask: 要为当前任务清除的模式位的位掩码,在应用 setmask 之前。零是一个可接受的值,这将导致无操作。
  • setmask: 要为当前任务设置的模式位的位掩码。零是一个可接受的值,这将导致无操作。
  • mode_r: 如果非 NULL,mode_r 必须是一个指向内存位置的指针,成功时将写入先前的活动模式位集。如果为 NULL,则不会返回先前的活动模式位集。

返回值

  • 成功时返回零。否则:
    • 如果 task 不是有效的任务描述符,或者 clrmasksetmask 中的任何位无效,则返回 -EINVAL
    • 如果从无效上下文调用此服务,则返回 -EPERM

标签

  • xthread-only
  • switch-primary

注意

  • 调用者必须是 Alchemy 任务。
  • 从用户代码中使用 T_CONFORMING 位强制任务模式几乎总是错误的,因为 Xenomai/cobalt 内核在需要时会内部处理模式切换。

示例代码

c{filename="app.c"} 复制代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#include <sched.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    int ret;
    RT_TASK_INFO info;
    cpu_set_t cpu;
    
    rt_task_set_mode(0,TASK_MODE,NULL);

    printf("This is a Demo Task\n");
    ret = rt_task_inquire(&demo_task_desc,&info);
    if(ret != 0){
       printf("Error while inquire task: %d\n", ret);
       return;
    }
    printf("Get task info:\n");
    printf("    name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);

    CPU_ZERO(&cpu);
    CPU_SET(1, &cpu); // 设置到cpu1
    rt_task_set_affinity(&demo_task_desc,&cpu);
    rt_task_set_priority(&demo_task_desc,TASK_PRIO+10);
    
    ret = rt_task_inquire(&demo_task_desc,&info);
    if(ret != 0){
       printf("Error while inquire task: %d\n", ret);
       return;
    }
    printf("Get New task info:\n");
    printf("    name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, 0)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, 0);

    rt_task_sleep(1000000000); // 等待 1 秒
    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_set_periodic()

int rt_task_set_periodic(RT_TASK *task, RTIME idate, RTIME period);

使实时任务周期化。

通过在处理器时间线上编程任务的第一个释放点及其周期,使任务周期化。然后任务应调用 rt_task_wait_period() 以休眠,直到处理器时间线中的下一个周期释放点到达。

参数:

  • task: 任务描述符。如果 task 为 NULL,则当前任务被设为周期性任务。任务必须属于当前进程。
  • idate: 第一个释放点的初始(绝对)日期,以时钟滴答表示。如果 idate 等于 TM_NOW,则使用当前系统日期,或者任务立即变为周期性任务。
  • period: 任务的周期,以时钟滴答表示。传递 TM_INFINITE 将停止任务的周期定时器(如果已启用),然后成功返回。

返回值:

  • 成功时返回零。否则:
    • 如果 task 为 NULL 但调用者不是 Xenomai 任务,或者 task 非 NULL 但不是有效的任务描述符,则返回 -EINVAL
    • 如果 idate 不等于 TM_INFINITE 并且表示过去的日期,则返回 -ETIMEDOUT

标签:

  • mode-unrestricted, switch-primary

注意:

  • 如果 task 为 NULL,则调用者必须是 Alchemy 任务。
  • 在 Cobalt 上,如果 period 不等于 TM_INFINITE 但短于目标系统的用户调度延迟值,则返回 -EINVAL
  • idateperiod 值被解释为 Alchemy 时钟分辨率的倍数。

注意事项:

  • 与其 Xenomai 2.x 对应物不同,rt_task_set_periodic() 不会阻塞 task 直到 idate 到达。周期时间线中的第一个节拍应通过调用 rt_task_wait_period() 来等待。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    int data =0;

    printf("This is a Demo Task\n");
    while(1){
        printf("%d\n",++data);
        if(data >= 5)
            break;
        rt_task_wait_period(NULL);
    }
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 设置周期任务,初始日期为当前时间,周期 1 秒
    rt_task_set_periodic(&demo_task_desc, rt_timer_read(), 1000000000);
    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_set_priority()

int rt_task_set_priority(RT_TASK *task, int prio);

更改实时任务的基本优先级。

任务的基本优先级定义了每个任务所执行工作的相对重要性,从而相应地获得 CPU 的控制权。

更改任务的基本优先级不会影响目标任务由于优先级继承而可能获得的优先级提升。

参数:

  • task: 任务描述符。如果 task 为 NULL,则更改当前任务的优先级。
  • prio: 新的优先级。此值必须在 [T_LOPRIO .. T_HIPRIO](包括边界)范围内,其中 T_LOPRIO 是最低有效优先级。

返回值:

  • 成功时返回零。否则:
    • 如果 task 不是有效的任务描述符,或者 prio 无效,则返回 -EINVAL
    • 如果 task 为 NULL 并且从无效上下文调用此服务,则返回 -EPERM

标签:

  • mode-unrestricted, switch-primary, switch-secondary

注意:

  • 如果 task 为 NULL,则调用者必须是 Alchemy 任务。
  • 将相同的优先级分配给正在运行或就绪的任务会将其移动到其优先级组的末尾,从而导致手动的时间片轮转。

示例代码

c{filename="app.c"} 复制代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#include <sched.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    int ret;
    RT_TASK_INFO info;
    cpu_set_t cpu;
    
    rt_task_set_mode(0,TASK_MODE,NULL);

    printf("This is a Demo Task\n");
    ret = rt_task_inquire(&demo_task_desc,&info);
    if(ret != 0){
       printf("Error while inquire task: %d\n", ret);
       return;
    }
    printf("Get task info:\n");
    printf("    name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);

    CPU_ZERO(&cpu);
    CPU_SET(1, &cpu); // 设置到cpu1
    rt_task_set_affinity(&demo_task_desc,&cpu);
    rt_task_set_priority(&demo_task_desc,TASK_PRIO+10);
    
    ret = rt_task_inquire(&demo_task_desc,&info);
    if(ret != 0){
       printf("Error while inquire task: %d\n", ret);
       return;
    }
    printf("Get New task info:\n");
    printf("    name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, 0)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, 0);

    rt_task_sleep(1000000000); // 等待 1 秒
    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_shadow()

int rt_task_shadow(RT_TASK *task, const char *name, int prio, int mode);

将调用者转换为实时任务。

将调用线程的个性设置为 Alchemy API,启用完整的 Alchemy 服务集。成功后,调用者不再是常规的 POSIX 线程,而是一个 Xenomai 扩展线程。

如果 prio 非零,新任务将移动到 Xenomai 的实时 FIFO 调度类,即 SCHED_FIFO。如果 prio 为零,任务将移动到常规的 SCHED_OTHER 类。

以零优先级运行 Xenomai 任务对于运行可能调用阻塞实时服务的非实时进程非常有用,例如等待信号量、从消息队列或缓冲区读取等。

参数:

  • task: 如果非 NULL,则为任务描述符的地址,该描述符可在此调用成功后用于唯一标识任务。如果为 NULL,则不返回描述符。
  • name: 代表任务符号名称的 ASCII 字符串。当非 NULL 且非空时,此字符串的副本用于将任务索引到对象注册表中。
  • prio: 任务的基本优先级。此值必须在 [0 .. 99] 范围内,其中 0 是最低有效优先级。
  • mode: 任务影子模式。以下标志可以 OR 进此位掩码:
    • T_LOCK 使当前任务在返回调用者之前锁定调度器,防止当前 CPU 上的所有进一步的非自愿任务切换。需要从当前任务调用 rt_task_set_mode() 来解除此锁。
    • 在 Cobalt 内核上运行时,T_WARNSW 使 SIGDEBUG 信号在当前任务切换到次级模式时发送。此功能对于检测到不必要的迁移到 Linux 域非常有用。此标志在 Mercury 内核上无效。

返回值:

  • 成功时返回零。否则:
    • 如果 prio 无效,则返回 -EINVAL
    • 如果系统无法从主堆获取内存以创建任务扩展,则返回 -ENOMEM
    • 如果 name 与已注册的任务冲突,则返回 -EEXIST
    • 如果调用者不是常规的 POSIX 线程,则返回 -EBUSY
    • 如果从无效上下文调用此服务,例如中断处理程序,则返回 -EPERM

标签:

  • pthread-only, switch-secondary, switch-primary

副作用:

  • 在 Cobalt 上,如果调用者是普通的 POSIX 线程,它将变成 Xenomai 影子线程,具有对所有 Cobalt 服务的完全访问权限。调用者总是以主模式从此服务返回。

注意:

  • 任务可以从属于同一 Xenomai 会话的多个进程中引用。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE 0
#define TASK_NAME "ShadowDemo"

RT_TASK shadow_task;

void *thread_function(void *arg)
{
    int ret;
    
    printf("Regular POSIX thread starting...\n");
    
    // 将当前线程转换为 Xenomai 实时任务
    ret = rt_task_shadow(&shadow_task, TASK_NAME, TASK_PRIO, TASK_MODE);
    if (ret < 0) {
        printf("Error converting to real-time task: %d\n", ret);
        return NULL;
    }
    
    printf("Now running as Xenomai real-time task\n");
    
    // 获取任务信息
    RT_TASK_INFO info;
    ret = rt_task_inquire(&shadow_task, &info);
    if (ret == 0) {
        printf("Task info:\n");
        printf("    Name: %s\n", info.name);
        printf("    Priority: %d\n", info.prio);
        printf("    PID: 0x%x\n", info.pid);
    } else {
        printf("Error getting task info: %d\n", ret);
    }
    
    // 演示实时任务功能:周期性执行
    rt_task_set_periodic(NULL, TM_NOW, 500000000); // 500ms 周期
    
    for (int i = 0; i < 5; i++) {
        printf("Periodic execution: %d\n", i);
        rt_task_wait_period(NULL);
    }
    
    printf("Real-time task complete\n");
    return NULL;
}

int main(int argc, char *argv[])
{
    pthread_t thread;
    int ret;
    
    // 创建普通 POSIX 线程
    ret = pthread_create(&thread, NULL, thread_function, NULL);
    if (ret != 0) {
        printf("Error creating thread\n");
        return 1;
    }
    
    // 等待线程完成
    pthread_join(thread, NULL);
    
    printf("Main program exiting\n");
    return 0;
}

rt_task_sleep()

int rt_task_sleep(RTIME delay);

延迟当前实时任务(相对延迟)。

此例程是 rt_task_sleep_until() 的变体,接受相对超时规范。

参数:

  • delay: 以时钟滴答表示的相对延迟(见注释)。零延迟将导致此服务立即返回给调用者,并带有成功状态。

返回值:

  • 参见 rt_task_sleep_until()

标签:

  • xthread-only, switch-primary

注释:

  • delay 值被解释为 Alchemy 时钟分辨率的倍数(参见 --alchemy-clock-resolution 选项,默认为 1 纳秒)。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    printf("This is a Demo Task\n");
    rt_task_suspend(&demo_task_desc);
    printf("Demo Task Continue to run\n");
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务运行
    rt_task_sleep(1000000000); // 1 秒
    rt_task_resume(&demo_task_desc);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_sleep_until()

int rt_task_sleep_until(RTIME date);

延迟当前实时任务(绝对唤醒日期)。

延迟调用任务的执行,直到达到给定日期。调用者进入休眠状态,在此状态下不消耗任何 CPU 时间。

参数:

  • date: 以时钟滴答表示的绝对日期,指定唤醒日期(见注释)。作为特例,TM_INFINITE 是一个可接受的值,它会导致调用者无限期阻塞,直到调用 rt_task_unblock()。否则,任何过去的唤醒日期都会导致任务立即返回。

返回值:

  • 成功时返回零。否则:
    • 如果为当前任务调用了 rt_task_unblock(),则返回 -EINTR
    • 如果 date 已经过期,则返回 -ETIMEDOUT
    • 如果从无效上下文调用此服务,则返回 -EPERM

标签:

  • xthread-only, switch-primary

注释:

  • 如果 task 为 NULL,则调用者必须是 Alchemy 任务。
  • date 值被解释为 Alchemy 时钟分辨率的倍数(参见 --alchemy-clock-resolution 选项,默认为 1 纳秒)。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    printf("This is a Demo Task\n");
    rt_task_suspend(&demo_task_desc);
    printf("Demo Task Continue to run\n");
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务运行
    RTIME timeout = rt_timer_read() + 1000000000; // 1 秒
    rt_task_sleep_until(timeout);
    rt_task_resume(&demo_task_desc);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_slice()

int rt_task_slice(RT_TASK *task, RTIME quantum);

设置任务的时间片轮转量。

设置任务在时间片轮转调度中分配的时间额度。如果 quantum 非零,rt_task_slice() 还会重新填充目标任务的当前时间片。否则,将停止该任务的时间片轮转。

换句话说,rt_task_slice() 应用于切换 Alchemy 任务的时间片轮转调度。

参数:

  • task: 任务描述符。如果 task 为 NULL,则更改当前任务的时间额度。task 必须属于当前进程。
  • quantum: 以时钟滴答表示的任务时间片(见注释)。

返回值:

  • 成功时返回零。否则:
    • 如果 task 不是有效的任务描述符或 prio 无效,则返回 -EINVAL
    • 如果 task 为 NULL 并且从无效上下文调用此服务,则返回 -EPERM

标签:

  • mode-unrestricted, switch-primary

注释:

  • 如果 task 为 NULL,则调用者必须是 Alchemy 任务。
  • quantum 值被解释为 Alchemy 时钟分辨率的倍数(参见 --alchemy-clock-resolution 选项,默认为 1 纳秒)。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME_PREFIX "SliceDemo"
#define NUM_TASKS 3

RT_TASK task_descs[NUM_TASKS];

void demo_task(void *arg)
{
    int task_id = *(int*)arg;
    int count = 0;
    
    while(count < 5) {
        printf("Task %d running (count: %d)\n", task_id, count);
        rt_task_sleep(100000000); // Sleep for 100ms
        count++;
    }
}

int main(int argc, char *argv[])
{
    int i;
    char task_name[20];
    int task_ids[NUM_TASKS];
    
    // 创建并启动多个任务
    for (i = 0; i < NUM_TASKS; i++) {
        snprintf(task_name, sizeof(task_name), "%s%d", TASK_NAME_PREFIX, i);
        task_ids[i] = i;
        
        if (rt_task_create(&task_descs[i], task_name, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
            printf("Error creating task %d\n", i);
            return 1;
        }
        
        // 为每个任务设置200ms的时间片
        rt_task_slice(&task_descs[i], 200000000);
        
        rt_task_start(&task_descs[i], &demo_task, &task_ids[i]);
    }

    // 等待所有任务完成
    for (i = 0; i < NUM_TASKS; i++) {
        rt_task_join(&task_descs[i]);
    }

    // 清理
    for (i = 0; i < NUM_TASKS; i++) {
        rt_task_delete(&task_descs[i]);
    }

    return 0;
}

rt_task_spawn()

int rt_task_spawn(RT_TASK *task, const char *name, int stksize, int prio, int mode, void(*entry)(void *), void *arg);

创建并启动一个实时任务。

此服务通过组合调用 rt_task_create()rt_task_start() 来生成一个新任务。

参数:

  • task: 任务描述符的地址,在此调用成功后可用于唯一标识创建的对象。
  • name: 代表任务符号名称的 ASCII 字符串。当非 NULL 且非空时,此字符串的副本用于将创建的任务索引到对象注册表中。
  • stksize: 新任务的堆栈大小(以字节为单位)。如果传递零,则会替换为系统依赖的默认大小。
  • prio: 新任务的基本优先级。此值必须在 [0 .. 99] 范围内,其中 0 是最低有效优先级。
  • mode: 任务创建模式。参见 rt_task_create()
  • entry: 任务入口点的地址。
  • arg: entry 将接收的用户定义的不透明参数。

返回值:

  • 参见 rt_task_create()

标签:

  • mode-unrestricted, switch-secondary

副作用:

  • 参见 rt_task_create()

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    printf("This is a Demo Task\n");
}

int main(int argc, char *argv[])
{
    // 创建并启动任务
    if (rt_task_spawn(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE, &demo_task, NULL)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_start()

int rt_task_start(RT_TASK *task, void(*entry)(void *arg), void *arg);

启动实时任务。

此调用启动先前由 rt_task_create() 创建的任务的执行。此服务使启动的任务离开初始的休眠状态。

参数:

  • task: 任务描述符。
  • entry: 任务入口点的地址。
  • arg: entry 将接收的用户定义的不透明参数。

返回值:

  • 成功时返回零。否则:
    • 如果 task 不是有效的任务描述符,则返回 -EINVAL

标签:

  • mode-unrestricted, switch-primary

注意:
启动已经启动的任务会导致无操作,并返回成功状态。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    printf("This is a Demo Task\n");
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_suspend()

int rt_task_suspend(RT_TASK *task);

挂起实时任务。

强制挂起任务的执行。此任务在被显式调用 rt_task_resume() 之前将不具备调度资格。换句话说,由 rt_task_suspend() 调用引起的挂起状态与其他服务引起的延迟和阻塞状态是累积的,并且与它们分开管理。

维护一个嵌套计数,因此 rt_task_suspend()rt_task_resume() 必须成对使用。

接收 Linux 信号会导致挂起的任务立即恢复。

参数:

  • task: 任务描述符。如果 task 为 NULL,则挂起当前任务。

返回值:

  • 成功时返回零。否则:
    • 如果 task 为 NULL 但调用者不是 Xenomai 任务,或者 task 非 NULL 但不是有效的任务描述符,则返回 -EINVAL
    • 如果调用者在挂起时接收到 Linux 信号,则返回 -EINTR
    • 如果 task 为 NULL 并且从无效上下文调用此服务,则返回 -EPERM

标签:

  • mode-unrestricted, switch-primary

注意:
如果 task 为 NULL,则调用者必须是 Alchemy 任务。

阻塞和挂起任务状态是累积的。因此,挂起当前等待同步对象(例如信号量、队列)的任务会保持其执行挂起状态,直到其恢复,尽管在此期间可能已获取到等待的资源或超时已过。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    printf("This is a Demo Task\n");
    rt_task_suspend(&demo_task_desc);
    printf("Demo Task Continue to run\n");
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务运行
    rt_task_sleep(1000000000); // 1 秒
    rt_task_resume(&demo_task_desc);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_unbind()

int rt_task_unbind(RT_TASK *task);

解除任务绑定。

参数:

  • task: 任务描述符。

此例程释放先前对 Alchemy 任务的绑定。在此调用返回后,该描述符将不再有效,无法引用此对象。

标签:

  • thread-unrestricted

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    RT_TASK current_task;
    RT_TASK_INFO info;

    printf("This is a Demo Task\n");

    // 通过TASK_NAME绑定到描述符
    if (rt_task_bind(&current_task, TASK_NAME, TM_INFINITE)) {
        printf("Error creating sender task\n");
        return;
    }

    // 使用描述符
    int ret = rt_task_inquire(&current_task,&info);
    if(ret == 0){
        printf("Get task info:\n");
        printf("    name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
    }else{
        printf("Error while inquire task: %d\n", ret);
    }

    // 解除绑定
    rt_task_unbind(&current_task);
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_unblock()

int rt_task_unblock(RT_TASK *task);

解除实时任务的阻塞状态。

将任务从当前的任何等待状态中解除。此调用会清除目标任务的所有延迟和/或资源等待条件。

然而,rt_task_unblock() 不会恢复先前通过 rt_task_suspend() 强制挂起的任务。如果所有的挂起条件都消失了,任务将重新具备调度资格。

参数:

  • task: 任务描述符。

返回值:

  • 成功时返回零。
  • 否则:
    • 如果 task 不是有效的任务描述符,则返回 -EINVAL

标签:

  • unrestricted, switch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    printf("This is a Demo Task\n");
    RTIME timeout = rt_timer_read() + 10000000000; // 10 秒
    rt_task_sleep_until(timeout);
    printf("Demo Task Continue to run\n");
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);
    rt_task_sleep(1000000000);  // 1 秒

    // 解除线程sleep状态
    printf("Unblocking task\n");
    rt_task_unblock(&demo_task_desc);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_wait_period()

int rt_task_wait_period(unsigned long *overruns_r)

等待下一个周期释放点。

将当前任务延迟到下一个周期释放点。周期定时器应已通过调用 rt_task_set_periodic()task 预先启动。

参数:

  • overruns_r: 如果非 NULL,overruns_r 应为指向内存位置的指针,该位置将被写入待处理的超时次数。仅当 rt_task_wait_period() 返回 -ETIMEDOUT 或成功时才会写入此值。否则,该内存位置保持不变。如果为 NULL,则不会返回此计数。

返回值:

  • 成功时返回零。如果 overruns_r 非 NULL,则零将写入指向的内存位置。否则:
    • 如果未为当前任务调用 rt_task_set_periodic(),则返回 -EWOULDBLOCK
    • 如果在到达下一个周期释放点之前为等待任务调用了 rt_task_unblock(),则返回 -EINTR
    • 如果发生定时器超时,表示调用任务错过了先前的释放点,则返回 -ETIMEOUT。如果 overruns_r 非 NULL,则待处理的超时次数将写入指向的内存位置。
    • 如果从无效上下文调用此服务,则返回 -EPERM

标签:

  • xthread-only, switch-primary

注意:

  • 如果在调用时当前释放点已到达,则当前任务立即从此服务返回而无需延迟。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"

RT_TASK demo_task_desc;

void demo_task(void *arg)
{
    int data =0;

    printf("This is a Demo Task\n");
    while(1){
        printf("%d\n",++data);
        if(data >= 5)
            break;
        rt_task_wait_period(NULL);
    }
}

int main(int argc, char *argv[])
{
    // 创建任务
    if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
        printf("Error creating sender task\n");
        return 1;
    }

    // 设置周期任务,初始日期为当前时间,周期 1 秒
    rt_task_set_periodic(&demo_task_desc, rt_timer_read(), 1000000000);
    // 启动任务
    rt_task_start(&demo_task_desc, &demo_task, NULL);

    // 等待任务结束
    rt_task_join(&demo_task_desc);

    // 清理
    rt_task_delete(&demo_task_desc);
    return 0;
}

rt_task_yield()

int rt_task_yield(void)

手动时间片轮转。

将当前任务移动到其优先级组的末尾,以便切换到下一个处于就绪状态的同等优先级任务。

返回值:

  • 成功时返回零。否则:
    • 如果从无效上下文调用此服务,则返回 -EPERM

标签:

  • xthread-only, switch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>

#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME_PREFIX "YieldDemo"
#define NUM_TASKS 3

RT_TASK task_descs[NUM_TASKS];

void demo_task(void *arg)
{
    int task_id = *(int*)arg;
    int count = 0;
    
    while(count < 5) {
        printf("Task %d running (count: %d)\n", task_id, count);
        count++;
        
        // 主动让出CPU
        if(task_id == count - 1)
            rt_task_yield();
        
        // 短暂睡眠,以便观察输出
        rt_task_sleep(10000000); // 10ms
    }
}

int main(int argc, char *argv[])
{
    int i;
    char task_name[20];
    int task_ids[NUM_TASKS];
    
    // 创建并启动多个任务
    for (i = 0; i < NUM_TASKS; i++) {
        snprintf(task_name, sizeof(task_name), "%s%d", TASK_NAME_PREFIX, i);
        task_ids[i] = i;
        
        if (rt_task_create(&task_descs[i], task_name, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
            printf("Error creating task %d\n", i);
            return 1;
        }
        
        rt_task_start(&task_descs[i], &demo_task, &task_ids[i]);
    }

    // 等待所有任务完成
    for (i = 0; i < NUM_TASKS; i++) {
        rt_task_join(&task_descs[i]);
    }

    // 清理
    for (i = 0; i < NUM_TASKS; i++) {
        rt_task_delete(&task_descs[i]);
    }

    return 0;
}

最近修改: 2025-07-24