git: bf46aec4b29a - main - libprocstat: add helper to query knotes for specific kqueue

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Thu, 13 Mar 2025 16:10:09 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=bf46aec4b29a72bcaaa9f1b2fc446ee299f5a6fd

commit bf46aec4b29a72bcaaa9f1b2fc446ee299f5a6fd
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-02-24 23:44:10 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-03-13 16:09:35 +0000

    libprocstat: add helper to query knotes for specific kqueue
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D49163
---
 lib/libprocstat/Symbol.map    |  2 ++
 lib/libprocstat/libprocstat.c | 66 +++++++++++++++++++++++++++++++++++++++++++
 lib/libprocstat/libprocstat.h |  4 +++
 3 files changed, 72 insertions(+)

diff --git a/lib/libprocstat/Symbol.map b/lib/libprocstat/Symbol.map
index c2ea7e95312c..3d71c3eaae4a 100644
--- a/lib/libprocstat/Symbol.map
+++ b/lib/libprocstat/Symbol.map
@@ -50,6 +50,8 @@ FBSD_1.7 {
 };
 
 FBSD_1.8 {
+	 procstat_get_kqueue_info;
 	 procstat_getrlimitusage;
+	 procstat_freekqinfo;
 	 procstat_freerlimitusage;
 };
\ No newline at end of file
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index 90e4879ca05b..3c70c939ff7e 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -2817,3 +2817,69 @@ procstat_freerlimitusage(struct procstat *procstat __unused, rlim_t *resusage)
 {
 	free(resusage);
 }
+
+static struct kinfo_knote *
+procstat_get_kqueue_info_sysctl(pid_t pid, int kqfd, unsigned int *cntp,
+    char *errbuf)
+{
+	int error, name[5];
+	struct kinfo_knote *val;
+	size_t len;
+
+	name[0] = CTL_KERN;
+	name[1] = KERN_PROC;
+	name[2] = KERN_PROC_KQUEUE;
+	name[3] = pid;
+	name[4] = kqfd;
+
+	len = 0;
+	error = sysctl(name, nitems(name), NULL, &len, NULL, 0);
+	if (error == -1) {
+		snprintf(errbuf, _POSIX2_LINE_MAX,
+		    "KERN_PROC_KQUEUE.pid<%d>.kq<%d> (size q) failed: %s",
+		    pid, kqfd, strerror(errno));
+		return (NULL);
+	}
+	val = malloc(len);
+	if (val == NULL) {
+		snprintf(errbuf, _POSIX2_LINE_MAX, "no memory");
+		return (NULL);
+	}
+
+	error = sysctl(name, nitems(name), val, &len, NULL, 0);
+	if (error == -1) {
+		snprintf(errbuf, _POSIX2_LINE_MAX,
+		    "KERN_PROC_KQUEUE.pid<%d>.kq<%d> failed: %s",
+		    pid, kqfd, strerror(errno));
+		free(val);
+		return (NULL);
+	}
+	*cntp = len / sizeof(*val);
+	return (val);
+}
+
+struct kinfo_knote *
+procstat_get_kqueue_info(struct procstat *procstat,
+    struct kinfo_proc *kp, int kqfd, unsigned int *count, char *errbuf)
+{
+	switch (procstat->type) {
+	case PROCSTAT_KVM:
+		warnx("kvm method is not supported");
+		return (NULL);
+	case PROCSTAT_SYSCTL:
+		return (procstat_get_kqueue_info_sysctl(kp->ki_pid, kqfd,
+		    count, errbuf));
+	case PROCSTAT_CORE:
+		warnx("core method is not supported");
+		return (NULL);
+	default:
+		warnx("unknown access method: %d", procstat->type);
+		return (NULL);
+	}
+}
+
+void
+procstat_freekqinfo(struct procstat *procstat __unused, struct kinfo_knote *v)
+{
+	free(v);
+}
diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h
index 81a3ac05393d..0e9a4214414c 100644
--- a/lib/libprocstat/libprocstat.h
+++ b/lib/libprocstat/libprocstat.h
@@ -110,6 +110,7 @@
 struct kinfo_kstack;
 struct kinfo_proc;
 struct kinfo_vmentry;
+struct kinfo_knote;
 struct procstat;
 struct ptrace_lwpinfo;
 struct rlimit;
@@ -204,6 +205,7 @@ void	procstat_freeauxv(struct procstat *procstat, Elf_Auxinfo *auxv);
 #endif
 void	procstat_freeenvv(struct procstat *procstat);
 void	procstat_freegroups(struct procstat *procstat, gid_t *groups);
+void	procstat_freekqinfo(struct procstat *procstat, struct kinfo_knote *kni);
 void	procstat_freekstack(struct procstat *procstat,
     struct kinfo_kstack *kkstp);
 void	procstat_freeprocs(struct procstat *procstat, struct kinfo_proc *p);
@@ -219,6 +221,8 @@ struct filestat_list	*procstat_getfiles(struct procstat *procstat,
     struct kinfo_proc *kp, int mmapped);
 struct kinfo_proc	*procstat_getprocs(struct procstat *procstat,
     int what, int arg, unsigned int *count);
+struct kinfo_knote	*procstat_get_kqueue_info(struct procstat *procstat,
+    struct kinfo_proc *kp, int kqfd, unsigned int *count, char *errbuf);
 int	procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst,
     struct pipestat *pipe, char *errbuf);
 int	procstat_get_pts_info(struct procstat *procstat, struct filestat *fst,