Spinroot

A forum for Spin users

You are not logged in.

#1 General » Unclear why an assert failed (modex) » 2015-02-02 03:02:50

Dharma
Replies: 2

The following C code (based on a OS book) implements a concurrent queue. http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks-usage.pdf (Figure 29.8) has the basic code used here.

In the test driver, I just have one reader and one writer.

I'm not sure why the assert(tmp != NULL) in the Queue_Init false. It happens only if I include the sample_reader as part of the extraction in the prx file.

I'm using the Queue_Init only from Queue_Enqueue, which sets the ready flag to true, making it possible for the Queue_Dequeue to run.


Thanks a lot for your help in advance.


#include <pthread.h>
#include <assert.h>

struct __node_t {
        int value;
        struct __node_t *next;
};

typedef struct __node_t node_t;

struct __queue_t {
        node_t *head;
        node_t *tail;
        pthread_mutex_t headLock;
        pthread_mutex_t tailLock;
};

typedef struct __queue_t queue_t;


void Queue_Init(queue_t *q) {
        node_t *tmp;

        tmp = (node_t*)cq_malloc(sizeof(node_t));
        assert(tmp != NULL);
        tmp->next = NULL;
        q->head = q->tail = tmp;
        pthread_mutex_init(&q->headLock, NULL);
        pthread_mutex_init(&q->tailLock, NULL);
}

void Queue_Enqueue(queue_t *q, int value) {
        node_t *tmp;

        tmp = (node_t*)cq_malloc(sizeof(node_t));
        assert(tmp != NULL);
        tmp->value = value;
        tmp->next = NULL;

        pthread_mutex_lock(&q->tailLock);
        q->tail->next = tmp;
        q->tail = tmp;
        pthread_mutex_unlock(&q->tailLock);
}

int Queue_Dequeue(queue_t *q, int *value) {
        node_t *tmp;
        node_t *newHead;

        pthread_mutex_lock(&q->headLock);
        tmp = q->head;
        newHead = tmp->next;

        if (newHead == NULL) {
                pthread_mutex_unlock(&q->headLock);
                return -1; // queue was empty
        }

        *value = newHead->value;
        q->head = newHead;
        pthread_mutex_unlock(&q->headLock);
        cq_free(tmp);
        return 0;
}

/* Test driver */
queue_t queue;
int Ready = 0;

void
sample_writer(void)
{       int i;

        Queue_Init(&queue);

        Ready = 1;

        for(i = 0; i < 5; i++)
        {
           Queue_Enqueue(&queue, i);
        }

}

void
sample_reader(void)
{
        int j = 0;
        int i = 0;
        int status = -1;

        while(!Ready)
        {
           ;
        }

        for(i = 0 ; i < 5; i++) {
                status = Queue_Dequeue(&queue, &j);
                if(status == -1)
                {
                        i = i - 1;
                }
                else {
                        assert(i == j);
                }
        }
}


----

%X -a sample_writer
%X -a sample_reader
%X -e Queue_Init
%X -e Queue_Enqueue
%X -e Queue_Dequeue
%G
        shortest: 1
%%
%C

#define MAX_HEAP        200

int cnt = 0;
char heap[MAX_HEAP];

char *
cq_malloc(unsigned int n)
{       char *p;
        p = (void *) 0;

        if (cnt + n <= sizeof(heap))
        {       p = &heap[cnt];
                cnt += n;
        }
        return p;
}

void
cq_free(void *p)
{
  p = NULL;
}

------------------

#2 Re: General » modex - compilation error » 2015-01-27 00:05:05

Never mind. I managed to fix it.

#3 General » modex - compilation error » 2015-01-26 03:55:47

Dharma
Replies: 1

Hi,
I'm trying the following C program but Modex is complaining.

    Extract Model:
    ==============
modex prod_cons_two_signals.c
MODEX Version 2.7 - 1 January 2015
created: model and _modex_.run

    Compile and Run:
    ================
sh _modex_.run
spin: model:66, Error: undeclared variable: get    saw ''(' = 40'
---


The following C program uses get() and put(int). They both are externally defined in another file. I put %O put_get.o in my prx file. That's the only thing in my prx file.

/* 1 producer; 2 consumers; two signals (fill, empty) */

#include <pthread.h>
#include <assert.h>

pthread_mutex_t mutex;
pthread_cond_t empty;
pthread_cond_t fill;

extern int count;
extern int get();
extern void put(int);


void *producer(void *arg) {
   int i;
   while(1) {
      pthread_mutex_lock(&mutex);
      while (count == 1)
        pthread_cond_wait(&empty, &mutex);
      put(i);
      pthread_cond_signal(&fill);
      pthread_mutex_unlock(&mutex);
   }
}


void *consumer(void *arg) {
    int i;
    while(1) {
       pthread_mutex_lock(&mutex);
       while(count == 0)
         pthread_cond_wait(&fill, &mutex);
       int tmp = get();
       pthread_cond_signal(&empty);
       pthread_mutex_unlock(&mutex);
    }
}


void main()
{
   pthread_t t1, t2, t3;
   pthread_mutex_init(&mutex, NULL);
   pthread_cond_init(&fill, NULL);
   pthread_cond_init(&empty, NULL);

   pthread_create(&t1, NULL, producer, NULL);
   pthread_create(&t2, NULL, consumer, NULL);
   pthread_create(&t3, NULL, consumer, NULL);

   pthread_join(t1, NULL);
   pthread_join(t2, NULL);
   pthread_join(t3, NULL);
}

#4 Re: General » race condition issue in C program » 2015-01-24 01:17:35

Hi,
Thanks. No, the shared variable can also be -1.

The problem I think is possibly in the interpretation of shared-- (or shared++) as one atomic entity. I may be wrong, of course.

I disassembled it for our discussion on a 64 bit VM.

shared++ is from instruction starting at 8 until 16.

0000000000000000 <thread1>:
   0:    55                       push   %rbp
   1:    48 89 e5                 mov    %rsp,%rbp
   4:    48 89 7d f8              mov    %rdi,-0x8(%rbp)
   8:    8b 05 00 00 00 00        mov    0x0(%rip),%eax        # e <thread1+0xe>
   e:    83 c0 01                 add    $0x1,%eax
  11:    89 05 00 00 00 00        mov    %eax,0x0(%rip)        # 17 <thread1+0x17>
  17:    b8 00 00 00 00           mov    $0x0,%eax
  1c:    5d                       pop    %rbp
  1d:    c3                       retq

shared-- is from instruction starting at 26 until 34.

000000000000001e <thread2>:
  1e:    55                       push   %rbp
  1f:    48 89 e5                 mov    %rsp,%rbp
  22:    48 89 7d f8              mov    %rdi,-0x8(%rbp)
  26:    8b 05 00 00 00 00        mov    0x0(%rip),%eax        # 2c <thread2+0xe>
  2c:    83 e8 01                 sub    $0x1,%eax
  2f:    89 05 00 00 00 00        mov    %eax,0x0(%rip)        # 35 <thread2+0x17>
  35:    b8 00 00 00 00           mov    $0x0,%eax
  3a:    5d                       pop    %rbp
  3b:    c3                       retq


What if the second thread 2 ran first and read the shared variable into its register, say eax. Now the eax register has just 0.

Assume context switch happens to thread 1, which also read shared variable's value 0 into its copy of register eax. Assume thread 1 finished the job, now shared is 1.

Assume now thread 2 runs, it will decrement its own copy of the eax register, from 0 to -1. Now -1 will be copied back to shared.

Just out of curiosity, I ran the divine model checker and it agrees that there is a possibility of shared to be -1. I did not make any effort in understanding the long trace they generated.

You may also try: http://divine.fi.muni.cz/try.cgi

#5 General » race condition issue in C program » 2015-01-23 02:39:51

Dharma
Replies: 3

Hi,

I'm playing with Modex to better understand it.

For the following C program, I have two threads: one for increment and another for decrement of a global variable.

I think the global variable "shared" can take the value -1 as well. That is, the assert below is incorrect but Modex is not reporting it.

I wonder whether Modex treats each C statement as an atomic statement. The problem is that, as you know, shared=shared+1 or shared++ is made of multiple instructions at the assembly level. Thus, race condition is possible here.

Could you please share your thoughts?

#include <pthread.h>
#include <assert.h>

// verify  race.c

int shared = 0;
pthread_mutex_t mutex;

void *
thread1(void *arg)
{
  shared++;
  return 0;
}

void *
thread2(void *arg)
{
  shared--;
  return 0;
}

int
main(void)
{
   pthread_t t[2];
   pthread_mutex_init(&mutex, 0);

   pthread_create(&t[0], 0, thread1, 0);
   pthread_create(&t[1], 0, thread2, 0);

   pthread_join(t[0], 0);
   pthread_join(t[1], 0);

   assert(shared == 1 || shared == 0); /* Modex agrees to this - but shared can be -1, too */

   return 0;
}

#6 General » unreached in proctype... » 2015-01-22 21:34:35

Dharma
Replies: 1

Hi,

I tried the following C program without any .prx file. The tool showed the following output:

unreached in proctype p_thread1
    model:49, state 23, "-end-"
    (1 of 23 states)
unreached in proctype p_thread2
    model:71, state 23, "-end-"
    (1 of 23 states)
unreached in proctype p_main
    (0 of 23 states)

--
Could you please explain the reason for unreached in these processes?

There are two threads: One for increment and another for decrement of a global variable.


#include <pthread.h>
#include <assert.h>

// verify 3_threads_new.c

int shared = 0;
pthread_mutex_t mutex;

void *
thread1(void *arg)
{       int tmp;

        pthread_mutex_lock( &mutex );
        tmp = shared;
        tmp++;
        shared = tmp;
        pthread_mutex_unlock( &mutex );

        return 0;
}

void *
thread2(void *arg)
{       int tmp;

         pthread_mutex_lock(&mutex);
         tmp = shared;
         tmp--;
         shared = tmp;
         pthread_mutex_unlock(&mutex);

         return 0;
}

int
main(void)
{
        pthread_t t[2];
        pthread_mutex_init(&mutex, 0);

        pthread_create(&t[0], 0, thread1, 0);
        pthread_create(&t[1], 0, thread2, 0);

        pthread_join(t[0], 0);
        pthread_join(t[1], 0);

        assert(shared == 1 || shared == 0);

        return 0;
}

#7 General » problem with the "verify" script? » 2015-01-22 21:29:23

Dharma
Replies: 1

Hi,
I'm using the latest version of modex - downloaded it two weeks ago.

When I ran verify 4_mutex.c, which is part of the modex/example, it says no error was found.

However, when I ran ./pan it does show the violation of  an assertion.

dharma@ubuntu:~/Downloads/modex/Examples$ verify 4_mutex.c

    Extract Model:
    ==============
modex 4_mutex.c
MODEX Version 2.7 - 1 January 2015
created: model and _modex_.run

    Compile and Run:
    ================
sh _modex_.run
hint: this search is more efficient if pan.c is compiled -DSAFETY
pan: out of memory
    662568 bytes used
    4.29497e+09 bytes more needed
    1.57286e+10 bytes limit
hint: to reduce memory, recompile with
  -DBITSTATE # supertrace, approximation

(Spin Version 6.4.3 -- 16 December 2014)
Warning: Search not completed
    + Partial Order Reduction

Hash-Compact 4 search for:
    never claim             - (none specified)
    assertion violations    +
    acceptance   cycles     - (not selected)
    invalid end states    +

State-vector 179 byte, depth reached 0, errors: 0
        0 states, stored
        0 states, matched
        0 transitions (= stored+matched)
        0 atomic steps
hash conflicts:         0 (resolved)

Stats on memory usage (in Megabytes):
    0.000    equivalent memory usage for states (stored*(State-vector + overhead))
    0.000    actual memory usage for states (less than 1k)
4096.000    memory used for hash table (-w29)
    0.534    memory used for DFS stack (-m10000)
    0.632    total actual memory usage



pan: elapsed time 1.73e+07 seconds
pan: rate         0 states/second

No Errors Found
----

dharma@ubuntu:~/Downloads/modex/Examples$ ./pan
hint: this search is more efficient if pan.c is compiled -DSAFETY
pan:1: c_code line 103 precondition false: (now.cnt==1) (at depth 59)
pan: wrote model.trail

(Spin Version 6.4.3 -- 16 December 2014)
Warning: Search not completed
    + Partial Order Reduction

Hash-Compact 4 search for:
    never claim             - (none specified)
    assertion violations    +
    acceptance   cycles     - (not selected)
    invalid end states    +

State-vector 260 byte, depth reached 100, errors: 1
     3643 states, stored
     2442 states, matched
     6085 transitions (= stored+matched)
     1012 atomic steps
hash conflicts:         0 (resolved)

Stats on memory usage (in Megabytes):
    1.001    equivalent memory usage for states (stored*(State-vector + overhead))
    0.373    actual memory usage for states (compression: 37.27%)
             state-vector as stored = 79 byte + 28 byte overhead
  128.000    memory used for hash table (-w24)
    0.534    memory used for DFS stack (-m10000)
  128.827    total actual memory usage



pan: elapsed time 0.07 seconds
pan: rate 52042.857 states/second

#8 General » unreached in init? » 2011-09-26 15:53:59

Dharma
Replies: 1

Hi,

I modeled the Petri net given in [url]http://en.wikipedia.org/wiki/File:Two-boundedness-cb.png[/url] using Promela as follows.

#define Place byte /* assume < 256 tokens per place */
Place p1, p2
Place cp1, cp2
#define inp1(x) (x>0) -> x=x-1
#define inp2(x,y) (x>0&&y>0) -> x = x-1; y=y-1
#define out1(x) x=x+1
#define out2(x,y) x=x+1; y=y+1
init
{ cp1 = 2; cp2 = 2; /* initial marking */
do
/*t1*/ :: atomic { inp1(cp1) -> out1(p1) }
/*t2*/ :: atomic { inp2(p1, cp2) -> out2(p2, cp1) }
/*t3*/ :: atomic { inp1(p2) -> out1(cp2) }
od
}

I was curious to check the 2-bounded property of this Petri net using spin. Got this output form spin:

unreached in init
    cp_net3.pml:15, state 20, "-end-"
    (1 of 20 states)


Does it mean that this model will not terminate?  Of course, the petri net is always running without any deadlock as far as I can see manually.

Of course, this model is based on SPIN exercises/examples.

#9 Re: General » Modex - syntax error » 2011-09-24 18:36:12

Great. Just modified the modex.c to use spin instead of spin4, and also added -O option directly in the modex.c file.

It works! Cool stuff. Thanks.

#10 General » Modex - syntax error » 2011-09-24 15:26:09

Dharma
Replies: 3

Tried the threads.c example given in the manual of Modex. Got this syntax error:

pan.m: In function 'do_transit':

pan.m:29: error: 'P1' has no member typed 'tmp'
pan.m:41: error: 'P1' has no member typed 'tmp'
pan.m:53: error: 'P1' has no member typed 'tmp'

pan.m:102: error: 'P0' has no member typed 'tmp'
pan.m:114: error: 'P0' has no member typed 'tmp'
pan.m:126: error: 'P0' has no member typed 'tmp'

No Errors Found



Any comment?

#11 Re: General » Visualizing the counter-example of an assertion violation » 2011-09-24 00:40:34

Ha ha, it was a typo in the ACM Inroads: " A Primer on Model Checking" by Mordechai (Moti) Ben-Ari, see page 44

Yes, counter == 10 not counter = 10.

Thanks!

#12 Re: General » Visualizing the counter-example of an assertion violation » 2011-09-23 23:43:10

Thanks. Tried it. It is mind-boggling to see the assertion violation. It is still unclear to me how come n is 0 when finish is 2. Any comment?

The output I got

ubuntu@ubuntu10:~/Downloads/Spin/iSpin/ltl_examples$ spin -p -g -l -v -t primer.pml

spin: warning, primer.pml, proctype P, 'byte  counter' variable is never used
i=3 pno 1
  1:    proc  1 (P) primer.pml:5 (state 1)    [counter = 10]
        P(1):counter = 10
i=3 pno 0
  2:    proc  0 (P) primer.pml:5 (state 1)    [counter = 10]
        P(0):counter = 10
i=3 pno 1
  3:    proc  1 (P) primer.pml:12 (state 11)    [finish = (finish+1)]
        finish = 1
i=3 pno 0
  4:    proc  0 (P) primer.pml:12 (state 11)    [finish = (finish+1)]
        finish = 2
i=3 pno 2
  5:    proc  2 (WaitForFinish) primer.pml:16 (state 1)    [((finish==2))]
i=3 pno 2
spin: primer.pml:17, Error: assertion violated
spin: text of failed assertion: assert((n>0))
  6:    proc  2 (WaitForFinish) primer.pml:17 (state 2)    [assert((n>0))]
spin: trail ends after 6 steps
#processes: 3
        n = 0
        finish = 2
  6:    proc  2 (WaitForFinish) primer.pml:18 (state 3) <valid end state>
  6:    proc  1 (P) primer.pml:13 (state 12) <valid end state>
  6:    proc  0 (P) primer.pml:13 (state 12) <valid end state>
3 processes created

#13 General » Visualizing the counter-example of an assertion violation » 2011-09-21 17:31:04

Dharma
Replies: 5

Hi,

Tried spin on the model given below. It reported a violation of the assertion. Is there a way to see the actual interleaving that led to this violation?


        byte n = 0, finish = 0;

        active [2] proctype P() {
          byte register, counter = 0;
          do :: counter = 10 -> break
              :: else ->
                     register = n;
                     register++;
                     n = register;
                     counter++
          od;
          finish++
        }

        active proctype WaitForFinish() {
          finish == 2;
          assert (n > 0);
        }


Tried spin -s -t primer.pml and got this output. It appears n = 0. But not clear to me what interleaving has led to this failure. Any comments? Thank a lot.


-----
spin: primer.pml:17, Error: assertion violated
spin: text of failed assertion: assert((n>0))
spin: trail ends after 6 steps
#processes: 3
        n = 0
        finish = 2
  6:    proc  2 (WaitForFinish) primer.pml:18 (state 3) <valid end state>
  6:    proc  1 (P) primer.pml:13 (state 12) <valid end state>
  6:    proc  0 (P) primer.pml:13 (state 12) <valid end state>
3 processes created

---

Board footer

Powered by FluxBB