标准C函数'localtime'的线程安全版本

时间:2013-12-28 23:11:51

标签: c multithreading stm32 iar localtime

我在多线程应用程序中使用localtime。

我必须用线程安全的版本替换它,据我所知,这个版本叫做localtime_r。

然而,当我这样做时,由于链接失败,我无法完成构建。

我甚至不确定从哪里开始寻找解决方案。

我的系统组件是:

  • 芯片 - STM32(基于ARM的皮层)
  • IDE - IAR(ST-Microcontrollers的编译器和链接器)
  • OS - ThreadX

我假设(虽然我不确定),这个函数通常会在随IDE提供的标准库中提供。我是对的吗?

我是否需要将另一个库添加到项目中,或者是项目设置中的某个库?

如果没有可行的方法将此函数“导入”我的代码,我还有哪些其他选项可用于本地时间函数的线程安全版本?

更新

我希望避免使用OS资源(即互斥锁),而是调用一个标准例程,该例程完全执行'localtime'所做的事情,只是没有它使用的静态结构(使其不安全)

我没有看到为什么localtime会使用静态结构开始的原因,所以我假设相应的localtime_r并没有用任何操作系统资源来解决它,而只是禁止使用静态结构。

如果没有这样的选择是可行的,那么我不妨自己实施,只是因为约会系统的“不规则”,我更喜欢使用已经过适当测试的东西。

这里的问题是,如何将localtime_r'链接到我的项目中(而不是如何实现localtime_r)。

由于

2 个答案:

答案 0 :(得分:5)

您需要为localtime()创建自己的线程安全包装器,它基本上是实现localtime_r()。

e.g。

static TX_MUTEX localtime_lock;
void my_localtime_init(void)
{
  tx_Mutex_create( &localtime_lock, "localtime_lock", TX_INHERIT);
}

struct tm *my_localtime_r(const time_t *tim, struct tm *result)
{
   struct tm *t;

   tx_Mutex_get(&localtime_lock, TX_WAIT_FOREVER);
   t = localtime(tim);
   if (t)
       *result = *t;
   tx_Mutex_put(&localtime_lock);

  return t ? result : NULL;
}

您需要在启动时的某处调用my_localtime_init

这也意味着你需要用my_localtime_r函数替换所有调用,没有人可以直接调用localtime(),因为这可能导致调用新my_localtime_r的代码出现竞争条件。

答案 1 :(得分:3)

如果没有可用的线程安全版本,则必须创建一个版本,该版本具有localtime_r()的标准接口,但使用互斥锁来确保互斥。我可能会使用相同的名称,但是有一些参数可以使用您经常调用的替代名称,如果可用,则会直接调用localtime_r

如果您的系统使用与Pthread互斥锁不同的互斥锁,则该概念适用;使用本机互斥锁而不是Pthread互斥锁。

static pthread_mutex_t mx_localtime_r = PTHREAD_MUTEX_INITIALIZER;

struct tm *localtime_r(const time_t *restrict timer, struct tm *restrict result)
{
    struct tm *r = 0;
    if (pthread_mutex_lock(&mx_localtime_r) == 0)
    {
        r = localtime(timer);
        if (r != 0)
        {
            *result = *r;
            r = result;
        }
        if (pthread_mutex_unlock(&mx_localtime_r) != 0)
            r = 0;
    }
    return r;
}

未编译 - 更少测试。

如果互斥锁的默认属性不适合您,那么您需要投入更多精力来正确初始化互斥锁。