title: Deadlock while implementing shared queue in c
body: <pre><code>#include "pc.h"
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  
  
  /**
  
  Contents of pc.h
  
  #ifndef __PC__H
  #define __PC__H
  
  #include &lt;pthread.h&gt;
  
  #define ITEM(q, i) (q-&gt;pc_buffer + q-&gt;pc_item_size * i)
  
  struct pc_queue_t {
      void *pc_buffer;
      size_t pc_next_full, pc_next_empty, pc_cur_size, pc_max_size, pc_item_size;
      pthread_cond_t pc_empty, pc_full;
      pthread_mutex_t pc_mutex;
  };
  
  struct pc_queue_t *alloc_q(size_t item_size, size_t no_of_items);
  
  void pc_insert(struct pc_queue_t *q, void *item);
  
  void *pc_remove(struct pc_queue_t *q);
  
  void free_queue(struct pc_queue_t *q);
  
  
  #endif
  
  **/
  
  
  struct pc_queue_t *alloc_q(size_t item_size, size_t no_of_items) {
      struct pc_queue_t *q   = (struct pc_queue_t *)malloc(sizeof(struct pc_queue_t));
      q-&gt;pc_buffer    = malloc(item_size * no_of_items);
      q-&gt;pc_next_full = q-&gt;pc_next_empty = q-&gt;pc_cur_size = 0;
      q-&gt;pc_item_size = item_size;
      q-&gt;pc_max_size  = no_of_items;
      // q-&gt;pc_empty     = PTHREAD_COND_INITIALIZER;
      // q-&gt;pc_full      = PTHREAD_COND_INITIALIZER;
      // q-&gt;pc_mutex     = PTHREAD_MUTEX_INITIALIZER;
      pthread_cond_init(&amp;q-&gt;pc_empty, NULL);
      pthread_cond_init(&amp;q-&gt;pc_full, NULL);
      pthread_mutex_init(&amp;q-&gt;pc_mutex, NULL);
      return q;
  }
  
  
  void pc_insert(struct pc_queue_t *q, void *item) {
      pthread_mutex_lock(&amp;q-&gt;pc_mutex);
      while(q-&gt;pc_cur_size == q-&gt;pc_max_size) 
          pthread_cond_wait(&amp;q-&gt;pc_empty, &amp;q-&gt;pc_mutex);
      q-&gt;pc_cur_size++;
      memcpy(ITEM(q, q-&gt;pc_next_empty), item, q-&gt;pc_item_size);
      q-&gt;pc_next_empty = (q-&gt;pc_next_empty + 1) % q-&gt;pc_max_size;
      pthread_mutex_unlock(&amp;q-&gt;pc_mutex);
      pthread_cond_signal(&amp;q-&gt;pc_full);
  }
  
  void *pc_remove(struct pc_queue_t *q) {
      pthread_mutex_lock(&amp;q-&gt;pc_mutex);
      while(q-&gt;pc_cur_size == 0) 
          pthread_cond_wait(&amp;q-&gt;pc_full, &amp;q-&gt;pc_mutex);
      q-&gt;pc_cur_size--;
      void *ret_item = ITEM(q, q-&gt;pc_next_full);
      q-&gt;pc_next_full = (q-&gt;pc_next_full + 1) % q-&gt;pc_max_size;
      pthread_mutex_unlock(&amp;q-&gt;pc_mutex);
      pthread_cond_signal(&amp;q-&gt;pc_empty);
      return ret_item;
  }
  
  void free_queue(struct pc_queue_t *q) {
      if(!q) return;
      free(q-&gt;pc_buffer);
      free(q);
  }
  </code></pre>
  
  <p>I was trying to solve the produer-consumer synchronisation problem with mutex and condition variables in c. And I'm stuck. Can someone help me figure out whats wrong with the above given code. pc_insert method works good. But for some reason, pc_remove method never returns from it's first call. What could be the problem?</p>
  
  <p>And this is how I used it --></p>
  
  <pre><code>typedef struct pc_queue_t shared_q;
  
  void *consumer(void *buf) {
      shared_q *q = (shared_q *)buf;
      while(true) {
          int *p = (int *)pc_remove(q);
          printf("Removed %d\n", *p);
          free(p);
          sleep(1);
      }
      return NULL;
  }
  
  void *producer(void *buf) {
      shared_q *q = (shared_q *)buf;
      int data = 0;
      while(true) {
          int *p = (int *)malloc(sizeof(int));
          *p = data++;
          pc_insert(q, p);
          printf("Inserted %d\n", data);
          sleep(1);
      }
      return NULL;
  }
  
  int main() {
      shared_q *q = alloc_q(sizeof(int), 5);
      pthread_t t1, t2;
      int succ = pthread_create(&amp;t1, NULL, producer, q) &amp;&amp;
              pthread_create(&amp;t2, NULL, consumer, q);
      if(succ) {
          perror("Failed to create threads!");
          exit(1);
      }
      pthread_join(t1, NULL);
      pthread_join(t2, NULL);
      return 0;
  }
  </code></pre>