File: Priority.m

package info (click to toggle)
psychtoolbox-3 3.0.9%2Bsvn2579.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 63,408 kB
  • sloc: ansic: 73,310; cpp: 11,139; objc: 3,129; sh: 1,669; python: 382; php: 272; makefile: 172; java: 113
file content (332 lines) | stat: -rw-r--r-- 14,267 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
function oldPriority=Priority(newPriority)

% oldPriority=Priority([newPriority])
%
% OS X: ___________________________________________________________________
%
% Unlike on OS 9 and Windows, On OS X setting a high priority will not
% disable important parts of your computer such as the keybaord and hard
% drive. Priority calls the Psychtoolbox mex function MachSetPriority.  For
% simple, OS-neutral control of process priority on OS X use Priority. For
% complicated, fine-grained, OS-specific control of process priority use
% MachSetPriority.    
%
% At priority settings greater than 0, your script must limit MATLAB's  use
% of CPU time to stay within the limits specified by the priority value.
% The consequence of failing to restrict the CPU time to the limits
% specified by the priority values is that OS X will demote MATLAB back to
% priority 0.  You can check to see if this has happened by calling
% Priority with no arguments.
%
% Within a script there are two ways to limit MATLAB's use of CPU time:
%
%   1. Call "WaitSecs" 
%   2. Call Screen('Flip',...)
% 
% Both calls will sleep the main MATLAB thread, surrendering CPU time to
% other threads on the system until the MATLAB thread is awakened.
% WaitSecs sleeps the MATLAB thread for a specified period.
% Screen('Flip',...) sleeps the MATLAB thread until the next video blanking
% interval.
%
% The priority value corresponds to the proportion of the video frame
% period  during which MATLAB is guranteed 100 percent of CPU time:
%
%   GuaranteedCPUtimePerFramePeriod = priority/10 * framePeriod
%
% If your computer has multiple video displays running at different frame
% rates then Priority will choose the shortest frame period.
%
% The consequence of a thread exceeding the specified limits on CPU usage
% are that the MACH kernel will revoke its real-time priority status.
% However, the threshold at which the MACH kernel decices to revoke
% priority is not known.  We have observed that at 100% CPU usage the
% Jaguar Mach kernel will revoke priority after 2.5 seconds, indepent of
% the CPU time requested when setting priority.  
%
% Note that if you change the video frame rate after setting priority then
% the framePeriod which Priority used when setting the priority level will
% no longer match the true frame period. Therefore you should change the
% priority level after changing the video mode and not before. 
%
% MacOS-X version before 10.4.7: __________________________________________
%
% Because the OS X update process causes setjmp calls within MATLAB to
% delay for up to about 13ms, Priority kills the system update process when
% setting any priority greater than 0.  Priority will restart the update
% proceess when setting priority back to 0, but only if it was Priority
% itself which killed the update process.  If update was already killed
% when Priority was set to a level greater than 0 then priority will not
% restart the update process when restoring priority to 0. You can use
% KillUpdateProcess and StartUpdateProcess to kill and restart the update
% process  without using Prioirity.  Because killing and starting the
% update process sometimes requires that an adminstrator password be
% entered in the MATLAB command window,  you might prefer not kill and
% restart  with every call to Priority, but instead to do this only at the
% beginning and end of a MATLAB session by using KillUpdateProcess and
% StartUpdateProcess.
%
% MacOS-X version 10.4.7 and later: _______________________________________
%
% Due to improvements in the realtime behaviour of OS-X 10.4.7 and later,
% it is no longer neccessary to kill the update process. If Priority()
% detects such an OS version, it will not kill update anymore. This
% provides an over hundred-fold speedup in the execution of Priority(). If
% you think that timing gets worse on your system, you can check the timing
% by running the test command 'TestMATLABTimingOSX'. If you rather want
% Priority to kill the update process on 10.4.7 and later, please create a
% file with the name 'AlwaysKillUpdate' in the Psychtoolbox root folder to
% enforce killing of the update process. The content of the file does not
% matter at all.
%
%
% WINDOWS: ________________________________________________________________
% 
% For the Windows version of Priority (and Rush), the priority levels set
% are  "process priority levels". There are 3 priority levels available,
% levels 0, 1, and 2. Level 0 is "normal priority level", level 1 is "high
% priority level", and level 2 is "real time priority level". Combined with
% thread priority levels, they determine the absolute priority level of the
% matlab  thread. Threads are executed in a "round robin" fashion on
% Windows, with the  lower priority threads getting cpu time slice only
% when no higher priority thread  is ready to execute. Currently, no tests
% had been done to see what tasks are pre-empted by setting the Matlab
% process to real-time priority. It does seem to block keyboard input,
% though, so for example if you have a clut animation going on at priority
% level 2, then the force-quit key combo (Ctrl-Alt-Delete) does not  work.
% However, the keyboard inputs are still sent to the message queue, so
% GetChar or GetClicks still work if they are also called at priority level
% 2.
% 
% LINUX: __________________________________________________________________
%
% GNU/Linux supports priority levels between 0 and 99. Zero means standard
% non-realtime timesharing operation -- Play fair with all other
% applications. Increasing values greater than zero mean realtime mode: The
% Matlab/Octave process is scheduled in round robin realtime mode with a
% priority corresponding to the given number - higher means better, but
% also more likelihood of interfering with system processes. Try to stick
% to a level of 1 unless you know what you're doing!
%
% In realtime mode, PTB will also try to lock down all of Matlab/Octaves
% memory into physical RAM, preventing it from being paged out to disk by
% the virtual memory manager. If it works, it's great! However, the amount
% of lockable memory is restricted to max. 50% of installed RAM memory on
% a standard Linux setup, so if Matlab/Octave/your experiment would need
% more than 50% of available system memory, this will fail. PTB will output
% an informative warning in this case, but continue otherwise unaffected.
% Realtime scheduling will be still effective, you'll just lose the bonus
% of memory locking.
%
% Be careful not to create any uninterruptible infinite loops in your code
% when running realtime, otherwise your system may lock up, reqiring a
% hard reboot!
% _________________________________________________________________________
%
% see also OS X:    Rush
% see also Windows: Rush
% see also OS 9:    Rush, ScreenTest, RushTest, LoopTest

% NOTES:
% priorityStruct looks like this.   
%
% threadID:
% flavor: 'THREAD_TIME_CONSTRAINT_POLICY'
% policy:
%     period: 
%     computation: 
%     constraint: 
%     preemptible: 
% policySize:
% policyFillSize:
% getDefault:
% isDefault:

% HISTORY:
% 4/13/97   dgp  Wrote it
% 4/22/97   dgp  Updated
% 5/1/97    dgp  Updated
% 5/31/97   dgp  Updated
% 6/3/97    dgp  Updated
% 3/15/99   xmz  Added comments for Windows version.
% 2/4/00    dgp  Updated for Mac OS 9.
% 6/13/02   awi  Cosmetic 
% 12/11/03  awi  Wrote documentation and scripting for OS X
% 7/16/03   awi  Merged together documetation for OS X and OS 9 and
%                Windows.
% 8/24/05   awi  Kill and start update under standard, not time constraint
%                priority.
%                When raising priority, issue error and return if we fail
%                to kill the update process.  Do not set time contstraint
%                priority.   
% 2/21/06   mk   Updated for Linux.
% 5/29/06   mk   Merged a fix for properly restarting update process.
%                Bug found & fix provided by Michael Ross.
% 8/02/06   mk   Bugfix by Michael Ross merged: oldPriority was sometimes
%                reported with some roundoff error.
% 8/02/06   mk   We now detect if we're running on a OS-X 10.4.7 system or
%                later. We do not kill and restart the system update process
%                anymore in that case as it isn't necessary anymore.
% 5/15/07   mk   Priority.dll on Windoze replaced by code in this M-File.
% 6/01/09   mk   Enable Priority() support for OS/X + Octave-3.

persistent killUpdateNotNeeded;
persistent didPriorityKillUpdate;

if IsLinux
   % Linux: We do not use a separate MEX file anymore. Instead we use a
   % built-in helper subroutine of Screen(), accessed via the special code -5
   % when calling the 'GetMouseHelper' subfunction.
   if nargin < 1
      newPriority = [];
   end

   if isempty(newPriority)
      % No priority provided: Just return the current level:
      oldPriority = Screen('GetMouseHelper', -5);
   else
      % New priority provided: Query and return old level, set new one:
      if newPriority < 0 | newPriority > 99 %#ok<OR2>
         error('Invalid Priority level specified! Not one between 0 and 99.');
      end

      oldPriority = Screen('GetMouseHelper', -5, newPriority);
   end

   % Done for Linux:
   return;
end;

if IsOSX
    if isempty(killUpdateNotNeeded)
        % Check if this is MacOS-X 10.4.7 or later. We don't need to kill
        % the update process anymore if that is the case.
        c = Screen('Computer');
        osrelease = sscanf(c.kern.osrelease, '%i.%i.%i');

        if (osrelease(1)==8 & osrelease(2)>=7) | (osrelease(1)>=9) %#ok<AND2,OR2>
            % OS-X 10.4.7 or later -> No need to kill update.
            killUpdateNotNeeded = 1;
        else
            % Pre 10.4.7 system -> Play safe and kill update.
            killUpdateNotNeeded = 0;
        end

        % Override for the scared.
        if exist('AlwaysKillUpdate', 'file')>0
            % Detected a veto file created by the user. We do kill update.
            killUpdateNotNeeded = 0;
        end
    end
    
    %Get the current settings.
    [flavorNameString, priorityStruct] = MachGetPriorityFlavor;
    if strcmp('THREAD_STANDARD_POLICY', flavorNameString)
        oldPriority=0;
    else % strcmp('THREAD_TIME_CONSTRAINT_POLICY', flavorNameString)
        %Values in priority struct returned by MachGetPriorityFlavor are in ticks but should be in seconds
        %it does not matter here because we are only concerned with the ratio
        if priorityStruct.policy.period == 0 | priorityStruct.policy.computation == 0 %#ok<OR2>
            %this is an illegitimate setting, so restore to standard priority
            %and go from there.
            MachSetStandardPriority;
            oldPriority=0;      
        else
            oldPriorityRatio= priorityStruct.policy.computation / priorityStruct.policy.period;
            % Make sure we never exceed an oldPriority of 9, even in case
            % of roundoff-error. Bug found and fixed by Michael Ross.
            oldPriority=min(oldPriorityRatio * 10, 9);
        end
    end
    
    
    %if no new setting is given then return
    if nargin==0
        return
    end
    
    %bounds check the input argument
    if newPriority > 9
        error('"newPriority" value exceeds maximum allowable value of 9');
    elseif newPriority < 0
        error('"newPriority" value is less than the minimum allowable value of 0');
    end
    
    %if the priority level calls for time constraint priority...
    if newPriority > 0
        if isempty(didPriorityKillUpdate)
            didPriorityKillUpdate = 0;
        end

        % Need to kill update process?
        if (killUpdateNotNeeded > 0)
            % Nope. This is a 10.47 or later system...
            tempWasKilledByUs = 0;
        else
            % Yes. Try to kill it, if it isn't already dead.
            tempWasKilledByUs=KillUpdateProcess;
        end
        
        if isnan(tempWasKilledByUs)
            error('Failed to raise priority because the simplepsychtoolboxsetup.sh script had not been run.  Run simplepsychtoolboxsetup.sh and try again.');
        else
            didPriorityKillUpdate=tempWasKilledByUs + didPriorityKillUpdate;
        end
        
        % Find the frame periods.  FrameRate returns the nominal frame rate, which
        % for LCD displays is 0.  We assume 60 in that case.
        defaultFrameRate=60;    %Hz
        screenNumbers=Screen('Screens');
        for i = 1:length(screenNumbers)
            frameRates(i)=Screen('FrameRate', screenNumbers(i)); %#ok<AGROW>
        end
        [zeroRates, zeroRateIndices]=find(frameRates==0);
        frameRates(zeroRateIndices)=defaultFrameRate;
        framePeriods=1./frameRates;
        
        % MachSetTimeConstraintPriority(periodSecs,computationSecs, constraintSecs, preemptibleFlag) 
        periodSecs=min(framePeriods);
        computationSecs = newPriority/10 * periodSecs;
        constraintSecs=computationSecs;
        preemptibleFlag=1;
        
        
        %set the prioirity
        MachSetTimeConstraintPriority(periodSecs,computationSecs, constraintSecs, preemptibleFlag);
        
        %if the priority level calls for standard priority then ..
    else    %priority==0
        %restore standard priority
        MachSetStandardPriority;
        
        %restore the update process if it was Priority which killed it.  
        if didPriorityKillUpdate        
            StartUpdateProcess;
            didPriorityKillUpdate=0;
        end
    end
end;

% Microsoft Windows?
if IsWin
   % Yes. We do not use a separate MEX file anymore. Instead we use a
   % built-in helper subroutine of Screen(), accessed via the special code -3
   % when calling the 'GetMouseHelper' subfunction.
   if nargin < 1
      newPriority = [];
   end
   
   if isempty(newPriority)
      % No priority provided: Just return the current level:
      oldPriority = Screen('GetMouseHelper', -3);
   else
      % New priority provided: Query and return old level, set new one:
      if newPriority<0 | newPriority>2 %#ok<OR2>
         error('Invalid Priority level specified! Not one of 0, 1 or 2.');
      end
      
      oldPriority = Screen('GetMouseHelper', -3, newPriority);
   end

   % Done for Windows...
end;