/*
 * System dependent file for Mach
 */

/* 
 * Melinda Shore, mt Xinu, 3/21/90 
 */

#include <mach.h>

#define NSTATES 3

extern char *xmalloc(/* int nbytes */);
extern kern_return_t host_info();
extern task_t task_self();
extern kern_return_t slot_info();
int *cpu_ids;
machine_slot_data_t **last_sinfo, **cur_sinfo, **tmp_sinfo;
task_t self;

/* Called by -version */
void
version()
{
	printf("Mach: numdisks=0\n");
}

/* 
 * Called at the beginning to enquire how many bars are needed,
 * and to determine which cpu slots are filled
 */

int
num_bars()
{
    machine_info_data_t minfo;
    machine_slot_data_t sinfo;
    int i, j = 0, result, ncpus;

    ncpus = 0;
    self = task_self();
    if ((result = host_info(self, &minfo)) != KERN_SUCCESS)  {
        mach_error("xcpustate", result);
        exit(1);
    }
    cpu_ids = (int *)xmalloc(minfo.max_cpus * sizeof (int));
    for (i = 0 ; i < minfo.max_cpus ; i++)  {
        if ((result = slot_info(self, i, &sinfo)) != KERN_SUCCESS)
            mach_error("xcpustate", result);
        else
            if (sinfo.is_cpu && sinfo.running)  {
                ncpus++;
                cpu_ids[j++] = i;
            }
    }
    return ncpus;
}

/*
 * Indicates how many levels each bar has.  For most machines, each bar will
 * have the same stuff.  But one can, for instance, display memory use on one
 * bar, processor levels on others, etc.
 */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
    int i;

    for(i = 0; i < nbars; i++)
        items[i] = NSTATES;
}

/* Called after num_bars to ask for the bar names */
/* ARGSUSED */
char **
label_bars(nbars)
{
    char **names;
    int i;

    names = (char **)xmalloc(nbars * sizeof (char *));
    for (i = 0 ; i < nbars ; i++)  {
        names[i] = xmalloc(10);
        (void) sprintf(names[i], "Slot %d", cpu_ids[i]);
    }
    return names;
}

/* 
 *  Called after the bars are created to perform any machine dependent
 *  initializations.
 */
/* ARGSUSED */
void
init_bars(nbars)
int nbars;
{
    int i;
    kern_return_t result;

    cur_sinfo = (machine_slot_data_t **)xmalloc(nbars *
                                               sizeof (machine_slot_data_t *));
    last_sinfo = (machine_slot_data_t **)xmalloc(nbars *
                                               sizeof (machine_slot_data_t *));
    for (i = 0 ; i < nbars ; i++)  {
        cur_sinfo[i] = (machine_slot_data_t *)xmalloc(sizeof
                                                   (machine_slot_data_t));
        last_sinfo[i] = (machine_slot_data_t *)xmalloc(sizeof
                                                   (machine_slot_data_t));
        if ((result = slot_info(self, cpu_ids[i], cur_sinfo[i])) !=
            KERN_SUCCESS)  {
            mach_error("xcpustate", result);
            exit(1);
        }
    }            
}

/* 
 *  This procedure gets called every interval to compute and display the
 *  bars. It should call draw_bar() with the bar number, the array of
 *  integer values to display in the bar, and the number of values in
 *  the array.
 */
/* ARGSUSED */
void
display_bars(nbars)
{
    int states[CPU_STATE_MAX];
    int nstates;
    int i;
    extern void draw_bar(/*int bar_num, int *states, int num_states*/);
    kern_return_t result;
    
    for (i = 0 ; i < nbars ; i++)  {
        if ((result = slot_info(self, cpu_ids[i], cur_sinfo[i])) != 
            KERN_SUCCESS)
            mach_error("xcpustate", result);
#define delta(cpustate) ((int) (cur_sinfo[i]->cpu_ticks[(cpustate)] - \
    last_sinfo[i]->cpu_ticks[(cpustate)]))

        nstates = 0;
        states[nstates++] = delta(CPU_STATE_USER);
        states[nstates++] = delta(CPU_STATE_SYSTEM);
        states[nstates++] = delta(CPU_STATE_IDLE);
        draw_bar(i, states, nstates);
    }
    tmp_sinfo = last_sinfo;
    last_sinfo = cur_sinfo;
    cur_sinfo = tmp_sinfo;
}


syntax highlighted by Code2HTML, v. 0.9.1