示例#1
0
/** 
 *  \brief Returns the ID of the CPU
 *
 *  It returns the ID of the CPU where the calling thread is running. It works
 *  on Linux OS and Apple OS.
 * 
 *  \return An integer value showing the ID of the core. If the ID of the core
 *  is not found, then -1 is returned.
 */
static inline int ff_getMyCpu() {
#if defined(__linux__) && defined(CPU_SET)
    cpu_set_t mask;
    CPU_ZERO(&mask);
    if (sched_getaffinity(gettid(), sizeof(mask), &mask) != 0) {
        perror("sched_getaffinity");
        return EINVAL;
    }
    for(int i=0;i<CPU_SETSIZE;++i) 
        if (CPU_ISSET(i,&mask)) return i;
#elif defined(__APPLE__) && MAC_OS_X_HAS_AFFINITY
    // Not tested
    struct thread_affinity_policy mypolicy;
    boolean_t get_default;
    mach_msg_type_number_t thread_info_count = THREAD_AFFINITY_POLICY_COUNT;
    thread_policy_get(mach_thread_self(), THREAD_AFFINITY_POLICY,
                      (integer_t*) &mypolicy,
                      &thread_info_count, &get_default);
    int res = mypolicy.affinity_tag;
    return(res);
#else
#if __GNUC__
#warning "ff_getMyCpu not supported"
#else 
std::cerr << "---> ff_getMyCpu not supported\n";
#pragma message( "ff_getMyCpu not supported")
#endif
#endif
return -1;
}
示例#2
0
static void get_affinity(pthread_t thread)
{
    thread_affinity_policy theTCPolicy;
    mach_msg_type_number_t count = THREAD_AFFINITY_POLICY_COUNT;
    boolean_t get_default = false;
    kern_return_t res = thread_policy_get(pthread_mach_thread_np(thread), THREAD_AFFINITY_POLICY, (thread_policy_t)&theTCPolicy, &count, &get_default);
    if (res == KERN_SUCCESS) {
        //printf("get_affinity = %d\n", theTCPolicy.affinity_tag);
    }
}
//Polls a (non-realtime) thread to find out how it is scheduled
//Results are undefined of an error is returned. Otherwise, the
//priority is returned in the address pointed to by the priority
//parameter, and whether or not the thread uses timeshare scheduling
//is returned at the address pointed to by the isTimeShare parameter
kern_return_t  GetStdThreadSchedule( mach_port_t    machThread,
                                    int            *priority,
                                    boolean_t      *isTimeshare )
{
    kern_return_t                       result = 0;
    thread_extended_policy_data_t       timeShareData;
    thread_precedence_policy_data_t     precedenceData;
    mach_msg_type_number_t		structItemCount;
    boolean_t				fetchDefaults = false;

    memset( &timeShareData, 0, sizeof( thread_extended_policy_data_t ));
    memset( &precedenceData, 0, sizeof( thread_precedence_policy_data_t ));

    if( 0 == machThread )
        machThread = mach_thread_self();

    if( NULL != isTimeshare )
    {
        structItemCount = THREAD_EXTENDED_POLICY_COUNT;
        result = thread_policy_get( machThread, THREAD_EXTENDED_POLICY,
                                    (integer_t*)&timeShareData, &structItemCount, &fetchDefaults );
        *isTimeshare = timeShareData.timeshare;
        if( 0 != result )
            return result;
    }

    if( NULL != priority )
    {
        fetchDefaults = false;
        structItemCount = THREAD_PRECEDENCE_POLICY_COUNT;
        result = thread_policy_get( machThread, THREAD_PRECEDENCE_POLICY,
                                    (integer_t*)&precedenceData, &structItemCount, &fetchDefaults );
        *priority = precedenceData.importance;
    }

    return result;
}
示例#4
0
int pthread_getaffinity(pthread_t thread, unsigned int *core)
{
	/* Convert pthread ID */
	mach_port_t mach_thread = pthread_mach_thread_np(thread);
	thread_affinity_policy_data_t policy;
	mach_msg_type_number_t count = THREAD_AFFINITY_POLICY_COUNT;
	boolean_t get_default = FALSE;

	kern_return_t rc = thread_policy_get(mach_thread,
					     THREAD_AFFINITY_POLICY,
					     (thread_policy_t) &policy, &count,
					     &get_default);
	*core = (unsigned int)policy.affinity_tag;

	return (rc == KERN_SUCCESS ? 0 : -1);
}
示例#5
0
int
thread_tag_get(thread_t thread)
{
	kern_return_t			ret;
	boolean_t			get_default = FALSE;
	thread_affinity_policy_data_t	policy;
	mach_msg_type_number_t		count = THREAD_AFFINITY_POLICY_COUNT;

	ret = thread_policy_get(
			thread, THREAD_AFFINITY_POLICY,
			(thread_policy_t) &policy, &count, &get_default);
	if (ret != KERN_SUCCESS) {
		printf("thread_policy_set(1) returned %d\n", ret);
		exit(1);
	}

	return policy.affinity_tag;
}
示例#6
0
static int GetParams(pthread_t thread, UInt64* period, UInt64* computation, UInt64* constraint)
{
    thread_time_constraint_policy_data_t theTCPolicy;
    mach_msg_type_number_t count = THREAD_TIME_CONSTRAINT_POLICY_COUNT;
    boolean_t get_default = false;

    kern_return_t res = thread_policy_get(pthread_mach_thread_np(thread),
                                          THREAD_TIME_CONSTRAINT_POLICY,
                                          (thread_policy_t) & theTCPolicy,
                                          &count,
                                          &get_default);
    if (res == KERN_SUCCESS) {
        *period = AudioConvertHostTimeToNanos(theTCPolicy.period);
        *computation = AudioConvertHostTimeToNanos(theTCPolicy.computation);
        *constraint = AudioConvertHostTimeToNanos(theTCPolicy.constraint);
        return 0;
    } else {
        return -1;
    }
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    bool				isError;
    thread_policy_flavor_t		flavorConstant;
    int					flavorPolicySize, flavorPolicySizeBytes, kernError;
    task_t				threadID;
    thread_policy_t			threadPolicy;
    mach_msg_type_number_t		policySizeFilled;
    boolean_t				isDefault, getDefault;
    char				commandString[COMMAND_STRING_LENGTH];
    // for return structure
    //  ...outer
    const char *outerNames[] = 		{"threadID", "flavor", "policy", "policySize", "policyFillSize", "getDefault", "isDefault"};
    int	numOuterDims=2, numOuterFields=7;
    int	outerDims[2]={1,1};
    //	...inner
    const char *standardNames[] = 	{"no_data"};
    int numInnerFieldsStandard=		1;
    /*
    const char *extendedNames[] = 	{"timeshare"};
    int numInnerFieldsExtended=		1;
    */
    const char *timeConstraintNames[]=	{"period", "computation", "constraint", "preemptible"};
    int numInnerFieldsTimeConstraint=	4;
    const char *precedenceNames[]=	{"imporantance"};
    int numInnerFieldsPrecedence=	1;
    int	numInnerDims=2;
    int	innerDims[2]={1,1};
    // ...both
    mxArray  *tempFieldValue, *innerStruct, *outerStruct;
    

    

    //get the policy flavor constant specified by the user and the getDefault argument
    if(nrhs<2 || nrhs > 2)
        mexErrMsgTxt("MachGetPriorityMex requires two input arguments.  See help MachGetPriorityMex.");
    if(!mxIsChar(prhs[0]))
        mexErrMsgTxt("First input argument is not a string.  See help MachGetPriorityMex.");
    mxGetString(prhs[0], commandString, COMMAND_STRING_LENGTH);
    isError=GetFlavorConstantFromFlavorString(commandString, mxGetM(prhs[0]) * mxGetN(prhs[0]), &flavorConstant);  //case sensitive.  
    if(isError)
        mexErrMsgTxt("Unrecognized command.  See help MachGetPriorityMex.");
    if(!(mxIsDouble(prhs[1]) || mxIsLogical(prhs[1])) || mxGetN(prhs[1]) * mxGetM(prhs[1]) != 1)
        mexErrMsgTxt("Second argument must be 1x1 logical or double value.  See help MachGetPriorityMex.");
    if(mxIsLogical(prhs[1]))
        getDefault= (boolean_t)mxGetLogicals(prhs[1])[0];
    if(mxIsDouble(prhs[1]))
        getDefault= (boolean_t)mxGetPr(prhs[1])[0];


    //read the priority settings
    switch(flavorConstant){
        case THREAD_STANDARD_POLICY: 
            flavorPolicySizeBytes=sizeof(thread_standard_policy_data_t); 
            flavorPolicySize=THREAD_STANDARD_POLICY_COUNT; 
            break;
        case THREAD_TIME_CONSTRAINT_POLICY: 
            flavorPolicySizeBytes=sizeof(thread_time_constraint_policy_data_t); 
            flavorPolicySize=THREAD_TIME_CONSTRAINT_POLICY_COUNT; 
            break;
        case THREAD_PRECEDENCE_POLICY: 
            flavorPolicySizeBytes=sizeof(thread_precedence_policy_data_t); 
            flavorPolicySize=THREAD_PRECEDENCE_POLICY_COUNT; 
            break;
    }
    threadPolicy=(thread_policy_t)malloc(flavorPolicySizeBytes);		
    threadID= mach_thread_self();
    policySizeFilled=flavorPolicySize;
    isDefault=getDefault;
    kernError=thread_policy_get(threadID, flavorConstant, threadPolicy, &policySizeFilled, &isDefault);

    //create and populate the return structure
    outerStruct= mxCreateStructArray(numOuterDims, outerDims, numOuterFields, outerNames);
    
    tempFieldValue= mxCreateDoubleMatrix(1,1,mxREAL);
    mxGetPr(tempFieldValue)[0]=(double)threadID;
    mxSetField(outerStruct, 0, "threadID", tempFieldValue);
    
    tempFieldValue= mxCreateString(commandString);
    mxSetField(outerStruct, 0, "flavor", tempFieldValue);
    
    
    switch(flavorConstant){
        case THREAD_STANDARD_POLICY: 				
            innerStruct= mxCreateStructArray(numInnerDims, innerDims, numInnerFieldsStandard, standardNames);
            tempFieldValue= mxCreateDoubleMatrix(1,1,mxREAL);
            mxGetPr(tempFieldValue)[0]= (double)((thread_standard_policy_t)threadPolicy)->no_data;
            mxSetField(innerStruct, 0, "no_data", tempFieldValue);
            break;
       /* THREAD_EXTENDED_POLICY is equal to THREAD_STANDARD_POLICY.  Also,  THREAD_EXTENDED_POLICY is undocumented.  So we ignore it.  
        case THREAD_EXTENDED_POLICY: 		
            innerStruct= mxCreateStructArray(numInnerDims, innerDims, numInnerFieldsExtended, extendedNames);
            tempFieldValue= mxCreateDoubleMatrix(1,1,mxREAL);
            mxGetPr(tempFieldValue)[0]= (double)((thread_extended_policy_t)threadPolicy)->timeshare;
            mxSetField(innerStruct, 1, "timeshare", tempFieldValue);
            break;
        */
        case THREAD_TIME_CONSTRAINT_POLICY: 	
            innerStruct= mxCreateStructArray(numInnerDims, innerDims, numInnerFieldsTimeConstraint, timeConstraintNames);
            tempFieldValue= mxCreateDoubleMatrix(1,1,mxREAL);
            mxGetPr(tempFieldValue)[0]= (double)((thread_time_constraint_policy_t)threadPolicy)->period;
            mxSetField(innerStruct, 0, "period", tempFieldValue);
            tempFieldValue= mxCreateDoubleMatrix(1,1,mxREAL);
            mxGetPr(tempFieldValue)[0]= (double)((thread_time_constraint_policy_t)threadPolicy)->computation;
            mxSetField(innerStruct, 0, "computation", tempFieldValue);
            tempFieldValue= mxCreateDoubleMatrix(1,1,mxREAL);
            mxGetPr(tempFieldValue)[0]= (double)((thread_time_constraint_policy_t)threadPolicy)->constraint;
            mxSetField(innerStruct, 0, "constraint", tempFieldValue);
            tempFieldValue= mxCreateDoubleMatrix(1,1,mxREAL);
            mxGetPr(tempFieldValue)[0]= (double)((thread_time_constraint_policy_t)threadPolicy)->preemptible;
            mxSetField(innerStruct, 0, "preemptible", tempFieldValue);
            break;
        case THREAD_PRECEDENCE_POLICY:
            innerStruct= mxCreateStructArray(numInnerDims, innerDims, numInnerFieldsPrecedence, precedenceNames);
            tempFieldValue= mxCreateDoubleMatrix(1,1,mxREAL);
            mxGetPr(tempFieldValue)[0]= (double)((thread_precedence_policy_t)threadPolicy)->importance;
            mxSetField(innerStruct, 0, "imporantance", tempFieldValue);
            break;
    }
    mxSetField(outerStruct,0, "policy", innerStruct);
    
    tempFieldValue= mxCreateDoubleMatrix(1,1,mxREAL);
    mxGetPr(tempFieldValue)[0]=flavorPolicySize;
    mxSetField(outerStruct, 0, "policySize", tempFieldValue);
    
    tempFieldValue= mxCreateDoubleMatrix(1,1,mxREAL);
    mxGetPr(tempFieldValue)[0]=policySizeFilled;
    mxSetField(outerStruct, 0, "policyFillSize", tempFieldValue);
    
    tempFieldValue= mxCreateLogicalMatrix(1, 1);
    mxGetLogicals(tempFieldValue)[0]=(bool)getDefault;
    mxSetField(outerStruct, 0, "getDefault", tempFieldValue);
    
    tempFieldValue= mxCreateLogicalMatrix(1, 1);
    mxGetLogicals(tempFieldValue)[0]=(bool)isDefault;
    mxSetField(outerStruct, 0, "isDefault", tempFieldValue);
    
    plhs[0]=outerStruct;
    
    free((void*)threadPolicy);        
}
示例#8
0
/* Change priority for thread 'threadhandle', or for the calling thread if 'threadhandle' == NULL.
 * threadhandle == 0x1 means "Main Psychtoolbox thread" and may incur special treatment.
 * 'basePriority' can be 0 for normal scheduling, 1 for higher priority and 2 for highest priority.
 * 'tweakPriority' modulates more fine-grained within the category given by 'basepriority'. It
 * can be anywhere between 0 and some big value where bigger means more priority.
 *
 * Returns zero on success, non-zero on failure to set new priority.
 */
int PsychSetThreadPriority(psych_thread* threadhandle, int basePriority, int tweakPriority)
{
	int							rc = 0;
	pthread_t					thread;
    int							kernError;
    task_t						threadID;
    thread_policy_t				threadPolicy;
    mach_msg_type_number_t		policyCount, policyCountFilled;
    boolean_t					isDefault;
	
	if ((NULL != threadhandle) && ((psych_thread*) 0x1 != threadhandle)) {
		// Retrieve thread handle of thread to change:
		thread = *threadhandle;
	}
	else {
		// Retrieve handle of calling thread:
		thread = pthread_self();
	}

	// Map Posix thread handle to Mach thread handle:
	threadID = pthread_mach_thread_np(thread);

	// Get timebase:
	double ticksPerSec = PsychGetKernelTimebaseFrequencyHz();
	double baseQuantum = 0.010;
	
	// tweakPriority <= 0 -> 10% cpu. Can go up to 90% at level >=8 in 10% increments.
	if (tweakPriority < 0) tweakPriority = 0;
	if (tweakPriority > 8) tweakPriority = 8;
	
	switch(basePriority) {
		case 0:	// Normal priority: Drop to standard scheduling.
			threadPolicy = (thread_policy_t) malloc(sizeof(thread_standard_policy_data_t));
			policyCount  = THREAD_STANDARD_POLICY_COUNT;
			policyCountFilled = policyCount;
			isDefault = TRUE;
			kernError = thread_policy_get(threadID, THREAD_STANDARD_POLICY, threadPolicy, &policyCountFilled, &isDefault);
			if (kernError == 0) kernError = thread_policy_set(threadID, THREAD_STANDARD_POLICY, threadPolicy, policyCountFilled);
			free(threadPolicy);
			rc = (int) kernError;
		break;
		
		case 1: // High priority: Up to 90% cpu utilization, but preemptible for urgent tasks, with an allowable total time to completion of baseQuantum.
			// This basically says: "I am more important than bog-standard threads, and i want to have x msecs of 10 msecs very 10 msecs, but i don't care
			// about startup delay (reaction times) or interruptions, as long as i don't lose more than 10 msecs. Good for high priority compute tasks
			// with lots of wiggle room wrt. when stuff happens, e.g., some data producer thread or i/o thread which needs to deliver/handle a certain
			// amount of data processing/shuffling/io within a certain time quantum, because it is feeding some other realtime thread or hw process,
			// due to things like intermediate fifo buffering, itself can tolerate a certain lag.
			// This may become useful in the future for i/o functions in IOPort/PsychHID, movie playback/recording helper threads etc...
			rc = set_realtime(threadID, baseQuantum * ticksPerSec, (((double) tweakPriority + 1) / 10) * baseQuantum * ticksPerSec, baseQuantum * ticksPerSec, TRUE);
		break;
		
		case 2: // Realtime priority: Up to (tweakPriority + 1) msecs out of 10 msecs of *uninterrupted* computation (non-preemptible after start).
			// However, after the thread becomes runnable, its actual start of uninterrupted execution can be delayed by up to 1 msec, e.g., if more
			// important (basePriority 10) threads are executing, or a high priority or lower priority thread needs some computation time.
			// This is our most common use-case: Most of our realtime threads are completely triggered (= reactive to) by external hardware input events.
			// They wait on the arrival of some external event, e.g., a user key press or mouse click, some trigger signal from some I/O device like
			// response box, serial port or parallel port, DAQ board etc., or for some timer going off at a certain time. Most often they have to respond
			// to some trigger event by either executing some action, or by simply timestamping the event, like a button press of a subject, or some TTL
			// trigger from some equipment. Executing the actual action, or timestamping, or storing the received data in some queue, is usually fast,
			// the computation finishes quickly. As timestamping or external hardware control can be involved, we don't want to get preempted once running,
			// to avoid impairing precision of timestamps or clock-sync algorithms or hw control actions. However for typical neuro-science experiments,
			// we can tolerate a random time delay (or imprecision in acquired timestamps) of 1 msec.
			// Typical consumers of this setup: IOPort, PsychHID, Movie playback or video capture high-level control.
			rc = set_realtime(threadID, baseQuantum * ticksPerSec, (((double) tweakPriority + 1) / 10) * baseQuantum * ticksPerSec, (((double) tweakPriority + 1 + 1) / 10) * baseQuantum * ticksPerSec, FALSE);
		break;

		case 10:  // Critical priority: Up to (tweakPriority + 1) msecs out of 10 msecs of *uninterrupted* computation (non-preemptible after start),
			// must run as soon as possible and then complete without distraction. This is good for timestamping operations that must not be interrupted
			// in the wrong moment, because that would impair timestamps significantly, and for time-based triggering of execution of operations with
			// the highest possible timing precision.
			// Out main client of this is currently the OpenGL flipperThread used by Screen for async flip scheduling and timestamping, and for
			// frame-sequential stereo fallback. For those apps, uninterrupted low latency is crucial. flipperThread uses tweakPriority == 2, so could
			// run for up to 3 msecs uninterrupted, something it usually won't do (closer to << 1 msec is expected), but can do in a worst case scenario,
			// where various workarounds for broken GPU drivers are active and screen resolution/refresh rate settings are especially suboptimal.
			// The other client is video refresh rate calibration during Screen('GetFlipInterval') active calibration or during Screen('Openwindow')
			// default calibration.
			//
			// Future clients may be found in the IOPort async-task framework for highly timing sensitive i/o operations.
			rc = set_realtime(threadID, baseQuantum * ticksPerSec, (((double) tweakPriority + 1) / 10) * baseQuantum * ticksPerSec, 0, FALSE);
		break;

		default:
			printf("PTB-CRITICAL: In call to PsychSetThreadPriority(): Invalid/Unknown basePriority %i provided!\n", basePriority);
			rc = 2;
	}

	// Try to apply new priority and scheduling method:
	if (rc != 0) {
		printf("PTB-WARNING: In call to PsychSetThreadPriority(): Failed to set new basePriority %i, tweakPriority %i, effective %i [%s] for thread %p provided!\n",
				basePriority, tweakPriority, tweakPriority, (basePriority > 0) ? "REALTIME" : "NORMAL", (void*) threadhandle);
		printf("PTB-WARNING: This can lead to timing glitches and odd performance behaviour.\n");
	}

	// rc is either zero for success, or 2 for invalid arg, or some other non-zero failure code:
	return(rc);
}
PsychError MACHPRIORITYMachPriority(void) 
{
    //double 			*returnValue;
    //int			newPriority;
    const char 			*outerStructFieldNames[]={"thread", "flavor", "policy"};
    const char 			*policyStructFieldNames[]={"period", "computation", "constraint", "preemptible"};
    int 			numOuterStructDimensions=1, numOuterStructFieldNames=3, numPolicyStructDimensions=1, numPolicyStructFieldNames=4;
    PsychGenericScriptType	*outerStructArray, *policyStructArray;
    int 			kernError, numInputArgs;
    thread_act_t 		threadID;
    static thread_policy_flavor_t	currentThreadFlavor=THREAD_STANDARD_POLICY;
    struct			thread_time_constraint_policy	oldPolicyInfo, newPolicyInfo;
    mach_msg_type_number_t	msgTypeNumber;
    boolean_t			getDefault;
    char 			*flavorStr;
    boolean			setNewMode;
    double			*periodArg, *computationArg, *constraintArg, *preemptibleArg;
    char 			errorMessageStr[256];
    	 



    //check to see if the user supplied superfluous arguments
    PsychErrorExit(PsychCapNumOutputArgs(1));
    PsychErrorExit(PsychCapNumInputArgs(4)); //actually we permit only zero or three arguments.
    numInputArgs=PsychGetNumInputArgs();
    if(numInputArgs==4)
        setNewMode=TRUE;
    else if(numInputArgs==0)
        setNewMode=FALSE;
    else
        PsychErrorExitMsg(PsychError_user,"Incorrect number of arguments.  Either zero or four arguments accepted");
        

    //read the current settings
    threadID= mach_thread_self();
    currentThreadFlavor=THREAD_TIME_CONSTRAINT_POLICY;
    msgTypeNumber=THREAD_TIME_CONSTRAINT_POLICY_COUNT;
    getDefault=FALSE;
    kernError= thread_policy_get(threadID, currentThreadFlavor, (int *)&oldPolicyInfo, &msgTypeNumber, &getDefault);
    if(kernError != KERN_SUCCESS)
        PsychErrorExitMsg(PsychError_internal,"\"thread_policy_get()\" returned and error when reading current thread policy");
    
    

    //fill in the outgoig struct with current thread settings values.
    //outer struct
    PsychAllocOutStructArray(1, FALSE, numOuterStructDimensions, numOuterStructFieldNames, outerStructFieldNames, &outerStructArray);
    PsychSetStructArrayDoubleElement("thread", 0, (double)threadID, outerStructArray);
    flavorStr=GetFlavorStringFromFlavorConstant(currentThreadFlavor);
    PsychSetStructArrayStringElement("flavor", 0, flavorStr, outerStructArray);
    //enclosed policy struct
    PsychAllocOutStructArray(-1, FALSE, numPolicyStructDimensions, numPolicyStructFieldNames, policyStructFieldNames, &policyStructArray);
    PsychSetStructArrayDoubleElement("period", 0, (double)oldPolicyInfo.period, policyStructArray);
    PsychSetStructArrayDoubleElement("computation", 0, (double)oldPolicyInfo.computation, policyStructArray);
    PsychSetStructArrayDoubleElement("constraint", 0, (double)oldPolicyInfo.constraint, policyStructArray);
    PsychSetStructArrayDoubleElement("preemptible", 0, (double)oldPolicyInfo.preemptible, policyStructArray);
    PsychSetStructArrayStructElement("policy",0, policyStructArray, outerStructArray);
    
    //Set the priority 
    if(setNewMode){
        //if there is only one argument then it must be the flavor argument re
        PsychAllocInDoubleArg(1, TRUE, &periodArg);
        PsychAllocInDoubleArg(2, TRUE, &computationArg);
        PsychAllocInDoubleArg(3, TRUE, &constraintArg);
        PsychAllocInDoubleArg(4, TRUE, &preemptibleArg);
        newPolicyInfo.period=(uint32_t)*periodArg;
	newPolicyInfo.computation=(uint32_t)*computationArg;
	newPolicyInfo.constraint=(uint32_t)*constraintArg;
	newPolicyInfo.preemptible=(boolean_t)*preemptibleArg;

	kernError= thread_policy_set(threadID, THREAD_TIME_CONSTRAINT_POLICY, (int *)&newPolicyInfo, THREAD_TIME_CONSTRAINT_POLICY_COUNT);
	if(kernError != KERN_SUCCESS){
		sprintf(errorMessageStr,"%s%d", "\"thread_policy_set()\" returned and error when setting new thread policy: ", (int)kernError);
		PsychErrorExitMsg(PsychError_internal, errorMessageStr);
		}
    }

        
    return(PsychError_none);	
}
static void thread_print_policies(int fDefault)
{
    thread_extended_policy_data_t           Extended = { 0 };
    thread_time_constraint_policy_data_t    TimeConstraint = { 0, 0, 0, 1 };
    thread_precedence_policy_data_t         Precedence = { 0 };
#ifdef THREAD_AFFINITY_POLICY /* 10.5 */
    thread_affinity_policy_data_t           Affinity = { 0 };
#endif
    boolean_t                               GetDefault;
    mach_msg_type_number_t                  Count;
    kern_return_t                           krc;

    GetDefault = fDefault;
    Count = THREAD_EXTENDED_POLICY_COUNT;
    krc = thread_policy_get(mach_thread_self(), THREAD_EXTENDED_POLICY, (thread_policy_t)&Extended, &Count, &GetDefault);
    printf("THREAD_EXTENDED_POLICY: krc=%#x default=%d timeshare=%d (%#x)\n",
           krc, GetDefault, Extended.timeshare, Extended.timeshare);

    GetDefault = fDefault;
    Count = THREAD_PRECEDENCE_POLICY_COUNT;
    krc = thread_policy_get(mach_thread_self(), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&Precedence, &Count, &GetDefault);
    printf("THREAD_PRECEDENCE_POLICY: krc=%#x default=%d importance=%d (%#x)\n",
           krc, GetDefault, Precedence.importance, Precedence.importance);

    GetDefault = fDefault;
    Count = THREAD_TIME_CONSTRAINT_POLICY_COUNT;
    krc = thread_policy_get(mach_thread_self(), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&TimeConstraint, &Count, &GetDefault);
    printf("THREAD_TIME_CONSTRAINT_POLICY: krc=%#x default=%d period=%u (%#x) computation=%u (%#x) constraint=%u (%#x) preemptible=%d\n",
           krc, GetDefault, TimeConstraint.period, TimeConstraint.period,
           TimeConstraint.computation, TimeConstraint.computation,
           TimeConstraint.constraint,  TimeConstraint.constraint,
           TimeConstraint.preemptible);

#ifdef THREAD_AFFINITY_POLICY /* 10.5 */
    GetDefault = fDefault;
    Count = THREAD_AFFINITY_POLICY_COUNT;
    krc = thread_policy_get(mach_thread_self(), THREAD_AFFINITY_POLICY, (thread_policy_t)&Affinity, &Count, &GetDefault);
    printf("THREAD_AFFINITY_POLICY: krc=%#x default=%d affinity_tag=%d (%#x)\n",
           krc, GetDefault, Affinity.affinity_tag, Affinity.affinity_tag);
#endif

    if (!fDefault)
    {
        struct sched_param              Param;
        int                             iPolicy = 0;
        struct thread_basic_info        BasicInfo = {{0,0},{0,0},0,0,0,0,0,0};
        struct policy_timeshare_info    TSInfo = {0,0,0,0,0};
        int                             rc;
        int                             i;

        memset(&Param, 0, sizeof(Param));
        rc = pthread_getschedparam(pthread_self(), &iPolicy, &Param);
        printf("pthread_getschedparam: rc=%d iPolicy=%d (%#x) sched_priority=%d (%#x) opaque=%d (%#x)\n",
               rc, iPolicy, iPolicy, Param.sched_priority, Param.sched_priority,
#ifdef THREAD_AFFINITY_POLICY /* 10.5 */
               *(int *)&Param.__opaque, *(int *)&Param.__opaque);
#else
               *(int *)&Param.opaque, *(int *)&Param.opaque);
#endif

        Count = THREAD_BASIC_INFO_COUNT;
        krc = thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)&BasicInfo, &Count);
        printf("THREAD_BASIC_INFO: krc=%#x user_time=%d.%06d system_time=%d.%06d cpu_usage=%d policy=%d\n"
               "    run_state=%d flags=%#x suspend_count=%d sleep_time=%d\n",
               krc,
               BasicInfo.user_time.seconds,   BasicInfo.user_time.microseconds,
               BasicInfo.system_time.seconds, BasicInfo.system_time.microseconds,
               BasicInfo.cpu_usage,
               BasicInfo.policy,
               BasicInfo.run_state,
               BasicInfo.flags,
               BasicInfo.suspend_count,
               BasicInfo.sleep_time);

        Count = POLICY_TIMESHARE_INFO_COUNT;
        krc = thread_info(mach_thread_self(), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&TSInfo, &Count);
        printf("THREAD_SCHED_TIMESHARE_INFO: krc=%#x max_priority=%d (%#x) base_priority=%d (%#x) cur_priority=%d (%#x)\n"
               "    depressed=%d depress_priority=%d (%#x)\n",
               krc,
               TSInfo.max_priority, TSInfo.max_priority,
               TSInfo.base_priority, TSInfo.base_priority,
               TSInfo.cur_priority, TSInfo.cur_priority,
               TSInfo.depressed,
               TSInfo.depress_priority, TSInfo.depress_priority);
    }
    else
    {
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    bool						isError;
    thread_policy_flavor_t		flavorConstant;
    int							kernError;
    task_t						threadID;
    thread_policy_t				threadPolicy;
    mach_msg_type_number_t		policyCount, policyCountFilled;
    boolean_t					isDefault;
    char						commandString[COMMAND_STRING_LENGTH];
    
    
    threadID= mach_thread_self();
    kernError=0;
    
    //get the policy flavor constant specified by the user and the getDefault argument
    if(nrhs<1)
        mexErrMsgTxt("MachGetPriorityMex requires at least one argument.  See help MachGetPriorityMex.");
    if(!mxIsChar(prhs[0]))
        mexErrMsgTxt("First input argument is not a string.  See help MachGetPriorityMex.");
    mxGetString(prhs[0], commandString, COMMAND_STRING_LENGTH);
    isError=GetFlavorConstantFromFlavorString(commandString, mxGetM(prhs[0]) * mxGetN(prhs[0]), &flavorConstant);  //case sensitive.  
    if(isError)
        mexErrMsgTxt("Unrecognized command.  See help MachGetPriorityMex.");


    //branch according to the first argument
    switch(flavorConstant){
        case THREAD_STANDARD_POLICY:
            if(nrhs>2)
                mexErrMsgTxt("Extra argument(s) detected.  See help MachGetPriorityMex.");
            if(nrhs==2){
                if(!mxIsChar(prhs[1]))
                    mexErrMsgTxt("Expecting string in second argument.  See help MachGetPriorityMex.");
                mxGetString(prhs[1], commandString, COMMAND_STRING_LENGTH);
                commandString[COMMAND_STRING_LENGTH-1]= '\0';  //guarantee strcmp an end of string character
                if(strcmp(commandString, "default"))
                    mexErrMsgTxt("Unrecognized second argument.  See help MachGetPriorityMex.");
            }
            threadPolicy=(thread_policy_t)malloc(sizeof(thread_standard_policy_data_t));
            policyCount=THREAD_STANDARD_POLICY_COUNT;
            policyCountFilled=policyCount;
            isDefault=TRUE;
            kernError=thread_policy_get(threadID, THREAD_STANDARD_POLICY, threadPolicy, &policyCountFilled, &isDefault);
            if (kernError==0) kernError=thread_policy_set(threadID, THREAD_STANDARD_POLICY, threadPolicy, policyCountFilled);
            break; 
        case THREAD_TIME_CONSTRAINT_POLICY:
            if(nrhs==1)
                mexErrMsgTxt("Missing argument detected.  See help MachGetPriorityMex.");
            else if(nrhs==2){
                if(!mxIsChar(prhs[1]))
                    mexErrMsgTxt("Expecting string in second argument.  See help MachGetPriorityMex.");
                mxGetString(prhs[1], commandString, COMMAND_STRING_LENGTH);
                commandString[COMMAND_STRING_LENGTH-1]= '\0';  //guarantee strcmp an end of string character
                if(strcmp(commandString, "default"))
                    mexErrMsgTxt("Unrecognized second argument.  See help MachGetPriorityMex.");
                threadPolicy=(thread_policy_t)malloc(sizeof(thread_time_constraint_policy_data_t));
                policyCount=THREAD_TIME_CONSTRAINT_POLICY_COUNT;
                policyCountFilled=policyCount;
                isDefault=TRUE;
                kernError=thread_policy_get(threadID, THREAD_TIME_CONSTRAINT_POLICY, threadPolicy, &policyCountFilled, &isDefault);
                if (kernError==0) kernError=thread_policy_set(threadID, THREAD_TIME_CONSTRAINT_POLICY, threadPolicy, policyCountFilled);
                free((void*)threadPolicy);        
                break;
            }else if(nrhs != 5)
                mexErrMsgTxt("Incorrect number of arguments.  See help MachGetPriorityMex.");
            else{
                if(! (mxIsDouble(prhs[1]) && mxGetM(prhs[1]) * mxGetN(prhs[1]) == 1)) 
                    mexErrMsgTxt("Expected double in second argument.  See help MachSetPriorityMex.");
                if(! (mxIsDouble(prhs[2]) && mxGetM(prhs[2]) * mxGetN(prhs[2]) == 1)) 
                    mexErrMsgTxt("Expected double in third argument.  See help MachSetPriorityMex.");
                if(! (mxIsDouble(prhs[3]) && mxGetM(prhs[3]) * mxGetN(prhs[3]) == 1)) 
                    mexErrMsgTxt("Expected double in fourth argument.  See help MachGetPriorityMex.");
                if(!((mxIsDouble(prhs[4]) || mxIsLogical(prhs[4])) && (mxGetM(prhs[4]) * mxGetN(prhs[4]) == 1)))
                    mexErrMsgTxt("Expected double or logical in fifth argument.  See help MachSetPriorityMex.");
                threadPolicy=(thread_policy_t)malloc(sizeof(thread_time_constraint_policy_data_t));
                ((thread_time_constraint_policy_t)threadPolicy)->period=(uint32_t)mxGetPr(prhs[1])[0];
                ((thread_time_constraint_policy_t)threadPolicy)->computation=(uint32_t)mxGetPr(prhs[2])[0];
                ((thread_time_constraint_policy_t)threadPolicy)->constraint=(uint32_t)mxGetPr(prhs[3])[0];
                ((thread_time_constraint_policy_t)threadPolicy)->preemptible= (boolean_t)(mxIsDouble(prhs[4]) ? mxGetPr(prhs[4])[0] : mxGetLogicals(prhs[4])[0]);
                policyCount=THREAD_TIME_CONSTRAINT_POLICY_COUNT;
                policyCountFilled=policyCount;
                kernError=thread_policy_set(threadID, THREAD_TIME_CONSTRAINT_POLICY, threadPolicy, policyCountFilled);
                free((void*)threadPolicy);
                break;
            }
        case THREAD_PRECEDENCE_POLICY:
            if(nrhs>2)
                mexErrMsgTxt("Extra argument(s) detected.  See help MachGetPriorityMex.");
            if(nrhs<2)
                mexErrMsgTxt("Missing argument detected.  See help MachGetPriorityMex.");
            if(mxIsChar(prhs[1])){  //set the default
                mxGetString(prhs[1], commandString, COMMAND_STRING_LENGTH);
                commandString[COMMAND_STRING_LENGTH-1]= '\0';  //guarantee strcmp an end of string character
                if(strcmp(commandString, "default"))
                    mexErrMsgTxt("Unrecognized second argument.  See help MachGetPriorityMex.");
                threadPolicy=(thread_policy_t)malloc(sizeof(thread_precedence_policy_data_t));
                policyCount=THREAD_PRECEDENCE_POLICY_COUNT;
                policyCountFilled=policyCount;
                isDefault=TRUE;
                kernError=thread_policy_get(threadID, THREAD_PRECEDENCE_POLICY, threadPolicy, &policyCountFilled, &isDefault);
                if (kernError==0) kernError=thread_policy_set(threadID, THREAD_PRECEDENCE_POLICY, threadPolicy, policyCountFilled);
                free((void*)threadPolicy);
                break; 
            }else if(mxIsDouble(prhs[1]) && mxGetM(prhs[1]) * mxGetN(prhs[1]) == 1){  //set a specified value
                threadPolicy=(thread_policy_t)malloc(sizeof(thread_precedence_policy_data_t));
                ((thread_precedence_policy_t)threadPolicy)->importance=(integer_t)mxGetPr(prhs[1])[0];
                policyCount=THREAD_PRECEDENCE_POLICY_COUNT;
                policyCountFilled=policyCount;
                kernError=thread_policy_set(threadID, THREAD_PRECEDENCE_POLICY, threadPolicy, policyCountFilled);
            }
    }

    // Check for and report errors in thread_policy_set:
    if (kernError!=0) {
        mexErrMsgTxt("ERROR: Failed to set requested thread scheduling policy! thread_policy_set() failed!");
    }
}
示例#12
0
/** PsychRealtimePriority: Temporarily boost priority to THREAD_TIME_CONSTRAINT_POLICY.
    PsychRealtimePriority(true) enables realtime-scheduling (like Priority(9) would do in Matlab).
    PsychRealtimePriority(false) restores scheduling to the state before last invocation of PsychRealtimePriority(true),
    it undos whatever the previous switch did.

    We switch to RT scheduling during PsychGetMonitorRefreshInterval() and a few other timing tests in
    PsychOpenWindow() to reduce measurement jitter caused by possible interference of other tasks.
*/
psych_bool PsychRealtimePriority(psych_bool enable_realtime)
{
    psych_bool				isError;
    thread_policy_flavor_t	flavorConstant;
    int						kernError;
    task_t					threadID;
    thread_policy_t			threadPolicy;
    static thread_policy_t	old_threadPolicy;
    mach_msg_type_number_t	policyCount, policyCountFilled;
    static mach_msg_type_number_t	old_policyCountFilled;
    boolean_t				isDefault;
    
    static psych_bool old_enable_realtime = FALSE;
    static psych_bool oldModeWasStandard = FALSE;
    
    if (old_enable_realtime == enable_realtime) {
        // No transition with respect to previous state -> Nothing to do.
        return(TRUE);
    }
    
    // Transition requested:
    old_enable_realtime = enable_realtime;
    
    // Determine our threadID:
    threadID = mach_thread_self();
    
    if (enable_realtime) {
        // Transition to realtime requested:

        // Get current scheduling policy and its settings and back it up for later restore:
        old_threadPolicy = (thread_policy_t) malloc(sizeof(thread_time_constraint_policy_data_t));
        policyCount = THREAD_TIME_CONSTRAINT_POLICY_COUNT;
        old_policyCountFilled = policyCount;
        isDefault = FALSE;
        // We check if STANDARD_POLICY is active and query its settings, if so...
        kernError = thread_policy_get(threadID, THREAD_STANDARD_POLICY, old_threadPolicy, &old_policyCountFilled, &isDefault);
        if (kernError) {
            // Failed!
            old_enable_realtime = FALSE;
            free(old_threadPolicy);
			printf("PsychRealtimePriority: ERROR! COULDN'T QUERY CURRENT SCHEDULING SETTINGS!!!\n");
            return(FALSE);
        }
        
        // oldModeWasStandard == TRUE --> We need to revert to STANDARD POLICY later...
        oldModeWasStandard = !isDefault;

        // printf("PRE-RT: CURRENTLY IN %s mode\n", oldModeWasStandard ? "STANDARD" : "REALTIME");

		if (!oldModeWasStandard) {
			// We are already RT scheduled. Backup settings for later switch-back:
			policyCount = THREAD_TIME_CONSTRAINT_POLICY_COUNT;
			old_policyCountFilled = policyCount;
			isDefault = FALSE;
			// We check if STANDARD_POLICY is active and query its settings, if so...
			kernError = thread_policy_get(threadID, THREAD_TIME_CONSTRAINT_POLICY, old_threadPolicy, &old_policyCountFilled, &isDefault);
			if (kernError) {
				// Failed!
				old_enable_realtime = FALSE;
				free(old_threadPolicy);
				printf("PsychRealtimePriority: ERROR! COULDN'T QUERY CURRENT RT SCHEDULING SETTINGS!!!\n");
				return(FALSE);
			}
		}

		// Switch to our ultra-high priority realtime mode: Guaranteed up to 3 msecs of uninterrupted
		// runtime as soon as we want to run: Perfect for swap completion timestamping in refresh rate
		// calibration - our only use-case:
		PsychSetThreadPriority(NULL, 10, 2);
    }
    else {
        // Transition from RT to Non-RT scheduling requested: We just reestablish the backed-up old
        // policy:
		kernError = thread_policy_set(threadID, (oldModeWasStandard) ? THREAD_STANDARD_POLICY : THREAD_TIME_CONSTRAINT_POLICY, old_threadPolicy, old_policyCountFilled);
		if (kernError) {
			// Failed!
			old_enable_realtime = TRUE;
			free((void*) old_threadPolicy);
			
			printf("PsychRealtimePriority: ERROR! COULDN'T SWITCH BACK TO NON-RT SCHEDULING!!!\n");
			fflush(NULL);
			return(FALSE);
		}
        
        // Successfully switchted to RT-Scheduling:
        free((void*) old_threadPolicy);
    }

    // Success.
    return(TRUE);
}