diff --git a/src/dev/vxStatsDev/devVXStats.c b/src/dev/vxStatsDev/devVXStats.c index 154603122..683fafef3 100644 --- a/src/dev/vxStatsDev/devVXStats.c +++ b/src/dev/vxStatsDev/devVXStats.c @@ -37,7 +37,7 @@ of this distribution. #include #include #include - + /* The following device definitions must exist @@ -110,40 +110,6 @@ of this distribution. } */ -#define MEMORY_TYPE 0 -#define CPU_TYPE 1 -#define FD_TYPE 2 -#define TOTAL_TYPES 3 - -#define SECONDS_TO_BURN 5 - -/* default rate in seconds (memory,cpu,fd) */ -static int default_scan_rate[] = { 10,50,10 }; - -static char *aiparmValue[TOTAL_TYPES] = {"memory","cpu","fd"}; -static char *aoparmValue[TOTAL_TYPES] = { - "memoryScanPeriod","cpuScanPeriod","fdScanPeriod"}; - -typedef struct devPvt -{ - int type; -}devPvt; - -typedef struct scanInfo -{ - IOSCANPVT ioscanpvt; - WDOG_ID wd; - int rate_tick; /* ticks */ -}scanInfo; - -static scanInfo scan[TOTAL_TYPES]; - -static double getMemory(void); -static double getCpu(void); -static double getFd(void); -static void wdCallback(int type); -static void cpuUsageInit(void); - typedef struct aiaodset { long number; @@ -154,23 +120,81 @@ typedef struct aiaodset DEVSUPFUN read_write; DEVSUPFUN special_linconv; }aiaodset; -static long ai_init(int pass); -static long ai_init_record(aiRecord*); -static long ai_read(aiRecord*); -static long ai_ioint_info(int cmd,aiRecord* pr,IOSCANPVT* iopvt); +typedef struct devPvt +{ + int type; +}devPvt; + +static long ai_init(int pass); +static long ai_ioint_info(int cmd,aiRecord* pr,IOSCANPVT* iopvt); +static long ai_init_record(aiRecord*); static long ao_init_record(aoRecord* pr); +static long ai_read(aiRecord*); static long ao_write(aoRecord*); + aiaodset devAiVXStats={ 6,NULL,ai_init,ai_init_record,ai_ioint_info,ai_read,NULL }; aiaodset devAoVXStats={ 6,NULL,NULL,ao_init_record,NULL,ao_write,NULL }; +#define MEMORY_TYPE 0 +#define CPU_TYPE 1 +#define FD_TYPE 2 +#define TOTAL_TYPES 3 + +/* default rate in seconds (memory,cpu,fd) */ +static int default_scan_rate[] = { 10,50,10 }; + +static char *aiparmValue[TOTAL_TYPES] = {"memory","cpu","fd"}; +static char *aoparmValue[TOTAL_TYPES] = { + "memoryScanPeriod","cpuScanPeriod","fdScanPeriod"}; + +typedef struct scanInfo +{ + IOSCANPVT ioscanpvt; + WDOG_ID wd; + int rate_tick; /* ticks */ +}scanInfo; +static scanInfo scan[TOTAL_TYPES]; + +static void wdCallback(int type); +static double getMemory(void); +static double getFd(void); + +#define SECONDS_TO_STARVATION 60 +#define SECONDS_TO_BURN 5 +#define SECONDS_TO_WAIT 15 + +typedef struct cpuUsage { + SEM_ID lock; + unsigned long ticksToDeclareStarvation; + unsigned long ticksToBurn; + unsigned long ticksToWait; + double nBurnNoContention; + unsigned long ticksLastUpdate; + double usage; +} cpuUsage; +static cpuUsage usage; + +static void wdCpu(void); +static double cpuBurn(); +static void cpuUsageTask(); +static double getCpu(void); +static void cpuUsageInit(void); + static long ai_init(int pass) { int type; if(pass==1) { - for(type=0;typedpvt; + + *iopvt=scan[pvt->type].ioscanpvt; + return 0; +} + static long ai_init_record(aiRecord* pr) { int type; @@ -243,21 +275,7 @@ static long ao_init_record(aoRecord* pr) pr->dpvt=pvt; return 2; } - -static void wdCallback(int type) -{ - scanIoRequest(scan[type].ioscanpvt); - wdStart(scan[type].wd,scan[type].rate_tick, (FUNCPTR)wdCallback,type); -} - -static long ai_ioint_info(int cmd,aiRecord* pr,IOSCANPVT* iopvt) -{ - devPvt* pvt=(devPvt*)pr->dpvt; - - *iopvt=scan[pvt->type].ioscanpvt; - return 0; -} - + static long ao_write(aoRecord* pr) { devPvt* pvt=(devPvt*)pr->dpvt; @@ -285,12 +303,16 @@ static long ai_read(aiRecord* pr) return 2; /* don't convert */ } +static void wdCallback(int type) +{ + scanIoRequest(scan[type].ioscanpvt); + wdStart(scan[type].wd,scan[type].rate_tick, (FUNCPTR)wdCallback,type); +} + /*Memory statistics*/ #include static MEM_PART_STATS meminfo; -/* -------------------------------------------------------------------- */ - static double getMemory(void) { double nfree,nalloc; @@ -315,17 +337,18 @@ static double getFd() return(100.0*(double)tot/(double)maxFiles); } -typedef struct cpuUsage { - SEM_ID startSem; - int didNotComplete; - unsigned long ticksNoContention; - int nBurnNoContention; - unsigned long ticksNow; - int nBurnNow; - double usage; -} cpuUsage; +static void wdCpu(void) +{ + unsigned long ticksLastUpdate = usage.ticksLastUpdate; + unsigned long ticksNow = tickGet(); -static cpuUsage *pcpuUsage=0; + if(ticksNow>=ticksLastUpdate /*ignore tick overflow*/ + && (ticksNow-ticksLastUpdate) >= usage.ticksToDeclareStarvation) { + usage.usage = 100.0; + scanIoRequest(scan[CPU_TYPE].ioscanpvt); + } + wdStart(scan[CPU_TYPE].wd,scan[CPU_TYPE].rate_tick,(FUNCPTR)wdCpu,0); +} static double cpuBurn() { @@ -338,68 +361,68 @@ static double cpuBurn() static void cpuUsageTask() { - while(TRUE) { - int i; - unsigned long tickStart,tickEnd; - semTake(pcpuUsage->startSem,WAIT_FOREVER); - pcpuUsage->ticksNow=0; - pcpuUsage->nBurnNow=0; + while(TRUE) { + unsigned long tickStart,tickEnd=0; + int nBurnNow; + double nBurnNoContention = (double)usage.nBurnNoContention; + double nBurnContention,newusage; + + nBurnNow=0; tickStart = tickGet(); - for(i=0; i< pcpuUsage->nBurnNoContention; i++) { + while(1) { cpuBurn(); - pcpuUsage->ticksNow = tickGet() - tickStart; - ++pcpuUsage->nBurnNow; + ++nBurnNow; + tickEnd = tickGet(); + if(tickEnd= usage.ticksToBurn) break; } - tickEnd = tickGet(); - pcpuUsage->didNotComplete = FALSE; - pcpuUsage->ticksNow = tickEnd - tickStart; + if(tickEnddidNotComplete && pcpuUsage->nBurnNow==0) { - pcpuUsage->usage = 0.0; - } else { - double temp; - double ticksNow,nBurnNow; - - ticksNow = (double)pcpuUsage->ticksNow; - nBurnNow = (double)pcpuUsage->nBurnNow; - ticksNow *= (double)pcpuUsage->nBurnNoContention/nBurnNow; - temp = ticksNow - (double)pcpuUsage->ticksNoContention; - temp = 100.0 * temp/ticksNow; - if(temp<0.0 || temp>100.0) temp=0.0;/*take care of tick overflow*/ - pcpuUsage->usage = temp; - } - pcpuUsage->didNotComplete = TRUE; - semGive(pcpuUsage->startSem); - return(pcpuUsage->usage); + double value; + semTake(usage.lock,WAIT_FOREVER); + value = usage.usage; + semGive(usage.lock); + return(value); } static void cpuUsageInit(void) { - unsigned long tickStart,tickNow; + unsigned long tickStart,tickEnd=0,tickNow; int nBurnNoContention=0; - int ticksToWait; - ticksToWait = SECONDS_TO_BURN*sysClkRateGet(); - pcpuUsage = calloc(1,sizeof(cpuUsage)); + usage.lock = + semMCreate(SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY); + usage.usage = 0.0; + usage.ticksToDeclareStarvation = SECONDS_TO_STARVATION * sysClkRateGet(); + usage.ticksToWait = SECONDS_TO_WAIT*sysClkRateGet(); + usage.ticksToBurn = SECONDS_TO_BURN*sysClkRateGet(); tickStart = tickGet(); /*wait for a tick*/ while(tickStart==(tickNow = tickGet())) {;} tickStart = tickNow; while(TRUE) { - if((tickGet() - tickStart)>=ticksToWait) break; cpuBurn(); nBurnNoContention++; + tickEnd = tickGet(); + if(tickEnd= usage.ticksToBurn) break; } - pcpuUsage->nBurnNoContention = nBurnNoContention; - pcpuUsage->startSem = semBCreate (SEM_Q_FIFO,SEM_EMPTY); - pcpuUsage->ticksNoContention = ticksToWait; - pcpuUsage->didNotComplete = TRUE; + if(tickEnd