0

比較と交換を使用して c でロック フリー キューを実装するように依頼されましたが、ポインターに関する知識はかなり限られています。

次のコードを使用して、(まだ不完全な) デキューの実装をテストしていますが、ポインター/演算子のアドレスを適切に使用する方法がよくわからないため、無限にループしていると思います。

私はアセンブラについて何も知らないので、この CAS 関数を使用するように与えられました。

long __cdecl compare_exchange(long *flag, long oldvalue, long newvalue)
{
    __asm
    {
        mov ecx, flag
        mov eax, oldvalue
        mov ebx, newvalue
        lock cmpxchg [ecx], ebx
        jz iftrue
    }
    return 0;
    iftrue: return 1;
}

私の現在の(関連する)コードは次のとおりです...

typedef struct QueueItem
{
    int data;
    struct QueueItem* next;
}item;

struct Queue
{
    item *head;
    item *tail;
}*queue;

int Dequeue()
{
    item *head;

    do
    {
        head = queue->head;
        if(head == NULL)
            return NULL_ITEM;
        printf("%d, %d, %d\n", (long *)queue->head, (long)&head, (long)&head->next);
    }
    while(!compare_exchange((long *)queue->head, (long)&head, (long)&head->next)); // Infinite loop.

    return head->data;
}

int main(int argc, char *argv[])
{
    item i, j;

    queue = (struct Queue *) malloc(sizeof(struct Queue));

    // Manually enqueue some data for testing dequeue.
    i.data = 5;
    j.data = 10;
    i.next = &j;
    j.next = NULL;

    queue->head = &i;

    printf("Dequeued: %d\n", Dequeue());
    printf("Dequeued: %d\n", Dequeue());
}

do while ループ内で not 演算子を使用する必要がありますか? その演算子を使用しない場合、"Dequeued 5" x2 の出力が得られます。これは、スワップが発生していないことを示しており、not を使用する必要があることを示しています。もしそうなら、どこが間違っていますか?ポインター/アドレス演算子の問題であることにお金をかけます。

4

1 に答える 1

0

ポインターと値には混乱があります。修正されたコードは次のとおりです。

 do
 {
    head = queue->head;
    if(head == NULL)
        return 0;
    printf("%d, %d, %d %d\n", (long *)queue->head, (long)head, (long)head->next, head->data);
  }  while (!compare_exchange((long *)&queue->head,   (long)head, (long)head->next));

queue->head 自体の値ではなく、queue->head が指しているものを書き込もうとしていました。

また、マルチコアで正常に動作させるには、head を volatile として定義する必要があると思います。

struct Queue
{
   volatile item *head;
   item *tail;
}*queue;
于 2012-08-24T03:51:01.690 に答える