/* Generated by Frama-C */
typedef void *framac_mthread_name;
typedef int framac_mthread_id;
typedef framac_mthread_id pthread_t;
typedef framac_mthread_id pthread_attr_t;
typedef framac_mthread_id pthread_mutex_t;
typedef framac_mthread_id pthread_mutexattr_t;
extern int __FRAMAC_MTHREAD_SHARED;
int __FRAMAC_MTHREAD_THREADS_RUNNING = 0;
int __FRAMAC_MTHREAD_THREADS[16];
int __FRAMAC_MTHREAD_MUTEXES[16];
int __FRAMAC_MTHREAD_QUEUES[16];
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern framac_mthread_id __FRAMAC_THREAD_CREATE(framac_mthread_name,
                                                void *(*)(void *) , ...);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern int __FRAMAC_THREAD_START(framac_mthread_id);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern int __FRAMAC_THREAD_SUSPEND(framac_mthread_id);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern int __FRAMAC_THREAD_CANCEL(framac_mthread_id);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern framac_mthread_id __FRAMAC_THREAD_ID();
/*@ terminates \false;
    ensures \false;
    assigns __FRAMAC_MTHREAD_SHARED;  */
extern void __FRAMAC_THREAD_EXIT(void *);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern framac_mthread_id __FRAMAC_MUTEX_INIT(framac_mthread_name);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern int __FRAMAC_MUTEX_LOCK(framac_mthread_id);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern int __FRAMAC_MUTEX_UNLOCK(framac_mthread_id);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern framac_mthread_id __FRAMAC_QUEUE_INIT(framac_mthread_name, int);
/*@ requires \valid(buf+(0..size-1));
    assigns __FRAMAC_MTHREAD_SHARED;  */
extern int __FRAMAC_MESSAGE_SEND(framac_mthread_id id, char const *buf,
                                 int size);
/*@ requires \valid(buf+(0..size-1));
    assigns *buf, __FRAMAC_MTHREAD_SHARED;
    assigns *buf \from \empty;
  
*/
extern int __FRAMAC_MESSAGE_RECEIVE(framac_mthread_id, int size, char *buf);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern void __FRAMAC_MTHREAD_SHOW(char const * , ...);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern void __FRAMAC_MTHREAD_NAME_THREAD(framac_mthread_id,
                                         framac_mthread_name);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern void __FRAMAC_MTHREAD_NAME_MUTEX(framac_mthread_id,
                                        framac_mthread_name);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern void __FRAMAC_MTHREAD_NAME_QUEUE(framac_mthread_id,
                                        framac_mthread_name);
/*@ assigns __FRAMAC_MTHREAD_SHARED;  */
extern void __FRAMAC_MTHREAD_SYNC();
pthread_mutex_t locks[5];
pthread_t jobs[5];
unsigned int matrix[150];
/*@ assigns \at(\result,Post) \from i, prev;  */
extern unsigned int compute(int i, unsigned int prev);
/*@ assigns \at(\result,Post) \from sum;  */
extern int completed(unsigned int sum);
void *job(void *k)
{
  void *__retres;
  int i;
  i = (int)k;
  while (1) {
    pthread_mutex_lock(& locks[i]);
    {
      int j;
      j = i;
      while (1) {
        if (! (j < 150)) { break; }
        matrix[j] = compute(j,matrix[j]);
        j += 5;
      }
    }
    
    pthread_mutex_unlock(& locks[i]);
  }
  return (__retres);
}

int main(void)
{
  int __retres;
  int i;
  int sum;
  sum = 0;
  i = 0;
  while (1) {
    if (! (i < 5)) { break; }
    pthread_mutex_init(& locks[i],(pthread_mutexattr_t *)((void *)0));
    i ++;
  }
  i = 0;
  while (1) {
    if (! (i < 5)) { break; }
    pthread_create(& jobs[i],(pthread_attr_t const *)((void *)0),& job,
                   (void *)i);
    i ++;
  }
  while (1) {
    int tmp;
    tmp = completed((unsigned int)sum);
    if (tmp) { break; }
    sum = 0;
    i = 0;
    if (! (i < 5)) { goto unrolling_2_loop; }
    {
      int *pj_unroll_40;
      pthread_mutex_lock(& locks[i]);
      pj_unroll_40 = (int *)(& matrix[i]);
      while (1) {
        if (! (pj_unroll_40 < & matrix[150])) { break; }
        sum += *pj_unroll_40;
        pj_unroll_40 += 5;
      }
      pthread_mutex_unlock(& locks[i]);
    }
    
    i ++;
    unrolling_7_loop: /* internal */ ;
    if (! (i < 5)) { goto unrolling_2_loop; }
    {
      int *pj_unroll_32;
      pthread_mutex_lock(& locks[i]);
      pj_unroll_32 = (int *)(& matrix[i]);
      while (1) {
        /*@ assert \pointer_comparable(pj_unroll_32, &matrix[150]);
              // synthesized
          
        */
        if (! (pj_unroll_32 < & matrix[150])) { break; }
        sum += *pj_unroll_32;
        pj_unroll_32 += 5;
      }
      pthread_mutex_unlock(& locks[i]);
    }
    
    i ++;
    unrolling_6_loop: /* internal */ ;
    if (! (i < 5)) { goto unrolling_2_loop; }
    {
      int *pj_unroll_24;
      pthread_mutex_lock(& locks[i]);
      pj_unroll_24 = (int *)(& matrix[i]);
      while (1) {
        /*@ assert \pointer_comparable(pj_unroll_24, &matrix[150]);
              // synthesized
          
        */
        if (! (pj_unroll_24 < & matrix[150])) { break; }
        sum += *pj_unroll_24;
        pj_unroll_24 += 5;
      }
      pthread_mutex_unlock(& locks[i]);
    }
    
    i ++;
    unrolling_5_loop: /* internal */ ;
    if (! (i < 5)) { goto unrolling_2_loop; }
    {
      int *pj_unroll_16;
      pthread_mutex_lock(& locks[i]);
      pj_unroll_16 = (int *)(& matrix[i]);
      while (1) {
        /*@ assert \pointer_comparable(pj_unroll_16, &matrix[150]);
              // synthesized
          
        */
        if (! (pj_unroll_16 < & matrix[150])) { break; }
        sum += *pj_unroll_16;
        pj_unroll_16 += 5;
      }
      pthread_mutex_unlock(& locks[i]);
    }
    
    i ++;
    unrolling_4_loop: /* internal */ ;
    if (! (i < 5)) { goto unrolling_2_loop; }
    {
      int *pj_unroll_8;
      pthread_mutex_lock(& locks[i]);
      pj_unroll_8 = (int *)(& matrix[i]);
      while (1) {
        /*@ assert \pointer_comparable(pj_unroll_8, &matrix[150]);
              // synthesized
          
        */
        if (! (pj_unroll_8 < & matrix[150])) { break; }
        sum += *pj_unroll_8;
        pj_unroll_8 += 5;
      }
      pthread_mutex_unlock(& locks[i]);
    }
    
    i ++;
    unrolling_3_loop: /* internal */ ;
    /*@ loop pragma UNROLL 5; */
    while (1) {
      if (! (i < 5)) { break; }
      {
        int *pj;
        pthread_mutex_lock(& locks[i]);
        pj = (int *)(& matrix[i]);
        while (1) {
          if (! (pj < & matrix[150])) { break; }
          sum += *pj;
          pj += 5;
        }
        pthread_mutex_unlock(& locks[i]);
      }
      
      i ++;
    }
    unrolling_2_loop: /* internal */ ;
  }
  __retres = 0;
  return (__retres);
}

int pthread_create(pthread_t *thread, pthread_attr_t const *attr,
                   void *(*start_routine)(void *), void *arg)
{
  int __retres;
  int result;
  result = __FRAMAC_THREAD_CREATE((void *)thread,start_routine,arg);
  if (result > 0) {
    *thread = result;
    __FRAMAC_THREAD_START(result);
    __retres = 0;
    goto return_label;
  }
  else {
    __retres = 11;
    goto return_label; }
  return_label: /* internal */ 
  return (__retres);
}

int pthread_cancel(pthread_t thread)
{
  int result;
  int tmp_0;
  result = __FRAMAC_THREAD_CANCEL(thread);
  if (result != -1) { tmp_0 = 0; }
  else { tmp_0 = 3; }
  return (tmp_0);
}

pthread_t pthread_self(void)
{
  pthread_t tmp;
  tmp = __FRAMAC_THREAD_ID();
  return (tmp);
}

int pthread_mutex_init(pthread_mutex_t * __restrict mutex,
                       pthread_mutexattr_t const * __restrict attr)
{
  int __retres;
  int result;
  result = __FRAMAC_MUTEX_INIT((void *)mutex);
  if (result > 0) {
    *mutex = result;
    __retres = 0;
    goto return_label; }
  else {
    __retres = 22;
    goto return_label; }
  return_label: /* internal */ 
  return (__retres);
}

int pthread_mutex_lock(pthread_mutex_t *mutex)
{
  int result;
  int tmp_0;
  result = __FRAMAC_MUTEX_LOCK(*mutex);
  if (result != -1) { tmp_0 = 0; }
  else { tmp_0 = 22; }
  return (tmp_0);
}

int pthread_mutex_trylock(pthread_mutex_t *mutex)
{
  int result;
  int tmp_0;
  result = __FRAMAC_MUTEX_LOCK(*mutex);
  if (result != -1) { tmp_0 = 0; }
  else { tmp_0 = 22; }
  return (tmp_0);
}

int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
  int result;
  int tmp_0;
  result = __FRAMAC_MUTEX_UNLOCK(*mutex);
  if (result != -1) { tmp_0 = 0; }
  else { tmp_0 = 22; }
  return (tmp_0);
}

void pthread_exit(void *thread_return)
{
  __FRAMAC_THREAD_EXIT(thread_return);
  return;
}

int volatile NON_DET_JOIN;
int pthread_join(pthread_t thread, void **thread_return)
{
  int tmp;
  *thread_return = (void *)NON_DET_JOIN;
  if (NON_DET_JOIN) { tmp = -1; }
  else { tmp = 0; }
  return (tmp);
}

int pthread_setcancelstate(int state, int *oldstate)
{
  int __retres;
  __retres = 0;
  return (__retres);
}

int pthread_setcanceltype(int type, int *oldtype)
{
  int __retres;
  __retres = 0;
  return (__retres);
}

void pthread_testcancel(void)
{
  return;
}

int queuecreate(framac_mthread_name *q, int size)
{
  int __retres;
  *((int *)q) = __FRAMAC_QUEUE_INIT((void *)q,size);
  __retres = 0;
  return (__retres);
}

int msgsnd(int msgqid, char const *mess, int size)
{
  int result;
  result = __FRAMAC_MESSAGE_SEND(msgqid,mess,size);
  return (result);
}

int msgrcv(int msgqid, int size, char *mess)
{
  int tmp;
  tmp = __FRAMAC_MESSAGE_RECEIVE(msgqid,size,mess);
  return (tmp);
}