[haiku-commits] haiku: hrev48139 - src/system/kernel headers/private/kernel

  • From: mmlr@xxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 29 Oct 2014 00:26:13 +0100 (CET)

hrev48139 adds 1 changeset to branch 'master'
old head: 4ed39e6a62d82721004656c5a1ecf19cb8e73e75
new head: 52d500e5b4abc36a9c2106de52412da5324ca9ee
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=52d500e+%5E4ed39e6

----------------------------------------------------------------------------

52d500e: kernel: Workaround for double lock of spinlock in user timers.
  
  The thread that is being [un]scheduled already has its time_lock locked
  in {stop|continue}_cpu_timers(). When updating the TeamTimeUserTimer,
  the team is asked for its cpu time. Team::CPUTime() then iterates the
  threads of the team and locks the time_lock of the thread again.
  
  This workaround passes a possibly locked thread through the relevant
  functions so Team::CPUTime() can decide whether or not a thread it
  iterates needs to be locked or not.
  
  This works around #11032 and its duplicates #11314 and #11344.

                                            [ Michael Lotz <mmlr@xxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev48139
Commit:      52d500e5b4abc36a9c2106de52412da5324ca9ee
URL:         http://cgit.haiku-os.org/haiku/commit/?id=52d500e
Author:      Michael Lotz <mmlr@xxxxxxxx>
Date:        Tue Oct 28 22:37:30 2014 UTC

Ticket:      https://dev.haiku-os.org/ticket/11032
Ticket:      https://dev.haiku-os.org/ticket/11314
Ticket:      https://dev.haiku-os.org/ticket/11344

----------------------------------------------------------------------------

4 files changed, 18 insertions(+), 11 deletions(-)
headers/private/kernel/UserTimer.h    |  6 ++++--
headers/private/kernel/thread_types.h |  3 ++-
src/system/kernel/UserTimer.cpp       | 12 ++++++------
src/system/kernel/team.cpp            |  8 ++++++--

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/UserTimer.h 
b/headers/private/kernel/UserTimer.h
index 026aa55..ca880be 100644
--- a/headers/private/kernel/UserTimer.h
+++ b/headers/private/kernel/UserTimer.h
@@ -117,14 +117,16 @@ struct TeamTimeUserTimer : public UserTimer {
 
                        void                            Deactivate();
 
-                       void                            Update(Thread* 
unscheduledThread);
+                       void                            Update(Thread* 
unscheduledThread,
+                                                                       Thread* 
lockedThread = NULL);
                        void                            TimeWarped(bigtime_t 
changedBy);
 
 protected:
        virtual void                            HandleTimer();
 
 private:
-                       void                            _Update(bool 
unscheduling);
+                       void                            _Update(bool 
unscheduling,
+                                                                       Thread* 
lockedThread = NULL);
 
 private:
                        team_id                         fTeamID;
diff --git a/headers/private/kernel/thread_types.h 
b/headers/private/kernel/thread_types.h
index a48a480..1bbab89 100644
--- a/headers/private/kernel/thread_types.h
+++ b/headers/private/kernel/thread_types.h
@@ -388,7 +388,8 @@ public:
        inline  TeamUserTimeUserTimerList::ConstIterator
                                                                        
UserTimeUserTimerIterator() const;
 
-                       bigtime_t                       CPUTime(bool 
ignoreCurrentRun) const;
+                       bigtime_t                       CPUTime(bool 
ignoreCurrentRun,
+                                                                       Thread* 
lockedThread = NULL) const;
                        bigtime_t                       UserCPUTime() const;
 
 private:
diff --git a/src/system/kernel/UserTimer.cpp b/src/system/kernel/UserTimer.cpp
index 88aa78a..8f1514e 100644
--- a/src/system/kernel/UserTimer.cpp
+++ b/src/system/kernel/UserTimer.cpp
@@ -625,7 +625,7 @@ TeamTimeUserTimer::Deactivate()
                currently running and which is in the process of being 
unscheduled.
 */
 void
-TeamTimeUserTimer::Update(Thread* unscheduledThread)
+TeamTimeUserTimer::Update(Thread* unscheduledThread, Thread* lockedThread)
 {
        if (fTeam == NULL)
                return;
@@ -639,7 +639,7 @@ TeamTimeUserTimer::Update(Thread* unscheduledThread)
                        fRunningThreads++;
        }
 
-       _Update(unscheduledThread != NULL);
+       _Update(unscheduledThread != NULL, lockedThread);
 }
 
 
@@ -695,7 +695,7 @@ TeamTimeUserTimer::HandleTimer()
                being unscheduled.
 */
 void
-TeamTimeUserTimer::_Update(bool unscheduling)
+TeamTimeUserTimer::_Update(bool unscheduling, Thread* lockedThread)
 {
        // unschedule the kernel timer, if scheduled
        if (fScheduled)
@@ -708,7 +708,7 @@ TeamTimeUserTimer::_Update(bool unscheduling)
        }
 
        // There are still threads running. Reschedule the kernel timer.
-       bigtime_t now = fTeam->CPUTime(unscheduling);
+       bigtime_t now = fTeam->CPUTime(unscheduling, lockedThread);
 
        // If periodic, check whether the start time is too far in the past.
        if (fInterval > 0)
@@ -1560,7 +1560,7 @@ user_timer_stop_cpu_timers(Thread* thread, Thread* 
nextThread)
                for (TeamTimeUserTimerList::ConstIterator it
                                        = 
thread->team->CPUTimeUserTimerIterator();
                                TeamTimeUserTimer* timer = it.Next();) {
-                       timer->Update(thread);
+                       timer->Update(thread, thread);
                }
        }
 }
@@ -1574,7 +1574,7 @@ user_timer_continue_cpu_timers(Thread* thread, Thread* 
previousThread)
                for (TeamTimeUserTimerList::ConstIterator it
                                        = 
thread->team->CPUTimeUserTimerIterator();
                                TeamTimeUserTimer* timer = it.Next();) {
-                       timer->Update(NULL);
+                       timer->Update(NULL, thread);
                }
        }
 
diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp
index a775d1b..e8c58de 100644
--- a/src/system/kernel/team.cpp
+++ b/src/system/kernel/team.cpp
@@ -924,7 +924,7 @@ Team::DeactivateCPUTimeUserTimers()
        \return The team's current total CPU time.
 */
 bigtime_t
-Team::CPUTime(bool ignoreCurrentRun) const
+Team::CPUTime(bool ignoreCurrentRun, Thread* lockedThread) const
 {
        bigtime_t time = cpu_clock_offset + dead_threads_kernel_time
                + dead_threads_user_time;
@@ -934,13 +934,17 @@ Team::CPUTime(bool ignoreCurrentRun) const
 
        for (Thread* thread = thread_list; thread != NULL;
                        thread = thread->team_next) {
-               SpinLocker threadTimeLocker(thread->time_lock);
+               bool alreadyLocked = thread == lockedThread;
+               SpinLocker threadTimeLocker(thread->time_lock, alreadyLocked);
                time += thread->kernel_time + thread->user_time;
 
                if (thread->last_time != 0) {
                        if (!ignoreCurrentRun || thread != currentThread)
                                time += now - thread->last_time;
                }
+
+               if (alreadyLocked)
+                       threadTimeLocker.Detach();
        }
 
        return time;


Other related posts:

  • » [haiku-commits] haiku: hrev48139 - src/system/kernel headers/private/kernel - mmlr