Think Stitch
  最近の更新


生産者・消費者問題 3

今回も Pthread Model Checker を使って生産者・消費者問題を調べます.

前回に引き続き,条件変数を1個にまとめたモデルを使います.バッファ長 2,生産者,消費者ともに2個にするとデッドロックはありません.

0  signal をロックの外で呼び出す

前回のモデルでは pthread_cond_signal をロックの中で呼び出していました.

void *producer(void *arg)
{
    while (true) {
        pthread_mutex_lock(&mutex);
        while (count == N) {
            pthread_cond_wait(&cv, &mutex);
        }
        count++;
        pthread_cond_signal(&cv);               // *A
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

これをロックの外にもっていったらどうなるでしょうかというのが今回の問題です.

void *producer(void *arg)
{
    while (true) {
        pthread_mutex_lock(&mutex);
        while (count == N) {
            pthread_cond_wait(&cv, &mutex);
        }
        count++;
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&cv);               // *B
    }
    return NULL;
}

検査をしてみるとデッドロックがあります.パスの長さは 104 ステップありますが,サマリーを作りながら読んでいくとそれほどたいへんではありません.レポートは長いので付録にまわして,サマリーを見てみます.

#13 pthc[0] lock mutex
#16 pthc[0] load count
#20 pthc[0] wait cv mutex

#21 pthc[1] lock mutex
#22 pthc[1] load count
#25 pthc[1] wait cv mutex

#26 pthp[1] lock mutex
#29 pthp[1] load count
#30 pthp[1] store count
    count = 1
#31 pthp[1] unlock mutex
    4 pthc[1] 24 wait cv
#32 pthp[1] signal cv
    4 pthc[1] 24

#33 pthp[1] lock mutex
#36 pthp[1] load count
#37 pthp[1] store count
    count = 2
#38 pthp[1] unlock mutex

#40 pthp[0] lock mutex
#41 pthp[0] load count
#43 pthp[0] wait cv mutex

    1 pthp[0] 34 wait cv
    2 pthp[1] 37
    3 pthc[0] 24 wait cv
    4 pthc[1] 24
#44 pthp[1] signal cv
    1 pthp[0] 34
    2 pthp[1] 37
    3 pthc[0] 24 wait cv
    4 pthc[1] 24

#45 pthp[1] lock mutex
#46 pthp[1] load count
#48 pthp[1] wait cv mutex

#49 pthp[0] lock mutex
#50 pthp[0] load count
#52 pthp[0] wait cv mutex

#53 pthc[1] lock mutex
#56 pthc[1] load count
#57 pthc[1] store count
    count = 1
    1 pthp[0] 34 wait cv
    2 pthp[1] 34 wait cv
    3 pthc[0] 24 wait cv
    4 pthc[1] 26
#58 pthc[1] signal cv
    1 pthp[0] 34 wait cv
    2 pthp[1] 34 wait cv
    3 pthc[0] 24
    4 pthc[1] 26
#59 pthc[1] unlock mutex

#60 pthc[1] lock mutex
#63 pthc[1] load count
#64 pthc[1] store count
    count = 0
#65 pthc[1] signal cv
#66 pthc[1] unlock mutex

#67 pthc[1] lock mutex
#68 pthc[1] load count
#70 pthc[1] wait cv mutex

#71 pthc[0] lock mutex
#72 pthc[0] load count
#74 pthc[0] wait cv mutex

#75 pthp[1] lock mutex
#78 pthp[1] load count
#79 pthp[1] store count
    count = 1
#80 pthp[1] unlock mutex
#81 pthp[1] signal cv

#82 pthp[1] lock mutex
#85 pthp[1] load count
#86 pthp[1] store count
    count = 2
#87 pthp[1] unlock mutex
                                (A)
#88 pthp[0] lock mutex
#89 pthp[0] load count
#91 pthp[0] wait cv mutex

    1 pthp[0] 34 wait cv
    2 pthp[1] 37
    3 pthc[0] 24 wait cv
    4 pthc[1] 24 wait cv
#92 pthp[1] signal cv           (B)
    1 pthp[0] 34
    2 pthp[1] 37
    3 pthc[0] 24 wait cv
    4 pthc[1] 24 wait cv

#93 pthp[1] lock mutex
#94 pthp[1] load count
#98 pthp[1] wait cv mutex

#99 pthp[0] lock mutex
#100 pthp[0] load count
#104 pthp[0] wait cv mutex
    1 pthp[0] 34 wait cv
    2 pthp[1] 34 wait cv
    3 pthc[0] 24 wait cv
    4 pthc[1] 24 wait cv

生産者の signal がロックの外にあるので,unlock と signal の間で他のスレッドが動いている箇所がいくつかあります.そのうち致命的なのは最後のところです.

(A) のところを見てください.生産者 pthp[1] がデータを置いてバッファがフルになったあと,signal を発行する前にもう1つの生産者 pthp[0] が動いて,バッファフルを見て wait します.そのあとで pthp[1] が signal を発行しますが,これがいま wait したばかりの pthp[0] を起こしてしまっています.

その結果,前回のようにバッファがフルなのに生産者だけが起きているという状況になり,デッドロックに至るというわけです.

このコードを実際にコンパイルして動かしてみたのですが,デッドロックさせることができませんでした.デッドロックを持つモデルはたいていの場合は再現させることができるんですけど,これは何度やってもできませんでした.たしかに unlock と signal の間に別のスレッドが絶妙に入らないと起きないわけですから難しいのはわかるんですけど,sleep を入れたりしてもだめでした.うまくいった人がいたらやり方を教えてください.

実行させるテストだと,起動した瞬間起きる場合もあれば数秒かかる場合,時には数分生き延びる場合もあります.4コアだと起きるのに1コアだとまったく起きないなんてこともありました.やはりマルチスレッドプログラムのテストはたいへんです.

2017/10/10

1  レポートファイル

------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 1
------------------------
#1 main tau
59: for (i = 0; i < NP; ++i) {
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 2
    i = 0
------------------------
#2 main tau
59: for (i = 0; i < NP; ++i) {
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 3
    i = 0
------------------------
#3 main create pthp[0]
60: pthread_create(&pthp[i], NULL, &producer, (void *)(intptr_t)i);
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 5
    i = 0
1 pthp[0] 28
    arg = 0
------------------------
#4 main tau
59: for (i = 0; i < NP; ++i) {
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 2
    i = 1
1 pthp[0] 28
    arg = 0
------------------------
#5 main tau
59: for (i = 0; i < NP; ++i) {
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 3
    i = 1
1 pthp[0] 28
    arg = 0
------------------------
#6 main create pthp[1]
60: pthread_create(&pthp[i], NULL, &producer, (void *)(intptr_t)i);
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 5
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
------------------------
#7 main tau
59: for (i = 0; i < NP; ++i) {
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 2
    i = 2
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
------------------------
#8 main tau
59: for (i = 0; i < NP; ++i) {
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 4
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
------------------------
#9 main tau
63: for (i = 0; i < NC; ++i) {
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 6
    i = 0
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
------------------------
#10 main tau
63: for (i = 0; i < NC; ++i) {
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 7
    i = 0
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
------------------------
#11 main create pthc[0]
64: pthread_create(&pthc[i], NULL, &consumer, (void *)(intptr_t)i);
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 0
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 18
    arg = 0
------------------------
#12 pthc[0] tau
40: while (true) {
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 0
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 19
------------------------
#13 pthc[0] lock mutex
41: pthread_mutex_lock(&mutex);
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[0]
thread:
0 main 9
    i = 0
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 20
------------------------
#14 main tau
63: for (i = 0; i < NC; ++i) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[0]
thread:
0 main 6
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 20
------------------------
#15 main tau
63: for (i = 0; i < NC; ++i) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[0]
thread:
0 main 7
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 20
------------------------
#16 pthc[0] load count
42: while (count == 0) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[0]
thread:
0 main 7
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 21
    t14 = 0
------------------------
#17 main create pthc[1]
64: pthread_create(&pthc[i], NULL, &consumer, (void *)(intptr_t)i);
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[0]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 21
    t14 = 0
4 pthc[1] 18
    arg = 1
------------------------
#18 pthc[0] tau
42: while (count == 0) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[0]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 22
4 pthc[1] 18
    arg = 1
------------------------
#19 pthc[1] tau
40: while (true) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[0]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 22
4 pthc[1] 19
------------------------
#20 pthc[0] wait cv mutex
44: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 24 wait cv
4 pthc[1] 19
------------------------
#21 pthc[1] lock mutex
41: pthread_mutex_lock(&mutex);
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 24 wait cv
4 pthc[1] 20
------------------------
#22 pthc[1] load count
42: while (count == 0) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 24 wait cv
4 pthc[1] 21
    t14 = 0
------------------------
#23 pthc[1] tau
42: while (count == 0) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 28
    arg = 1
3 pthc[0] 24 wait cv
4 pthc[1] 22
------------------------
#24 pthp[1] tau
21: while (true) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 29
3 pthc[0] 24 wait cv
4 pthc[1] 22
------------------------
#25 pthc[1] wait cv mutex
44: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 29
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#26 pthp[1] lock mutex
22: pthread_mutex_lock(&mutex);
------------------------
global vars:
    count = 0
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 30
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#27 pthp[1] load count
23: while (count == N) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 31
    t16 = 0
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#28 pthp[1] tau
23: while (count == N) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 33
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#29 pthp[1] load count
28: count++;
------------------------
global vars:
    count = 0
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 35
    t17 = 0
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#30 pthp[1] store count
28: count++;
------------------------
global vars:
    count = 1
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 36
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#31 pthp[1] unlock mutex
30: pthread_mutex_unlock(&mutex);
------------------------
global vars:
    count = 1
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#32 pthp[1] signal cv
32: pthread_cond_signal(&cv); // ###
------------------------
global vars:
    count = 1
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 29
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#33 pthp[1] lock mutex
22: pthread_mutex_lock(&mutex);
------------------------
global vars:
    count = 1
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 30
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#34 pthp[1] load count
23: while (count == N) {
------------------------
global vars:
    count = 1
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 31
    t16 = 1
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#35 pthp[1] tau
23: while (count == N) {
------------------------
global vars:
    count = 1
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 33
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#36 pthp[1] load count
28: count++;
------------------------
global vars:
    count = 1
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 35
    t17 = 1
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#37 pthp[1] store count
28: count++;
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 36
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#38 pthp[1] unlock mutex
30: pthread_mutex_unlock(&mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 28
    arg = 0
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#39 pthp[0] tau
21: while (true) {
------------------------
global vars:
    count = 2
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 29
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#40 pthp[0] lock mutex
22: pthread_mutex_lock(&mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 9
    i = 1
1 pthp[0] 30
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#41 pthp[0] load count
23: while (count == N) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 9
    i = 1
1 pthp[0] 31
    t16 = 2
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#42 pthp[0] tau
23: while (count == N) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 9
    i = 1
1 pthp[0] 32
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#43 pthp[0] wait cv mutex
25: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#44 pthp[1] signal cv
32: pthread_cond_signal(&cv); // ###
------------------------
global vars:
    count = 2
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 29
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#45 pthp[1] lock mutex
22: pthread_mutex_lock(&mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 30
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#46 pthp[1] load count
23: while (count == N) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 31
    t16 = 2
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#47 pthp[1] tau
23: while (count == N) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 32
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#48 pthp[1] wait cv mutex
25: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#49 pthp[0] lock mutex
25: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 9
    i = 1
1 pthp[0] 30
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#50 pthp[0] load count
23: while (count == N) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 9
    i = 1
1 pthp[0] 31
    t16 = 2
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#51 pthp[0] tau
23: while (count == N) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 9
    i = 1
1 pthp[0] 32
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#52 pthp[0] wait cv mutex
25: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 24
------------------------
#53 pthc[1] lock mutex
44: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 20
------------------------
#54 pthc[1] load count
42: while (count == 0) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 21
    t14 = 2
------------------------
#55 pthc[1] tau
42: while (count == 0) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 23
------------------------
#56 pthc[1] load count
47: count--;
------------------------
global vars:
    count = 2
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 25
    t15 = 2
------------------------
#57 pthc[1] store count
47: count--;
------------------------
global vars:
    count = 1
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 26
------------------------
#58 pthc[1] signal cv
49: pthread_cond_signal(&cv);
------------------------
global vars:
    count = 1
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24
4 pthc[1] 27
------------------------
#59 pthc[1] unlock mutex
50: pthread_mutex_unlock(&mutex);
------------------------
global vars:
    count = 1
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24
4 pthc[1] 19
------------------------
#60 pthc[1] lock mutex
41: pthread_mutex_lock(&mutex);
------------------------
global vars:
    count = 1
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24
4 pthc[1] 20
------------------------
#61 pthc[1] load count
42: while (count == 0) {
------------------------
global vars:
    count = 1
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24
4 pthc[1] 21
    t14 = 1
------------------------
#62 pthc[1] tau
42: while (count == 0) {
------------------------
global vars:
    count = 1
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24
4 pthc[1] 23
------------------------
#63 pthc[1] load count
47: count--;
------------------------
global vars:
    count = 1
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24
4 pthc[1] 25
    t15 = 1
------------------------
#64 pthc[1] store count
47: count--;
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24
4 pthc[1] 26
------------------------
#65 pthc[1] signal cv
49: pthread_cond_signal(&cv);
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34
3 pthc[0] 24
4 pthc[1] 27
------------------------
#66 pthc[1] unlock mutex
50: pthread_mutex_unlock(&mutex);
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34
3 pthc[0] 24
4 pthc[1] 19
------------------------
#67 pthc[1] lock mutex
41: pthread_mutex_lock(&mutex);
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34
3 pthc[0] 24
4 pthc[1] 20
------------------------
#68 pthc[1] load count
42: while (count == 0) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34
3 pthc[0] 24
4 pthc[1] 21
    t14 = 0
------------------------
#69 pthc[1] tau
42: while (count == 0) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34
3 pthc[0] 24
4 pthc[1] 22
------------------------
#70 pthc[1] wait cv mutex
44: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34
3 pthc[0] 24
4 pthc[1] 24 wait cv
------------------------
#71 pthc[0] lock mutex
44: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[0]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34
3 pthc[0] 20
4 pthc[1] 24 wait cv
------------------------
#72 pthc[0] load count
42: while (count == 0) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[0]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34
3 pthc[0] 21
    t14 = 0
4 pthc[1] 24 wait cv
------------------------
#73 pthc[0] tau
42: while (count == 0) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthc[0]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34
3 pthc[0] 22
4 pthc[1] 24 wait cv
------------------------
#74 pthc[0] wait cv mutex
44: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 0
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 34
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#75 pthp[1] lock mutex
25: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 0
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 30
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#76 pthp[1] load count
23: while (count == N) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 31
    t16 = 0
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#77 pthp[1] tau
23: while (count == N) {
------------------------
global vars:
    count = 0
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 33
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#78 pthp[1] load count
28: count++;
------------------------
global vars:
    count = 0
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 35
    t17 = 0
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#79 pthp[1] store count
28: count++;
------------------------
global vars:
    count = 1
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 36
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#80 pthp[1] unlock mutex
30: pthread_mutex_unlock(&mutex);
------------------------
global vars:
    count = 1
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#81 pthp[1] signal cv
32: pthread_cond_signal(&cv); // ###
------------------------
global vars:
    count = 1
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 29
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#82 pthp[1] lock mutex
22: pthread_mutex_lock(&mutex);
------------------------
global vars:
    count = 1
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 30
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#83 pthp[1] load count
23: while (count == N) {
------------------------
global vars:
    count = 1
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 31
    t16 = 1
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#84 pthp[1] tau
23: while (count == N) {
------------------------
global vars:
    count = 1
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 33
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#85 pthp[1] load count
28: count++;
------------------------
global vars:
    count = 1
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 35
    t17 = 1
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#86 pthp[1] store count
28: count++;
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 36
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#87 pthp[1] unlock mutex
30: pthread_mutex_unlock(&mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#88 pthp[0] lock mutex
25: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 9
    i = 1
1 pthp[0] 30
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#89 pthp[0] load count
23: while (count == N) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 9
    i = 1
1 pthp[0] 31
    t16 = 2
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#90 pthp[0] tau
23: while (count == N) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 9
    i = 1
1 pthp[0] 32
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#91 pthp[0] wait cv mutex
25: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34 wait cv
2 pthp[1] 37
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#92 pthp[1] signal cv
32: pthread_cond_signal(&cv); // ###
------------------------
global vars:
    count = 2
mutex:
    mutex <unlocked>
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 29
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#93 pthp[1] lock mutex
22: pthread_mutex_lock(&mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 30
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#94 pthp[1] load count
23: while (count == N) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 31
    t16 = 2
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#95 pthp[1] tau
23: while (count == N) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[1]
thread:
0 main 9
    i = 1
1 pthp[0] 34
2 pthp[1] 32
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#96 main tau
63: for (i = 0; i < NC; ++i) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[1]
thread:
0 main 6
    i = 2
1 pthp[0] 34
2 pthp[1] 32
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#97 main tau
63: for (i = 0; i < NC; ++i) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[1]
thread:
0 main 8
1 pthp[0] 34
2 pthp[1] 32
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#98 pthp[1] wait cv mutex
25: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex <unlocked>
thread:
0 main 8
1 pthp[0] 34
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#99 pthp[0] lock mutex
25: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 8
1 pthp[0] 30
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#100 pthp[0] load count
23: while (count == N) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 8
1 pthp[0] 31
    t16 = 2
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#101 main tau
67: for (i = 0; i < NP; ++i) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 10
    i = 0
1 pthp[0] 31
    t16 = 2
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#102 pthp[0] tau
23: while (count == N) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 10
    i = 0
1 pthp[0] 32
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#103 main tau
67: for (i = 0; i < NP; ++i) {
------------------------
global vars:
    count = 2
mutex:
    mutex pthp[0]
thread:
0 main 11
    i = 0
1 pthp[0] 32
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
#104 pthp[0] wait cv mutex
25: pthread_cond_wait(&cv, &mutex);
------------------------
global vars:
    count = 2
mutex:
    mutex <unlocked>
thread:
0 main 11
    i = 0
1 pthp[0] 34 wait cv
2 pthp[1] 34 wait cv
3 pthc[0] 24 wait cv
4 pthc[1] 24 wait cv
------------------------
© 2013-2017 PRINCIPIA Limited