This source file includes following definitions.
- memory_available_uv
- mem_parse_value
- sim_memory_available
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 #include <errno.h>
29 #include <stdbool.h>
30 #include <limits.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <uv.h>
35
36 #define MEM_BUFFER_SIZE 4096
37 #define UV_VERSION(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
38
39 static uint64_t
40 memory_available_uv(void) {
41 uint64_t available_memory_b = 0;
42
43 #if UV_VERSION(1, 45, 0) <= UV_VERSION_HEX
44 available_memory_b = uv_get_available_memory();
45 #endif
46 if (0 == available_memory_b)
47 available_memory_b = uv_get_free_memory();
48
49 return available_memory_b;
50 }
51
52 static int
53 mem_parse_value(const char *line, const char *label, uint64_t *value)
54 {
55 if (!line || !label || !value)
56 return -1;
57
58 size_t label_len = strlen(label);
59 if (0 != strncmp(line, label, label_len))
60 return -1;
61
62 const char *ptr = line + label_len;
63 while (' ' == *ptr || '\t' == *ptr)
64 ptr++;
65
66 char *endptr;
67 errno = 0;
68 *value = strtoull(ptr, &endptr, 10) * 1024;
69 if (ERANGE == errno || ULLONG_MAX == *value || ptr == endptr)
70 return -1;
71
72 while (' ' == *endptr || '\t' == *endptr)
73 endptr++;
74 if (0 != strncmp(endptr, "kB", 2) || 3 < strlen(endptr))
75 return -1;
76
77 return 0;
78 }
79
80 uint64_t
81 sim_memory_available(void) {
82 FILE *fp = fopen("/proc/meminfo", "r");
83 uint64_t uv_usable_memory = memory_available_uv();
84
85 if (!fp)
86 return uv_usable_memory;
87
88 char buffer[MEM_BUFFER_SIZE];
89 uint64_t commit_limit = 0, mem_free = 0, buffers = 0, cached = 0, mem_available = 0;
90 bool found_commit = false, found_free = false, found_buffers = false, found_cached = false, found_available = false;
91
92 while (fgets(buffer, sizeof(buffer), fp)) {
93 buffer[sizeof(buffer) - 1] = '\0';
94
95 if (false == found_commit && 0 == mem_parse_value(buffer, "CommitLimit:", &commit_limit))
96 found_commit = true;
97 else if (false == found_free && 0 == mem_parse_value(buffer, "MemFree:", &mem_free))
98 found_free = true;
99 else if (false == found_buffers && 0 == mem_parse_value(buffer, "Buffers:", &buffers))
100 found_buffers = true;
101 else if (false == found_cached && 0 == mem_parse_value(buffer, "Cached:", &cached))
102 found_cached = true;
103 else if (false == found_available && 0 == mem_parse_value(buffer, "MemAvailable:", &mem_available))
104 found_available = true;
105
106 if (found_commit && found_free && found_buffers && found_cached && found_available)
107 break;
108 }
109
110 (void)fclose(fp);
111
112 uint64_t linux_commit_memory = found_commit ? commit_limit : 0;
113 uint64_t linux_freebufcache_memory = (found_free && found_buffers && found_cached) ?
114 (mem_free + buffers + cached) : 0;
115 uint64_t linux_available_memory = found_available ? mem_available : 0;
116
117 if (uv_usable_memory)
118 return uv_usable_memory;
119
120 if (linux_available_memory)
121 return linux_available_memory;
122
123 if (linux_freebufcache_memory)
124 return linux_freebufcache_memory;
125
126 if (linux_commit_memory)
127 return linux_commit_memory;
128
129 return 0;
130 }