# Cobalt/Alarm

通用看门狗定时器。

### 详细描述

通用看门狗定时器。

警报是通用的看门狗定时器。`Alchemy`任务可以创建任意数量的警报，并在指定的初始延迟过去后使用它们运行用户定义的处理程序。警报可以是一次性的或周期性的；在后一种情况下，实时系统会根据用户定义的间隔值自动为下一次触发重新编程警报。

### 函数文档

#### rt_alarm_create

> int rt_alarm_create (RT_ALARM *alarm, const char *name, void(*handler)(void *arg), void *arg);

创建一个警报对象。

此例程创建一个在未来指定时间触发警报例程的对象。警报可以是周期性的或一次性的，这取决于传递给 rt_alarm_start() 的重载间隔值。

参数

- alarm 警报描述符的地址，如果此调用成功，可以稍后用来唯一标识创建的对象。
- name 代表警报符号名称的ASCII字符串。当非NULL且非空时，此字符串的副本用于将创建的警报索引到对象注册表中。
- handler 警报到期时调用的例程的地址。此例程传递 arg 值。
- arg 传递给处理程序的用户定义的不透明参数。

返回值

成功时返回零。否则：

- 如果系统无法从本地池获取内存以创建警报，则返回 -ENOMEM。
- 如果名称与已注册的警报冲突，则返回 -EEXIST。
- 如果此服务是从异步上下文中调用的，则返回 -EPERM。

标签

`mode-unrestricted`, `switch-secondary`

注意

警报是进程私有对象，因此不能由多个进程共享，即使它们属于同一 `xkernel` 会话。

示例代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <copperplate/traceobj.h>
    #include <alchemy/task.h>
    #include <alchemy/alarm.h>

    #define ALARM_PERIOD 1000000000LL  // 1秒,以纳秒为单位

    static RT_ALARM alarm_desc;

    void alarm_handler(void *arg)
    {
        printf("Alarm Trigger! Current Time: %lld ns\n", rt_timer_read());
    }

    int main(int argc, char *argv[])
    {
        int ret;

        ret = rt_alarm_create(&alarm_desc, "my_alarm", alarm_handler, NULL);
        if (ret) {
            perror("rt_alarm_start");
            return EXIT_FAILURE;
        }

        printf("Alarm Start...\n");

        ret = rt_alarm_start(&alarm_desc, ALARM_PERIOD, ALARM_PERIOD);
        if (ret) {
            perror("rt_alarm_start");
            rt_alarm_delete(&alarm_desc);
            return EXIT_FAILURE;
        }

        // 让主线程休眠,以便警报可以触发几次
        rt_task_sleep(ALARM_PERIOD * 5);

        printf("Stop and delete alarm...\n");
        rt_alarm_stop(&alarm_desc);
        rt_alarm_delete(&alarm_desc);

        return EXIT_SUCCESS;
    }

#### rt_alarm_delete

> int rt_alarm_delete (RT_ALARM * alarm);

删除一个警报。 此例程删除由 rt_alarm_create() 创建的警报对象。

参数

- alarm 警报描述符。

返回值

成功时返回零。否则：

- 如果 alarm 不是有效的警报描述符，则返回 -EINVAL。
- 如果此服务是从异步上下文中调用的，则返回 -EPERM。

标签

`mode-unrestricted`, `switch-secondary`

示例代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <copperplate/traceobj.h>
    #include <alchemy/task.h>
    #include <alchemy/alarm.h>

    #define ALARM_PERIOD 1000000000LL  // 1秒,以纳秒为单位

    static RT_ALARM alarm_desc;

    void alarm_handler(void *arg)
    {
        printf("Alarm Trigger! Current Time: %lld ns\n", rt_timer_read());
    }

    int main(int argc, char *argv[])
    {
        int ret;

        ret = rt_alarm_create(&alarm_desc, "my_alarm", alarm_handler, NULL);
        if (ret) {
            perror("rt_alarm_start");
            return EXIT_FAILURE;
        }

        printf("Alarm Start...\n");

        ret = rt_alarm_start(&alarm_desc, ALARM_PERIOD, ALARM_PERIOD);
        if (ret) {
            perror("rt_alarm_start");
            rt_alarm_delete(&alarm_desc);
            return EXIT_FAILURE;
        }

        // 让主线程休眠,以便警报可以触发几次
        rt_task_sleep(ALARM_PERIOD * 5);

        printf("Stop and delete alarm...\n");
        rt_alarm_stop(&alarm_desc);
        rt_alarm_delete(&alarm_desc);

        return EXIT_SUCCESS;
    }

#### rt_alarm_inquire

> int rt_alarm_inquire (RT_ALARM *alarm, RT_ALARM_INFO *info);

查询警报状态。 此例程返回有关指定“警报”的状态信息。

参数

- alarm 警报描述符。
- info 指向要将信息复制到的返回缓冲区的指针。

返回值

成功后返回零并将状态信息写入 info 指向的结构。否则：

- 如果 alarm 不是有效的警报描述符，则返回 -EINVAL。

标签

`unrestricted`, `switch-primary`

示例代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <copperplate/traceobj.h>
    #include <alchemy/task.h>
    #include <alchemy/alarm.h>

    #define ALARM_PERIOD 1000000000LL  // 1秒,以纳秒为单位

    static RT_ALARM alarm_desc;
    static RT_ALARM_INFO alarm_info;

    void alarm_handler(void *arg)
    {
        if(rt_alarm_inquire(&alarm_desc,&alarm_info) != 0)
        {
            perror("rt_alarm_inquire");
            exit(1);
        }
        printf("%s [%s]: expired %ld\n",alarm_info.name,alarm_info.active > 0? "active":"passive"
        ,alarm_info.expiries);
    }

    int main(int argc, char *argv[])
    {
        int ret;

        ret = rt_alarm_create(&alarm_desc, "my_alarm", alarm_handler, NULL);
        if (ret) {
            perror("rt_alarm_start");
            return EXIT_FAILURE;
        }

        printf("Alarm Start...\n");

        ret = rt_alarm_start(&alarm_desc, ALARM_PERIOD, ALARM_PERIOD);
        if (ret) {
            perror("rt_alarm_start");
            rt_alarm_delete(&alarm_desc);
            return EXIT_FAILURE;
        }

        // 让主线程休眠,以便警报可以触发几次
        rt_task_sleep(ALARM_PERIOD * 5);

        printf("Stop and delete alarm...\n");
        rt_alarm_stop(&alarm_desc);

        if(rt_alarm_inquire(&alarm_desc,&alarm_info) != 0)
        {
            perror("rt_alarm_inquire");
            return EXIT_FAILURE;
        }
        printf("%s [%s]: expired %ld\n",alarm_info.name,alarm_info.active > 0? "active":"passive"
        ,alarm_info.expiries);

        rt_alarm_delete(&alarm_desc);
        return EXIT_SUCCESS;
    }

#### rt_alarm_start

> int rt_alarm_start (RT_ALARM *alarm, RTIME value, RTIME interval)

启动一个警报。

此例程设置警报对象的触发日期。警报可以是周期性的或一次性的，这取决于间隔值。

警报处理程序总是由xkernel的内部定时器事件例程代理调用。因此，可以从这些处理程序中调用的xkernel例程被限制为可以代表异步上下文提供的服务集。

此服务覆盖了警报的到期日期和重新加载间隔的任何先前设置。

参数

- alarm 警报描述符。
- value 第一次到期的相对日期，以时钟滴答表示（见注意）。
- interval 警报的重新加载值。它是用于重新编程下一个警报发射的周期间隔值，以时钟滴答表示（见注意）。如果 interval 等于 TM_INFINITE，则警报在过期后将不会被重新加载。

返回值

成功时返回零。否则：

- 如果 alarm 不是有效的警报描述符，则返回 -EINVAL。
- 如果此服务是从无效上下文中调用的，则返回 -EPERM。

标签

`xthread-only`, `switch-primary`

注意

初始值和间隔的每一个都被解释为Alchemy时钟分辨率的倍数（参见 alchemy-clock-resolution 选项，默认为1纳秒）。

示例代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <copperplate/traceobj.h>
    #include <alchemy/task.h>
    #include <alchemy/alarm.h>

    #define ALARM_PERIOD 1000000000LL  // 1秒,以纳秒为单位

    static RT_ALARM alarm_desc;

    void alarm_handler(void *arg)
    {
        printf("Alarm Trigger! Current Time: %lld ns\n", rt_timer_read());
    }

    int main(int argc, char *argv[])
    {
        int ret;

        ret = rt_alarm_create(&alarm_desc, "my_alarm", alarm_handler, NULL);
        if (ret) {
            perror("rt_alarm_start");
            return EXIT_FAILURE;
        }

        printf("Alarm Start...\n");

        ret = rt_alarm_start(&alarm_desc, ALARM_PERIOD, ALARM_PERIOD);
        if (ret) {
            perror("rt_alarm_start");
            rt_alarm_delete(&alarm_desc);
            return EXIT_FAILURE;
        }

        // 让主线程休眠,以便警报可以触发几次
        rt_task_sleep(ALARM_PERIOD * 5);

        printf("Stop and delete alarm...\n");
        rt_alarm_stop(&alarm_desc);
        rt_alarm_delete(&alarm_desc);

        return EXIT_SUCCESS;
    }

#### rt_alarm_stop

> int rt_alarm_stop (RT_ALARM *alarm)

停止一个警报。

此例程禁用警报对象，防止任何进一步到期，直到通过 rt_alarm_start() 重新启用它。

参数

- alarm 警报描述符的地址，如果此调用成功，可以稍后用来唯一标识创建的对象。

返回值

成功时返回零。否则：

- 如果 alarm 不是有效的警报描述符，则返回 -EINVAL。

标签

`unrestricted`, `switch-primary`

示例代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <copperplate/traceobj.h>
    #include <alchemy/task.h>
    #include <alchemy/alarm.h>

    #define ALARM_PERIOD 1000000000LL  // 1秒,以纳秒为单位

    static RT_ALARM alarm_desc;

    void alarm_handler(void *arg)
    {
        printf("Alarm Trigger! Current Time: %lld ns\n", rt_timer_read());
    }

    int main(int argc, char *argv[])
    {
        int ret;

        ret = rt_alarm_create(&alarm_desc, "my_alarm", alarm_handler, NULL);
        if (ret) {
            perror("rt_alarm_start");
            return EXIT_FAILURE;
        }

        printf("Alarm Start...\n");

        ret = rt_alarm_start(&alarm_desc, ALARM_PERIOD, ALARM_PERIOD);
        if (ret) {
            perror("rt_alarm_start");
            rt_alarm_delete(&alarm_desc);
            return EXIT_FAILURE;
        }

        // 让主线程休眠,以便警报可以触发几次
        rt_task_sleep(ALARM_PERIOD * 5);

        printf("Stop and delete alarm...\n");
        rt_alarm_stop(&alarm_desc);
        rt_alarm_delete(&alarm_desc);

        return EXIT_SUCCESS;
    }