Linux カーネルのソース コードには、多くのメモリ バリア (smp_mb() など) があります。
しかし、redisのソースでは、私はそれを見ませんでした。redis の Makefile では、gcc の最適化オプションが -O2 になっているため、これらの命令の順序を変更する必要があります。正しい動作を保証するために mb() を使用しないのはなぜですか?
追加した:
例: Linux カーネルの kfifo では:
unsigned int __kfifo_put(struct kfifo *fifo,unsigned char *buffer, unsigned int len)
{
unsigned int l;
len = min(len, fifo->size - fifo->in + fifo->out);
smp_mb();
l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
...
smp_wmb();
fifo->in += len;
...
}
Redis ソースでは、プロジェクト全体を調査しましたが、メモリ バリアを見つけることができません。たとえば、次のようになります。
zskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj) {
zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
unsigned int rank[ZSKIPLIST_MAXLEVEL];
int i, level;
...
level = zslRandomLevel();
if (level > zsl->level) {
for (i = zsl->level; i < level; i++) {
rank[i] = 0;
update[i] = zsl->header;
/////need a mb() ???
update[i]->level[i].span = zsl->length;
}
zsl->level = level;
}
...
}
なぜredisにメモリバリアがないのは特別ですか?
おそらく mb() に対する私の理解は未熟だと思います。コメントありがとうございます...
追加した:
しかし、上記の 2 つのコードでは、Linux カーネルの kfifo が mb() を使用しています。スレッドのスタック空間に割り当てられた変数と、r/w 操作の間のユーザー mb() を変更するだけです。したがって、マルチスレッドに完全に関連するわけではありません...(redisはシングルスレッドですが)