STAT_CTL *stats_config_defaults( void ) { STAT_CTL *s; s = (STAT_CTL *) allocz( sizeof( STAT_CTL ) ); s->stats = (ST_CFG *) allocz( sizeof( ST_CFG ) ); s->stats->threads = DEFAULT_STATS_THREADS; s->stats->loopfn = &stats_stats_pass; s->stats->period = DEFAULT_STATS_MSEC; s->stats->prefix = stats_prefix( DEFAULT_STATS_PREFIX ); s->stats->type = STATS_TYPE_STATS; s->stats->dtype = DATA_TYPE_STATS; s->stats->name = stats_type_names[STATS_TYPE_STATS]; s->stats->hsize = -1; s->stats->enable = 1; s->adder = (ST_CFG *) allocz( sizeof( ST_CFG ) ); s->adder->threads = DEFAULT_ADDER_THREADS; s->adder->loopfn = &stats_adder_pass; s->adder->period = DEFAULT_STATS_MSEC; s->adder->prefix = stats_prefix( DEFAULT_ADDER_PREFIX ); s->adder->type = STATS_TYPE_ADDER; s->adder->dtype = DATA_TYPE_ADDER; s->adder->name = stats_type_names[STATS_TYPE_ADDER]; s->adder->hsize = -1; s->adder->enable = 1; s->gauge = (ST_CFG *) allocz( sizeof( ST_CFG ) ); s->gauge->threads = DEFAULT_GAUGE_THREADS; s->gauge->loopfn = &stats_gauge_pass; s->gauge->period = DEFAULT_STATS_MSEC; s->gauge->prefix = stats_prefix( DEFAULT_GAUGE_PREFIX ); s->gauge->type = STATS_TYPE_GAUGE; s->gauge->dtype = DATA_TYPE_GAUGE; s->gauge->name = stats_type_names[STATS_TYPE_GAUGE]; s->gauge->hsize = -1; s->gauge->enable = 1; s->self = (ST_CFG *) allocz( sizeof( ST_CFG ) ); s->self->threads = 1; s->self->loopfn = &stats_self_pass; s->self->period = DEFAULT_STATS_MSEC; s->self->prefix = stats_prefix( DEFAULT_SELF_PREFIX ); s->self->type = STATS_TYPE_SELF; s->self->dtype = -1; s->self->name = stats_type_names[STATS_TYPE_SELF]; s->self->enable = 1; return s; }
void stats_init_control( ST_CFG *c, int alloc_data ) { char wkrstrbuf[128]; ST_THR *t; int i, l; // maybe fall back to default hash size if( c->hsize < 0 ) c->hsize = ctl->mem->hashsize; debug( "Hash size set to %d for %s", c->hsize, c->name ); // create the hash structure if( alloc_data ) c->data = (DHASH **) allocz( c->hsize * sizeof( DHASH * ) ); // convert msec to usec c->period *= 1000; c->offset *= 1000; // offset can't be bigger than period c->offset = c->offset % c->period; // make the control structures c->ctls = (ST_THR *) allocz( c->threads * sizeof( ST_THR ) ); for( i = 0; i < c->threads; i++ ) { t = &(c->ctls[i]); t->conf = c; t->id = i; t->max = c->threads; // worker path l = snprintf( wkrstrbuf, 128, "workers.%s.%d", c->name, t->id ); t->wkrstr = str_dup( wkrstrbuf, l ); // make some floats workspace - we realloc this if needed if( c->type == STATS_TYPE_STATS ) { t->wkspcsz = 1024; t->wkbuf = (float *) allocz( t->wkspcsz * sizeof( float ) ); } pthread_mutex_init( &(t->lock), NULL ); // and that starts locked lock_stthr( t ); } }
IOBUF *mem_new_buf( int sz ) { IOBUF *b; b = (IOBUF *) __mtype_new( ctl->mem->iobufs ); if( sz < 0 ) sz = MIN_NETBUF_SZ; if( b->sz < sz ) { if( b->ptr ) free( b->ptr ); b->ptr = (char *) allocz( sz ); b->sz = sz; } if( b->sz == 0 ) { b->buf = NULL; b->hwmk = NULL; } else { b->buf = b->ptr; b->hwmk = b->buf + ( ( 5 * b->sz ) / 6 ); } b->refs = 0; return b; }
/* Try to find sdvo panel data */ static void parse_sdvo_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) { struct lvds_dvo_timing *dvo_timing; struct drm_display_mode *panel_fixed_mode; int index; index = i915_vbt_sdvo_panel_type; if (index == -1) { struct bdb_sdvo_lvds_options *sdvo_lvds_options; sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); if (!sdvo_lvds_options) return; index = sdvo_lvds_options->panel_type; } dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); if (!dvo_timing) return; panel_fixed_mode = allocz(sizeof(*panel_fixed_mode)); if (!panel_fixed_mode) return; fill_detail_timing_data(panel_fixed_mode, dvo_timing + index); dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; fprintf(stderr, "Found SDVO panel mode in BIOS VBT tables:\n"); drm_mode_debug_printmodeline(panel_fixed_mode); }
LOCK_CTL *lock_config_defaults( void ) { LOCK_CTL *l; int i; l = (LOCK_CTL *) allocz( sizeof( LOCK_CTL ) ); // and init all the mutexes // used in mem.c pthread_mutex_init( &(l->host), NULL ); pthread_mutex_init( &(l->path), NULL ); pthread_mutex_init( &(l->point), NULL ); // used in data.c pthread_mutex_init( &(l->data), NULL ); // used in query.c pthread_mutex_init( &(l->query), NULL ); // used in sync.c pthread_mutex_init( &(l->field), NULL ); // used in loop control pthread_mutex_init( &(l->loop), NULL ); // used to lock nodes for( i = 0; i < NODE_MUTEX_COUNT; i++ ) pthread_mutex_init( l->node + i, NULL ); l->init_done = 1; return l; }
void thread_throw_init_attr( void ) { tt_attr = (pthread_attr_t *) allocz( sizeof( pthread_attr_t ) ); pthread_attr_init( tt_attr ); if( pthread_attr_setdetachstate( tt_attr, PTHREAD_CREATE_DETACHED ) ) err( 0x0101, "Cannot set default attr state to detached -- %s", Err ); }
// throw a network socket watcher and a handler void thread_throw_watched( void *(*fp) (void *), void *arg ) { THRD *t; if( !tt_attr ) thread_throw_init_attr( ); t = (THRD *) allocz( sizeof( THRD ) ); t->arg = arg; t->fp = fp; pthread_create( &(t->id), tt_attr, &net_watched_socket, t ); }
pthread_t thread_throw( void *(*fp) (void *), void *arg ) { THRD *t; if( !tt_attr ) thread_throw_init_attr( ); t = (THRD *) allocz( sizeof( THRD ) ); t->arg = arg; pthread_create( &(t->id), tt_attr, fp, t ); return t->id; }
// grab some more memory of the proper size // must be called inside a lock void __mtype_alloc_free( MTYPE *mt, int count ) { MTBLANK *p, *list; void *vp; int i; if( count <= 0 ) count = mt->alloc_ct; list = (MTBLANK *) allocz( mt->alloc_sz * count ); if( !list ) fatal( "Failed to allocate %d * %d bytes.", mt->alloc_sz, count ); mt->fcount += count; mt->total += count; // the last one needs next -> flist so decrement count count--; vp = list; p = list; // link them up for( i = 0; i < count; i++ ) { #ifdef __GNUC__ #if __GNUC_PREREQ(4,8) #pragma GCC diagnostic ignored "-Wpointer-arith" #pragma GCC diagnostic ignored "-Wpedantic" #endif #endif // yes GCC, I know what I'm doing, thanks vp += mt->alloc_sz; #ifdef __GNUC__ #if __GNUC_PREREQ(4,8) #pragma GCC diagnostic pop #pragma GCC diagnostic pop #endif #endif p->next = (MTBLANK *) vp; p = p->next; } // and attach to the free list (it might not be null) p->next = mt->flist; // and update our type mt->flist = list; }
MTYPE *__mem_type_ctl( int sz, int ct, int extra ) { MTYPE *mt; mt = (MTYPE *) allocz( sizeof( MTYPE ) ); mt->alloc_sz = sz; mt->alloc_ct = ct; mt->stats_sz = sz + extra; // and alloc some already __mtype_alloc_free( mt, mt->alloc_ct ); // init the mutex pthread_mutex_init( &(mt->lock), NULL ); return mt; }
// return a copy of a prefix with a trailing . char *stats_prefix( char *s ) { int len, dot = 0; char *p; if( !( len = strlen( s ) ) ) return strdup( "" ); // do we need a dot? if( s[len - 1] != '.' ) dot = 1; // include space for a dot p = (char *) allocz( len + dot + 1 ); memcpy( p, s, len ); if( dot ) p[len] = '.'; return p; }
DHASH *mem_new_dhash( char *str, int len, int type ) { DHASH *d = __mtype_new( ctl->mem->dhash ); d->type = type; if( len >= d->sz ) { if( d->path ) free( d->path ); d->sz = len + 1; d->path = (char *) allocz( d->sz ); } // copy the string memcpy( d->path, str, len ); d->path[len] = '\0'; d->len = len; return d; }
MEM_CTL *mem_config_defaults( void ) { MEM_CTL *m; m = (MEM_CTL *) allocz( sizeof( MEM_CTL ) ); m->hosts = __mem_type_ctl( sizeof( HOST ), MEM_ALLOCSZ_HOSTS, 0 ); m->iobufs = __mem_type_ctl( sizeof( IOBUF ), MEM_ALLOCSZ_IOBUF, ( MIN_NETBUF_SZ + IO_BUF_SZ ) / 2 ); m->points = __mem_type_ctl( sizeof( PTLIST ), MEM_ALLOCSZ_POINTS, 0 ); m->dhash = __mem_type_ctl( sizeof( DHASH ), MEM_ALLOCSZ_DHASH, 64 ); // guess on path length m->iolist = __mem_type_ctl( sizeof( IOLIST ), MEM_ALLOCSZ_IOLIST, 0 ); m->token = __mem_type_ctl( sizeof( TOKEN ), MEM_ALLOCSZ_TOKEN, 0 ); m->max_kb = DEFAULT_MEM_MAX_KB; m->interval = DEFAULT_MEM_CHECK_INTV; m->gc_enabled = 1; m->gc_thresh = DEFAULT_GC_THRESH; m->gc_gg_thresh = DEFAULT_GC_GG_THRESH; m->hashsize = MEM_HSZ_LARGE; m->stacksize = DEFAULT_MEM_STACK_SIZE; return m; }
int stats_config_line( AVP *av ) { char *d, *pm, *lbl, *fmt, thrbuf[64]; int i, t, l, mid, top; ST_THOLD *th; STAT_CTL *s; ST_CFG *sc; WORDS wd; s = ctl->stats; if( !( d = strchr( av->att, '.' ) ) ) { if( attIs( "thresholds" ) ) { if( strwords( &wd, av->val, av->vlen, ',' ) <= 0 ) { warn( "Invalid thresholds string: %s", av->val ); return -1; } if( wd.wc > 20 ) { warn( "A maximum of 20 thresholds is allowed." ); return -1; } for( i = 0; i < wd.wc; i++ ) { t = atoi( wd.wd[i] ); // sort out percent from per-mille if( ( pm = memchr( wd.wd[i], 'm', wd.len[i] ) ) ) { mid = 500; top = 1000; lbl = "per-mille"; fmt = "%s_%03d"; } else { mid = 50; top = 100; lbl = "percent"; fmt = "%s_%02d"; } // sanity check before we go any further if( t <= 0 || t == mid || t >= top ) { warn( "A %s threshold value of %s makes no sense: t != %d, 0 < t < %d.", lbl, wd.wd[i], mid, top ); return -1; } l = snprintf( thrbuf, 64, fmt, ( ( t < mid ) ? "lower" : "upper" ), t ); // OK, make a struct th = (ST_THOLD *) allocz( sizeof( ST_THOLD ) ); th->val = t; th->max = top; th->label = str_dup( thrbuf, l ); th->next = ctl->stats->thresholds; ctl->stats->thresholds = th; } debug( "Acquired %d thresholds.", wd.wc ); } else return -1; return 0; } d++; if( !strncasecmp( av->att, "stats.", 6 ) ) sc = s->stats; else if( !strncasecmp( av->att, "adder.", 6 ) ) sc = s->adder; // because I'm nice that way (plus, I keep mis-typing it...) else if( !strncasecmp( av->att, "gauge.", 6 ) || !strncasecmp( av->att, "guage.", 6 ) ) sc = s->gauge; else if( !strncasecmp( av->att, "self.", 5 ) ) sc = s->self; else return -1; if( !strcasecmp( d, "threads" ) ) { t = atoi( av->val ); if( t > 0 ) sc->threads = t; else warn( "Stats threads must be > 0, value %d given.", t ); } else if( !strcasecmp( d, "enable" ) ) { if( valIs( "y" ) || valIs( "yes" ) || atoi( av->val ) ) sc->enable = 1; else { debug( "Stats type %s disabled.", sc->name ); sc->enable = 0; } } else if( !strcasecmp( d, "prefix" ) ) { free( sc->prefix ); sc->prefix = stats_prefix( av->val ); debug( "%s prefix set to '%s'", sc->name, sc->prefix ); } else if( !strcasecmp( d, "period" ) ) { t = atoi( av->val ); if( t > 0 ) sc->period = t; else warn( "Stats period must be > 0, value %d given.", t ); } else if( !strcasecmp( d, "offset" ) || !strcasecmp( d, "delay" ) ) { t = atoi( av->val ); if( t > 0 ) sc->offset = t; else warn( "Stats offset must be > 0, value %d given.", t ); } else if( !strcasecmp( d, "size" ) || !strcasecmp( d, "hashsize" ) ) { if( valIs( "tiny" ) ) sc->hsize = MEM_HSZ_TINY; else if( valIs( "small" ) ) sc->hsize = MEM_HSZ_SMALL; else if( valIs( "medium" ) ) sc->hsize = MEM_HSZ_MEDIUM; else if( valIs( "large" ) ) sc->hsize = MEM_HSZ_LARGE; else if( valIs( "xlarge" ) ) sc->hsize = MEM_HSZ_XLARGE; else if( valIs( "x2large" ) ) sc->hsize = MEM_HSZ_X2LARGE; else { if( !isdigit( av->val[0] ) ) { warn( "Unrecognised hash table size '%s'", av->val ); return -1; } t = atoi( av->val ); if( t == 0 ) { warn( "Cannot set zero size hash table." ); return -1; } // < 0 means default sc->hsize = t; } } else return -1; return 0; }
static void parse_device_mapping(struct drm_i915_private *dev_priv, struct bdb_header *bdb) { struct bdb_general_definitions *p_defs; struct child_device_config *p_child, *child_dev_ptr; int i, child_device_num, count; u16 block_size; p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); if (!p_defs) { fprintf(stderr, "No general definition block is found, no devices defined.\n"); return; } /* judge whether the size of child device meets the requirements. * If the child device size obtained from general definition block * is different with sizeof(struct child_device_config), skip the * parsing of sdvo device info */ if (p_defs->child_dev_size != sizeof(*p_child)) { /* different child dev size . Ignore it */ fprintf(stderr, "different child size is found. Invalid.\n"); return; } /* get the block size of general definitions */ block_size = get_blocksize(p_defs); /* get the number of child device */ child_device_num = (block_size - sizeof(*p_defs)) / sizeof(*p_child); count = 0; /* get the number of child device that is present */ for (i = 0; i < child_device_num; i++) { p_child = &(p_defs->devices[i]); if (!p_child->device_type) { /* skip the device block if device type is invalid */ continue; } count++; } if (!count) { fprintf(stderr, "no child dev is parsed from VBT\n"); return; } dev_priv->child_dev = allocz(count * sizeof(*p_child)); if (!dev_priv->child_dev) { fprintf(stderr, "No memory space for child device\n"); return; } dev_priv->child_dev_num = count; count = 0; for (i = 0; i < child_device_num; i++) { p_child = &(p_defs->devices[i]); if (!p_child->device_type) { /* skip the device block if device type is invalid */ continue; } child_dev_ptr = dev_priv->child_dev + count; count++; memcpy((void *)child_dev_ptr, (void *)p_child, sizeof(*p_child)); } return; }
int stats_report_one( DHASH *d, ST_THR *t, time_t ts, IOBUF **buf ) { PTLIST *list, *p; int i, ct, idx; ST_THOLD *thr; char *prfx; float sum; IOBUF *b; // grab the points list list = d->proc.points; d->proc.points = NULL; // count the points for( ct = 0, p = list; p; p = p->next ) ct += p->count; // anything to do? if( ct == 0 ) { if( list ) mem_free_point_list( list ); return 0; } b = *buf; prfx = ctl->stats->stats->prefix; // if we have just one points structure, we just use // it's own vals array as our workspace. We need to // sort in place, but only this fn holds that space // now, so that's ok. If we have more than one, we // need a flat array, so make sure the workbuf is big // enough and copy each vals array into it if( list->next == NULL ) t->wkspc = list->vals; else { // do we have enough workspace? if( ct > t->wkspcsz ) { // double it until we have enough while( ct > t->wkspcsz ) t->wkspcsz *= 2; // free the existing and grab a new chunk free( t->wkbuf ); t->wkbuf = (float *) allocz( t->wkspcsz * sizeof( float ) ); } // and the workspace is the buffer t->wkspc = t->wkbuf; // now copy the data in for( i = 0, p = list; p; p = p->next ) { memcpy( t->wkspc + i, p->vals, p->count * sizeof( float ) ); i += p->count; } } sum = 0; kahan_summation( t->wkspc, ct, &sum ); // median offset idx = ct / 2; // and sort them qsort( t->wkspc, ct, sizeof( float ), cmp_floats ); bprintf( "%s.count %d", d->path, ct ); bprintf( "%s.mean %f", d->path, sum / (float) ct ); bprintf( "%s.upper %f", d->path, t->wkspc[ct-1] ); bprintf( "%s.lower %f", d->path, t->wkspc[0] ); bprintf( "%s.median %f", d->path, t->wkspc[idx] ); // variable thresholds for( thr = ctl->stats->thresholds; thr; thr = thr->next ) { // find the right index into our values idx = ( thr->val * ct ) / thr->max; bprintf( "%s.%s %f", d->path, thr->label, t->wkspc[idx] ); } mem_free_point_list( list ); *buf = b; return ct; }
/* Try to find integrated panel data */ static void parse_lfp_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) { const struct bdb_lvds_options *lvds_options; const struct bdb_lvds_lfp_data *lvds_lfp_data; const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; const struct lvds_dvo_timing *panel_dvo_timing; struct drm_display_mode *panel_fixed_mode; int i, downclock; lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); if (!lvds_options) return; dev_priv->lvds_dither = lvds_options->pixel_dither; if (lvds_options->panel_type == 0xff) return; panel_type = lvds_options->panel_type; lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); if (!lvds_lfp_data) return; lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS); if (!lvds_lfp_data_ptrs) return; dev_priv->lvds_vbt = 1; panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data, lvds_lfp_data_ptrs, lvds_options->panel_type); panel_fixed_mode = allocz(sizeof(*panel_fixed_mode)); if (!panel_fixed_mode) return; fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing); dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; fprintf(stderr, "Found panel mode in BIOS VBT tables:\n"); drm_mode_debug_printmodeline(panel_fixed_mode); /* * Iterate over the LVDS panel timing info to find the lowest clock * for the native resolution. */ downclock = panel_dvo_timing->clock; for (i = 0; i < 16; i++) { const struct lvds_dvo_timing *dvo_timing; dvo_timing = get_lvds_dvo_timing(lvds_lfp_data, lvds_lfp_data_ptrs, i); if (lvds_dvo_timing_equal_size(dvo_timing, panel_dvo_timing) && dvo_timing->clock < downclock) downclock = dvo_timing->clock; } if (downclock < panel_dvo_timing->clock && i915_lvds_downclock) { dev_priv->lvds_downclock_avail = 1; dev_priv->lvds_downclock = downclock * 10; fprintf(stderr, "LVDS downclock is found in VBT. " "Normal Clock %dKHz, downclock %dKHz\n", panel_fixed_mode->clock, 10*downclock); } }