diff --git a/resfs.c b/resfs.c index 0e7bc1a..ac18ad6 100644 --- a/resfs.c +++ b/resfs.c @@ -37,16 +37,16 @@ int getfsinfo(int res_id, void *out, size_t sz, void **hint, int flags) switch (res_id) { case FS_AIONR: ret = file_to_buf(AIONR, buffer, sizeof(buffer)); - if (ret <= 0) - return -1; + if (ret < 0) + return ret; ret = sscanf(buffer, "%Lu", (unsigned long long *) out); if (ret != 1) return -1; break; case FS_AIOMAXNR: ret = file_to_buf(AIOMAXNR, buffer, sizeof(buffer)); - if (ret <= 0) - return -1; + if (ret < 0) + return ret; ret = sscanf(buffer, "%Lu", (unsigned long long *) out); if (ret != 1) return -1; @@ -54,16 +54,16 @@ int getfsinfo(int res_id, void *out, size_t sz, void **hint, int flags) case FS_FILENR: fs = (unsigned long long *) out; ret = file_to_buf(FILENR, buffer, sizeof(buffer)); - if (ret <= 0) - return -1; + if (ret < 0) + return ret; ret = sscanf(buffer, "%Lu %Lu %Lu", &fs[0], &fs[1], &fs[2]); if (ret != 3) return -1; break; case FS_FILEMAXNR: ret = file_to_buf(FILEMAXNR, buffer, sizeof(buffer)); - if (ret <= 0) - return -1; + if (ret < 0) + return ret; ret = sscanf(buffer, "%Lu", (unsigned long long *) out); if (ret != 1) return -1; diff --git a/resmem.c b/resmem.c index 5a0a221..c134f46 100644 --- a/resmem.c +++ b/resmem.c @@ -156,14 +156,15 @@ int getmemexist(int res_id, void *exist, size_t sz, void *hint, int flags) char buf[4096]; ret = file_to_buf("./mem_info.orig", buf, sizeof(buf)); - if (ret == -1) - return -1; + if (ret < 0) + return ret; ret = populate_minfo(buf, exist, 1); return ret; } /* Read resource information corresponding to res_id */ -int getmeminfo(int res_id, void *out, size_t sz, void **hint, int pid, int flags) +int getmeminfo(int res_id, void *out, size_t sz, void **hint, int pid, + int flags) { char buf[4096]; int ret; diff --git a/resmem.h b/resmem.h index 8d3d767..72afb59 100644 --- a/resmem.h +++ b/resmem.h @@ -28,6 +28,7 @@ #define MEMCGNAME "memory" extern int populate_meminfo(struct res_blk *res, int pid, int flags); +extern int populate_meminfo_cg(res_blk_t *res, int pid, int flags); extern int getmeminfo(int res_id, void *out, size_t sz, void **hint, int pid, int flags); extern int getmeminfo_cg(int res_id, void *out, size_t sz, diff --git a/resmem_cg.c b/resmem_cg.c index d222d29..3ad2dc7 100644 --- a/resmem_cg.c +++ b/resmem_cg.c @@ -27,8 +27,6 @@ #include #include -static int cg_error; - /* read a specific information from file on the basis of a string. * String should tell what information is being read. */ @@ -53,179 +51,182 @@ int get_info_infile(char *fname, char *res, void *out) /* read information from a cgroup file. */ -static inline size_t cgmemread(char *cg, char *name, char *elem) +static inline int cgmem(char *cg, char *name, unsigned long *out) { char fn[FNAMELEN]; - unsigned long ret; + int ret; + char buf[2048]; + + snprintf(fn, FNAMELEN, "%s/%s", cg, name); + + ret = file_to_buf(fn, buf, sizeof(buf)); + if (ret < 0) + return ret; + + if (strncmp(buf, "max", 3) == 0) { + ret = get_info_infile(MEMINFO_FILE, "MemTotal:", out); + if (ret < 0) + return ret; + /* + * MemTotal from /proc/meminfo returns value in kB + * Convert to bytes + */ + *out *= 1000; + return ret; + } + *out = strtoul(buf, NULL, 10); + return 0; +} - snprintf(fn, FNAMELEN, "%s/%s%s/%s", DEFAULTCGFS, - MEMCGNAME, cg, name); +static inline int cgmemval(char *cg, char *name, char *elem, + unsigned long *out) +{ + char fn[FNAMELEN]; - cg_error = get_info_infile(fn, elem, &ret); + snprintf(fn, FNAMELEN, "%s/%s", cg, name); - return ret / 1024; + return (get_info_infile(fn, elem, out)); } -/* Get all memory info for a cgroup */ -static int getmeminfoall(char *cg, void *out) +static inline int cg_free_mem(char *cg, unsigned long *out) { - res_mem_infoall_t *memall = out; + unsigned long mcurr; + int err; - memall->memfree = (size_t) - (cgmemread(cg, "memory", "limit_in_bytes") - - - cgmemread(cg, "memory", "usage_in_bytes")); - memall->memavailable = (size_t) - (cgmemread(cg, "memory", "limit_in_bytes") - - - cgmemread(cg, "memory", "usage_in_bytes") - + - cgmemread(cg, "memory.stat", "cache")); - memall->memtotal = (size_t) cgmemread(cg, "memory", "limit_in_bytes"); - memall->active = (size_t) (cgmemread(cg, "memory", "\nactive_anon") - + - cgmemread(cg, "memory", "\nactive_file")); - memall->inactive = (size_t) (cgmemread(cg, "memory", "\ninactive_anon") - + - cgmemread(cg, "memory", "\ninactive_file")); - memall->swaptotal = (size_t) - cgmemread(cg, "memory", "memsw.limit_in_bytes"); - memall->swapfree = (size_t) - (cgmemread(cg, "memory", "memsw.limit_in_bytes") - - - cgmemread(cg, "memory", "memsw.usage_in_bytes")); - return cg_error; + if ((err = cgmem(cg, "memory.max", out)) < 0) + return err; + if ((err = cgmem(cg, "memory.current", &mcurr)) < 0) + return err; + *out -= mcurr; + return 0; } -/* - * Returns: -1 on error, 0 on success - */ -int getmeminfo_cg(int res_id, void *out, size_t sz, void **hint, int pid, int flags) +static inline int cg_free_swap(char *cg, unsigned long *out) { - char *cg; + unsigned long scurr; + int err; - cg = get_cgroup(pid, MEMCGNAME); - if (!cg) { - printf("get_cgroups error\n"); - return -1; - } + if ((err = cgmem(cg, "memory.swap.max", out)) < 0) + return err; + if ((err = cgmem(cg, "memory.swap.current", &scurr)) < 0) + return err; + *out -= scurr; + return 0; +} - clean_init(cg); +static inline int cg_active(char *cg, unsigned long *out) +{ + unsigned long afile; + int err; + if ((err = cgmemval(cg, "memory.stat", "active_anon", out)) < 0) + return err; + if ((err = cgmemval(cg, "memory.stat", "active_file", &afile)) < 0) + return err; + *out += afile; + return 0; +} + +static inline int cg_inactive(char *cg, unsigned long *out) +{ + unsigned long ifile; + int err; + + if ((err = cgmemval(cg, "memory.stat", "inactive_anon", out)) < 0) + return err; + if ((err = cgmemval(cg, "memory.stat", "inactive_file", &ifile)) < 0) + return err; + *out += ifile; + return 0; +} + +/* Get all memory info for a cgroup */ +static int getmeminfoall(char *cg, void *out) +{ + res_mem_infoall_t *memall = out; + + cg_free_mem(cg, &memall->memfree); + cgmem(cg, "memory.max", &memall->memtotal); + cgmem(cg, "memory.current", &memall->memavailable); + cg_active(cg, &memall->active); + cg_inactive(cg, &memall->inactive); + cgmem(cg, "memory.swap.max", &memall->swaptotal); + cg_free_swap(cg, &memall->swapfree); + return 0; +} + +static inline int cg_res_val(int res_id, char *cg, unsigned long *out) +{ switch (res_id) { case RES_MEM_FREE: - *(size_t *)out = (size_t) - (cgmemread(cg, "memory", "limit_in_bytes") - - - cgmemread(cg, "memory", "usage_in_bytes")); - break; + return cg_free_mem(cg, out); case RES_MEM_AVAILABLE: - *(size_t *)out = (size_t) - (cgmemread(cg, "memory", "limit_in_bytes") - - - cgmemread(cg, "memory", "usage_in_bytes") - + - cgmemread(cg, "memory.stat", "cache")); + return cgmem(cg, "memory.current", out); break; case RES_MEM_TOTAL: - *(size_t *)out = (size_t) - cgmemread(cg, "memory", "limit_in_bytes"); - break; + return cgmem(cg, "memory.max", out); case RES_MEM_ACTIVE: - *(size_t *)out = (size_t) (cgmemread(cg, "memory", "\nactive_anon") - + - cgmemread(cg, "memory", "\nactive_file")); - break; + return cg_active(cg, out); case RES_MEM_INACTIVE: - *(size_t *)out = (size_t) (cgmemread(cg, "memory", "\ninactive_anon") + - cgmemread(cg, "memory", "\ninactive_file")); - break; + return cg_inactive(cg, out); case RES_MEM_SWAPTOTAL: - *(size_t *)out = (size_t) - cgmemread(cg, "memory", "memsw.limit_in_bytes"); - break; + return cgmem(cg, "memory.swap.max", out); case RES_MEM_SWAPFREE: - *(size_t *)out = (size_t) - (cgmemread(cg, "memory", "memsw.limit_in_bytes") - - - cgmemread(cg, "memory", "memsw.usage_in_bytes")); - break; + return cg_free_swap(cg, out); + } + return -1; +} - case RES_MEM_INFOALL: - return (getmeminfoall(cg, out)); +/* + * Returns: 0 on success, <0 if error + */ +int getmeminfo_cg(int res_id, void *out, size_t sz, void **hint, int pid, + int flags) +{ + char *cg; + int err; + + cg = get_cgroup(pid, MEMCGNAME); + if (!cg) + return -1; + + //clean_init(cg); + + if (res_id == RES_MEM_INFOALL) { + CHECK_SIZE(sz, sizeof(res_mem_infoall_t)); + err = getmeminfoall(cg, out); + free(cg); + return err; } - return cg_error; + CHECK_SIZE(sz, sizeof(unsigned long)); + err = cg_res_val(res_id, cg, (unsigned long *)out); + free(cg); + return err; } int populate_meminfo_cg(res_blk_t *res, int pid, int flags) { char *cg; + int err; cg = get_cgroup(pid, MEMCGNAME); - if (!cg) { - printf("%s: get_cgroups error\n", __FUNCTION__); + if (!cg) return -1; - } - clean_init(cg); + //clean_init(cg); for (int i = 0; i < res->res_count; i++) { - switch (res->res_unit[i]->res_id) { - case RES_MEM_FREE: - (res->res_unit[i]->data).sz = (size_t) - (cgmemread(cg, "memory", "limit_in_bytes") - - - cgmemread(cg, "memory", "usage_in_bytes")); - break; - - case RES_MEM_AVAILABLE: - (res->res_unit[i]->data).sz = (size_t) - (cgmemread(cg, "memory", "limit_in_bytes") - - - cgmemread(cg, "memory", "usage_in_bytes") - + - cgmemread(cg, "memory.stat", "cache")); - break; - - case RES_MEM_TOTAL: - (res->res_unit[i]->data).sz = (size_t) - cgmemread(cg, "memory", "limit_in_bytes"); - break; - - case RES_MEM_ACTIVE: - (res->res_unit[i]->data).sz = (size_t) - (cgmemread(cg, "memory.stat", "\nactive_anon") - + - cgmemread(cg, "memory.stat", "\nactive_file")); - break; - - case RES_MEM_INACTIVE: - (res->res_unit[i]->data).sz = (size_t) - (cgmemread(cg, "memory.stat", "\ninactive_anon") - + - cgmemread(cg, "memory.stat", "\ninactive_file")); - break; - - case RES_MEM_SWAPTOTAL: - (res->res_unit[i]->data).sz = - cgmemread(cg, "memory", "memsw.limit_in_bytes"); - break; - - case RES_MEM_SWAPFREE: - (res->res_unit[i]->data).sz = - (cgmemread(cg, "memory", "memsw.limit_in_bytes") - - - cgmemread(cg, "memory", "memsw.usage_in_bytes")); - break; - } - res->res_unit[i]->status = cg_error; + err = cg_res_val(res->res_unit[i]->res_id, cg, + &((res->res_unit[i]->data).sz)); + res->res_unit[i]->status = err; } + free(cg); return 0; } diff --git a/resnet.c b/resnet.c index 748debc..e06b8fb 100644 --- a/resnet.c +++ b/resnet.c @@ -260,47 +260,39 @@ int getnetinfo(int res_id, void *out, size_t sz, void *hint, int pid, int flags) char buffer[4096]; unsigned long long *n = (unsigned long long *) out; -#define CHECK_SIZE(sz, req_sz) \ - if (sz < req_sz) { \ - eprintf("memory (%ld) is not enough to hold data (%ld)",\ - sz, req_sz); \ - errno = ENOMEM; \ - return -1; \ - } - switch (res_id) { case RES_NET_IP_LOCAL_PORT_RANGE: ret = file_to_buf(IP_PORT_RANGE, buffer, sizeof(buffer)); - if (ret == -1) - return -1; + if (ret < 0) + return ret; sscanf(buffer, "%Lu %Lu", &n[0], &n[1]); break; case RES_NET_TCP_RMEM_MAX: ret = file_to_buf(TCP_RMEM_MAX, buffer, sizeof(buffer)); - if (ret == -1) - return -1; + if (ret < 0) + return ret; sscanf(buffer, "%Lu %Lu %Lu", &n[0], &n[1], &n[2]); break; case RES_NET_TCP_WMEM_MAX: ret = file_to_buf(TCP_WMEM_MAX, buffer, sizeof(buffer)); - if (ret == -1) - return -1; + if (ret < 0) + return ret; sscanf(buffer, "%Lu %Lu %Lu", &n[0], &n[1], &n[2]); break; case RES_NET_RMEM_MAX: ret = file_to_buf(CORE_RMEM_MAX, buffer, sizeof(buffer)); - if (ret == -1) - return -1; + if (ret < 0) + return ret; sscanf(buffer, "%Lu", n); break; case RES_NET_WMEM_MAX: ret = file_to_buf(CORE_WMEM_MAX, buffer, sizeof(buffer)); - if (ret == -1) - return -1; + if (ret < 0) + return ret; sscanf(buffer, "%Lu", n); break; diff --git a/resource.c b/resource.c index bf4a3f5..2cd0a65 100644 --- a/resource.c +++ b/resource.c @@ -189,12 +189,15 @@ int res_read(int res_id, void *out, size_t out_sz, void **hint, int pid, int fla if (res_id >= PROC_MIN && res_id < PROC_MAX) return getprocinfo(res_id, out, out_sz, hint, pid, flags); - if (res_id >= MEM_MIN && res_id < MEM_MAX) -#ifdef CGROUPS - return getmeminfo_cg(res_id, out, out_sz, hint, pid, flags); -#else - return getmeminfo(res_id, out, out_sz, hint, pid, flags); -#endif + if (res_id >= MEM_MIN && res_id < MEM_MAX) { + if (pid > 0) { + return getmeminfo_cg(res_id, out, out_sz, hint, + pid, flags); + } else { + return getmeminfo(res_id, out, out_sz, hint, + pid, flags); + } + } if (res_id >= RES_NET_MIN && res_id < RES_NET_MAX) return getnetinfo(res_id, out, out_sz, hint, pid, flags); @@ -314,12 +317,13 @@ int res_read_blk(res_blk_t *res, int pid, int flags) if (isprocreq) populate_procinfo(res, pid, flags); - if (ismeminforeq) -#ifdef CGROUPS - return (populate_meminfo_cg(res, pid, flags)); -#else - return (populate_meminfo(res, pid, flags)); -#endif + if (ismeminforeq) { + if (pid > 0) { + return (populate_meminfo_cg(res, pid, flags)); + } else { + return (populate_meminfo(res, pid, flags)); + } + } if (isnetdevreq) populate_netinfo(res, pid, flags); diff --git a/resource_impl.h b/resource_impl.h index 073d0de..268d1ae 100644 --- a/resource_impl.h +++ b/resource_impl.h @@ -29,29 +29,30 @@ #define FNAMELEN RESOURCE_256 +#define CG_MAX_PATH_LEN 200 + #define INITSCOPE "/init.scope" /* We are assuming that cgroup is mounted at its usual location, * If we have reeust from applications who do not mount cgroup at * usual location, then we need to change this. */ -#define DEFAULTCGFS "/sys/fs/cgroup" +#define CGFS "/sys/fs/cgroup" #define eprintf(msg, ...) fprintf(stderr,\ "Err at line %d in file %s: "msg"\n",\ __LINE__, __FILE__, ##__VA_ARGS__)\ -#define libres_iterate_parts(__iterator, __str, __separators) \ +/*#define libres_iterate_parts(__iterator, __str, __separators) \ for (char *__p = NULL, *__it = strtok_r(__str, __separators, &__p);\ (__iterator = __it); \ - __iterator = __it = strtok_r(NULL, __separators, &__p)) + __iterator = __it = strtok_r(NULL, __separators, &__p)) */ #define CHECK_SIZE(sz, req_sz) \ if (sz < req_sz) { \ eprintf("memory (%ld) is not enough to hold data (%ld)",\ sz, req_sz); \ - errno = ENOMEM; \ - return -1; \ + return -ENOMEM; \ } /* Helper function to skip first n spaces from string s and return @@ -72,7 +73,7 @@ static inline char *skip_spaces(char *s, size_t len, int n) { return NULL; } -static inline void clean_init(char *cg) +/*static inline void clean_init(char *cg) { char *p; size_t cg_len = strlen(cg), init_len = strlen(INITSCOPE); @@ -87,31 +88,28 @@ static inline void clean_init(char *cg) else *p = '\0'; } -} +}*/ /* Find a cgroup controller in list of comma(,) seperated cgroup controller * list. */ -static inline int controller_in_clist(char *cgline, const char *c) +/*static inline int controller_in_clist(char *cgline, const char *c) { char *tok; libres_iterate_parts(tok, cgline, ",") if (strcmp(tok, c) == 0) return 1; return 0; -} +}*/ /* Get cgroup path for a particular controller */ static inline char *get_cgroup(pid_t pid, const char *contrl) { char fn[FNAMELEN]; - FILE *f; - char *line = NULL; - size_t len = 0; - size_t l = 0; + FILE *fp; int ret; - char *cgrp = NULL; - char *c1, *c2; + char *cgrp1; + char *cgrp = (char*) malloc(CG_MAX_PATH_LEN); /* If no pid is provided then return cgroup info for current process. */ @@ -121,39 +119,24 @@ static inline char *get_cgroup(pid_t pid, const char *contrl) ret = snprintf(fn, FNAMELEN, "/proc/self/cgroup"); } - if (ret < 0 || ret >= FNAMELEN) + if (ret < 0 || ret >= FNAMELEN) { + eprintf("snprintf returned %d\n", ret); return NULL; + } - if (!(f = fopen(fn, "r"))) + if (!(fp = fopen(fn, "r"))) { + eprintf("fopen %s error\n", fn); return NULL; - - while (getline(&line, &len, f) != -1) { - if (!line[0]) - continue; - c1 = strchr(line, ':'); - if (!c1) - goto out; - c1++; - - c2 = strchr(c1, ':'); - if (!c2) - goto out; - *c2 = '\0'; - if (!controller_in_clist(c1, contrl)) - continue; - c2++; - l = strlen(c2); - if (l && c2[l-1] == '\n') - c2[l-1] = '\0'; - if (strcmp(c2, "/") == 0) - goto out; - cgrp = strdup(c2); - break; } -out: - fclose(f); - free(line); + strcpy(cgrp, CGFS); + cgrp1 = cgrp + strlen(cgrp); + if ((fscanf(fp, "0::%s", cgrp1)) != 1) { + eprintf("fscanf error\n"); + fclose(fp); + return NULL; + } + fclose(fp); return cgrp; } @@ -172,9 +155,9 @@ static inline int file_to_buf(char *fname, char *buf, unsigned int bufsz) } rdsz = read(fd, buf, bufsz - 1); - if (rdsz < 0) { + if (rdsz <= 0) { err = errno; - eprintf("in read from File %s with errno: %d", fname, errno); + eprintf("read File %s errno: %d rdsz %lu", fname, errno, rdsz); close(fd); return -err; } diff --git a/resproc.c b/resproc.c index a4eaec2..4989379 100644 --- a/resproc.c +++ b/resproc.c @@ -132,15 +132,6 @@ int getprocinfo(int res_id, void *out, size_t sz, void *hint, int pid, int flags res_proc_infoall_t *p; char buf[PROCBUF_1024]; -#define CHECK_SIZE(sz, req_sz) \ - if (sz < req_sz) { \ - eprintf("memory (%ld) is not enough to hold data (%ld)",\ - sz, req_sz); \ - errno = ENOMEM; \ - return -1; \ - } - - switch (res_id) { case RES_PROC_INFOALL: CHECK_SIZE(sz, sizeof(res_proc_infoall_t)); diff --git a/resvm.c b/resvm.c index 32da6dc..dc566ac 100644 --- a/resvm.c +++ b/resvm.c @@ -288,8 +288,8 @@ int getvmexist(int res_id, void *exist, size_t sz, void *hint, int flags) int ret; memset(exist, 0, sz); ret = file_to_buf("./vm_info.orig", buffer, sizeof(buffer)); - if (ret == -1) - return -1; + if (ret < 0) + return ret; ret = populate_vminfo(exist, 1); return ret; } @@ -306,8 +306,8 @@ int getvmstatinfo(int res_id, void *out, size_t sz, void **hint, int flags) #else ret = file_to_buf(VMINFO_FILE, buffer, sizeof(buffer)); #endif - if (ret == -1) - return -1; + if (ret < 0) + return ret; switch (res_id) { case RES_VMSTAT_INFO: diff --git a/stat.c b/stat.c index 831cfeb..d45ad98 100644 --- a/stat.c +++ b/stat.c @@ -129,10 +129,9 @@ int getstatexist(int res_id, void *exist, size_t sz, void *hint, int flags) { int ret; ret = file_to_buf("./stat_info.orig", buffer, sizeof(buffer)); - if (ret == -1) - return -1; - ret = populate_statinfo(exist, 1); - return ret; + if (ret < 0) + return ret; + return (populate_statinfo(exist, 1)); } int getstatinfo(int res_id, void *out, size_t sz, void **hint, int flags) @@ -144,8 +143,8 @@ int getstatinfo(int res_id, void *out, size_t sz, void **hint, int flags) #else ret = file_to_buf(STAT_FILE, buffer, sizeof(buffer)); #endif - if (ret == -1) - return -1; + if (ret < 0) + return ret; switch (res_id) { case RES_STAT_INFO: diff --git a/tests/MEM/Makefile b/tests/MEM/Makefile new file mode 100644 index 0000000..ad590dd --- /dev/null +++ b/tests/MEM/Makefile @@ -0,0 +1,14 @@ +CC = gcc +export LD_LIBRARY_PATH = `git rev-parse --show-toplevel` +CFLAGS = -g -Wall -Werror -I $(LD_LIBRARY_PATH) -std=gnu99 -L $(LD_LIBRARY_PATH) -lresource +REXE = mem_test mem_test_cg +MFILES = mem_info.* + +mem_test: mem_test.c + $(CC) $(CFLAGS) -o $@ $^ + +mem_test_cg: mem_test_cg.c + $(CC) $(CFLAGS) -o $@ $^ + +clean: + rm -rf $(MFILES) $(REXE) diff --git a/tests/MEM/mem.sh b/tests/MEM/mem.sh index 70a5f42..786146b 100755 --- a/tests/MEM/mem.sh +++ b/tests/MEM/mem.sh @@ -1,14 +1,13 @@ #!/bin/sh # Enable -DTESTING in Makefile and the recompile library - make -export LD_LIBRARY_PATH=`git rev-parse --show-toplevel` -cd $LD_LIBRARY_PATH -cd tests/MEM -rm -f mem_test -rm -f mem_info.orig -rm -f mem_info.txt -cc -I $LD_LIBRARY_PATH -std=gnu99 -o mem_test mem_test.c -L $LD_LIBRARY_PATH -lresource +make clean + +make mem_test cat /proc/meminfo > mem_info.orig -./mem_test sed -i 's/[ ]\+/ /g' mem_info.orig +./mem_test diff mem_info.orig mem_info.txt + +#make mem_test_cg +#./mem_test_cg diff --git a/tests/MEM/mem_test.c b/tests/MEM/mem_test.c index 536b6e5..7f481d8 100644 --- a/tests/MEM/mem_test.c +++ b/tests/MEM/mem_test.c @@ -25,7 +25,6 @@ int main(int argc, char **argv) { struct memstat mem, exist; - unsigned long value; FILE *fp; int ret; diff --git a/tests/MEM/mem_test_cg.c b/tests/MEM/mem_test_cg.c new file mode 100644 index 0000000..a86017d --- /dev/null +++ b/tests/MEM/mem_test_cg.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + unsigned long value; + int ret; + int pid = 43044; + + /* Non-zero value of pid field (second last variable) to res_read + * indicates to read RES_MEM_FREE value from cgroups + */ + ret = res_read(RES_MEM_AVAILABLE, &value, sizeof(value), NULL, + pid, 0); + if (ret != 0) { + printf("RES_MEM_AVAILABLE returned error %d\n",ret); + exit(1); + } + printf("RES_MEM_AVAILABLE for pid %d is %lu\n", pid, value); + + ret = res_read(RES_MEM_TOTAL, &value, sizeof(value), NULL, + pid, 0); + if (ret != 0) { + printf("RES_MEM_TOTAL returned error %d\n",ret); + exit(1); + } + printf("RES_MEM_TOTAL for pid %d is %lu\n", pid, value); + + ret = res_read(RES_MEM_FREE, &value, sizeof(value), NULL, + pid, 0); + if (ret != 0) { + printf("RES_MEM_FREE returned error %d\n",ret); + exit(1); + } + printf("RES_MEM_FREE for pid %d is %lu\n", pid, value); +}