dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / rcap / rcapd / rcapd_collection.c
blobfdaf8dbfe0a8c5a8e916496812740aac92c45457
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <strings.h>
31 #include "rcapd.h"
32 #include "utils.h"
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))
42 typedef struct {
43 rcid_t *lfa_colidp;
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,
52 int);
54 rcid_t(*rc_getidbypsinfo)(psinfo_t *);
55 uint64_t phys_total = 0;
56 static lcollection_t *lcollection_head = NULL;
58 void
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
70 * set.
72 * LCST_CAP_CHANGED
73 * LCST_CAP_REMOVED
74 * LCSS_CAP_ZERO
76 lcollection_t *
77 lcollection_insert_update(rcid_t *colidp, uint64_t rss_cap, char *name,
78 int *changes)
80 lcollection_t *lcol;
82 *changes = 0;
84 if (rss_cap == 0)
85 *changes |= LCST_CAP_ZERO;
87 lcol = lcollection_find(colidp);
90 * If the specified collection is capped, add it to lcollection.
92 if (lcol == NULL) {
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.
97 if (rss_cap == 0)
98 return (NULL);
100 *changes |= LCST_CAP_CHANGED;
101 lcol = malloc(sizeof (*lcol));
102 if (lcol == NULL) {
103 debug("not enough memory to monitor %s %s",
104 (colidp->rcid_type == RCIDT_PROJECT ?
105 "project" : "zone"), name);
106 return (NULL);
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));
126 * Set cap flags.
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;
135 if (rss_cap > 0)
136 lcol->lcol_mark++;
138 return (lcol);
141 static void
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.
149 if (mark > 1)
150 return;
152 if (changes & LCST_CAP_ZERO)
153 debug("%s %s: %s\n", col_type, name,
154 (changes & LCST_CAP_REMOVED) ? "cap removed" : "uncapped");
155 else
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.
165 void
166 list_walk_collection(int (*cb)(lcollection_t *, void *), void *arg)
168 lcollection_t *lcol;
169 lcollection_t *next;
171 lcol = lcollection_head;
172 while (lcol != NULL) {
173 next = lcol->lcol_next;
174 if (cb(lcol, arg) != 0)
175 return;
176 lcol = next;
181 * Returns a nonzero value if an lprocess_t is still a valid member of a given
182 * collection.
185 lcollection_member(lcollection_t *lcol, lprocess_t *lpc)
187 lprocess_t *cur = lcol->lcol_lprocess;
189 while (cur != NULL)
190 if (cur == lpc)
191 return (1);
192 else
193 cur = cur->lpc_next;
194 return (0);
197 static int
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;
205 return (1);
208 return (0);
211 lcollection_t *
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.
226 void
227 lcollection_free(lcollection_t *lcol)
229 lprocess_t *lpc;
230 lprocess_t *next;
232 lpc = lcol->lcol_lprocess;
233 while (lpc != NULL) {
234 next = lpc->lpc_next;
235 if (lpc->lpc_collection == lcol)
236 lprocess_free(lpc);
237 lpc = next;
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;
251 free(lcol);