4

私は興味深い問題を抱えています。完全に私のせいだといいのですが。

次のように、キューから読み取るコードがあります。

 do {
    evt       = &newevts[ evt_head++ ];
    evt_head &=  MAX_EVENTS;

    if (evt->index <= 0 || evt->index > MAX_INDEX) {
         printf("RX EVENT BAD NDX: ndx=%d h=%d\n",evt->index, evt_head);
         continue;
    }

    //... etc ...

 } while(evt_head != evt_tail) ;

奇妙な問題は、if ステートメントが evt->index が不適切な値であると評価される可能性があることですが、printf が表示されると、完全に有効な値が表示されます! 例:

RX EVENT BAD NDX: ndx=1 h=64

if ステートメントは、条件が <= 0 OR > 1024 (最大インデックス) でなければならないことを明確に示しています。さらに悪いことに、これはたまにしか発生しません。私はGCC、Centos 6.3を使用しています。このスレッド以外のスレッドは evt_head に触れません。(私はそれを数回名前を変更し、念のため再コンパイルしました。)

テールは、ヘッドがアイテムを削除するのと同じ方法でキューにアイテムを追加する関数によって処理されます (インクリメントしてから AND)。また、イベント構造自体の内部にカウンターを追加して、イベントがキューに配置されたときにヘッド/テール値を記録し、失われた値やスキップされた値を検出しませんでした。文字通り、メモリの読み取りに問題があるように見えます。しかし、それはばかげています。もしそうなら、システムがクラッシュするか、少なくともプログラムがクラッシュすると思います。

世界でこれが散発的にどのように発生する可能性があるかについてのアイデアはありますか? (頻度は 100 回の読み取りのうち約 1 回です) ご意見をお待ちしております。

typedef struct {
    int    index;
    int    event;
} EVENT;

#define  MAX_EVENTS  0x01ff
#define  MAX_INDEX   1024

evt_head に触れるスレッドやその他のコードはありません。このループだけ。キューがいっぱいになることはありません。また、キューに追加されるルーチンへのエントリに "SPIN LOCK" があり (後で他のスレッドからアクセスされる場合に備えて)、終了時に UNLOCK があります。

4

1 に答える 1

2

私の推測では、イベントを末尾に追加する関数は、フィールドevt_tailを書き込む前に変更されると思います。indexこれにより、リーダーはまだ書き込み中のイベントにアクセスできます。

于 2013-01-22T06:09:45.990 に答える