4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
35 * An abstract "collection" of processes. Multiple types of collections can
36 * exist, one of which is selected at run-time. Currently, the only one
37 * defined corresponds to project(4)s.
40 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
44 lcollection_t
*lfa_found
;
45 } lcollection_find_arg_t
;
47 extern void lcollection_update_project(lcollection_update_type_t
,
48 void(*)(char *, char *, int, uint64_t, int));
49 extern void lcollection_update_zone(lcollection_update_type_t
,
50 void(*)(char *, char *, int, uint64_t, int));
51 static void lcollection_update_notification_cb(char *, char *, int, uint64_t,
54 rcid_t(*rc_getidbypsinfo
)(psinfo_t
*);
55 uint64_t phys_total
= 0;
56 static lcollection_t
*lcollection_head
= NULL
;
59 lcollection_update(lcollection_update_type_t ut
)
61 lcollection_update_zone(ut
, lcollection_update_notification_cb
);
62 lcollection_update_project(ut
, lcollection_update_notification_cb
);
66 * Inserts a collection with the supplied identity, or updates the caps of an
67 * existing one. The return value will have these bits set, depending on the
68 * previous and new cap values. If no cap was displaced, and the requested cap
69 * is 0, no collection will be added, and the applicable *ZERO flags will be
77 lcollection_insert_update(rcid_t
*colidp
, uint64_t rss_cap
, char *name
,
85 *changes
|= LCST_CAP_ZERO
;
87 lcol
= lcollection_find(colidp
);
90 * If the specified collection is capped, add it to lcollection.
94 * If the cap has been zeroed and the collection doesn't exist,
95 * don't create the collection just to remvoe the cap later.
100 *changes
|= LCST_CAP_CHANGED
;
101 lcol
= malloc(sizeof (*lcol
));
103 debug("not enough memory to monitor %s %s",
104 (colidp
->rcid_type
== RCIDT_PROJECT
?
105 "project" : "zone"), name
);
108 (void) bzero(lcol
, sizeof (*lcol
));
110 lcol
->lcol_id
= *colidp
;
111 debug("added collection %s\n", name
);
112 lcol
->lcol_prev
= NULL
;
113 lcol
->lcol_next
= lcollection_head
;
114 lcol
->lcol_stat
.lcols_min_rss
= (uint64_t)-1;
115 if (lcollection_head
!= NULL
)
116 lcollection_head
->lcol_prev
= lcol
;
117 lcollection_head
= lcol
;
121 * Set/update the collection's name.
123 (void) strlcpy(lcol
->lcol_name
, name
, sizeof (lcol
->lcol_name
));
128 if (rss_cap
!= lcol
->lcol_rss_cap
) {
129 *changes
|= LCST_CAP_CHANGED
;
130 lcol
->lcol_rss_cap
= rss_cap
;
131 if (lcol
->lcol_rss_cap
== 0)
132 *changes
|= LCST_CAP_REMOVED
;
142 lcollection_update_notification_cb(char *col_type
, char *name
, int changes
,
143 uint64_t rss_cap
, int mark
)
146 * Assume the collection has been updated redundantly if its mark count
147 * exceeds 1, and that another notification is unnecessary.
152 if (changes
& LCST_CAP_ZERO
)
153 debug("%s %s: %s\n", col_type
, name
,
154 (changes
& LCST_CAP_REMOVED
) ? "cap removed" : "uncapped");
156 debug("%s %s: cap: %llukB\n", col_type
, name
,
157 (unsigned long long)rss_cap
);
161 * Function to walk list of collections and invoke the specified callback with
162 * the specified argument. Callbacks are allowed to change the linkage of the
163 * collection on which they act.
166 list_walk_collection(int (*cb
)(lcollection_t
*, void *), void *arg
)
171 lcol
= lcollection_head
;
172 while (lcol
!= NULL
) {
173 next
= lcol
->lcol_next
;
174 if (cb(lcol
, arg
) != 0)
181 * Returns a nonzero value if an lprocess_t is still a valid member of a given
185 lcollection_member(lcollection_t
*lcol
, lprocess_t
*lpc
)
187 lprocess_t
*cur
= lcol
->lcol_lprocess
;
198 lcollection_find_cb(lcollection_t
*lcol
, void *arg
)
200 rcid_t
*colidp
= ((lcollection_find_arg_t
*)arg
)->lfa_colidp
;
202 if (lcol
->lcol_id
.rcid_type
== colidp
->rcid_type
&&
203 lcol
->lcol_id
.rcid_val
== colidp
->rcid_val
) {
204 ((lcollection_find_arg_t
*)arg
)->lfa_found
= lcol
;
212 lcollection_find(rcid_t
*colidp
)
214 lcollection_find_arg_t lfa
;
216 lfa
.lfa_colidp
= colidp
;
217 lfa
.lfa_found
= NULL
;
218 list_walk_collection(lcollection_find_cb
, &lfa
);
220 return (lfa
.lfa_found
);
224 * Unlinks a collection from lcollection.
227 lcollection_free(lcollection_t
*lcol
)
232 lpc
= lcol
->lcol_lprocess
;
233 while (lpc
!= NULL
) {
234 next
= lpc
->lpc_next
;
235 if (lpc
->lpc_collection
== lcol
)
241 * Unlink the collection.
243 if (lcol
->lcol_prev
!= NULL
)
244 lcol
->lcol_prev
->lcol_next
= lcol
->lcol_next
;
245 if (lcol
->lcol_next
!= NULL
)
246 lcol
->lcol_next
->lcol_prev
= lcol
->lcol_prev
;
247 if (lcollection_head
== lcol
)
248 lcollection_head
= lcol
->lcol_next
;
249 lcol
->lcol_next
= lcol
->lcol_prev
= NULL
;