Esempio n. 1
0
// Real timer filter
bool driver::perfTimerEvent(IOTimerEventSource *src, int count) {
 uint64_t msr;
 uint32_t vid;
 
 uint32_t next_check_delay;
 uint32_t wantspeed,wantstep;
 long i,idle,used,total;

 if (driverStatus != driverDrive) return(false);

 //ok, so we're using adaptive mode..
 if (get_cpu_ticks(&idle, &total)) fail("get_cpu_load");

 // Used = % used x 10
 used = ((total-idle)*1000)/total;

 // If used > 95% we can't really guess how much is needed, so step to highest speed
 if (used>=950) wantspeed=speedstep_cpu_setting[num_speeds-1].cpuMhz;
		
 // Otherwise wantspeed is the ideal frequency to maintain idle % target
 else wantspeed = (speedstep_cpu_setting[stepCurrent].cpuMhz * (used+1)) / TARGET_CPULOAD;

 if (wantspeed>=speedstep_cpu_setting[num_speeds-1].cpuMhz)	wantstep = num_speeds-1;	// We want something higher than our highest
 else if (wantspeed<=speedstep_cpu_setting[0].cpuMhz)			wantstep = 0;				// We want something lower than our lowest
 
 // Otherwise, find the best step
 else for (i = 0; i < (num_speeds-1); i++) if ((wantspeed >= speedstep_cpu_setting[i].cpuMhz) && (wantspeed < speedstep_cpu_setting[i+1].cpuMhz)) wantstep=i;
 //dbg("pctused=%u idle=%u total=%u wantspeed=%u wantstep=%u\n",used,idle,total,wantspeed,wantstep);

 if (wantstep == stepCurrent) goto check_soon;

 stepCurrent = wantstep; // Assume we got the one we wanted

 eist_update_all_cpus(speedstep_cpu_setting[wantstep].VID);
// IOSleep(1);
 msr = rdmsr64(MSR_PERF_CTL);
 vid = msr & 0xFFFF;
 dbg("Stepping to %u pctused=%u VID=0x%04x\n",speedstep_cpu_setting[wantstep].cpuMhz,used,vid);
 
 perfTimer->setTimeoutMS(512 * (wantstep+1)); // Make the delay until the next check proportional to the speed we picked
 return(true);
 

 perfTimer->setTimeoutMS(1024);
 success:
 return(true);

 check_soon:
 perfTimer->setTimeoutMS(512);
 return(true);

 fail:
 return(false);
}
Esempio n. 2
0
/* called on every vsync */
void pl_frame_limit(void)
{
	static struct timeval tv_old, tv_expect;
	static int vsync_cnt_prev;
	struct timeval now;
	int diff, usadj;

	vsync_cnt++;

	/* doing input here because the pad is polled
	 * thousands of times per frame for some reason */
	update_input();

	pcnt_end(PCNT_ALL);
	gettimeofday(&now, 0);

	if (now.tv_sec != tv_old.tv_sec) {
		diff = tvdiff(now, tv_old);
		vsps_cur = 0.0f;
		if (0 < diff && diff < 2000000)
			vsps_cur = 1000000.0f * (vsync_cnt - vsync_cnt_prev) / diff;
		vsync_cnt_prev = vsync_cnt;
		flips_per_sec = flip_cnt;
		flip_cnt = 0;
		tv_old = now;
		if (g_opts & OPT_SHOWCPU)
			tick_per_sec = get_cpu_ticks();

		if (hud_new_msg > 0) {
			hud_new_msg--;
			if (hud_new_msg == 0)
				hud_msg[0] = 0;
		}
	}
#ifdef PCNT
	static int ya_vsync_count;
	if (++ya_vsync_count == PCNT_FRAMES) {
		pcnt_print(vsps_cur);
		ya_vsync_count = 0;
	}
#endif

	tvadd(tv_expect, pl_frame_interval);
	diff = tvdiff(tv_expect, now);
	if (diff > MAX_LAG_FRAMES * pl_frame_interval || diff < -MAX_LAG_FRAMES * pl_frame_interval) {
		//printf("pl_frame_limit reset, diff=%d, iv %d\n", diff, pl_frame_interval);
		tv_expect = now;
		diff = 0;
		// try to align with vsync
		usadj = vsync_usec_time;
		while (usadj < tv_expect.tv_usec - pl_frame_interval)
			usadj += pl_frame_interval;
		tv_expect.tv_usec = usadj;
	}

	if (!(g_opts & OPT_NO_FRAMELIM) && diff > pl_frame_interval) {
		// yay for working usleep on pandora!
		//printf("usleep %d\n", diff - pl_frame_interval / 2);
		usleep(diff - pl_frame_interval / 2);
	}

	if (UseFrameSkip) {
		if (diff < -pl_frame_interval) {
			// P.E.Op.S. makes skip decision based on this
			fps_skip = 1.0f;
			plugin_skip_advice = 1;
		}
		else if (diff >= 0) {
			fps_skip = 100.0f;
			plugin_skip_advice = 0;
		}
	}

	pcnt_start(PCNT_ALL);
}