build: remove map.noexstk and map.noexdata (now default)
[unleashed.git] / usr / src / lib / liblgrp / common / lgrp.c
blob4a6f07a93913cd1528789f8ecad3ec6d6a21ad15
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
31 * lgroup interface
33 #include <errno.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <strings.h>
37 #include <unistd.h>
38 #include <sys/bitmap.h>
39 #include <sys/pset.h>
40 #include <sys/types.h>
42 #include <sys/lgrp_user.h>
46 * Fast trap for getting home lgroup of current thread
48 extern lgrp_id_t _lgrp_home_fast(void);
51 * lgroup system call
53 extern int _lgrpsys(int subcode, long arg, void *ap);
55 static int lgrp_cpus_hier(lgrp_snapshot_header_t *snap, lgrp_id_t lgrp,
56 processorid_t **cpuids, uint_t *count);
60 * Get generation ID of lgroup hierarchy given view
61 * which changes whenever the hierarchy changes (eg. DR or pset contents
62 * change for caller's view)
64 static lgrp_gen_t
65 lgrp_generation(lgrp_view_t view)
67 return (_lgrpsys(LGRP_SYS_GENERATION, view, NULL));
72 * Get supported revision number of lgroup interface
74 int
75 lgrp_version(int version)
77 return (_lgrpsys(LGRP_SYS_VERSION, version, NULL));
82 * Get affinity for given lgroup
84 lgrp_affinity_t
85 lgrp_affinity_get(idtype_t idtype, id_t id, lgrp_id_t lgrp)
87 lgrp_affinity_args_t args;
89 args.idtype = idtype;
90 args.id = id;
91 args.lgrp = lgrp;
92 return (_lgrpsys(LGRP_SYS_AFFINITY_GET, 0, (void *)&args));
97 * Set affinity for given lgroup
99 int
100 lgrp_affinity_set(idtype_t idtype, id_t id, lgrp_id_t lgrp,
101 lgrp_affinity_t aff)
103 lgrp_affinity_args_t args;
105 args.idtype = idtype;
106 args.id = id;
107 args.lgrp = lgrp;
108 args.aff = aff;
109 return (_lgrpsys(LGRP_SYS_AFFINITY_SET, 0, (void *)&args));
114 * Get home lgroup for given process or thread
116 lgrp_id_t
117 lgrp_home(idtype_t idtype, id_t id)
120 * Use fast trap to get home lgroup of current thread or process
121 * Otherwise, use system call for other process or thread
123 if (id == P_MYID && (idtype == P_LWPID || idtype == P_PID))
124 return (_lgrp_home_fast());
125 else
126 return (_lgrpsys(LGRP_SYS_HOME, idtype, (void *)(intptr_t)id));
131 * Get a snapshot of the lgroup hierarchy
133 static int
134 lgrp_snapshot(void *buf, size_t bufsize)
136 return (_lgrpsys(LGRP_SYS_SNAPSHOT, bufsize, buf));
141 * Find any orphan lgroups without parents and make them be children of
142 * root lgroup
144 static int
145 parent_orphans(lgrp_snapshot_header_t *snap)
147 int i;
148 lgrp_info_t *lgrp_info;
149 int nlgrpsmax;
150 int orphan;
151 lgrp_info_t *root;
152 ulong_t *parents;
154 if (snap == NULL || snap->ss_info == NULL ||
155 snap->ss_parents == NULL || snap->ss_root < 0 ||
156 snap->ss_root >= snap->ss_nlgrps_max)
157 return (-1);
159 nlgrpsmax = snap->ss_nlgrps_max;
160 root = &snap->ss_info[snap->ss_root];
162 for (i = 0; i < nlgrpsmax; i++) {
163 int j;
166 * Skip root lgroup
168 if (i == snap->ss_root)
169 continue;
171 lgrp_info = &snap->ss_info[i];
172 if (lgrp_info == NULL || lgrp_info->info_lgrpid == LGRP_NONE)
173 continue;
176 * Make sure parents bitmap is setup
178 if (lgrp_info->info_parents == NULL)
179 lgrp_info->info_parents =
180 (ulong_t *)((uintptr_t)snap->ss_parents +
181 (i * BT_SIZEOFMAP(nlgrpsmax)));
184 * Look for orphans (lgroups with no parents)
186 orphan = 1;
187 parents = lgrp_info->info_parents;
188 for (j = 0; j < BT_BITOUL(nlgrpsmax); j++)
189 if (parents[j] != 0) {
190 orphan = 0;
191 break;
195 * Make root be parent of any orphans
197 if (orphan) {
198 BT_SET(parents, root->info_lgrpid);
199 if (root->info_children) {
200 BT_SET(root->info_children, i);
205 return (0);
210 * Remove given lgroup from parent lgroup(s)
212 static void
213 prune_child(lgrp_snapshot_header_t *snap, lgrp_id_t lgrp)
215 int i;
216 lgrp_info_t *lgrp_info;
217 ulong_t *parents;
219 if (snap == NULL || lgrp < 0 || lgrp > snap->ss_nlgrps_max)
220 return;
222 lgrp_info = &snap->ss_info[lgrp];
224 parents = lgrp_info->info_parents;
225 if (parents == NULL)
226 return;
229 * Update children of parents not to include given lgroup
231 for (i = 0; i < snap->ss_nlgrps_max; i++) {
232 if (BT_TEST(parents, i)) {
233 lgrp_info = &snap->ss_info[i];
234 BT_CLEAR(lgrp_info->info_children, lgrp);
240 * Prune any CPUs not in given array from specified lgroup
242 static void
243 prune_cpus(lgrp_snapshot_header_t *snap, lgrp_id_t lgrp, processorid_t *cpus,
244 int ncpus)
246 int count;
247 int i;
248 int j;
249 int k;
250 lgrp_info_t *lgrp_info;
251 uint_t lgrp_ncpus;
252 processorid_t *lgrp_cpus;
254 if (snap == NULL || lgrp < 0 || lgrp > snap->ss_nlgrps_max)
255 return;
257 lgrp_info = &snap->ss_info[lgrp];
260 * No CPUs to remove
262 if (ncpus == 0 || lgrp_info->info_ncpus == 0)
263 return;
266 * Remove all CPUs from lgroup
268 if (cpus == NULL && ncpus == -1) {
269 lgrp_info->info_ncpus = 0;
270 return;
274 * Remove any CPUs from lgroup not in given list of CPUs
276 lgrp_cpus = lgrp_info->info_cpuids;
277 lgrp_ncpus = lgrp_info->info_ncpus;
278 i = 0;
279 for (count = 0; count < lgrp_ncpus; count++) {
281 * Look for CPU in list
283 for (j = 0; j < ncpus; j++)
284 if (lgrp_cpus[i] == cpus[j])
285 break;
288 * Go to next CPU if found this one in list
290 if (j < ncpus) {
291 i++;
292 continue;
296 * Remove this CPU and shift others into its place
297 * and decrement number of CPUs
299 for (k = i + 1; k < lgrp_info->info_ncpus; k++)
300 lgrp_cpus[k - 1] = lgrp_cpus[k];
301 lgrp_cpus[k - 1] = -1;
302 lgrp_info->info_ncpus--;
308 * Prune lgroup hierarchy for caller's view
310 static int
311 prune_tree(lgrp_snapshot_header_t *snap)
313 processorid_t *cpus;
314 int i;
315 lgrp_info_t *lgrp_info;
316 lgrp_mem_size_t nbytes;
317 uint_t ncpus;
318 int nlgrps_max;
320 if (snap == NULL || snap->ss_info == NULL)
321 return (-1);
324 * Get CPUs in caller's pset
326 if (pset_info(PS_MYID, NULL, &ncpus, NULL) == -1)
327 return (-1);
329 cpus = NULL;
330 if (ncpus > 0) {
331 cpus = malloc(ncpus * sizeof (processorid_t));
332 if (pset_info(PS_MYID, NULL, &ncpus, cpus) == -1) {
333 free(cpus);
334 return (-1);
339 * Remove any CPUs not in caller's pset from lgroup hierarchy
341 nlgrps_max = snap->ss_nlgrps_max;
342 for (i = 0; i < nlgrps_max; i++) {
343 lgrp_info = &snap->ss_info[i];
344 if (BT_TEST(snap->ss_lgrpset, i))
345 prune_cpus(snap, i, cpus, ncpus);
346 else if (lgrp_info->info_lgrpid != LGRP_NONE)
347 prune_cpus(snap, i, NULL, -1);
350 if (ncpus > 0)
351 free(cpus);
354 * Change lgroup bitmask from just reflecting lgroups overlapping
355 * caller's pset to all lgroups available to caller, starting by
356 * filling in all lgroups and then removing any empty ones below
358 for (i = 0; i < nlgrps_max; i++) {
359 lgrp_info = &snap->ss_info[i];
360 if (lgrp_info->info_lgrpid == LGRP_NONE)
361 continue;
363 BT_SET(snap->ss_lgrpset, i);
367 * Remove empty lgroups from lgroup hierarchy, removing it from its
368 * parents and decrementing nlgrps
370 for (i = 0; i < nlgrps_max; i++) {
371 lgrp_info = &snap->ss_info[i];
372 if (lgrp_info->info_lgrpid == LGRP_NONE)
373 continue;
375 ncpus = lgrp_cpus_hier(snap, i, NULL, NULL);
376 nbytes = lgrp_mem_size((lgrp_cookie_t)snap, i,
377 LGRP_MEM_SZ_INSTALLED, LGRP_CONTENT_HIERARCHY);
378 if (ncpus == 0 && nbytes == 0) {
379 BT_CLEAR(snap->ss_lgrpset, i);
380 prune_child(snap, i);
381 snap->ss_nlgrps--;
385 return (0);
390 * Initialize lgroup interface
392 lgrp_cookie_t
393 lgrp_init(lgrp_view_t view)
395 ssize_t bufsize;
396 uint_t gen;
397 int i;
398 lgrp_snapshot_header_t *snap;
401 * Check for legal view
403 if (view != LGRP_VIEW_OS && view != LGRP_VIEW_CALLER) {
404 errno = EINVAL;
405 return (LGRP_COOKIE_NONE);
409 * Try to take a consistent snapshot of lgroup hierarchy
411 snap = NULL;
412 while (snap == NULL) {
414 * Get lgroup generation number before taking snapshot
416 gen = lgrp_generation(view);
419 * Get size of buffer needed for snapshot
421 bufsize = lgrp_snapshot(NULL, 0);
422 if (bufsize <= 0) {
423 if (errno == ENOMEM)
424 return (LGRP_COOKIE_NONE);
426 snap = NULL;
427 continue;
431 * Allocate buffer
433 snap = malloc(bufsize);
434 if (snap == NULL)
435 return (LGRP_COOKIE_NONE);
436 bzero(snap, bufsize);
439 * Take snapshot of lgroup hierarchy
441 bufsize = lgrp_snapshot(snap, bufsize);
442 if (bufsize <= 0) {
443 free(snap);
444 if (errno == ENOMEM)
445 return (LGRP_COOKIE_NONE);
447 snap = NULL;
448 continue;
452 * See whether lgroup generation number changed
454 if (gen == lgrp_generation(view))
455 break;
457 free(snap);
458 snap = NULL;
462 * Remember generation number and view of this snapshot
464 snap->ss_gen = gen;
465 snap->ss_view = view;
468 * Keep caller's pset ID for caller's view
470 snap->ss_pset = 0;
471 if (view == LGRP_VIEW_CALLER) {
472 psetid_t pset;
474 if (pset_bind(PS_QUERY, P_LWPID, P_MYID, &pset) == -1)
475 return ((uintptr_t)-1);
477 snap->ss_pset = pset;
481 * Find any orphan lgroups without parents and make them be children
482 * of the root lgroup
484 if (snap->ss_levels > 1)
485 (void) parent_orphans(snap);
488 * Prune snapshot of lgroup hierarchy for caller's view
490 if (view == LGRP_VIEW_CALLER)
491 (void) prune_tree(snap);
492 else {
494 * Change lgroup bitmask from just reflecting lgroups
495 * overlapping caller's pset to all lgroups available
497 for (i = 0; i < snap->ss_nlgrps_max; i++) {
498 lgrp_info_t *lgrp_info;
500 lgrp_info = &snap->ss_info[i];
501 if (lgrp_info->info_lgrpid == LGRP_NONE)
502 continue;
504 BT_SET(snap->ss_lgrpset, i);
508 return ((uintptr_t)snap);
513 * Return whether given cookie is out-of-date (stale) or not
516 lgrp_cookie_stale(lgrp_cookie_t cookie)
518 psetid_t pset;
519 lgrp_snapshot_header_t *snap;
522 * Check for bad cookie
524 snap = (lgrp_snapshot_header_t *)cookie;
525 if (snap == NULL || snap->ss_magic != cookie) {
526 errno = EINVAL;
527 return (-1);
531 * Check generation number which changes when lgroup hierarchy changes
532 * or pset contents change for caller's view
534 if (snap->ss_gen != lgrp_generation(snap->ss_view))
535 return (1);
538 * See whether pset binding has changed for caller's view
540 if (snap->ss_view == LGRP_VIEW_CALLER) {
541 if (pset_bind(PS_QUERY, P_LWPID, P_MYID, &pset) == -1)
542 return (-1);
543 if (snap->ss_pset != pset)
544 return (1);
547 return (0); /* cookie isn't stale */
552 * Get view of lgroup hierarchy from snapshot represented by given cookie
554 lgrp_view_t
555 lgrp_view(lgrp_cookie_t cookie)
557 lgrp_snapshot_header_t *snap;
559 snap = (lgrp_snapshot_header_t *)cookie;
560 if (snap == NULL || snap->ss_magic != cookie) {
561 errno = EINVAL;
562 return (-1);
565 return (snap->ss_view);
570 * Get number of lgroups
573 lgrp_nlgrps(lgrp_cookie_t cookie)
575 lgrp_snapshot_header_t *snap;
577 snap = (lgrp_snapshot_header_t *)cookie;
579 if (snap == NULL || snap->ss_magic != cookie) {
580 errno = EINVAL;
581 return (-1);
584 return (snap->ss_nlgrps);
589 * Return root lgroup ID
591 lgrp_id_t
592 lgrp_root(lgrp_cookie_t cookie)
594 lgrp_snapshot_header_t *snap;
596 snap = (lgrp_snapshot_header_t *)cookie;
598 if (snap == NULL || snap->ss_magic != cookie) {
599 errno = EINVAL;
600 return (-1);
603 return (snap->ss_root);
608 * Get parent lgroups of given lgroup
611 lgrp_parents(lgrp_cookie_t cookie, lgrp_id_t lgrp, lgrp_id_t *parents,
612 uint_t count)
614 int i;
615 ulong_t *lgrp_parents;
616 lgrp_snapshot_header_t *snap;
617 int nlgrps_max;
618 int nparents;
620 snap = (lgrp_snapshot_header_t *)cookie;
623 * Check for valid arguments
625 if (snap == NULL || snap->ss_magic != cookie ||
626 lgrp < 0 || lgrp == LGRP_NONE) {
627 errno = EINVAL;
628 return (-1);
632 * See whether given lgroup exists
634 nlgrps_max = snap->ss_nlgrps_max;
635 if (lgrp >= nlgrps_max || !BT_TEST(snap->ss_lgrpset, lgrp)) {
636 errno = ESRCH;
637 return (-1);
641 * No parents, since given lgroup is root lgroup or
642 * only one level in lgroup hierarchy (ie. SMP)
644 if (lgrp == snap->ss_root || snap->ss_levels == 1) {
645 if (parents == NULL || count < 1)
646 return (0);
647 return (0);
651 * Make sure that parents exist
653 if (snap->ss_parents == NULL) {
654 errno = ESRCH;
655 return (-1);
659 * Given lgroup should have a parent
661 lgrp_parents = &snap->ss_parents[lgrp * BT_BITOUL(nlgrps_max)];
662 if (lgrp_parents == NULL) {
663 errno = ESRCH;
664 return (-1);
668 * Check lgroup parents bitmask, fill in parents array, and return
669 * number of parents
671 nparents = 0;
672 for (i = 0; i < nlgrps_max; i++) {
673 if (BT_TEST(lgrp_parents, i)) {
674 if (parents != NULL && nparents < count) {
675 parents[nparents] = i;
677 nparents++;
680 return (nparents);
685 * Get children lgroups of given lgroup
688 lgrp_children(lgrp_cookie_t cookie, lgrp_id_t lgrp, lgrp_id_t *children,
689 uint_t count)
691 int i;
692 ulong_t *lgrp_children;
693 int nlgrps_max;
694 int nchildren;
695 lgrp_snapshot_header_t *snap;
697 snap = (lgrp_snapshot_header_t *)cookie;
700 * Check for valid arguments
702 if (snap == NULL || snap->ss_magic != cookie ||
703 lgrp < 0 || lgrp == LGRP_NONE) {
704 errno = EINVAL;
705 return (-1);
709 * See whether given lgroup exists
711 nlgrps_max = snap->ss_nlgrps_max;
712 if (lgrp >= nlgrps_max || !BT_TEST(snap->ss_lgrpset, lgrp)) {
713 errno = ESRCH;
714 return (-1);
718 * No children, since only one level in lgroup hierarchy (ie. SMP)
720 if (snap->ss_levels == 1) {
721 if (children == NULL || count < 1)
722 return (0);
723 return (0);
727 * Make sure that children exist
729 if (snap->ss_children == NULL) {
730 errno = ESRCH;
731 return (-1);
735 * Given lgroup may not have any children
737 lgrp_children = &snap->ss_children[lgrp * BT_BITOUL(nlgrps_max)];
739 if (lgrp_children == NULL)
740 return (0);
743 * Check lgroup children bitmask, fill in children array, and return
744 * number of children
746 nchildren = 0;
747 for (i = 0; i < nlgrps_max; i++) {
748 if (BT_TEST(lgrp_children, i)) {
749 if (children != NULL && nchildren < count)
750 children[nchildren] = i;
751 nchildren++;
754 return (nchildren);
759 * Get all CPUs within given lgroup (hierarchy)
761 static int
762 lgrp_cpus_hier(lgrp_snapshot_header_t *snap, lgrp_id_t lgrp,
763 processorid_t **cpuids, uint_t *count)
765 processorid_t *cpus;
766 int i;
767 int j;
768 lgrp_info_t *lgrp_info;
769 int ncpus;
770 int nlgrps_max;
771 ulong_t *rset;
772 int total;
775 * Get lgroup info
777 lgrp_info = &snap->ss_info[lgrp];
779 if (lgrp_info == NULL) {
780 errno = ESRCH;
781 return (-1);
785 * Check whether given lgroup contains any lgroups with CPU resources
787 if (lgrp_info->info_rset == NULL)
788 return (0);
790 nlgrps_max = snap->ss_nlgrps_max;
791 rset = &lgrp_info->info_rset[LGRP_RSRC_CPU * BT_BITOUL(nlgrps_max)];
794 * Get all CPUs within this lgroup
796 total = 0;
797 for (i = 0; i < nlgrps_max; i++) {
798 if (!BT_TEST(rset, i))
799 continue;
801 lgrp_info = &snap->ss_info[i];
804 * Get all CPUs within lgroup
806 cpus = lgrp_info->info_cpuids;
807 ncpus = lgrp_info->info_ncpus;
808 total += ncpus;
811 * Copy as many CPU IDs into array that will fit
812 * and decrement count and increment array pointer
813 * as we go
815 if (cpuids && *cpuids && count) {
816 for (j = 0; j < ncpus; j++) {
817 if (*count) {
818 **cpuids = cpus[j];
819 (*cpuids)++;
820 (*count)--;
826 return (total);
831 * Get CPUs in given lgroup
834 lgrp_cpus(lgrp_cookie_t cookie, lgrp_id_t lgrp, processorid_t *cpuids,
835 uint_t count, lgrp_content_t content)
837 int i;
838 processorid_t *cpus;
839 lgrp_info_t *lgrp_info;
840 int ncpus;
841 lgrp_snapshot_header_t *snap;
843 snap = (lgrp_snapshot_header_t *)cookie;
846 * Check for valid arguments
848 if (snap == NULL || snap->ss_magic != cookie ||
849 lgrp < 0 || lgrp == LGRP_NONE ||
850 (content != LGRP_CONTENT_DIRECT &&
851 content != LGRP_CONTENT_HIERARCHY)) {
852 errno = EINVAL;
853 return (-1);
857 * See whether given lgroup exists
859 if (lgrp >= snap->ss_nlgrps_max || snap->ss_info == NULL ||
860 !BT_TEST(snap->ss_lgrpset, lgrp)) {
861 errno = ESRCH;
862 return (-1);
866 * Get lgroup info
868 lgrp_info = &snap->ss_info[lgrp];
871 * Get contents of lgroup
873 switch (content) {
874 case LGRP_CONTENT_DIRECT:
876 * Get CPUs contained directly within given lgroup
878 cpus = lgrp_info->info_cpuids;
879 ncpus = lgrp_info->info_ncpus;
882 * No array to copy CPU IDs into,
883 * so just return number of CPUs.
885 if (cpuids == NULL)
886 return (ncpus);
889 * Copy as many CPU IDs into array that will fit
891 for (i = 0; i < ncpus; i++)
892 if (i < count)
893 cpuids[i] = cpus[i];
895 return (ncpus);
897 case LGRP_CONTENT_ALL:
898 return (lgrp_cpus_hier(snap, lgrp, &cpuids, &count));
900 default:
901 errno = EINVAL;
902 return (-1);
908 * Return physical memory size in pages for given lgroup
910 lgrp_mem_size_t
911 lgrp_mem_size(lgrp_cookie_t cookie, lgrp_id_t lgrp, lgrp_mem_size_flag_t type,
912 lgrp_content_t content)
914 int i;
915 lgrp_info_t *lgrp_info;
916 int nlgrps_max;
917 int pgsz;
918 ulong_t *rset;
919 lgrp_mem_size_t size;
920 lgrp_snapshot_header_t *snap;
922 snap = (lgrp_snapshot_header_t *)cookie;
925 * Check for valid arguments
927 if (snap == NULL || snap->ss_magic != cookie ||
928 lgrp < 0 || lgrp == LGRP_NONE) {
929 errno = EINVAL;
930 return (-1);
934 * See whether given lgroup exists
936 nlgrps_max = snap->ss_nlgrps_max;
937 if (lgrp >= nlgrps_max || snap->ss_info == NULL ||
938 !BT_TEST(snap->ss_lgrpset, lgrp)) {
939 errno = ESRCH;
940 return (-1);
943 pgsz = getpagesize();
946 * Get lgroup info
948 lgrp_info = &snap->ss_info[lgrp];
950 switch (content) {
951 case LGRP_CONTENT_DIRECT:
953 * Get memory contained directly in this lgroup
955 switch (type) {
956 case LGRP_MEM_SZ_FREE:
957 size = (lgrp_mem_size_t)pgsz *
958 lgrp_info->info_mem_free;
959 return (size);
960 case LGRP_MEM_SZ_INSTALLED:
961 size = (lgrp_mem_size_t)pgsz *
962 lgrp_info->info_mem_install;
963 return (size);
964 default:
965 errno = EINVAL;
966 return (-1);
969 case LGRP_CONTENT_ALL:
971 * Get memory contained within this lgroup (and its children)
974 * Check whether given lgroup contains any lgroups with CPU
975 * resources
977 if (lgrp_info->info_rset == NULL)
978 return (0);
980 rset = &lgrp_info->info_rset[LGRP_RSRC_MEM *
981 BT_BITOUL(nlgrps_max)];
984 * Add up memory in lgroup resources
986 size = 0;
987 for (i = 0; i < nlgrps_max; i++) {
988 if (!BT_TEST(rset, i))
989 continue;
991 lgrp_info = &snap->ss_info[i];
992 switch (type) {
993 case LGRP_MEM_SZ_FREE:
994 size += (lgrp_mem_size_t)pgsz *
995 lgrp_info->info_mem_free;
996 break;
997 case LGRP_MEM_SZ_INSTALLED:
998 size += (lgrp_mem_size_t)pgsz *
999 lgrp_info->info_mem_install;
1000 break;
1001 default:
1002 errno = EINVAL;
1003 return (-1);
1008 return (size);
1010 default:
1011 errno = EINVAL;
1012 return (-1);
1018 * Get resources for a particuliar lgroup
1021 lgrp_resources(lgrp_cookie_t cookie, lgrp_id_t lgrp, lgrp_id_t *lgrps,
1022 uint_t count, lgrp_rsrc_t type)
1024 int i;
1025 lgrp_info_t *lgrp_info;
1026 int nlgrps;
1027 int nlgrps_max;
1028 ulong_t *rset;
1029 lgrp_snapshot_header_t *snap;
1031 snap = (lgrp_snapshot_header_t *)cookie;
1034 * Check for valid arguments
1036 if (snap == NULL || snap->ss_magic != cookie ||
1037 lgrp < 0 || lgrp == LGRP_NONE ||
1038 (type != LGRP_RSRC_CPU && type != LGRP_RSRC_MEM)) {
1039 errno = EINVAL;
1040 return (-1);
1044 * See whether given lgroup exists
1046 nlgrps_max = snap->ss_nlgrps_max;
1047 if (lgrp >= nlgrps_max || snap->ss_info == NULL ||
1048 !BT_TEST(snap->ss_lgrpset, lgrp)) {
1049 errno = ESRCH;
1050 return (-1);
1054 * Get lgroup info
1056 lgrp_info = &snap->ss_info[lgrp];
1059 * Count number lgroups contained within this lgroup and
1060 * copy as many lgroup IDs into array that will fit
1062 rset = &lgrp_info->info_rset[type * BT_BITOUL(nlgrps_max)];
1063 nlgrps = 0;
1064 for (i = 0; i < snap->ss_nlgrps_max; i++)
1065 if (BT_TEST(rset, i)) {
1066 if (lgrps != NULL && nlgrps < count)
1067 lgrps[nlgrps] = i;
1068 nlgrps++;
1071 return (nlgrps);
1076 * Finish using lgroup interface
1079 lgrp_fini(lgrp_cookie_t cookie)
1081 lgrp_snapshot_header_t *snap;
1083 snap = (lgrp_snapshot_header_t *)cookie;
1085 if (snap == NULL || snap->ss_magic != cookie) {
1086 errno = EINVAL;
1087 return (-1);
1090 bzero(snap, snap->ss_size);
1091 free(snap);
1092 snap = NULL;
1094 return (0);
1099 * Return latency between "from" and "to" lgroups
1101 * This latency number can only be used for relative comparison
1102 * between lgroups on the running system, cannot be used across platforms,
1103 * and may not reflect the actual latency. It is platform and implementation
1104 * specific, so platform gets to decide its value. It would be nice if the
1105 * number was at least proportional to make comparisons more meaningful though.
1108 lgrp_latency(lgrp_id_t from, lgrp_id_t to)
1110 lgrp_cookie_t cookie;
1111 int latency;
1113 cookie = lgrp_init(LGRP_VIEW_OS);
1114 latency = lgrp_latency_cookie(cookie, from, to, LGRP_LAT_CPU_TO_MEM);
1115 (void) lgrp_fini(cookie);
1117 return (latency);
1122 * Return latency between "from" and "to" lgroups
1124 * This latency number can only be used for relative comparison
1125 * between lgroups on the running system, cannot be used across platforms,
1126 * and may not reflect the actual latency. It is platform and implementation
1127 * specific, so platform gets to decide its value. It would be nice if the
1128 * number was at least proportional to make comparisons more meaningful though.
1131 lgrp_latency_cookie(lgrp_cookie_t cookie, lgrp_id_t from, lgrp_id_t to,
1132 lgrp_lat_between_t between)
1134 lgrp_info_t *lgrp_info;
1135 lgrp_mem_size_t nbytes;
1136 int ncpus;
1137 int nlgrps_max;
1138 lgrp_snapshot_header_t *snap;
1140 snap = (lgrp_snapshot_header_t *)cookie;
1143 * Check for valid snapshot, lgroup, and between flag
1145 if (snap == NULL || snap->ss_magic != cookie || from < 0 || to < 0 ||
1146 between != LGRP_LAT_CPU_TO_MEM) {
1147 errno = EINVAL;
1148 return (-1);
1152 * Check whether lgroups exist
1154 nlgrps_max = snap->ss_nlgrps_max;
1155 if (from >= nlgrps_max || to >= nlgrps_max) {
1156 errno = ESRCH;
1157 return (-1);
1161 * Check whether "from" lgroup has any CPUs
1163 ncpus = lgrp_cpus(cookie, from, NULL, 0, LGRP_CONTENT_HIERARCHY);
1164 if (ncpus <= 0) {
1165 if (ncpus == 0)
1166 errno = ESRCH;
1167 return (-1);
1171 * Check whether "to" lgroup has any memory
1173 nbytes = lgrp_mem_size(cookie, to, LGRP_MEM_SZ_INSTALLED,
1174 LGRP_CONTENT_HIERARCHY);
1175 if (nbytes <= 0) {
1176 if (nbytes == 0)
1177 errno = ESRCH;
1178 return (-1);
1181 if (from == to) {
1182 lgrp_info = &snap->ss_info[from];
1183 return (lgrp_info->info_latency);
1186 return (snap->ss_latencies[from][to]);