struct cpuidle_datas *idlestat_load(const char *filename) { const struct trace_ops **ops_it; int ret; /* * The linker places pointers to all entries declared with * EXPORT_TRACE_OPS into a special segment. This creates * an array of pointers preceded by trace_ops_head. Let * the static analysis tool know that we know what we are * doing. */ /* coverity[array_vs_singleton] */ for (ops_it = (&trace_ops_head)+1 ; *ops_it ; ++ops_it) { assert((*ops_it)->name); assert((*ops_it)->check_magic); assert((*ops_it)->load); ret = (*ops_it)->check_magic(filename); if (ret == -1) return ptrerror(NULL); /* File format supported by these ops? */ if (ret > 0) { return (*ops_it)->load(filename); } } fprintf(stderr, "Trace file format not recognized\n"); return ptrerror(NULL); }
/** * build_cstate_info - parse cpuidle sysfs entries and build per-CPU * structs to maintain statistics of C-state transitions * * @nrcpus: number of CPUs * * @return: per-CPU array of structs (success) or ptrerror() (error) */ struct cpuidle_cstates *build_cstate_info(int nrcpus) { int cpu; struct cpuidle_cstates *cstates; assert(nrcpus > 0); cstates = calloc(nrcpus, sizeof(*cstates)); if (!cstates) return ptrerror(__func__); /* initialize cstate_max for each cpu */ for (cpu = 0; cpu < nrcpus; cpu++) { int i; struct cpuidle_cstate *c; cstates[cpu].cstate_max = -1; cstates[cpu].current_cstate = -1; for (i = 0; i < MAXCSTATE; i++) { c = &(cstates[cpu].cstate[i]); c->name = cpuidle_cstate_name(cpu, i); c->data = NULL; c->nrdata = 0; c->early_wakings = 0; c->late_wakings = 0; c->avg_time = 0.; c->max_time = 0.; c->min_time = DBL_MAX; c->duration = 0.; c->target_residency = cpuidle_get_target_residency(cpu, i); } } return cstates; }
/* * Declare a static variable (i.e. define for use) * * makes an entry in the symbol table so subsequent * references can call symbol by name */ void declglb( int typ , /* typ is CCHAR, CINT, DOUBLE, STRUCT, LONG, */ int storage, TAG_SYMBOL *mtag , /* tag of struct whose members are being declared, or zero */ TAG_SYMBOL *otag , /* tag of struct for object being declared */ int is_struct , /* TRUE if struct member being declared, zero if union */ char sign , /* TRUE if need signed */ char zfar ) /* TRUE if far */ { char sname[NAMESIZE]; int size, ident, more, itag, type, size_st; long addr = -1; char flagdef,match,ptrtofn; char libdef,fastcall,callee; SYMBOL *myptr ; do { if ( endst() ) break; /* do line */ type = typ ; size = 1 ; /* assume 1 element */ more = /* assume dummy symbol not required */ itag = 0 ; /* just for tidiness */ flagdef=libdef=fastcall=callee=NO; match=ptrtofn=NO; while (blanks(),rcmatch('_') ) { match=NO; if (amatch("__APPFUNC__") ) { match=YES; flagdef=1; } if (amatch("__LIB__") /* && libdef==0 */) {match=YES; libdef|=LIBRARY; } if (amatch("__FASTCALL__") ) {match=YES; fastcall=REGCALL; } if (amatch("__SHARED__") ) {match=YES; libdef|=SHARED; } if (amatch("__SHAREDC__") ) {match=YES; libdef|=SHAREDC; } if (amatch("__CALLEE__") ) {match=YES; callee=CALLEE; } if (match ==NO )break; } ident = get_ident() ; if (storage==TYPDEF && ident !=VARIABLE && mtag ==0 ) warning(W_TYPEDEF); if ( symname(sname) == 0 ) /* name ok? */ illname(sname) ; /* no... */ if ( ident == PTR_TO_FNP ) { /* function returning pointer needs dummy symbol */ more = dummy_idx(typ, otag) ; type = (zfar ? CPTR : CINT ); size=0; ptrtofn=YES; } else if ( ident == PTR_TO_FN ) { ident = POINTER ; ptrtofn=YES; #if 0 } else if ( cmatch('@') ) { storage = EXTERNP; constexpr(&addr,1); #endif } else if ( cmatch('(') ) { /* * Here we check for functions, but we can never have a pointer to * function because thats considered above. Which means as a very * nice side effect that we don't have to consider structs/unions * since they can't contain functions, only pointers to functions * this, understandably(!) makes the work here a lot, lot easier! */ storage=AddNewFunc(sname,type,storage,zfar,sign,otag,ident,&addr); /* * On return from AddNewFunc, storage will be: * EXTERNP = external pointer, in which case addr will be set * !! FUNCTION = have prototyped a function (NOT USED!) * 0 = have declared a function/!! prototyped ANSI * * If 0, then we have to get the hell out of here, FUNCTION * then gracefully loop round again, if EXTERNP, carry on with * this function, anything else means that we've come up * against a K&R style function definition () so carry on * as normal! * * If we had our function prefixed with __APPFUNC__ then we want * to write it out to the zcc_opt.def file (this bloody thing * is becoming invaluable for messaging! * * __SHARED__ indicates in a library so preserve carry flag * (so we can test with iferror) * * __CALLEE__ indicates that the function called cleans up * the stack * * __SHAREDC__ is indicates call by rst 8 but is unused.. * (old idea unused, but may yet be useful) */ if (flagdef) WriteDefined(sname,0); if (currfn) { /* djm 1/2/03 - since we can override lib functions don't reset the library flag currfn->flags&=(~LIBRARY); */ if (libdef) { // currfn->flags|=LIBRARY; currfn->flags|=libdef; } if (callee && (libdef&SHARED) != SHARED && \ (libdef&SHAREDC) != SHAREDC ) currfn->flags|=callee; if (fastcall) currfn->flags|=fastcall; } if (storage==0) { if ( addr != -1 ) { currfn->size = addr; } return; } /* * External pointer..check for the closing ')' */ if (storage==EXTERNP) { needchar(')'); } else { /* * Must be a devilishly simple prototype! ();/, type... */ ptrerror(ident) ; if ( ident == POINTER ) { /* function returning pointer needs dummy symbol */ more = dummy_idx(typ, otag) ; type = (zfar ? CPTR : CINT ); ident=FUNCTIONP; } else { ident=FUNCTION; } size = 0 ; } } if (cmatch('[')) { /* array? */ ptrerror(ident) ; if ( ident == POINTER) { /* array of pointers needs dummy symbol */ more = dummy_idx(typ, otag) ; type = (zfar ? CPTR : CINT ); } size = needsub() ; /* get size */ if (size == 0 && ident == POINTER ) size=0; ident = ARRAY; if ( ptrtofn ) needtoken(")()"); } else if ( ptrtofn ) { needtoken(")()") ; } else if ( ident == PTR_TO_PTR ) { ident = POINTER ; more = dummy_idx(typ, otag) ; type = (zfar ? CPTR : CINT ); } if ( cmatch('@') ) { storage = EXTERNP; constexpr(&addr,1); }
int AddNewFunc( char *sname, int type, int storage, char zfar, char sign, TAG_SYMBOL *otag, int ident, long *addr) { SYMBOL *ptr; int more; char simple; /* Simple def () */ more=0; /* * First of all check to see if we have a number - this is * external pointer type */ if (number(addr)) return (EXTERNP); /* * Now, check for simple prototyping, we can drop that * back as well, we have to check for punctuation - ; or , * afterwards, so that we can know its not a function * definitions */ simple=NO; if ( cmatch(')') ) { if ( rcmatch(';') || rcmatch(',') ) return(storage); simple=YES; } ptrerror(ident) ; if ( ident == POINTER ) { /* function returning pointer needs dummy symbol */ more = dummy_idx(type, otag) ; /* type = (zfar ? CPTR : CINT ); */ ident=FUNCTIONP; /* func returning ptr */ } else ident=FUNCTION; /* * Okay, we've got rid of everything that could pop up apart * from: * - ANSI prototypes * - Functions themselves (ANSI & K&R) * * First call AddNewFunc(), if this returns 0 then we have defined * a function (including code) */ ptr=AddFuncCode(sname, type, ident,sign, zfar, storage, more,NO,simple,otag,addr); if (ptr==0) { /* Defined a function */ /* trap external int blah() { } things */ if (currfn->storage==EXTERNAL) currfn->storage=STATIK; return(0); } else { StoreFunctionSignature(ptr); } return(0); }
SYMBOL * #endif getarg( int typ , /* typ = CCHAR, CINT, DOUBLE or STRUCT */ TAG_SYMBOL *otag , /* structure tag for STRUCT type objects */ int deftype, /* YES=ANSI -> addloc NO=K&R -> findloc */ SYMBOL *prevarg, /* ptr to previous argument, only of use to ANSI */ char issigned, /* YES=unsigned NO=signed */ char zfar, /* FARPTR=far NO=near */ char proto) /* YES=prototyping -> names not needed */ { char n[NAMESIZE] ; SYMBOL *argptr ; int legalname, ident, more ; int brkflag; /* Needed to correctly break out for K&R*/ /* * This is of dubious need since prototyping came about, we could * inadvertently include fp packages if the user includes <math.h> but * didn't actually use them, we'll save the incfloat business for * static doubles and definitions of local doubles * * if (typ == DOUBLE) * incfloat=1; */ argptr = NULL; /* Only need while loop if K&R defs */ while ( undeclared) { ident = get_ident() ; more =0; if ( (legalname=symname(n)) == 0 ) { if (!proto) { illname(n); } else { /* * Obligatory silly fake name */ sprintf(n,"sg6p_%d",proto); legalname=1; } } if ( ident == FUNCTIONP ) { needtoken(")()"); /* function returning pointer needs dummy symbol */ more = dummy_idx(typ, otag) ; typ = (zfar ? CPTR : CINT ); } else if ( ident == PTR_TO_FN ) { needtoken(")()") ; ident = POINTER ; } if ( cmatch('[') ) { /* pointer ? */ ptrerror(ident) ; /* it is a pointer, so skip all */ /* stuff between "[]" */ while ( inbyte() != ']' ) if ( endst() ) break; /* add entry as pointer */ ident = (ident == POINTER) ? PTR_TO_PTR : POINTER ; } if ( legalname ) { /* * For ANSI we need to add symbol name to local table - this CINT is * temporary */ if (deftype) { argptr=addloc(n,0,CINT,0,0); argptr->offset.p = prevarg; } /* * If prototyping, then we can't find the name, but if we're prototyping * we have been defined as ANSI, therefore argptr already holds * the correct pointer - kinda neat! */ if ( proto || (argptr=findloc(n)) ) { argptr->flags=(zfar&FARPTR)|(issigned&UNSIGNED); /* add in details of the type of the name */ if ( ident == PTR_TO_PTR ) { /* djm mods will be here for long pointer */ // argptr->flags = UNSIGNED |FARPTR ; /*unsigned*/ argptr->ident = POINTER ; argptr->type = typ; // argptr->type = ( (zfar&FARPTR) ? CPTR : CINT ); argptr->more = dummy_idx(typ, otag) ; } else { argptr->more = more; argptr->ident = ident ; argptr->type = typ ; } } else warning(W_EXPARG); if ( otag ) { argptr->tag_idx = otag - tagtab ; argptr->ident = POINTER ; argptr->type = STRUCT ; } } brkflag=0; if (!deftype) { --undeclared; /* cnt down */ if ( endst() ) { brkflag=1; break; } if ( cmatch(',') == 0 ) warning(W_EXPCOM) ; } if (brkflag || deftype) break; } if (deftype) return(argptr); ns(); return(0); }
/** * load_and_build_cstate_info - load c-state info written to idlestat * trace file. * * @f: the file handle of the idlestat trace file * @nrcpus: number of CPUs * * @return: per-CPU array of structs (success) or ptrerror() (error) */ static struct cpuidle_cstates *load_and_build_cstate_info(FILE* f, char *buffer, int nrcpus, struct cpu_topology * topo) { int cpu; struct cpuidle_cstates *cstates; assert(f != NULL); assert(buffer != NULL); assert(nrcpus > 0); cstates = calloc(nrcpus, sizeof(*cstates)); if (!cstates) return ptrerror(__func__); for (cpu = 0; cpu < nrcpus; cpu++) { int i, read_cpu; struct cpuidle_cstate *c; cstates[cpu].cstate_max = -1; cstates[cpu].current_cstate = -1; if (!cpu_is_online(topo, cpu)) continue; if (sscanf(buffer, "cpuid %d:\n", &read_cpu) != 1 || read_cpu != cpu) { release_cstate_info(cstates, cpu); fprintf(stderr, "%s: Error reading trace file\n" "Expected: cpuid %d:\n" "Read: %s", __func__, cpu, buffer); return ptrerror(NULL); } for (i = 0; i < MAXCSTATE; i++) { int residency; char *name = malloc(128); if (!name) { release_cstate_info(cstates, cpu); return ptrerror(__func__); } fgets(buffer, BUFSIZE, f); sscanf(buffer, "\t%s\n", name); fgets(buffer, BUFSIZE, f); sscanf(buffer, "\t%d\n", &residency); c = &(cstates[cpu].cstate[i]); if (!strcmp(name, "(null)")) { free(name); c->name = NULL; } else { c->name = name; } c->data = NULL; c->nrdata = 0; c->early_wakings = 0; c->late_wakings = 0; c->avg_time = 0.; c->max_time = 0.; c->min_time = DBL_MAX; c->duration = 0.; c->target_residency = residency; } fgets(buffer, BUFSIZE, f); } return cstates; }
static struct cpuidle_datas * idlestat_native_load(const char *filename) { FILE *f; unsigned int nrcpus; struct cpuidle_datas *datas; char *line; char buffer[BUFSIZE]; f = fopen(filename, "r"); if (!f) { fprintf(stderr, "%s: failed to open '%s': %m\n", __func__, filename); return ptrerror(NULL); } /* Version line */ line = fgets(buffer, BUFSIZE, f); if (!line) goto error_close; /* Number of CPUs */ line = fgets(buffer, BUFSIZE, f); if (!line) goto error_close; if (sscanf(buffer, "cpus=%u", &nrcpus) != 1 || nrcpus == 0) { fclose(f); return ptrerror("Cannot load trace file (nrcpus == 0)"); } line = fgets(buffer, BUFSIZE, f); if (!line) goto error_close; datas = calloc(sizeof(*datas), 1); if (!datas) { fclose(f); return ptrerror(__func__); } datas->nrcpus = nrcpus; datas->pstates = build_pstate_info(nrcpus); if (!datas->pstates) goto propagate_error_free_datas; /* Read topology information */ datas->topo = read_cpu_topo_info(f, buffer); if (is_err(datas->topo)) goto propagate_error_free_datas; /* Read C-state information */ datas->cstates = load_and_build_cstate_info(f, buffer, nrcpus, datas->topo); if (is_err(datas->cstates)) goto propagate_error_free_datas; load_text_data_lines(f, buffer, datas); fclose(f); return datas; propagate_error_free_datas: fclose(f); if (!is_err(datas->topo)) release_cpu_topo_info(datas->topo); if (!is_err(datas->cstates)) release_cstate_info(datas->cstates, nrcpus); free(datas); return ptrerror(NULL); error_close: fclose(f); fprintf(stderr, "%s: error or EOF while reading '%s': %m", __func__, filename); return ptrerror(NULL); }
static struct cpuidle_datas * tracecmd_report_load(const char *filename) { FILE *f; unsigned int nrcpus; struct cpuidle_datas *datas; int ret; char *line; char buffer[BUFSIZE]; f = fopen(filename, "r"); if (!f) { fprintf(stderr, "%s: failed to open '%s': %m\n", __func__, filename); return ptrerror(NULL); } /* Version line */ line = fgets(buffer, BUFSIZE, f); if (!line) goto error_close; /* Number of CPUs */ nrcpus = 0; line = fgets(buffer, BUFSIZE, f); ret = sscanf(buffer, "cpus=%u", &nrcpus); if (ret != 1) nrcpus = 0; line = fgets(buffer, BUFSIZE, f); if (!line) goto error_close; if (!nrcpus) { fclose(f); return ptrerror("Cannot load trace file (nrcpus == 0)"); } datas = calloc(sizeof(*datas), 1); if (!datas) { fclose(f); return ptrerror(__func__); } datas->nrcpus = nrcpus; datas->pstates = build_pstate_info(nrcpus); if (!datas->pstates) goto propagate_error_free_datas; datas->topo = read_sysfs_cpu_topo(); if (is_err(datas->topo)) goto propagate_error_free_datas; /* Build C-state information from current host sysfs */ datas->cstates = build_cstate_info(nrcpus); if (is_err(datas->cstates)) goto propagate_error_free_datas; tracecmd_load_text_data_lines(f, buffer, datas); fclose(f); return datas; propagate_error_free_datas: fclose(f); if (!is_err(datas->topo)) release_cpu_topo_info(datas->topo); if (!is_err(datas->cstates)) release_cstate_info(datas->cstates, nrcpus); free(datas); return ptrerror(NULL); error_close: fclose(f); fprintf(stderr, "%s: error or EOF while reading '%s': %m", __func__, filename); return ptrerror(NULL); }