Using libc APIs to calculate memory reservations

Updated: April 19, 2023

You can use the code snippets in this section to calculate how much private and shared memory your process is using.

Calculating private memory reservations

Set up a notification on the private memory of your process and read its value when the notification is triggered. In the code snippet below, rsv contains the private memory reservation of the process with the Process ID pid. Return checks have been omitted for simplicity.

int ev_id;
struct sigevent sev;
uint64_t rsv;
SIGEV_NONE_INIT(&sev);
ev_id = procmgr_value_notify_add(PROCMGR_VALUE_PRIVATE_MEM, pid, 0, &sev);
rsv = procmgr_value_current(ev_id);
procmgr_event_notify_delete(ev_id);

Calculating shared memory usage

Collect page data for the process for which /proc/<pid>/ctl was opened. In this example, fd is proc_fd. Call get_pagedata with *entries_num initialized to 0 and *mapinfo_buf == NULL. The first call to devctl(DCMD_PROC_PAGEDATA) will report the number of entries in entries_num, which is then used to resize *mapinfo_buf. In the next call, actual data will be copied into *mapinfo_buf. You can use this data to calculate shared memory usage. Return checks have been omitted for simplicity.

#include <sys/procfs.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/mman.h>

uint64_t get_pagedata(const int proc_fd, procfs_mapinfo **mapinfo_buf,
                      int *entries_num)
{
    size_t buffer_size = 0;
    int result;
    procfs_mapinfo *mapinfo_buf_new = NULL;

    do {
        /* resize buffer if/when required */
        if (*entries_num > (int)buffer_size) {
            buffer_size = (size_t)*entries_num;
            mapinfo_buf_new = realloc(*mapinfo_buf, buffer_size * sizeof(procfs_mapinfo));
            /* if call was successful: */
            *mapinfo_buf = mapinfo_buf_new;
        }

        result = devctl(proc_fd, DCMD_PROC_PAGEDATA, *mapinfo_buf,
                buffer_size * sizeof(procfs_mapinfo), entries_num);
    } while (*entries_num > (int)buffer_size);

    // example how caller can use values.
    // printf( "Number of page entries read: %d \n", *entries_num);

    uint64_t total_map_shared = 0;

    /* example usage: calculate shared memory for this process */
    for(int i = 0; i < *entries_num; i++) {
        if((mapinfo_buf[i]->flags & (PG_HWMAPPED|MAP_SYSRAM)) ==
                (PG_HWMAPPED| MAP_SYSRAM)) {
            if((mapinfo_buf[i]->flags & MAP_TYPE) == MAP_SHARED) {
                total_map_shared += mapinfo_buf[i]->size;
            }
        }
    }
    return total_map_shared;
}