#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "init.h" #include "cpul.h" #define CORE_NUM_MAX 32 #define LINE_BUFFER_SIZE 1024 /** * Structure for recording CPU counters in stat */ typedef struct { uint64_t user; /**< Time spent in user mode */ uint64_t nice; /**< Time spent in low-priority user mode */ uint64_t system; /**< Time spent in system mode */ uint64_t idle; /**< Time spent waiting for tasks */ uint64_t iowait; /**< Time spent waiting for I/O to complete */ uint64_t irq; /**< Time spent processing interrupts */ uint64_t softirq; /**< Time spent processing soft interrupts */ uint64_t steal; /**< Time spent by other OS in virtual environment */ uint64_t guest; /**< Time spent running guest OS */ uint64_t guest_nice; /**< Time spent running low priority guest OS */ } cputime_t; static uint16_t loadTable[CORE_NUM_MAX] = {0}; static cputime_t read_stat(int coreid) { cputime_t work; FILE *file; char line[LINE_BUFFER_SIZE]; file = fopen("/proc/stat", "rb"); if (file == NULL) { } if (fgets(line, sizeof(line), file) == NULL) { goto error; } if (sscanf(line, "cpu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", &work.user, &work.nice, &work.system, &work.idle, &work.iowait, &work.irq, &work.softirq, &work.steal, &work.guest, &work.guest_nice) < 4) { goto error; } if (coreid > 0) { int i; for (i = 0; i < coreid; i++) { if (fgets(line, sizeof(line), file) == NULL) { goto error; } if (sscanf(line, "cpu%*u %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", &work.user, &work.nice, &work.system, &work.idle, &work.iowait, &work.irq, &work.softirq, &work.steal, &work.guest, &work.guest_nice) < 4) { goto error; } } } error: fclose(file); return work; } void *loadupdate_entry(void *ptr) { const int coreNum = *(int *)ptr; cputime_t before[coreNum], after[coreNum], diff[coreNum]; int i = 0; while(1) { /* Calcul real time load */ for (i = 0; i < coreNum; i++) before[i] = read_stat(i); usleep(1000000); for (i = 0; i < coreNum; i++) after[i] = read_stat(i); for (i = 0; i < coreNum; i++) { if (after[i].user > before[i].user && after[i].idle > before[i].idle) { diff[i].user = after[i].user - before[i].user; diff[i].idle = after[i].idle - before[i].idle; loadTable[i] = (uint16_t)(((float)(diff[i].user) / (float)(diff[i].user + diff[i].idle)) * 10000); } else { loadTable[i] = 0; } // printf("[core%d] load %d\r\n", i, loadTable[i]); } } } uint16_t cpul_raw(uint8_t coreid) { if (coreid >= CORE_NUM_MAX) return 0xFFFF; return (uint16_t)(loadTable[coreid]); } void *loadgen_entry(void *ptr) { #define PERIOD 10 const int coreid = *(int *)ptr; CPUL cpul; int ret = 0; uint32_t count = 0; uint16_t load = 0; cpul.coreid = coreid; cpul.resolution = 10; cpul.raw = cpul_raw; ret = cpul_init(&cpul); ret = cpul_set(&cpul, 5000); while(1) { count += PERIOD; if (count >= 25200000) count = 0; if (count % 1000 == 0) { ret = cpul_get(&cpul, &load); printf("cpul_get<%d> %2d.%02d%%, %d, %d\r\n", coreid, (uint16_t)(load / 100), load % 100, cpul.ctrl.tload, cpul.ctrl.refine); } cpul_task(&cpul); usleep(1000 * PERIOD); } } static void test(void) { int num_cpus = sysconf(_SC_NPROCESSORS_CONF); pthread_t thread_update, thread_gen[num_cpus]; int coreid[num_cpus]; int ret; printf("Number of CPUs: %d\n", num_cpus); ret = pthread_create(&thread_update, NULL, &loadupdate_entry, &num_cpus); if (ret != 0) { printf("pthread_create failed!\n"); } for (int i = 0; i < num_cpus; i++) { coreid[i] = i; ret = pthread_create(&thread_gen[i], NULL, &loadgen_entry, &coreid[i]); if (ret != 0) { printf("pthread_create failed!\n"); } cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(i, &cpuset); sched_setaffinity(thread_gen[i], sizeof(cpu_set_t), &cpuset); } pthread_join(thread_update, NULL); for (int i = 0; i < num_cpus; i++) { pthread_join(thread_gen[i], NULL); } } init_export_app(test);