title: Pthreads- Mutex Locks but variables don't change
body: <p>I'm writing an extremely simple program to demonstrate a Pthreads implementation I ported from C++ back to C.</p>
  <p>I create two lock-step threads and give them two jobs</p>
  <p>One increments a1 once per step</p>
  <p>One decrements a2 once per step</p>
  <p>During the synchronized phase (When the mutexes are locked for both t1 and t2) I compare a1 and a2 to see if we should stop stepping.</p>
  <p>I'm wondering if i'm going crazy here because not only does the variable <em>not always change after stepping and locking</em> but they sometimes <em>change at different rates</em> as if the threads were running even after the locks.</p>
  <p>EDIT: Yes, I did research this. Yes, the C++ implementation works. Yes, the C++ implementation is nearly identical to this one, but I had to cast PTHREAD_MUTEX_INITIALIZER and PTHREAD_COND_INITIALIZER in c and pass this as the first argument to every function. I spent a while trying to debug this (short of whipping out gdb) to no avail.</p>
  <pre><code>#ifndef LOCKSTEPTHREAD_H
  #define LOCKSTEPTHREAD_H
  #include &lt;pthread.h&gt;
  #include &lt;stdio.h&gt;
  typedef struct {
      pthread_mutex_t myMutex;
      pthread_cond_t myCond;
      pthread_t myThread;
      int isThreadLive;
      int shouldKillThread;
      void (*execute)();
  } lsthread;
  void init_lsthread(lsthread* t);
  void start_lsthread(lsthread* t);
  void kill_lsthread(lsthread* t);
  void kill_lsthread_islocked(lsthread* t);
  void lock(lsthread* t);
  void step(lsthread* t);
  void* lsthread_func(void* me_void);
  #ifdef LOCKSTEPTHREAD_IMPL
  //function declarations
  
  void init_lsthread(lsthread* t){
      //pthread_mutex_init(&amp;(t-&gt;myMutex), NULL);
      //pthread_cond_init(&amp;(t-&gt;myCond), NULL);
      t-&gt;myMutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
      t-&gt;myCond = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
      t-&gt;isThreadLive = 0;
      t-&gt;shouldKillThread = 0;
      t-&gt;execute = NULL;
  }
  void destroy_lsthread(lsthread* t){
      pthread_mutex_destroy(&amp;t-&gt;myMutex);
      pthread_cond_destroy(&amp;t-&gt;myCond);
  }
  void kill_lsthread_islocked(lsthread* t){
      if(!t-&gt;isThreadLive)return;
      //lock(t);
      t-&gt;shouldKillThread = 1;
      step(t);
      pthread_join(t-&gt;myThread,NULL);
      t-&gt;isThreadLive = 0;
      t-&gt;shouldKillThread = 0;
  }
  
  void kill_lsthread(lsthread* t){
      if(!t-&gt;isThreadLive)return;
      lock(t);
      t-&gt;shouldKillThread = 1;
      step(t);
      pthread_join(t-&gt;myThread,NULL);
      t-&gt;isThreadLive = 0;
      t-&gt;shouldKillThread = 0;
  }
  void lock(lsthread* t){
      if(pthread_mutex_lock(&amp;t-&gt;myMutex))
          puts(&quot;\nError locking mutex.&quot;);
  }
  
  void step(lsthread* t){
      if(pthread_cond_signal(&amp;(t-&gt;myCond)))
          puts(&quot;\nError signalling condition variable&quot;);
      if(pthread_mutex_unlock(&amp;(t-&gt;myMutex)))
          puts(&quot;\nError unlocking mutex&quot;);
  }
  void* lsthread_func(void* me_void){
      lsthread* me = (lsthread*) me_void;
      int ret;
      if (!me)pthread_exit(NULL);
      if(!me-&gt;execute)pthread_exit(NULL);
      while (!(me-&gt;shouldKillThread)) {
          ret = pthread_cond_wait(&amp;(me-&gt;myCond), &amp;(me-&gt;myMutex));
          if(ret)pthread_exit(NULL);
          if (!(me-&gt;shouldKillThread) &amp;&amp; me-&gt;execute)
              me-&gt;execute();
      }
      pthread_exit(NULL);
  }
  void start_lsthread(lsthread* t){
      if(t-&gt;isThreadLive)return;
      t-&gt;isThreadLive = 1;
      t-&gt;shouldKillThread = 0;
      pthread_create(
          &amp;t-&gt;myThread,
          NULL,
          lsthread_func,
          (void*)t
      );
  }
  #endif
  #endif
  </code></pre>
  <p>This is my driver program:</p>
  <pre><code>#define LOCKSTEPTHREAD_IMPL
  #include &quot;include/lockstepthread.h&quot;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;math.h&gt;
  unsigned char a1, a2;
  void JobThread1(){
      unsigned char copy = a1;
      copy++;
      a1 = copy;
  }
  void JobThread2(){
      unsigned char copy = a2;
      copy--;
      a2 = copy;
  }
  int main(){
      char inputline[2048];
      inputline[2047] = '\0';
      lsthread t1, t2;
      init_lsthread(&amp;t1);
      init_lsthread(&amp;t2);
      t1.execute = JobThread1;
      t2.execute = JobThread2;
      printf(
      &quot;\nThis program demonstrates threading by having&quot;
      &quot;\nTwo threads \&quot;walk\&quot; toward each other using unsigned chars.&quot;
      &quot;\nunsigned Integer overflow guarantees the two will converge.&quot;
      );
      printf(&quot;\nEnter a number for thread 1 to process: &quot;);
      fgets(inputline, 2047,stdin);
      a1 = (unsigned char)atoi(inputline);
      printf(&quot;\nEnter a number for thread 2 to process: &quot;);
      fgets(inputline, 2047,stdin);
      a2 = (unsigned char)atoi(inputline);
      start_lsthread(&amp;t1);
      start_lsthread(&amp;t2);
      unsigned int i = 0;
      lock(&amp;t1);
      lock(&amp;t2);
      do{
          printf(&quot;\n%u: a1 = %d, a2 = %d&quot;,i++,(int)a1,(int)a2);
          fflush(stdout);
          step(&amp;t1);
          step(&amp;t2);
          lock(&amp;t1);
          lock(&amp;t2);
      }while(a1 &lt; a2);
      kill_lsthread_islocked(&amp;t1);
      kill_lsthread_islocked(&amp;t2);
      destroy_lsthread(&amp;t1);
      destroy_lsthread(&amp;t2);
      return 0;
  }
  </code></pre>
  <p>Example program usage:</p>
  <pre><code>Enter a number for thread 1 to process: 5
  
  Enter a number for thread 2 to process: 10
  
  0: a1 = 5, a2 = 10
  1: a1 = 5, a2 = 10
  2: a1 = 5, a2 = 10
  3: a1 = 5, a2 = 10
  4: a1 = 5, a2 = 10
  5: a1 = 5, a2 = 10
  6: a1 = 6, a2 = 9
  7: a1 = 6, a2 = 9
  8: a1 = 7, a2 = 9
  9: a1 = 7, a2 = 9
  10: a1 = 7, a2 = 9
  11: a1 = 7, a2 = 9
  12: a1 = 8, a2 = 9
  </code></pre>
  <p>So, what's the deal?</p>