Skip to content

Instantly share code, notes, and snippets.

@midnightmagic
Created January 30, 2012 05:27
Show Gist options
  • Save midnightmagic/1702722 to your computer and use it in GitHub Desktop.
Save midnightmagic/1702722 to your computer and use it in GitHub Desktop.
artfan
#define LINUX 1
#include "adl_sdk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define DEBUG_ERROR (verbosity == verbosity)
#define DEBUG_INFO (verbosity >= 1)
#define LOGBUFSIZE 1024
//Main Group of APIs
extern int ADL_Main_Control_Create(ADL_MAIN_MALLOC_CALLBACK, int);
extern int ADL_Main_Control_Destroy();
//General Adapter APIs
extern int ADL_Adapter_NumberOfAdapters_Get(int *);
extern int ADL_Adapter_AdapterInfo_Get(LPAdapterInfo, int);
//Overdrive5 APIs
extern int ADL_Overdrive5_Temperature_Get(int, int, ADLTemperature *);
extern int ADL_Overdrive5_FanSpeedInfo_Get(int, int, ADLFanSpeedInfo *);
extern int ADL_Overdrive5_FanSpeed_Get(int, int, ADLFanSpeedValue *);
extern int ADL_Overdrive5_FanSpeed_Set(int, int, ADLFanSpeedValue *);
extern int ADL_Overdrive5_CurrentActivity_Get(int, ADLPMActivity *);
struct tinfo {
int iAdapterIndex;
char strUDID[256];
int iBusNumber;
int iSlaveIndex;
int iMasterTemp;
int iSlaveTemp;
int iMinPercent;
int iMaxPercent;
int iFanSpeed;
int iTemp;
char velocity;
int nPrevTemp;
float fIntegral;
int iPrevSum;
int iPrevTemps[60];
int iRealFanSpeed;
int iEngineClock;
int iMemoryClock;
int iActivityPercent;
int iSlaveEngineClock;
int iSlaveMemoryClock;
int iSlaveActivityPercent;
int iMaxActivityPercent;
};
struct slave_candidates {
int iAdapterIndex;
int iBusNumber;
int candidate;
};
#define MAX_ADAPTERS 8
int ninfos;
//struct tinfo info[MAX_ADAPTERS];
struct tinfo *info=NULL;
struct slave_candidates *sinfo=NULL;
// Memory allocation function
void* __stdcall ADL_Main_Memory_Alloc ( int iSize )
{
void* lpBuffer = calloc ( iSize, 1 );
return lpBuffer;
}
// Optional Memory de-allocation function
void __stdcall ADL_Main_Memory_Free ( void** lpBuffer )
{
if ( NULL != *lpBuffer )
{
free ( *lpBuffer );
*lpBuffer = NULL;
}
}
void do_dump_info(LPAdapterInfo b, unsigned long int i) {
printf("Retrieving from index %ld..\n", i);
printf("iSize: %d iAdapterIndex: %d\n", (*b).iSize, (*b).iAdapterIndex);
printf("strUDID: %s\n", (*b).strUDID);
printf("iBusNumber: %d iDeviceNumber: %d iFunctionNumber: %d\n",
(*b).iBusNumber, (*b).iDeviceNumber, (*b).iFunctionNumber);
printf("iVendorID: %d\n", (*b).iVendorID);
printf("strAdapterName: %s\n", (*b).strAdapterName);
printf("strDisplayName: %s\n", (*b).strDisplayName);
printf("iPresent: %d iXScreenNum: %d iDrvIndex: %d\n",
(*b).iPresent, (*b).iXScreenNum, (*b).iDrvIndex);
printf("strXScreenConfigName: %s\n", (*b).strXScreenConfigName);
printf("Calculated struct size: %ld\n", sizeof(*b));
printf("----------\n");
}
void dump_info(LPAdapterInfo b, int size, int i) {
if (0>i) {
i=0;
while(i<size) {
do_dump_info(b+i, i);
i++;
}
} else {
do_dump_info(b+i, (unsigned long int)i);
}
}
int enum_adapters(int minfan, int verbosity)
{
int iNumAdapters = 0;
LPAdapterInfo lpAdapterInfo = NULL;
int i, j, dupe, lpStatus;
ADLTemperature Temperature;
ADLFanSpeedInfo FanSpeedInfo;
ADLFanSpeedValue FanSpeedValue;
if(ADL_Main_Control_Create(ADL_Main_Memory_Alloc, 1) != ADL_OK) {
if (DEBUG_ERROR)
fprintf(stderr, "ADL Initialization Error!\n");
return 1;
}
if(ADL_Adapter_NumberOfAdapters_Get(&iNumAdapters) != ADL_OK) {
if (DEBUG_ERROR)
fprintf(stderr, "Cannot get the number of adapters!\n");
return 1;
} else {
if (DEBUG_INFO)
printf("Total number of adapters known: %d\n", iNumAdapters);
if (8<iNumAdapters) {
if (DEBUG_INFO)
printf("Do you really have %d adapters in-system? I guess we'll see.\n", iNumAdapters);
}
}
if(iNumAdapters <= 0) {
if (DEBUG_ERROR)
fprintf(stderr, "No adapters found!\n");
return 1;
}
if (!info) {
info=calloc(sizeof(struct tinfo),iNumAdapters);
if (!info) {
if (DEBUG_ERROR)
printf("Unable to allocate %ld bytes!\n", sizeof(struct tinfo)*iNumAdapters);
return 1;
}
}
if (!sinfo) {
sinfo=calloc(sizeof(struct slave_candidates),iNumAdapters);
if (!sinfo) {
if (DEBUG_ERROR)
printf("Unable to allocate %ld bytes!\n", sizeof(struct slave_candidates)*iNumAdapters);
return 1;
}
}
lpAdapterInfo = calloc(iNumAdapters,sizeof(AdapterInfo));
// memset(lpAdapterInfo, 0, iNumAdapters * sizeof(AdapterInfo));
if(ADL_Adapter_AdapterInfo_Get(lpAdapterInfo, iNumAdapters * sizeof(AdapterInfo)) != ADL_OK) {
if (DEBUG_ERROR)
fprintf(stderr, "Cannot get adapter info!\n");
return 1;
}
ninfos = 0;
for(i = 0; i < iNumAdapters; i++) {
// skip ghost adapters..
if (ADL_Adapter_Active_Get(lpAdapterInfo[i].iAdapterIndex, &lpStatus) != ADL_OK) {
if (DEBUG_INFO)
printf("Unable to check adapter %d active state. Skipping.\n", lpAdapterInfo[i].iAdapterIndex);
return 1;
} else {
if (lpStatus != ADL_TRUE) {
if (DEBUG_INFO)
printf("Reported state of %d is %d, NOT ADL_TRUE, skipping.\n", lpAdapterInfo[i].iAdapterIndex, lpStatus);
continue;
}
}
if(! lpAdapterInfo[i].iPresent || lpAdapterInfo[i].iXScreenNum < 0
|| lpAdapterInfo[i].strXScreenConfigName[0] == 0x0 ) {
if (DEBUG_INFO)
printf("Adapter %d appears to be a ghost. Skipping.\n", lpAdapterInfo[i].iAdapterIndex);
continue;
}
//ignore duplicate adapters
dupe = 0;
for(j = 0; j < ninfos; j++) {
if(!strcmp(lpAdapterInfo[i].strUDID, info[j].strUDID)) {
if (DEBUG_INFO)
printf("Adapter %d appears to have a duplicate strUDID with adapter %d. Skipping.\n", lpAdapterInfo[i].iAdapterIndex, lpAdapterInfo[j].iAdapterIndex);
dupe = 1;
break;
}
}
if(dupe)
continue;
memset(&Temperature, 0, sizeof(ADLTemperature));
Temperature.iSize = sizeof(ADLTemperature);
if(ADL_Overdrive5_Temperature_Get(lpAdapterInfo[i].iAdapterIndex, 0, &Temperature) != ADL_OK) {
if (DEBUG_INFO)
fprintf(stderr, "Cannot get temperature!\n");
return 1;
} else {
if (DEBUG_INFO)
printf("Retrieved temp from %d %3i.%01i°C\n", lpAdapterInfo[i].iAdapterIndex, Temperature.iTemperature / 1000, (Temperature.iTemperature % 1000) / 100 );
}
memset(&FanSpeedInfo, 0, sizeof(ADLFanSpeedInfo));
FanSpeedInfo.iSize = sizeof(ADLFanSpeedInfo);
if(ADL_Overdrive5_FanSpeedInfo_Get(lpAdapterInfo[i].iAdapterIndex, 0, &FanSpeedInfo) != ADL_OK) {
if (DEBUG_INFO)
fprintf(stderr, "Cannot get fan speed info!\n");
// return 1;
}
if(!(FanSpeedInfo.iFlags & (ADL_DL_FANCTRL_SUPPORTS_PERCENT_READ | ADL_DL_FANCTRL_SUPPORTS_PERCENT_WRITE))) {
if (DEBUG_INFO)
fprintf(stderr, "Adapter doesn't support fan speed control! %i Slave candidate..?\n", FanSpeedInfo.iFlags);
sinfo[lpAdapterInfo[i].iAdapterIndex].iAdapterIndex=lpAdapterInfo[i].iAdapterIndex;
sinfo[lpAdapterInfo[i].iAdapterIndex].iBusNumber=lpAdapterInfo[i].iBusNumber;
sinfo[lpAdapterInfo[i].iAdapterIndex].candidate=1;
continue;
}
memset(&FanSpeedValue, 0, sizeof(ADLFanSpeedValue));
FanSpeedValue.iSize = sizeof(ADLFanSpeedValue);
FanSpeedValue.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
if(ADL_Overdrive5_FanSpeed_Get(lpAdapterInfo[i].iAdapterIndex, 0, &FanSpeedValue) != ADL_OK) {
if (DEBUG_INFO)
fprintf(stderr, "Cannot get fan speed!\n");
return 1;
}
info[ninfos].iAdapterIndex = lpAdapterInfo[i].iAdapterIndex;
strcpy(info[ninfos].strUDID, lpAdapterInfo[i].strUDID);
info[ninfos].iBusNumber = lpAdapterInfo[i].iBusNumber;
info[ninfos].iSlaveIndex = -1; // Sentinel value, -1 means Master has no slave
// info[ninfos].iMinPercent = FanSpeedInfo.iMinPercent;
info[ninfos].iMinPercent = (FanSpeedInfo.iMinPercent < minfan ? minfan : FanSpeedInfo.iMinPercent);
// info[ninfos].iMinPercent = 30.0; // FTS man..! Setting fan minimum to 0?!
info[ninfos].iMaxPercent = FanSpeedInfo.iMaxPercent;
info[ninfos].iFanSpeed = FanSpeedValue.iFanSpeed;
info[ninfos].iTemp = Temperature.iTemperature;
info[ninfos].fIntegral = 0.;
info[ninfos].nPrevTemp = 0;
info[ninfos].iPrevSum = info[ninfos].iTemp * 60;
for(j = 0; j < 60; j++)
info[ninfos].iPrevTemps[j] = info[ninfos].iTemp;
if (DEBUG_INFO)
fprintf(stdout, "Adapter %i: idx %i temp %3i.%01i°C speed %3i%% (%3i%% - %3i%%)\n",
ninfos,
info[ninfos].iAdapterIndex,
info[ninfos].iTemp / 1000, (info[ninfos].iTemp % 1000) / 100,
info[ninfos].iFanSpeed,
info[ninfos].iMinPercent,
info[ninfos].iMaxPercent);
ninfos += 1;
}
if(ninfos == 0) {
if (DEBUG_ERROR)
fprintf(stderr, "No adapters found!\n");
return 1;
}
//find slaves
for(i = 0; i < iNumAdapters; i++) {
for(j = 0; j < ninfos; j++) {
if(info[j].iSlaveIndex == -1) {
if((info[j].iBusNumber == lpAdapterInfo[i].iBusNumber + 1) || (info[j].iBusNumber == lpAdapterInfo[i].iBusNumber - 1)) {
if (sinfo[i].candidate != 0) {
info[j].iSlaveIndex = lpAdapterInfo[i].iAdapterIndex;
if (DEBUG_INFO)
printf("Found probable slave for Bus %d on Bus %d\n", info[j].iBusNumber,lpAdapterInfo[i].iBusNumber);
break;
}
}
}
}
}
return 0;
}
static float targettemp = 85.0; //deg C
static int minfan = 30;
static float Kp = 1.;
static float Ki = 0.5;
static float Kd = 1.;
static float Ff = 0.2;
static int verbosity=0;
static int sleepytime=3;
int calc_new_fanspeed(int idx)
{
float curtemp, avgtemp;
float Sp, Si, Sd, Sf, Ss;
int newfanspeed;
curtemp = (float)(info[idx].iTemp) / 1000.0;
info[idx].fIntegral += curtemp - targettemp;
// Clamp integral else long-running fan controller
// running @ 10% or whatever minfan is, would NEVER
// POSSIBLY hope to ever catch up to runaway card temps
// and we guarantee we hit the danger safety zone
// trigger, throwing away the smooth PID curves. :(
// The clamp value was chosen because we want
// at most 10 seconds to overcome historical
// fIntegral accumulation.
if (info[idx].fIntegral < (float)minfan/Ki)
info[idx].fIntegral = (float)minfan/Ki;
avgtemp = (float)(info[idx].iPrevSum) / (1000.0 * 60);
Sp = (curtemp - targettemp) * Kp;
Si = info[idx].fIntegral * Ki;
Sd = (curtemp - avgtemp) * Kd;
Sf = (float)(info[idx].iMaxActivityPercent) * Ff;
Ss = Sp + Si + Sd;
if (idx == 0 && (DEBUG_INFO))
printf("\n(Sp:%f + Si:%f + Sd:%f)>Sf:%f?\n", Sp, Si, Sd, Sf);
newfanspeed = Ss;
// This is a feed-forward override.
// When the card is extra-busy, we can set the
// Fan to some fraction of max based on card busy-ness
// Which will prevent insane runaway that PID isn't
// reacting fast enough to.
newfanspeed=(newfanspeed < Sf)?Sf:newfanspeed;
if(newfanspeed < info[idx].iMinPercent)
newfanspeed = info[idx].iMinPercent;
if(newfanspeed > info[idx].iMaxPercent)
newfanspeed = info[idx].iMaxPercent;
if(curtemp > targettemp + 5.0) {
newfanspeed = info[idx].iMaxPercent;
// The integral is the knob that most directly contributes
// to fanspeed. If we set it to 100 here, fanspeed goes to
// 100% -- so this should probably more accurately be
// set to iMaxPercent..
info[idx].fIntegral = 100.;
}
if (newfanspeed < minfan) {
return minfan;
} else {
return newfanspeed;
}
}
int main(int argc, char **argv)
{
int i, tfanspeed, opt;
int opflags;
char *logfile=NULL, *logbuf=NULL;
int f=0; off_t l; time_t t;
ADLTemperature Temperature;
ADLFanSpeedValue FanSpeedValue;
ADLFanSpeedValue FanSpeedCurrent;
ADLPMActivity PMActivity;
if (argc > 1) {
while ((opt=getopt(argc, argv, "hl:t:m:p:i:d:s:vf:")) != -1) {
switch(opt) {
case 'h':
printf("artfan v0.2, based originally on ArtForZz's awesome generous pastebin.\n");
printf("Seriously, very very few of you fully realise how important his contributions have been.\n");
printf("Modified very heavily by midnightmagic. Modifications ©2011 midnightmagic\n");
printf("Usage: %s [ [-h] | [-l logfile] [-t targettemp] [-m minfan] [-s sleepinterval] [-v[v]] [-p Kp] [-i Ki] [-d Kd] [ -f FeedForward ]\n", argv[0]);
return 1;
case 'l':
printf("Logging to: %s\n", optarg);
if (logfile) {
free(logfile);
logfile=NULL; // probably unnecessary
}
logfile=calloc(strlen(optarg)+1, 1);
if (NULL==logfile) {
if (DEBUG_ERROR)
printf("Error allocating %d bytes.\n", (int)strlen(optarg)+1);
return 1;
}
strncpy(logfile, optarg, strlen(optarg)+1);
if (logbuf) {
free(logbuf);
logbuf=NULL; // also probably unnecessary
}
if ((logbuf=calloc(LOGBUFSIZE+1,1)) == NULL) {
// and now we can use logbuf != NULL to check if we should log, later on.
if (DEBUG_ERROR)
printf("Could not allocate %d bytes for logfile buffer.\n", LOGBUFSIZE);
return 1;
}
break;
case 't':
targettemp=atof(optarg);
if (DEBUG_INFO)
printf("Setting target temperature to %.2f\n", targettemp);
break;
case 'm':
minfan=atoi(optarg);
if (DEBUG_INFO)
printf("Setting minfan speed to %d\n", minfan);
break;
case 'p':
Kp=atof(optarg);
if (DEBUG_INFO)
printf("Setting Kp to %f\n", Kp);
break;
case 'i':
Ki=atof(optarg);
if (DEBUG_INFO)
printf("Setting Ki to %f\n", Ki);
break;
case 'd':
Kd=atof(optarg);
if (DEBUG_INFO)
printf("Setting Kd to %f\n", Kd);
break;
case 's':
sleepytime=atoi(optarg);
if (DEBUG_INFO)
printf("Setting reset interval to %d seconds.\n", sleepytime);
break;
case 'v':
++verbosity;
if (DEBUG_INFO)
printf("Verbosity increased, now: %d\n", verbosity);
break;
case 'f':
Ff=atof(optarg);
if (DEBUG_INFO)
printf("Setting feedforward multiplier (times activityPercent) to %f\n", Ff);
break;
default:
if (DEBUG_ERROR)
printf("Unknown arg. Try -h.\n");
return 1;
}
} // End of arg-runner while loop.
if (optind>argc) if (DEBUG_INFO) printf("Remaining args:\n");
for(i=optind;i<argc;i++){
if (DEBUG_INFO)
printf("%s\n", argv[i]);
}
if (optind>argc) return 1;
}
if(enum_adapters(minfan, verbosity))
return 1;
memset(&Temperature, 0, sizeof(ADLTemperature));
Temperature.iSize = sizeof(ADLTemperature);
memset(&FanSpeedValue, 0, sizeof(ADLFanSpeedValue));
FanSpeedValue.iSize = sizeof(ADLFanSpeedValue);
FanSpeedValue.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
FanSpeedValue.iFlags = ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED;
memset(&FanSpeedCurrent, 0, sizeof(ADLFanSpeedValue));
FanSpeedCurrent.iSize=sizeof(ADLFanSpeedValue);
FanSpeedCurrent.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
memset(&PMActivity, 0, sizeof(PMActivity));
PMActivity.iSize=sizeof(PMActivity);
while(1) {
for(i = 0; i < ninfos; i++) {
//retrieve current fanspeed
if(ADL_Overdrive5_FanSpeed_Get(info[i].iAdapterIndex, 0, &FanSpeedCurrent) != ADL_OK) {
if (DEBUG_ERROR)
fprintf(stderr, "Cannot get FanSpeed for card %d\n", info[i].iAdapterIndex);
return 1;
}
if(FanSpeedCurrent.iSpeedType==ADL_DL_FANCTRL_SPEED_TYPE_RPM) {
if (DEBUG_ERROR)
fprintf(stderr,"WARNING: Current Fan Speed in RPM NOT PERCENT AS REQUESTED! DANGER! MANUALLY SET FANSPEEDS TO SOMETHING HIGHER! QUICK!\n");
return 1;
}
if(ADL_Overdrive5_CurrentActivity_Get(info[i].iAdapterIndex, &PMActivity) != ADL_OK) {
if (DEBUG_ERROR)
fprintf(stderr, "Cannot get current activity for adapter %d\n", info[i].iAdapterIndex);
return 1;
}
info[i].iEngineClock=PMActivity.iEngineClock;
info[i].iMemoryClock=PMActivity.iMemoryClock;
info[i].iActivityPercent=PMActivity.iActivityPercent;
// And record the MaxActivity, which will possibly be overwritten later if the slave is doing more
info[i].iMaxActivityPercent=info[i].iActivityPercent;
//get current temp
if(ADL_Overdrive5_Temperature_Get(info[i].iAdapterIndex, 0, &Temperature) != ADL_OK) {
if (DEBUG_ERROR)
fprintf(stderr, "Cannot get temperature for adapter %d\n", info[i].iAdapterIndex);
return 1;
}
info[i].iMasterTemp = Temperature.iTemperature;
if(info[i].iSlaveIndex != -1) {
if(ADL_Overdrive5_Temperature_Get(info[i].iSlaveIndex, 0, &Temperature) != ADL_OK) {
if (DEBUG_ERROR)
fprintf(stderr, "Cannot get temperature for adapter %d\n", info[i].iSlaveIndex);
return 1;
}
info[i].iSlaveTemp = Temperature.iTemperature;
if(Temperature.iTemperature < info[i].iMasterTemp) {
Temperature.iTemperature = info[i].iMasterTemp;
}
if(ADL_Overdrive5_CurrentActivity_Get(info[i].iSlaveIndex, &PMActivity) != ADL_OK) {
if (DEBUG_ERROR)
fprintf(stderr, "Cannot get current activity for adapter %d\n", info[i].iSlaveIndex);
return 1;
}
info[i].iSlaveEngineClock=PMActivity.iEngineClock;
info[i].iSlaveMemoryClock=PMActivity.iMemoryClock;
info[i].iSlaveActivityPercent=PMActivity.iActivityPercent;
if (info[i].iMaxActivityPercent < info[i].iSlaveActivityPercent)
info[i].iMaxActivityPercent = info[i].iSlaveActivityPercent;
}
info[i].iRealFanSpeed = FanSpeedCurrent.iFanSpeed;
info[i].iPrevSum -= info[i].iPrevTemps[info[i].nPrevTemp];
info[i].iPrevSum += info[i].iTemp;
info[i].iPrevTemps[info[i].nPrevTemp] = info[i].iTemp;
info[i].iTemp = Temperature.iTemperature;
tfanspeed = calc_new_fanspeed(i);
if (tfanspeed > info[i].iFanSpeed) {
info[i].velocity='^';
} else if (tfanspeed == info[i].iFanSpeed) {
info[i].velocity='*';
} else {
info[i].velocity='v';
}
if(tfanspeed != info[i].iFanSpeed) {
info[i].iFanSpeed = info[i].iRealFanSpeed; // was tfanspeed here too before..
// info[i].iFanSpeed = tfanspeed;
FanSpeedValue.iFanSpeed = tfanspeed;
if(ADL_Overdrive5_FanSpeed_Set(info[i].iAdapterIndex, 0, &FanSpeedValue) != ADL_OK) {
if (DEBUG_ERROR)
fprintf(stderr, "Cannot set fan speed!\n");
return 1;
}
}
info[i].nPrevTemp = (info[i].nPrevTemp + 1) % 60; // advance the round-robin head ptr..
}
//print status line
for(i = 0; i < ninfos; i++) {
if(i)
fprintf(stdout, "|");
if(info[i].iSlaveIndex != -1) {
fprintf(stdout, "%i:%2i.%01i/%2i.%01i°C%c%2i",
i,
info[i].iMasterTemp / 1000, (info[i].iMasterTemp % 1000) / 100,
info[i].iSlaveTemp / 1000, (info[i].iSlaveTemp % 1000) / 100,
info[i].velocity,
info[i].iFanSpeed);
} else {
fprintf(stdout, "%i:%3i.%01i°C:%c%2i%%",
i,
info[i].iMasterTemp / 1000, (info[i].iMasterTemp % 1000) / 100,
info[i].velocity,
info[i].iFanSpeed);
}
}
fprintf(stdout, " \r");
fflush(stdout);
if (logbuf) {
t=time();
f=open(logfile, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
if (!f) {
if (DEBUG_ERROR)
fprintf(stderr, "ERROR: Unable to open logfile %s.\n", logfile);
} else {
if ((l=lseek(f, 0, SEEK_END)) >= 0) { // We'll be appending..
for (i=0;i<ninfos;i++) {
snprintf(logbuf, LOGBUFSIZE-1, "%ld:%d:%.1f:%d:%d:%d:%d\n",
t,
info[i].iAdapterIndex, (float)info[i].iMasterTemp/1000.0,
info[i].iRealFanSpeed,
info[i].iEngineClock/100, info[i].iMemoryClock/100,
info[i].iActivityPercent);
write(f, logbuf, strlen(logbuf)); // who cares if it works.
if (info[i].iSlaveIndex != -1) {
snprintf(logbuf, LOGBUFSIZE-1, "%ld:%d:%.1f:%d:%d:%d:%d\n",
t,
info[i].iSlaveIndex, (float)info[i].iSlaveTemp/1000.0,
info[i].iRealFanSpeed,
info[i].iSlaveEngineClock/100,
info[i].iSlaveMemoryClock/100,
info[i].iSlaveActivityPercent);
write(f,logbuf,strlen(logbuf));
}
}
} else {
if (DEBUG_ERROR)
fprintf(stderr, "ERROR: Unable to seek to end of logfile.\n");
}
fsync(f);
close(f);
}
}
sleep(sleepytime);
}
printf("done\n");
ADL_Main_Control_Destroy();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment