summaryrefslogtreecommitdiff
path: root/psutil/arch/netbsd/mem.c
blob: b7f5ba23a6971619ea284fcc86af57c4f2dbc90c (plain)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
 * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil.
 * All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/*
Memory related functions. Original code was refactored and moved from
psutil/arch/netbsd/specific.c in 2023 (and was moved in there previously
already) from cset 84219ad. For reference, here's the git history with
original(ish) implementations:
- virtual memory: 0749a69c01b374ca3e2180aaafc3c95e3b2d91b9 (Oct 2016)
- swap memory: 312442ad2a5b5d0c608476c5ab3e267735c3bc59 (Jan 2016)
*/

#include <Python.h>
#include <sys/swap.h>
#include <sys/sysctl.h>
#include <uvm/uvm_extern.h>

#include "../../_psutil_common.h"
#include "../../_psutil_posix.h"


// Virtual memory stats, taken from:
// https://github.com/satterly/zabbix-stats/blob/master/src/libs/zbxsysinfo/
//     netbsd/memory.c
PyObject *
psutil_virtual_mem(PyObject *self, PyObject *args) {
    size_t size;
    struct uvmexp_sysctl uv;
    int mib[] = {CTL_VM, VM_UVMEXP2};
    long pagesize = psutil_getpagesize();

    size = sizeof(uv);
    if (sysctl(mib, 2, &uv, &size, NULL, 0) < 0) {
        PyErr_SetFromErrno(PyExc_OSError);
        return NULL;
    }

    return Py_BuildValue("KKKKKKKK",
        (unsigned long long) uv.npages << uv.pageshift,  // total
        (unsigned long long) uv.free << uv.pageshift,  // free
        (unsigned long long) uv.active << uv.pageshift,  // active
        (unsigned long long) uv.inactive << uv.pageshift,  // inactive
        (unsigned long long) uv.wired << uv.pageshift,  // wired
        (unsigned long long) (uv.filepages + uv.execpages) * pagesize,  // cached
        // These are determined from /proc/meminfo in Python.
        (unsigned long long) 0,  // buffers
        (unsigned long long) 0  // shared
    );
}


PyObject *
psutil_swap_mem(PyObject *self, PyObject *args) {
    uint64_t swap_total, swap_free;
    struct swapent *swdev;
    int nswap, i;
    long pagesize = psutil_getpagesize();

    nswap = swapctl(SWAP_NSWAP, 0, 0);
    if (nswap == 0) {
        // This means there's no swap partition.
        return Py_BuildValue("(iiiii)", 0, 0, 0, 0, 0);
    }

    swdev = calloc(nswap, sizeof(*swdev));
    if (swdev == NULL) {
        PyErr_SetFromErrno(PyExc_OSError);
        return NULL;
    }

    if (swapctl(SWAP_STATS, swdev, nswap) == -1) {
        PyErr_SetFromErrno(PyExc_OSError);
        goto error;
    }

    // Total things up.
    swap_total = swap_free = 0;
    for (i = 0; i < nswap; i++) {
        if (swdev[i].se_flags & SWF_ENABLE) {
            swap_total += (uint64_t)swdev[i].se_nblks * DEV_BSIZE;
            swap_free += (uint64_t)(swdev[i].se_nblks - swdev[i].se_inuse) * DEV_BSIZE;
        }
    }
    free(swdev);

    // Get swap in/out
    unsigned int total;
    size_t size = sizeof(total);
    struct uvmexp_sysctl uv;
    int mib[] = {CTL_VM, VM_UVMEXP2};
    size = sizeof(uv);
    if (sysctl(mib, 2, &uv, &size, NULL, 0) < 0) {
        PyErr_SetFromErrno(PyExc_OSError);
        goto error;
    }

    return Py_BuildValue("(LLLll)",
                         swap_total,
                         (swap_total - swap_free),
                         swap_free,
                         (long) uv.pgswapin * pagesize,  // swap in
                         (long) uv.pgswapout * pagesize);  // swap out

error:
    free(swdev);
    return NULL;
}