【发布时间】:2013-01-21 10:09:23
【问题描述】:
在我的代码中,我有一个缓冲区,向其中添加数据的代码是:
bool push_string(file_buffer *cb, const char* message, const unsigned short msglen)
{
unsigned int size = msglen;
if(cb->head >= (cb->size - size))
{
size = cb->size - cb->head - 1;
}
if(size < 1) return false;
char* dest = cb->head += size;
memcpy(dest, message, size);
return (size == msglen);
}
由于我从多个中断添加数据(可以相互豁免),我想知道这段代码是否是线程安全的?我将 'cb->head' 标记为 volatile,但如果另一个中断恰好在 'head' 的增加和对 'dest' 的分配之间豁免,事情可能会出错。
如何改进此代码以使其更安全?
编辑:也许我不应该使用“线程安全”这个词,因为没有并行运行的线程,只有中断的可能性。
【问题讨论】:
-
不...绝对不是线程安全的,因为根本没有同步机制。使无锁算法健壮地实现是困难的——如果你必须问上面是否安全,你应该从互斥体开始。上面的数据结构甚至无法以无锁方式填充,因为您正在写入任意大的消息,而读者无法知道它们何时可以安全使用。
-
其实我收回了。它不像使用自旋锁那么简单。问题是,如果一个 ISR 获得了自旋锁,然后被另一个 ISR 中断/抢占,那么其他 ISR 将无法获得自旋锁。如果是这样,系统就会死锁。
-
@AlexeyFrunze:这应该有什么帮助?大多数互斥锁实现会在回退到对 CPU 更友好的操作系统级锁之前旋转。简单地旋转用户代码有浪费大量 CPU 周期的风险。至于死锁 - 是否会发生取决于中断是否可以相互抢占或始终运行到完成。
-
@AlexeyFrunze:无锁算法是关于数据本身的旋转——而不是单独的锁。 “旋转不会成为问题” - 您仍然可以获得锁,让步,并让其他线程燃烧它们的整个时间片,并且当互斥体首先旋转时会发生什么?谁想要一种随着锁定频率的增加而呈指数级恶化的锁定方法?
-
在我的嵌入式系统上,我禁用了中断抢占,(FIQ 除外),正是出于这个原因 - 使缓冲区指针能够在不受其他中断干扰的情况下推入/弹出队列。每个中断处理程序都足够短,足以让我获得足够的性能。 FIQ 可以中断另一个中断,但只能通过启动“普通”软件中断来表示其 SD 卡读/写完成,因此它的缓冲区队列以类似的方式受到保护。 Mutex 在中断处理程序中不可用,即使您有 RTOS。
标签: c thread-safety locking buffer c99