Jack2  1.9.8
JackEngineControl.cpp
00001 /*
00002 Copyright (C) 2003 Paul Davis
00003 Copyright (C) 2004-2008 Grame
00004 
00005 This program is free software; you can redistribute it and/or modify
00006 it under the terms of the GNU Lesser General Public License as published by
00007 the Free Software Foundation; either version 2.1 of the License, or
00008 (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU Lesser General Public License for more details.
00014 
00015 You should have received a copy of the GNU Lesser General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 
00019 */
00020 
00021 #include "JackClientInterface.h"
00022 #include "JackEngineControl.h"
00023 #include "JackGraphManager.h"
00024 #include "JackClientControl.h"
00025 #include <algorithm>
00026 #include <math.h>
00027 
00028 namespace Jack
00029 {
00030 
00031 static inline jack_time_t JACK_MAX(jack_time_t a, jack_time_t b)
00032 {
00033     return (a < b) ? b : a;
00034 }
00035 
00036 void JackEngineControl::CalcCPULoad(JackClientInterface** table,
00037                                     JackGraphManager* manager,
00038                                     jack_time_t cur_cycle_begin,
00039                                     jack_time_t prev_cycle_end)
00040 {
00041     fPrevCycleTime = fCurCycleTime;
00042     fCurCycleTime = cur_cycle_begin;
00043     jack_time_t last_cycle_end = prev_cycle_end;
00044 
00045     // In Asynchronous mode, last cycle end is the max of client end dates
00046     if (!fSyncMode) {
00047         for (int i = fDriverNum; i < CLIENT_NUM; i++) {
00048             JackClientInterface* client = table[i];
00049             JackClientTiming* timing = manager->GetClientTiming(i);
00050             if (client && client->GetClientControl()->fActive && timing->fStatus == Finished)
00051                 last_cycle_end = JACK_MAX(last_cycle_end, timing->fFinishedAt);
00052         }
00053     }
00054 
00055     // Store the execution time for later averaging
00056     if (last_cycle_end > 0)
00057         fRollingClientUsecs[fRollingClientUsecsIndex++] = last_cycle_end - fPrevCycleTime;
00058     if (fRollingClientUsecsIndex >= JACK_ENGINE_ROLLING_COUNT)
00059         fRollingClientUsecsIndex = 0;
00060 
00061     // Each time we have a full set of iterations, recompute the current
00062     // usage from the latest JACK_ENGINE_ROLLING_COUNT client entries.
00063     if (fRollingClientUsecsCnt && (fRollingClientUsecsIndex == 0)) {
00064         jack_time_t avg_usecs = 0;
00065         jack_time_t max_usecs = 0;
00066 
00067         for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) {
00068             avg_usecs += fRollingClientUsecs[i]; // This is really a running
00069                                                  // total to be averaged later
00070             max_usecs = JACK_MAX(fRollingClientUsecs[i], max_usecs);
00071         }
00072 
00073         fMaxUsecs = JACK_MAX(fMaxUsecs, max_usecs);
00074 
00075         if (max_usecs < ((fPeriodUsecs * 95) / 100)) {
00076             // Average the values from our JACK_ENGINE_ROLLING_COUNT array
00077             fSpareUsecs = (jack_time_t)(fPeriodUsecs - (avg_usecs / JACK_ENGINE_ROLLING_COUNT));
00078         } else {
00079             // Use the 'worst case' value (or zero if we exceeded 'fPeriodUsecs')
00080             fSpareUsecs = jack_time_t((max_usecs < fPeriodUsecs) ? fPeriodUsecs - max_usecs : 0);
00081         }
00082 
00083         fCPULoad = ((1.f - (float(fSpareUsecs) / float(fPeriodUsecs))) * 50.f + (fCPULoad * 0.5f));
00084     }
00085 
00086     fRollingClientUsecsCnt++;
00087 }
00088 
00089 void JackEngineControl::ResetRollingUsecs()
00090 {
00091     memset(fRollingClientUsecs, 0, sizeof(fRollingClientUsecs));
00092     fRollingClientUsecsIndex = 0;
00093     fRollingClientUsecsCnt = 0;
00094     fSpareUsecs = 0;
00095     fRollingInterval = int(floor((JACK_ENGINE_ROLLING_INTERVAL * 1000.f) / fPeriodUsecs));
00096 }
00097 
00098 void JackEngineControl::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs)
00099 {
00100     ResetFrameTime(callback_usecs);
00101     fXrunDelayedUsecs = delayed_usecs;
00102     if (delayed_usecs > fMaxDelayedUsecs)
00103         fMaxDelayedUsecs = delayed_usecs;
00104 }
00105 
00106 } // end of namespace