Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 17 Jan 2010 14:22:00 +0900 (JST)
From:      Kohji Okuno <okuno.kohji@jp.panasonic.com>
To:        freebsd-current@freebsd.org
Cc:        okuno.kohji@jp.panasonic.com
Subject:   Bug about sched_4bsd?
Message-ID:  <20100117.142200.321689433999177718.okuno.kohji@jp.panasonic.com>

next in thread | raw e-mail | index | archive | help
Hello, 

I think that sched_4bsd.c:sched_switch() has a problem.


I encounterd the problem that a process could not exit. 
That process has multi threads and p_flag was as below.

 p_flag : (P_INMEM|P_STOPPED_SINGLE|P_EXEC|P_SINGLE_EXIT|P_PPWAIT|P_CONTROLT)


One thread (THREAD A) was suspended as below.
 sched_switch()
 mi_switch()
 thread_suspend_switch()
 thread_single()
 exit1()
 sys_exit()

 td_flags : TDF_NEEDSIGCHK|TDF_ASTPENDING|TDF_CANSWAP|TDF_INMEM


Another thread (THREAD B) was sleeping as below.
 sched_switch()
 mi_switch()
 sleepq_switch()
 sleepq_catch_signals()
 sleepq_wait_sig()
 _cv_wait_sig()
 seltdwait()
 kern_select()
 select()

 td_flags : TDF_CANSWAP|TDF_SINTR|TDF_INMEM


That process could not exit, because THREAD B did not execute
"thread_suspend_check()" and THREAD A had been suspended.


I think that the race condition had occurred about td_flags as below.

In sched_switch(), when td->td_lock is not &sched_lock, td->td_lock
will be unlocked as shown below. And then, td->td_flags will change
without td->td_lock.


<<THREAD A>>
  kern_thread.c:
  int
  thread_single(int mode)
  {
          ...

          thread_lock(td2);
          td2->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK;
          
   *** I think that td2 specified THREAD B in this time.
      
<<THREAD B>>
  sched_4bsd.c:
  void
  sched_switch(struct thread *td, struct thread *newtd, int flags)
  {
          ...

          /*
           * Switch to the sched lock to fix things up and pick
           * a new thread.
           */
          if (td->td_lock != &sched_lock) {
                  mtx_lock_spin(&sched_lock);
                  thread_unlock(td);
          }

   *** I think that td_lock was sleepqueue_chagin->sc_lock.
          ...

          td->td_lastcpu = td->td_oncpu;
          td->td_flags &= ~TDF_NEEDRESCHED;
          td->td_owepreempt = 0;
          td->td_oncpu = NOCPU;

--
Thanks,
 Kohji Okuno.




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20100117.142200.321689433999177718.okuno.kohji>