File: TestPriorityMex.c

package info (click to toggle)
psychtoolbox-3 3.0.14.20170103%2Bgit6-g605ff5c.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 103,044 kB
  • ctags: 69,483
  • sloc: ansic: 167,371; cpp: 11,232; objc: 4,708; sh: 1,875; python: 383; php: 344; makefile: 207; java: 113
file content (151 lines) | stat: -rwxr-xr-x 5,820 bytes parent folder | download | duplicates (4)
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
/*
  PsychToolbox3/Source/Common/TestProirityMex/TestPriorityMex.c		
  
  PROJECTS: TestPriority only.
  
  PLATFORMS:  Only OS X so far.  
  
  AUTHORS:
  Allen.Ingling@nyu.edu		awi 
      
  HISTORY:
  4/21/03  awi		Created.
  9/22/03  awi		Rewrote to use same arguments as TimeTest standalone application and replaced ScriptingGlue calls with 
                        mx/mex API calls.
  
  DESCRIPTION:
  
  The function accepts the following arguments:
  
    POSITION	DESCRIPTION			UNITS		SIZE
        1	policy period			ticks		1x1
        2	policy computation		ticks		1x1
        3	policy constraint		ticks		1x1
        4	policy preemptible		flag		1x1
        5	blocking period 		seconds		1x1
        6	test  duration			seconds		1x1	
    

*/
// includes
#include "TestPriorityMex.h"

//name  the positions of values in the list of input  arguments.
#define POLICY_PERIOD_ARG		0
#define POLICY_COMPUTATION_ARG		1
#define POLICY_CONSTRAINT_ARG		2
#define POLICY_PREEMPTIBLE_ARG		3
#define LOOP_BLOCKINGPERIOD_ARG		4
#define LOOP_DURATION_ARG		5

#define PRETRIAL_DURATION_SECS		5


void PsychGetPrecisionTimerSeconds(double *secs)
{
    UInt64	ticks;
    
    ticks=AudioGetCurrentHostTime();
    *secs=(double)(AudioConvertHostTimeToNanos(ticks) / (double)1000000000.0);
}


void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    double					startTime, endTime, now, waitPeriodDouble;
    int 					estimatedNumLoops, numTimeValues;
    unsigned int				waitPeriodInt, i, memFactor=2;
    double					*timesBuffer, preTrialDurationRatio;
    thread_time_constraint_policy_data_t	tcPolicy;
    thread_standard_policy_data_t		sPolicy;
    task_t					threadID;
    int						kernError;
    bool					outOfMemoryFlag;
    	 
    //check for valid arguments and copy them in
    if(nrhs != 6)
        mexErrMsgTxt("Wrong number of arguments supplied to function.  TestPriorityMex uses exactly six arguments.");
    for(i=0;i<6;i++){
        if(mxGetM(prhs[i]) * mxGetN(prhs[i]) != 1 || !mxIsDouble(prhs[i])){
            mexPrintf("Argument %d must be 1x1 double\n", i);
            mexErrMsgTxt("Exiting");
        }
    }


    
    //Set time constraint  priority and  other test parameters from arguments.  
    //We don't need to save the old priority setting, we just set it to something reasonable when we are done with the test.
    if(mxGetPr(prhs[LOOP_BLOCKINGPERIOD_ARG])[0] > 1)
        mexErrMsgTxt("waitPeriod value must not exceed 1 second"); 
    waitPeriodDouble=mxGetPr(prhs[LOOP_BLOCKINGPERIOD_ARG])[0] * 1000000;  //IOSleep accepts time in unit of ms
    waitPeriodInt = (unsigned int)waitPeriodDouble;
    tcPolicy.period=(uint32_t)mxGetPr(prhs[POLICY_PERIOD_ARG])[0];
    tcPolicy.computation=(uint32_t)mxGetPr(prhs[POLICY_COMPUTATION_ARG])[0];
    tcPolicy.constraint=(uint32_t)mxGetPr(prhs[POLICY_CONSTRAINT_ARG])[0];
    tcPolicy.preemptible=(boolean_t)(mxGetPr(prhs[POLICY_PREEMPTIBLE_ARG])[0] ? TRUE : FALSE);
    threadID= mach_thread_self();
    kernError=thread_policy_set(threadID, THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&tcPolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT);

    //Run a trail loop of the specified duration to estimate how much memory we need to allocate
    //for storing the timing results
    mexPrintf("Executing pre-trial for specified test period of %d seconds....\n", PRETRIAL_DURATION_SECS);
    i=0;
    PsychGetPrecisionTimerSeconds(&startTime);
    endTime=startTime + PRETRIAL_DURATION_SECS;
    for(PsychGetPrecisionTimerSeconds(&now); now<endTime; PsychGetPrecisionTimerSeconds(&now)){ 
        usleep(waitPeriodInt);
        ++i; 
    }
    mexPrintf("Pre-trial loop complete.  Executed %d loops.\n", i);
    preTrialDurationRatio = mxGetPr(prhs[LOOP_DURATION_ARG])[0] / (double)PRETRIAL_DURATION_SECS;
    estimatedNumLoops=(int)(i * memFactor * preTrialDurationRatio);
    mexPrintf("Pre-trial loop complete.  Executed %d loops.\n", i);
    timesBuffer=(double *)malloc(estimatedNumLoops * sizeof(double));



    //Do the test and record the times.  This loop code is (trivially) different the standalone
    // timing test application. This is a bit better becasue we only read the time once through the loop.
    mexPrintf("Executing test for specified test period of %f seconds....\n", mxGetPr(prhs[LOOP_DURATION_ARG])[0]);
    i=0;
    PsychGetPrecisionTimerSeconds(&startTime);
    endTime=startTime+mxGetPr(prhs[LOOP_DURATION_ARG])[0];
    outOfMemoryFlag=FALSE;
    for(PsychGetPrecisionTimerSeconds(&(timesBuffer[i])); timesBuffer[i] < endTime; PsychGetPrecisionTimerSeconds(&(timesBuffer[i]))){
        usleep(waitPeriodInt);
        ++i;
        if(i == estimatedNumLoops){
            mexPrintf("Did not allocate sufficient memory to hold timing results:\n");
            mexPrintf("\tallocated:%d\n",estimatedNumLoops);
            mexPrintf("\tused:%d\n", i);
            mexPrintf("\ttestDuration:%f\n", mxGetPr(prhs[LOOP_DURATION_ARG])[0]);
            mexPrintf("\tpre-trial duration:%f\n", timesBuffer[i-1]);
            mexPrintf("\tpre-trial loops:%d\n", estimatedNumLoops);
            outOfMemoryFlag=TRUE;
            break;
	} 
    }
    numTimeValues=i-1;
              
    //restore standard policy.  Content of sPolicy is empty and unread by thread_policy_set().  
    kernError=thread_policy_set(threadID, THREAD_STANDARD_POLICY, (thread_policy_t)&sPolicy, THREAD_STANDARD_POLICY_COUNT);
    
    if(outOfMemoryFlag)
        mexErrMsgTxt("Exiting");
    else{
        //Create return matrix, copy out the result, and free the temporary buffer.
	plhs[0]=mxCreateDoubleMatrix(1, numTimeValues, mxREAL);
        for(i=0;i<numTimeValues;i++)
            mxGetPr(plhs[0])[i]=timesBuffer[i];
    }

    //free memory allocated  for storage during the timing loop
     free((void *)timesBuffer);

}