Page MenuHomeFreeBSD

D57632.1794519786.diff
No OneTemporary

Authored By
Unknown
Size
17 KB
Referenced Files
None
Subscribers
None

D57632.1794519786.diff

diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c
--- a/sys/dev/hwpmc/hwpmc_amd.c
+++ b/sys/dev/hwpmc/hwpmc_amd.c
@@ -52,6 +52,8 @@
#include <machine/md_var.h>
#include <machine/specialreg.h>
+#include "hwpmc_pmu.h"
+
#define OVERFLOW_WAIT_COUNT 50
DPCPU_DEFINE_STATIC(uint32_t, nmi_counter);
@@ -609,6 +611,47 @@
return (0);
}
+/*
+ * Return scheduling constraints for AMD PMCs.
+ */
+static int
+amd_get_sched_constraint(struct pmc *pm __unused,
+ const struct pmc_op_pmcallocate *a, pmc_sched_constraint_t *cons)
+{
+ u_int first, count, i;
+
+ if (cons == NULL || a == NULL)
+ return (EINVAL);
+ bzero(cons, sizeof(*cons));
+
+ switch (a->pm_md.pm_amd.pm_amd_sub_class) {
+ case PMC_AMD_SUB_CLASS_CORE:
+ first = 0;
+ count = amd_core_npmcs;
+ break;
+ case PMC_AMD_SUB_CLASS_L3_CACHE:
+ first = amd_core_npmcs;
+ count = amd_l3_npmcs;
+ break;
+ case PMC_AMD_SUB_CLASS_DATA_FABRIC:
+ first = amd_core_npmcs + amd_l3_npmcs;
+ count = amd_df_npmcs;
+ break;
+ default:
+ return (EOPNOTSUPP);
+ }
+ if (count == 0 || first >= PMC_ROWSET_SIZE ||
+ count > PMC_ROWSET_SIZE - first)
+ return (EOPNOTSUPP);
+
+ for (i = 0; i < count; i++)
+ BIT_SET(PMC_ROWSET_SIZE, first + i, &cons->pc_allowed_rows);
+ cons->pc_weight = (uint8_t)count;
+ cons->pc_flags = PMC_SC_F_SHARED;
+ cons->pc_fixed_row = (uint8_t)first;
+ return (0);
+}
+
/*
* Check if a given PMC allocation is feasible.
*/
@@ -1680,6 +1723,10 @@
pcd->pcd_write_pmc = amd_write_pmc;
pcd->pcd_get_caps = amd_get_caps;
+ /* These are the grouping and multiplex constraint functions. */
+ pcd->pcd_can_assign_pmc = amd_can_assign_pmc;
+ pcd->pcd_get_sched_constraint = amd_get_sched_constraint;
+
pmc_mdep->pmd_cputype = cputype;
pmc_mdep->pmd_intr = amd_intr;
pmc_mdep->pmd_switch_in = amd_switch_in;
diff --git a/sys/dev/hwpmc/hwpmc_assign.c b/sys/dev/hwpmc/hwpmc_assign.c
new file mode 100644
--- /dev/null
+++ b/sys/dev/hwpmc/hwpmc_assign.c
@@ -0,0 +1,449 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Advanced Micro Devices, Inc.
+ *
+ * This is the greedy row assigner for PMU event groups.
+ *
+ * Algorithm:
+ * 1. Read the event constraints from the class backend.
+ * 2. Sort the events by weight, lowest first.
+ * 3. Assign each event to the first free allowed row.
+ * 4. On assignment failure, release all assigned rows.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/pmc.h>
+#include <sys/proc.h>
+
+#include "hwpmc_pmu.h"
+
+/*
+ * Find the class descriptor for a PMC class.
+ */
+static struct pmc_classdep *
+pmu_class_to_classdep(enum pmc_class class)
+{
+ struct pmc_mdep *mdep;
+ struct pmc_classdep *pcd;
+ u_int i;
+
+ mdep = hwpmc_get_mdep();
+ if (mdep == NULL)
+ return (NULL);
+ for (i = 0; i < mdep->pmd_nclass; i++) {
+ pcd = &mdep->pmd_classdep[i];
+ if (pcd->pcd_class == class)
+ return (pcd);
+ }
+ return (NULL);
+}
+
+/*
+ * Ask the class backend if the row assignment is possible.
+ */
+static int
+pmu_can_assign_pmc(struct pmc_classdep *pcd, int adjri, struct pmc *pm,
+ const struct pmc_op_pmcallocate *a)
+{
+ if (pcd == NULL || pcd->pcd_can_assign_pmc == NULL)
+ return (0);
+ return (pcd->pcd_can_assign_pmc(adjri, pm, a));
+}
+
+/*
+ * Get the scheduling constraints for an event from the class backend.
+ */
+int
+pmu_event_get_constraint(pmu_event_t *pe,
+ pmc_sched_constraint_t *cons)
+{
+ const struct pmc_op_pmcallocate *a;
+ struct pmc_classdep *pcd;
+
+ if (pe == NULL || cons == NULL)
+ return (EINVAL);
+ a = &pe->pe_alloc;
+ pcd = pmu_class_to_classdep(a->pm_class);
+ if (pcd == NULL || pcd->pcd_get_sched_constraint == NULL)
+ return (EOPNOTSUPP);
+ return (pcd->pcd_get_sched_constraint(pe->pe_pmc, a, cons));
+}
+
+/*
+ * Return true if the PMC class supports event grouping.
+ */
+bool
+pmu_class_supports_grouping(enum pmc_class class)
+{
+ struct pmc_classdep *pcd;
+
+ pcd = pmu_class_to_classdep(class);
+ return (pcd != NULL && pcd->pcd_get_sched_constraint != NULL);
+}
+
+/*
+ * Assign one event to a hardware row.
+ */
+static int
+pmu_assign_one(pmu_group_t *pg, pmu_event_t *pe, struct proc *p, int cpu,
+ struct pmc_rowset *used_rows, bool dry_run,
+ const struct pmc_rowset *evictable_rows)
+{
+ struct pmc_rowset allowed;
+ struct pmu_group_target *pgt;
+ struct pmc *pm;
+ struct pmc_classdep *pcd;
+ enum pmc_mode mode;
+ int adjri, idcpu, n;
+ bool evictable, sys;
+
+ /*
+ * Constraints use the per-class row index (adjri).
+ * The global row index is pcd->pcd_ri + adjri.
+ */
+ pcd = pmu_class_to_classdep(pe->pe_alloc.pm_class);
+ if (pcd == NULL)
+ return (EBUSY);
+ pm = pe->pe_pmc;
+ mode = pe->pe_alloc.pm_mode;
+ BIT_COPY(PMC_ROWSET_SIZE, &pe->pe_cons.pc_allowed_rows, &allowed);
+ /* System mode binds to one CPU. Process mode can use any CPU. */
+ sys = PMC_IS_SYSTEM_MODE(mode);
+ idcpu = sys ? cpu : PMC_CPU_ANY;
+
+ if ((pe->pe_cons.pc_flags & PMC_SC_F_FIXED) != 0) {
+ adjri = pe->pe_cons.pc_fixed_row;
+ if (adjri < 0 || adjri >= PMC_ROWSET_SIZE ||
+ !BIT_ISSET(PMC_ROWSET_SIZE, adjri, &allowed))
+ return (EBUSY);
+ } else {
+ adjri = -1;
+ }
+
+ for (;;) {
+ if (adjri < 0) {
+ adjri = BIT_FFS(PMC_ROWSET_SIZE, &allowed) - 1;
+ if (adjri < 0)
+ return (EBUSY);
+ }
+ if (adjri >= pcd->pcd_num)
+ goto skip;
+ n = pcd->pcd_ri + adjri;
+ /* Used and evictable rows use the global row index. */
+ if (n < 0 || n >= PMC_ROWSET_SIZE ||
+ BIT_ISSET(PMC_ROWSET_SIZE, n, used_rows))
+ goto skip;
+ evictable = evictable_rows != NULL &&
+ BIT_ISSET(PMC_ROWSET_SIZE, n, evictable_rows);
+ if (p != NULL) {
+ if (!hwpmc_can_allocate_row(n, mode) && !evictable)
+ goto skip;
+ if (LIST_EMPTY(&pg->pg_targets)) {
+ if (!hwpmc_can_allocate_rowindex(p, n, idcpu) &&
+ !evictable)
+ goto skip;
+ } else {
+ LIST_FOREACH(pgt, &pg->pg_targets,
+ pgt_group_next) {
+ if (hwpmc_can_allocate_rowindex(
+ pgt->pgt_pp->pp_proc, n, idcpu) || evictable)
+ continue;
+ goto skip;
+ }
+ }
+ }
+ /* Check the system row occupancy. */
+ if (sys && p != NULL && !hwpmc_row_is_unallocated(cpu, n) &&
+ !evictable)
+ goto skip;
+ if (pmu_can_assign_pmc(pcd, adjri, pm, &pe->pe_alloc) != 0)
+ goto skip;
+ if (!dry_run &&
+ pcd->pcd_allocate_pmc(cpu, adjri, pm, &pe->pe_alloc) != 0)
+ goto skip;
+
+ BIT_SET(PMC_ROWSET_SIZE, n, used_rows);
+ if (dry_run)
+ return (0);
+ pm->pm_id = PMC_ID_MAKE_ID(idcpu, mode,
+ pe->pe_alloc.pm_class, n);
+ /* Mark system rows STANDALONE and process rows THREAD. */
+ if (sys)
+ hwpmc_mark_row_standalone(n);
+ else
+ hwpmc_mark_row_thread(n);
+ return (0);
+
+skip:
+ if ((pe->pe_cons.pc_flags & PMC_SC_F_FIXED) != 0)
+ return (EBUSY);
+ BIT_CLR(PMC_ROWSET_SIZE, adjri, &allowed);
+ adjri = -1;
+ }
+}
+
+/*
+ * Release all hardware rows assigned to a group.
+ */
+void
+pmu_unassign_group(pmu_group_t *pg, int cpu)
+{
+ pmu_event_t *pe;
+ struct pmc *pm;
+ struct pmc_classdep *pcd;
+ enum pmc_mode mode;
+ int adjri, n;
+ bool sys;
+
+ sys = (pg != NULL && pg->pg_system);
+
+ /* Set the CPU index to 0 for process mode. */
+ if (cpu < 0)
+ cpu = 0;
+
+ TAILQ_FOREACH(pe, &pg->pg_events, pe_sibling) {
+ pm = pe->pe_pmc;
+ if (PMC_ROW_IS_UNASSIGNED(pm))
+ continue;
+ n = PMC_TO_ROWINDEX(pm);
+ mode = PMC_TO_MODE(pm);
+ pcd = hwpmc_ri_to_classdep(n, &adjri);
+ if (pcd != NULL) {
+ /*
+ * Clear the configuration before you release the row.
+ * For process mode, unconfigure all CPUs.
+ */
+ if (sys)
+ (void)pcd->pcd_config_pmc(cpu, adjri, NULL);
+ else
+ hwpmc_unconfigure_row_all_cpus(pm, n);
+ (void)pcd->pcd_release_pmc(cpu, adjri, pm);
+ }
+ pm->pm_id = PMC_ID_MAKE_ID(PMC_CPU_ANY, mode,
+ pe->pe_alloc.pm_class, PMC_ROW_UNASSIGNED);
+ /* Clear the row disposition. */
+ if (sys)
+ hwpmc_unmark_row_standalone(n);
+ else
+ hwpmc_unmark_row_thread(n);
+ }
+ pg->pg_assigned = false;
+}
+
+/*
+ * Sort events by constraint weight, lowest first.
+ */
+static void
+pmu_sort_by_weight(pmu_group_t *pg, pmu_event_t **order, u_int n)
+{
+ pmu_event_t *pe, *cur;
+ u_int i, j;
+
+ i = 0;
+ TAILQ_FOREACH(pe, &pg->pg_events, pe_sibling) {
+ if (i >= n)
+ break;
+ order[i++] = pe;
+ }
+ for (i = 1; i < n; i++) {
+ cur = order[i];
+ j = i;
+ while (j > 0 &&
+ order[j - 1]->pe_cons.pc_weight > cur->pe_cons.pc_weight) {
+ order[j] = order[j - 1];
+ j--;
+ }
+ order[j] = cur;
+ }
+}
+
+static int
+pmu_group_probe(pmu_group_t *pg, struct proc *p, int cpu,
+ const struct pmc_rowset *evictable_rows)
+{
+ pmu_event_t *order[PMC_GROUP_MAX_MEMBERS];
+ struct pmc_rowset used_rows;
+ u_int i;
+ int error;
+
+ if (pg == NULL || pg->pg_nevents == 0)
+ return (EINVAL);
+ KASSERT(pg->pg_nevents <= PMC_GROUP_MAX_MEMBERS,
+ ("[pmu] probe: gid=%u nevents=%u", pg->pg_id, pg->pg_nevents));
+ pmu_sort_by_weight(pg, order, pg->pg_nevents);
+ BIT_ZERO(PMC_ROWSET_SIZE, &used_rows);
+ error = 0;
+ for (i = 0; i < pg->pg_nevents; i++) {
+ error = pmu_assign_one(pg, order[i], p, cpu, &used_rows, true,
+ evictable_rows);
+ if (error != 0)
+ break;
+ }
+ return (error == 0 ? 0 : ENOSPC);
+}
+
+int
+pmu_group_can_fit(pmu_group_t *pg)
+{
+ return (pmu_group_probe(pg, NULL, 0, NULL));
+}
+
+int
+pmu_group_can_place(pmu_group_t *pg, struct proc *p, int cpu)
+{
+ if (p == NULL)
+ return (EINVAL);
+ return (pmu_group_probe(pg, p, cpu, NULL));
+}
+
+/*
+ * Check if a group can fit once the evictable rows are free.
+ */
+int
+pmu_group_satisfiable(pmu_group_t *pg, struct proc *p, int cpu,
+ const struct pmc_rowset *evictable_rows)
+{
+ if (p == NULL)
+ return (EINVAL);
+ return (pmu_group_probe(pg, p, cpu, evictable_rows));
+}
+
+int
+pmu_assign_group(pmu_group_t *pg, struct proc *p, int cpu)
+{
+ pmu_event_t *order[PMC_GROUP_MAX_MEMBERS];
+ struct pmc_rowset used_rows;
+ u_int i;
+ int error;
+
+ if (pg == NULL || p == NULL)
+ return (EINVAL);
+ if (pg->pg_assigned)
+ return (0);
+
+ /* Validate the group configuration before assignment. */
+ error = pmu_validate_group(pg);
+ if (error != 0)
+ return (error);
+
+ KASSERT(pg->pg_nevents <= PMC_GROUP_MAX_MEMBERS,
+ ("[pmu] assign: gid=%u nevents=%u", pg->pg_id, pg->pg_nevents));
+
+ /* Set the CPU index to 0 for process mode. */
+ if (cpu < 0)
+ cpu = 0;
+
+ pmu_sort_by_weight(pg, order, pg->pg_nevents);
+
+ BIT_ZERO(PMC_ROWSET_SIZE, &used_rows);
+ error = 0;
+ for (i = 0; i < pg->pg_nevents; i++) {
+ error = pmu_assign_one(pg, order[i], p, cpu, &used_rows, false,
+ NULL);
+ if (error != 0)
+ break;
+ }
+
+ if (error != 0) {
+ pmu_unassign_group(pg, cpu);
+ return (error);
+ }
+
+ pg->pg_assigned = true;
+ return (0);
+}
+
+int
+pmu_validate_group(pmu_group_t *pg)
+{
+ pmc_sched_constraint_t cons;
+ pmu_event_t *pe;
+ enum pmc_mode m;
+ u_int nleaders;
+ int lcpu, rc;
+ bool sys;
+
+ if (pg == NULL || pg->pg_leader == NULL)
+ return (EINVAL);
+ if (pg->pg_nevents == 0)
+ return (EINVAL);
+ nleaders = 0;
+
+ /*
+ * Validate the group mode. Siblings must stay on the leader's side
+ * of the process/system split. Counting and sampling may mix within
+ * one side. A system group binds to one CPU.
+ */
+ sys = PMC_IS_SYSTEM_MODE(pg->pg_leader->pe_alloc.pm_mode);
+ lcpu = pg->pg_leader->pe_alloc.pm_cpu;
+
+ /*
+ * PMC_F_DESCENDANTS is leader-only. It governs the whole group. A
+ * system group is bound to a CPU and has no process target, so it
+ * cannot follow a fork.
+ */
+ if (sys && (pg->pg_leader->pe_alloc.pm_flags & PMC_F_DESCENDANTS) !=
+ 0) {
+ PMCDBG1(PMC, OPS, 1,
+ "validate: gid=%u PMC_F_DESCENDANTS on a system group",
+ pg->pg_id);
+ return (EINVAL);
+ }
+
+ TAILQ_FOREACH(pe, &pg->pg_events, pe_sibling) {
+ m = pe->pe_alloc.pm_mode;
+
+ if (pe->pe_is_leader) {
+ nleaders++;
+ if (pg->pg_leader != pe)
+ return (EINVAL);
+ } else if ((pe->pe_alloc.pm_flags &
+ (PMC_F_GROUP_MUX | PMC_F_DESCENDANTS)) != 0) {
+ /* Both flags are leader-only. */
+ return (EINVAL);
+ }
+ if (pe->pe_pmc == NULL)
+ return (EINVAL);
+ if (!PMC_ROW_IS_UNASSIGNED(pe->pe_pmc)) {
+ PMCDBG2(PMC, OPS, 1,
+ "validate: gid=%u pm_id=0x%jx already assigned",
+ pg->pg_id, (uintmax_t)pe->pe_pmc->pm_id);
+ return (EINVAL);
+ }
+ if ((pe->pe_alloc.pm_flags & PMC_F_GROUP_DEFER) == 0)
+ return (EINVAL);
+ if (PMC_IS_SYSTEM_MODE(m) != sys) {
+ PMCDBG1(PMC, OPS, 1,
+ "validate: gid=%u mixed system/virtual siblings",
+ pg->pg_id);
+ return (EINVAL);
+ }
+ if (sys) {
+ if (pe->pe_alloc.pm_cpu != lcpu) {
+ PMCDBG3(PMC, OPS, 1,
+ "validate: gid=%u system siblings span "
+ "cpus (%d != %d)", pg->pg_id,
+ pe->pe_alloc.pm_cpu, lcpu);
+ return (EINVAL);
+ }
+ } else if (!PMC_IS_VIRTUAL_MODE(m)) {
+ return (EINVAL);
+ }
+ rc = pmu_event_get_constraint(pe, &cons);
+ if (rc != 0) {
+ PMCDBG2(PMC, OPS, 1,
+ "validate: constraint err=%d class=%d",
+ rc, (int)pe->pe_alloc.pm_class);
+ return (EOPNOTSUPP);
+ }
+ if (BIT_EMPTY(PMC_ROWSET_SIZE, &cons.pc_allowed_rows))
+ return (EOPNOTSUPP);
+ }
+ if (nleaders != 1)
+ return (EINVAL);
+ return (0);
+}
diff --git a/sys/dev/hwpmc/hwpmc_pmu.h b/sys/dev/hwpmc/hwpmc_pmu.h
--- a/sys/dev/hwpmc/hwpmc_pmu.h
+++ b/sys/dev/hwpmc/hwpmc_pmu.h
@@ -10,6 +10,8 @@
#ifndef _DEV_HWPMC_PMU_H_
#define _DEV_HWPMC_PMU_H_
+#include <sys/_bitset.h>
+#include <sys/bitset.h>
#include <sys/mutex.h>
#include <sys/pmc.h>
#include <sys/queue.h>
@@ -28,16 +30,20 @@
PMC_FLAG_NOWAIT = 0x04, /* do not wait for mallocs */
};
+/* The PMC handle reserves PMC_ROW_UNASSIGNED for an unassigned row. */
+#define PMC_ROWSET_SIZE PMC_ROW_UNASSIGNED
+BITSET_DEFINE(pmc_rowset, PMC_ROWSET_SIZE);
+
/*
* Scheduling constraint from the class backend.
- * pc_allowed_rows is a bitmask of valid class row indices.
+ * pc_allowed_rows contains valid class row indices.
*/
#define PMC_SC_F_FIXED 0x0001 /* must use pc_fixed_row */
#define PMC_SC_F_SHARED 0x0004 /* tolerates sharing siblings */
struct pmc_sched_constraint {
- uint32_t pc_allowed_rows; /* bitmask of legal rows */
- uint8_t pc_weight; /* popcount(pc_allowed_rows) */
+ struct pmc_rowset pc_allowed_rows; /* legal class rows */
+ uint8_t pc_weight; /* number of allowed rows */
uint8_t pc_fixed_row; /* used iff PMC_SC_F_FIXED */
uint16_t pc_flags; /* PMC_SC_F_* */
};
@@ -207,7 +213,7 @@
int pmu_group_can_fit(pmu_group_t *pg);
int pmu_group_can_place(pmu_group_t *pg, struct proc *p, int cpu);
int pmu_group_satisfiable(pmu_group_t *pg, struct proc *p, int cpu,
- uint64_t evictable_rows);
+ const struct pmc_rowset *evictable_rows);
int pmu_validate_group(pmu_group_t *pg);
int pmu_event_get_constraint(pmu_event_t *pe,
pmc_sched_constraint_t *cons);
diff --git a/sys/dev/hwpmc/hwpmc_pmu.c b/sys/dev/hwpmc/hwpmc_pmu.c
--- a/sys/dev/hwpmc/hwpmc_pmu.c
+++ b/sys/dev/hwpmc/hwpmc_pmu.c
@@ -2132,27 +2132,27 @@
}
/*
- * Return the bitmask of rows held by assigned MUX groups.
+ * Find the rows held by assigned MUX groups.
*/
-static uint64_t
-pmu_list_evictable_rows(struct pmu_group_list *gl)
+static void
+pmu_list_evictable_rows(struct pmu_group_list *gl,
+ struct pmc_rowset *evictable)
{
pmu_event_t *pe;
pmu_group_t *pg;
- uint64_t evictable;
u_int n;
- evictable = 0;
+ BIT_ZERO(PMC_ROWSET_SIZE, evictable);
LIST_FOREACH(pg, gl, pg_proc_next) {
if (!pg->pg_assigned || !pg->pg_defer_ok)
continue;
TAILQ_FOREACH(pe, &pg->pg_events, pe_sibling) {
n = PMC_TO_ROWINDEX(pe->pe_pmc);
- if (n < 64)
- evictable |= 1ULL << n;
+ if (n < PMC_ROWSET_SIZE)
+ BIT_SET(PMC_ROWSET_SIZE, n, evictable);
}
}
- return (evictable);
+
}
/*
@@ -2183,9 +2183,9 @@
static void
pmu_pp_rotate_one(struct pmc_process *pp)
{
+ struct pmc_rowset evictable;
pmu_group_t *cursor, *pg, *victim, *vpg;
struct proc *p;
- uint64_t evictable;
u_int ngroups, seen, vseen;
int sin_err;
bool found_cursor, placed_any, satisfiable;
@@ -2210,14 +2210,14 @@
cursor = LIST_FIRST(&pp->pp_pmu_groups);
/* Do not rotate if no deferred group can run. */
- evictable = pmu_list_evictable_rows(&pp->pp_pmu_groups);
+ pmu_list_evictable_rows(&pp->pp_pmu_groups, &evictable);
satisfiable = false;
LIST_FOREACH(pg, &pp->pp_pmu_groups, pg_proc_next) {
if (!pg->pg_running || pg->pg_assigned || !pg->pg_defer_ok)
continue;
p = pmu_group_target_proc(pg);
if (p != NULL && pmu_group_satisfiable(pg, p, PMC_CPU_ANY,
- evictable) == 0) {
+ &evictable) == 0) {
satisfiable = true;
break;
}
@@ -2251,7 +2251,7 @@
goto next;
p = pmu_group_target_proc(pg);
if (p == NULL || pmu_group_satisfiable(pg, p, PMC_CPU_ANY,
- evictable) != 0)
+ &evictable) != 0)
goto next;
sin_err = pmu_pp_schedule_in(pp, pg);
while (sin_err == ENOSPC && !placed_any) {
@@ -2724,10 +2724,10 @@
static void
pmu_syscpu_rotate_one(int cpu)
{
+ struct pmc_rowset evictable;
struct pmu_syscpu *sc;
pmu_group_t *cursor, *pg, *victim, *vpg;
struct proc *owner;
- uint64_t evictable;
u_int ngroups, seen, vseen;
int sin_err;
bool found_cursor, placed_any, satisfiable;
@@ -2749,14 +2749,14 @@
if (!found_cursor)
cursor = LIST_FIRST(&sc->sc_groups);
- evictable = pmu_list_evictable_rows(&sc->sc_groups);
+ pmu_list_evictable_rows(&sc->sc_groups, &evictable);
satisfiable = false;
LIST_FOREACH(pg, &sc->sc_groups, pg_proc_next) {
if (!pg->pg_running || pg->pg_assigned || !pg->pg_defer_ok)
continue;
owner = pg->pg_owner != NULL ? pg->pg_owner->po_owner : NULL;
if (owner != NULL && pmu_group_satisfiable(pg, owner, cpu,
- evictable) == 0) {
+ &evictable) == 0) {
satisfiable = true;
break;
}
@@ -2789,7 +2789,7 @@
goto next;
owner = pg->pg_owner != NULL ? pg->pg_owner->po_owner : NULL;
if (owner == NULL || pmu_group_satisfiable(pg, owner, cpu,
- evictable) != 0)
+ &evictable) != 0)
goto next;
sin_err = pmu_sys_schedule_in(cpu, pg);
while (sin_err == ENOSPC && !placed_any) {

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 12, 9:43 PM (12 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41669473
Default Alt Text
D57632.1794519786.diff (17 KB)

Event Timeline