int main(int argc, char **argv) { struct rlimit lim; struct map_list *list, *entry; size_t page_size, i; void *map = NULL; unsigned long mem_free = 0; unsigned long hugepage_size = 0; unsigned long mem_fragmentable = 0; if (prereq() != 0) { printf("Either the sysctl compact_unevictable_allowed is not\n" "set to 1 or couldn't read the proc file.\n" "Skipping the test\n"); return 0; } lim.rlim_cur = RLIM_INFINITY; lim.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_MEMLOCK, &lim)) { perror("Failed to set rlimit:\n"); return -1; } page_size = getpagesize(); list = NULL; if (read_memory_info(&mem_free, &hugepage_size) != 0) { printf("ERROR: Cannot read meminfo\n"); return -1; } mem_fragmentable = mem_free * 0.8 / 1024; while (mem_fragmentable > 0) { map = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_LOCKED, -1, 0); if (map == MAP_FAILED) break; entry = malloc(sizeof(struct map_list)); if (!entry) { munmap(map, MAP_SIZE); break; } entry->map = map; entry->next = list; list = entry; /* Write something (in this case the address of the map) to * ensure that KSM can't merge the mapped pages */ for (i = 0; i < MAP_SIZE; i += page_size) *(unsigned long *)(map + i) = (unsigned long)map + i; mem_fragmentable--; } for (entry = list; entry != NULL; entry = entry->next) { munmap(entry->map, MAP_SIZE); if (!entry->next) break; entry = entry->next; } if (check_compaction(mem_free, hugepage_size) == 0) return 0; return -1; }
static status_t read_sys_info( struct SYSInfo * sysinfo ) { char buff[BUFFLEN], buff1[BUFFLEN], str[BUFFLEN]; char *new_line, *find_str; int i, j, k, net_num, rval, fd; int kernel_26 = 0; /*************************** Initialization ****************************/ bzero(buff, BUFFLEN); bzero(buff1, BUFFLEN); bzero(str, BUFFLEN); init_sysinfo_data(sysinfo); /* Copy the network interface names from predefined CONSTNETNAME in * util.h if user has not specified a nic name */ if ( ! Defined_Nic_Name ) for ( i = 0; i < NETTYPE; i++ ) strcpy(NETNAME[i], CONSTNETNAME[i]); /************** Fill in loopback "interface" as the first NIC **********/ /* Loopback "interface" has no records in /proc/interrupts. We are still * interested in some statistics about this "interface", whose info be * found in /proc/net/dev. */ for ( i = 0; i < NETTYPE; i++ ) { if ( strncmp(NETNAME[i], "loop", strlen(NETNAME[i])) == 0 ) { sysinfo->net_num = 1; strcpy(sysinfo->net[0].name, "loop"); } } /*** Interrupt information is stored in /proc/interrupts in Linux ******/ if ( (fd = open("/proc/interrupts", O_RDONLY)) < 0 || (rval=read(fd, buff, BUFFLEN-1)) <= 0) { perror("Fail to get interrupt information from /proc/interrupts"); return NOTOK; } close(fd); /**** Frist line of /proc/interrupts indicates the number of CPUs ******/ for ( i = 0; buff[i] != '\n' && i < BUFFLEN-1; i++) // copy the first line to buff1 buff1[i] = buff[i]; if ( strlen(buff) == 0 || ( sysinfo->cpu_num = sscanf(buff1, "%s %s %s %s %s %s %s %s", str, str, str, str, str, str, str, str)) < 1 ) { perror("Failed to parse /proc/interrupts"); return NOTOK; } if ( sysinfo->cpu_num > 8 ) { fprintf(stderr, "Exceed the maximum CPU number: %d.\n",sysinfo->cpu_num); return NOTOK; } /********** Parse the interrupt information line by line ***************/ new_line = buff; net_num = sysinfo->net_num; while ( net_num < MAXNETWORK ) { /******************* Copy next line to buff1 for parsing ***********/ if ( (new_line = strstr(new_line, "\n")) == NULL ) break; new_line++; if ( strlen(new_line) == 0 ) break; strncpy(buff1, new_line, BUFFLEN-1); for ( i = 0; buff1[i] != '\n' && i < BUFFLEN-1; i++ ); buff1[i] = '\0'; /****************** Search the network interface entry *************/ for ( i = 0; i < NETTYPE; i++ ) { if ( (find_str = strstr(buff1, NETNAME[i])) != NULL ) { // got one /******************* First number is IRQ *******************/ sysinfo->net[net_num].irq = atoi(strtok(buff1, " :\t().,")); /******** Following are interrupts for each CPU ************/ for ( j = 0; j < sysinfo->cpu_num; j++ ) { sysinfo->cpu[j].net_int[net_num] = atol(strtok(NULL, " :\t().")); sysinfo->net[net_num].interrupt += sysinfo->cpu[j].net_int[net_num]; } /** The last part is device name such as keyboard and eth0 */ while ( (find_str = (char *)strtok(NULL, " :\t().,")) != NULL ) { if ( (find_str = strstr(find_str, NETNAME[i])) != NULL ) { strncpy(sysinfo->net[net_num].name, find_str, NETNAMELEN-1); break; } } net_num++; break; } // end of if find_str } // end of for loop } // end of while loop sysinfo->net_num = net_num; #ifdef DEBUG fprintf(stderr, " DEBUG: Parse /proc/interrupts (%d bytes read). CPU: %d Network-card: %d (%s %s %s)\n", rval, sysinfo->cpu_num, net_num, sysinfo->net[0].name, sysinfo->net[1].name, sysinfo->net[2].name); #endif /* FILE *fd1; if ( (fd1 = open("/proc/stat", "r")) == NULLf || fscanf(fp1, "%s %d %d %d %d", &str, &sysinfo->cpu_user, &sysinfo->cpu_nice, &sysinfo->cpu_system, &sysinfo->cpu_idle) != 5 ) { perror("Failed to get cpu information from /proc/stat."); return NOTOK; } fclose(fp1); */ /************************* Read CPU usage ******************************/ /* CPU information is stored in /proc/stat in Linux. Format: * cpu-name user-jiffies nice-jiffies system-jiffies idle-jiffies. For example, * cpu 123456 123 12345 1234567 * The number of jiffies that the system spent in user/nice/system/idle mode are * 123456, 123, 12345, and 1234567, respectively. Jiffy is defined by kernel (HZ). */ bzero(buff, BUFFLEN); if ( (fd = open("/proc/stat", O_RDONLY)) < 0 || (rval=read(fd, buff, BUFFLEN-1)) <= 0) { perror("Failed to get cpu information from /proc/stat."); return NOTOK; } close(fd); /************* First line shows the summary of CPU statistics **********/ if ( strlen(buff) == 0 || sscanf(buff, "%s %lld %lld %lld %lld", str, &sysinfo->cpu_user, &sysinfo->cpu_nice, &sysinfo->cpu_system, &sysinfo->cpu_idle) != 5 ) { perror("Failed to get cpu information from /proc/stat."); return NOTOK; } #ifdef DEBUG fprintf(stderr, " DEBUG: Parse /proc/stat (%d byt read): %lld[user] %lld[nice] %lld[system] %lld[idle]\n", rval, sysinfo->cpu_user, sysinfo->cpu_nice, sysinfo->cpu_system, sysinfo->cpu_idle); #endif /************************ Get each CPU's usage *************************/ new_line = buff; for( i = 0; i < sysinfo->cpu_num; i++){ if ( (new_line = strstr(new_line, "\n")) == NULL ) break; new_line++; if ( strlen(new_line) == 0 || sscanf(new_line, "%s %lld %lld %lld %lld", str, &sysinfo->cpu[i].user_mode, &sysinfo->cpu[i].nice_mode, &sysinfo->cpu[i].system_mode, &sysinfo->cpu[i].idle_mode) != 5 ) { perror("Failed to get cpu information from /proc/stat."); return NOTOK; } } if ( (new_line = strstr(buff, "page")) == NULL ) { kernel_26 = 1; } else { if ( sscanf(new_line, "%s %lld %lld", str, &sysinfo->page_in, &sysinfo->page_out) != 3 ) { perror("Fail to parse page info from /proc/stat."); return NOTOK; } if ( (new_line = strstr(buff, "swap")) == NULL || sscanf(new_line, "%s %lld %lld", str, &sysinfo->swap_in, &sysinfo->swap_out) != 3 ) { perror("Fail to parse swap info."); return NOTOK; } } if ( (new_line = strstr(buff, "intr")) == NULL || sscanf(new_line, "%s %lld", str, &sysinfo->interrupts) != 2 ) { perror("Fail to parse interrupt info from /proc/stat."); return NOTOK; } if ( (new_line = strstr(buff, "ctxt")) == NULL || sscanf(new_line, "%s %lld", str, &sysinfo->context_switch) != 2 ) { perror("Fail to parse context switch info from /proc/stat."); return NOTOK; } if ( kernel_26 ) { read_from_vmstat(sysinfo); read_memory_info(sysinfo); } else { /*************** Read memory information Kernel 2.4 ****************/ bzero(buff, BUFFLEN); if ( (fd = open("/proc/meminfo", O_RDONLY)) < 0 || (rval=read(fd, buff, BUFFLEN-1)) <= 0) { perror("Failed to open /proc/meminfo."); return NOTOK; } close(fd); /********* Ignore the first comment line of /proc/meminfo ************/ if ( (new_line = strstr(buff, "\n")) == NULL ) { perror("Fail to parse /proc/meminfo (No newline?)."); return NOTOK; } new_line++; /************* Parse the second line of /proc/meminfo ****************/ if ( strlen(new_line) == 0 || sscanf(new_line, "%s %lld %lld", str, &sysinfo->mem_total, &sysinfo->mem_used) != 3 ) { perror("Fail to parse /proc/meminfo (Wrong format)."); return NOTOK; } } #ifdef DEBUG fprintf(stderr, " DEBUG: Parse /proc/meminfo (%d byt read): %lld[mem-total] %lld[mem-used]\n", rval, sysinfo->mem_total, sysinfo->mem_used); #endif /*************** Read network device information ***********************/ bzero(buff, BUFFLEN); if ( (fd = open("/proc/net/dev", O_RDONLY)) < 0 || (rval=read(fd, buff, BUFFLEN-1)) <= 0) { perror("Failed to open /proc/net/dev."); return NOTOK; } close(fd); /******* Ignore the first two comment lines of /proc/net/dev ***********/ if ( (new_line = strstr(buff, "\n")) == NULL ) { perror("Fail to parse /proc/net/dev (No newline?)."); return NOTOK; } new_line++; for ( i = 0; i < MAXNETWORK; ) { /******************* Copy next line to buff1 for parsing ***********/ if ( (new_line = strstr(new_line, "\n")) == NULL ) break; new_line++; if ( strlen(new_line) == 0 ) break; strncpy(buff1, new_line, BUFFLEN-1); for ( j = 0; buff1[j] != '\n' && j < BUFFLEN-1; j++); buff1[j] = '\0'; strcpy(str, strtok(buff1, " :\t().")); for ( j = 0; j < sysinfo->net_num; j++ ) { if ( strncmp(str, sysinfo->net[j].name, strlen(str)) == 0 ) { sysinfo->net[j].recv_byte = parse_size( strtok(NULL, " :\t().")); sysinfo->net[j].recv_packet = parse_size(strtok(NULL, " :\t().")); for ( k = 0; k < 6; k++) // We don't use those middle six fields strtok(NULL, " :\t()."); sysinfo->net[j].send_byte = parse_size(strtok(NULL, " :\t().")); sysinfo->net[j].send_packet = parse_size(strtok(NULL, " :\t().")); #ifdef DEBUG fprintf(stderr, " DEBUG: %s: recv-bytes: %lld recv-packets: %lld send-bytes: %lld send-packets: %lld\n", sysinfo->net[j].name, sysinfo->net[j].recv_byte, sysinfo->net[j].recv_packet, sysinfo->net[j].send_byte, sysinfo->net[j].send_packet); #endif i++; break; } // end of if strncmp } // end of for loop of j } // end of for loop of i return OK; }