title: Why does this code deadlock?
body: <p>I created 2 Linux kernel threads in my loadable module and I bind them to separate CPU cores running on a dual core Android device. After I run this few times, I noticed that the device reboots with a HW watchdog timer reset. I hit the issue consistently. What could be causing the deadlock?</p>
  
  <p>Basically, what i need to do is, make sure both the threads run do_something() at the same time on different cores without anybody stealing the cpu cycles(i.e. interrupts are disabled). I am using a spinlock and a volatile variable for this. I also have a semaphore for parent thread to wait on child thread.</p>
  
  <pre><code>#define CPU_COUNT 2
  
  /* Globals */
  spinlock_t lock;
  struct semaphore sem;
  volatile unsigned long count;
  
  /* Thread util function for binding the thread to CPU*/
  struct task_struct* thread_init(kthread_fn fn, void* data, int cpu)
  {
      struct task_struct *ts;
  
      ts=kthread_create(fn, data, "per_cpu_thread");
      kthread_bind(ts, cpu);
      if (!IS_ERR(ts)) {
          wake_up_process(ts);
      }
      else {
          ERR("Failed to bind thread to CPU %d\n", cpu);
      }
      return ts;
  }
  
  /* Sync both threads */
  void thread_sync()
  {   
      spin_lock(&amp;lock);
      ++count;
      spin_unlock(&amp;lock); 
  
      while (count != CPU_COUNT);
  }
  
  void do_something()
  {
  }
  
  /* Child thread */
  int per_cpu_thread_fn(void* data)
  {
      int i = 0;
      unsigned long flags = 0;
      int cpu = smp_processor_id();
  
      DBG("per_cpu_thread entering (cpu:%d)...\n", cpu);
  
      /* Disable local interrupts */
      local_irq_save(flags);
  
      /* sync threads */
      thread_sync();
  
      /* Do something */
      do_something();
  
      /* Enable interrupts */
      local_irq_restore(flags);
  
      /* Notify parent about exit */
      up(&amp;sem);
      DBG("per_cpu_thread exiting (cpu:%d)...\n", cpu);
      return value;
  }
  
  /* Main thread */
  int main_thread()
  {
      int cpuB;
      int cpu = smp_processor_id();
      unsigned long flags = 0;
  
      DBG("main thread running (cpu:%d)...\n", cpu);
  
      /* Init globals*/
      sema_init(&amp;sem, 0);
      spin_lock_init(&amp;lock);
      count = 0;
  
      /* Launch child thread and bind to the other CPU core */
      if (cpu == 0) cpuB = 1; else cpuB = 0;        
      thread_init(per_cpu_thread_fn, NULL, cpuB);
  
      /* Disable local interrupts */
      local_irq_save(flags);
  
      /* thread sync */
      thread_sync();
  
      /* Do something here */
      do_something();
  
      /* Enable interrupts */
      local_irq_restore(flags);
  
      /* Wait for child to join */
      DBG("main thread waiting for all child threads to finish ...\n");
      down_interruptible(&amp;sem);
  }
  </code></pre>