dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fm / fmd / common / fmd_serd.c
blob166b565666e137f501e3b6afd90449ae6908a4cf
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"
29 #include <fmd_alloc.h>
30 #include <fmd_string.h>
31 #include <fmd_subr.h>
32 #include <fmd_api.h>
33 #include <fmd_serd.h>
34 #include <fmd.h>
36 static fmd_serd_eng_t *
37 fmd_serd_eng_alloc(const char *name, uint64_t n, hrtime_t t)
39 fmd_serd_eng_t *sgp = fmd_zalloc(sizeof (fmd_serd_eng_t), FMD_SLEEP);
41 sgp->sg_name = fmd_strdup(name, FMD_SLEEP);
42 sgp->sg_flags = FMD_SERD_DIRTY;
43 sgp->sg_n = n;
44 sgp->sg_t = t;
46 return (sgp);
49 static void
50 fmd_serd_eng_free(fmd_serd_eng_t *sgp)
52 fmd_serd_eng_reset(sgp);
53 fmd_strfree(sgp->sg_name);
54 fmd_free(sgp, sizeof (fmd_serd_eng_t));
57 void
58 fmd_serd_hash_create(fmd_serd_hash_t *shp)
60 shp->sh_hashlen = fmd.d_str_buckets;
61 shp->sh_hash = fmd_zalloc(sizeof (void *) * shp->sh_hashlen, FMD_SLEEP);
62 shp->sh_count = 0;
65 void
66 fmd_serd_hash_destroy(fmd_serd_hash_t *shp)
68 fmd_serd_eng_t *sgp, *ngp;
69 uint_t i;
71 for (i = 0; i < shp->sh_hashlen; i++) {
72 for (sgp = shp->sh_hash[i]; sgp != NULL; sgp = ngp) {
73 ngp = sgp->sg_next;
74 fmd_serd_eng_free(sgp);
78 fmd_free(shp->sh_hash, sizeof (void *) * shp->sh_hashlen);
79 bzero(shp, sizeof (fmd_serd_hash_t));
82 void
83 fmd_serd_hash_apply(fmd_serd_hash_t *shp, fmd_serd_eng_f *func, void *arg)
85 fmd_serd_eng_t *sgp;
86 uint_t i;
88 for (i = 0; i < shp->sh_hashlen; i++) {
89 for (sgp = shp->sh_hash[i]; sgp != NULL; sgp = sgp->sg_next)
90 func(sgp, arg);
94 uint_t
95 fmd_serd_hash_count(fmd_serd_hash_t *shp)
97 return (shp->sh_count);
101 fmd_serd_hash_contains(fmd_serd_hash_t *shp, fmd_event_t *ep)
103 fmd_serd_eng_t *sgp;
104 uint_t i;
106 for (i = 0; i < shp->sh_hashlen; i++) {
107 for (sgp = shp->sh_hash[i]; sgp != NULL; sgp = sgp->sg_next) {
108 if (fmd_serd_eng_contains(sgp, ep)) {
109 fmd_event_transition(ep, FMD_EVS_ACCEPTED);
110 return (1);
115 return (0);
118 fmd_serd_eng_t *
119 fmd_serd_eng_insert(fmd_serd_hash_t *shp,
120 const char *name, uint_t n, hrtime_t t)
122 uint_t h = fmd_strhash(name) % shp->sh_hashlen;
123 fmd_serd_eng_t *sgp = fmd_serd_eng_alloc(name, n, t);
125 sgp->sg_next = shp->sh_hash[h];
126 shp->sh_hash[h] = sgp;
127 shp->sh_count++;
129 return (sgp);
132 fmd_serd_eng_t *
133 fmd_serd_eng_lookup(fmd_serd_hash_t *shp, const char *name)
135 uint_t h = fmd_strhash(name) % shp->sh_hashlen;
136 fmd_serd_eng_t *sgp;
138 for (sgp = shp->sh_hash[h]; sgp != NULL; sgp = sgp->sg_next) {
139 if (strcmp(name, sgp->sg_name) == 0)
140 return (sgp);
143 return (NULL);
146 void
147 fmd_serd_eng_delete(fmd_serd_hash_t *shp, const char *name)
149 uint_t h = fmd_strhash(name) % shp->sh_hashlen;
150 fmd_serd_eng_t *sgp, **pp = &shp->sh_hash[h];
152 for (sgp = *pp; sgp != NULL; sgp = sgp->sg_next) {
153 if (strcmp(sgp->sg_name, name) != 0)
154 pp = &sgp->sg_next;
155 else
156 break;
159 if (sgp != NULL) {
160 *pp = sgp->sg_next;
161 fmd_serd_eng_free(sgp);
162 ASSERT(shp->sh_count != 0);
163 shp->sh_count--;
167 static void
168 fmd_serd_eng_discard(fmd_serd_eng_t *sgp, fmd_serd_elem_t *sep)
170 fmd_list_delete(&sgp->sg_list, sep);
171 sgp->sg_count--;
173 fmd_event_rele(sep->se_event);
174 fmd_free(sep, sizeof (fmd_serd_elem_t));
178 fmd_serd_eng_contains(fmd_serd_eng_t *sgp, fmd_event_t *ep)
180 fmd_serd_elem_t *sep;
182 for (sep = fmd_list_next(&sgp->sg_list);
183 sep != NULL; sep = fmd_list_next(sep)) {
184 if (fmd_event_equal(sep->se_event, ep))
185 return (1);
188 return (0);
192 fmd_serd_eng_record(fmd_serd_eng_t *sgp, fmd_event_t *ep)
194 fmd_serd_elem_t *sep, *oep;
197 * If the fired flag is already set, return false and discard the
198 * event. This means that the caller will only see the engine "fire"
199 * once until fmd_serd_eng_reset() is called. The fmd_serd_eng_fired()
200 * function can also be used in combination with fmd_serd_eng_record().
202 if (sgp->sg_flags & FMD_SERD_FIRED)
203 return (FMD_B_FALSE);
205 while (sgp->sg_count > sgp->sg_n)
206 fmd_serd_eng_discard(sgp, fmd_list_next(&sgp->sg_list));
208 fmd_event_hold(ep);
209 fmd_event_transition(ep, FMD_EVS_ACCEPTED);
211 sep = fmd_alloc(sizeof (fmd_serd_elem_t), FMD_SLEEP);
212 sep->se_event = ep;
214 fmd_list_append(&sgp->sg_list, sep);
215 sgp->sg_count++;
218 * Pick up the oldest element pointer for comparison to 'sep'. We must
219 * do this after adding 'sep' because 'oep' and 'sep' can be the same.
221 oep = fmd_list_next(&sgp->sg_list);
223 if (sgp->sg_count > sgp->sg_n &&
224 fmd_event_delta(oep->se_event, sep->se_event) <= sgp->sg_t) {
225 sgp->sg_flags |= FMD_SERD_FIRED | FMD_SERD_DIRTY;
226 return (FMD_B_TRUE);
229 sgp->sg_flags |= FMD_SERD_DIRTY;
230 return (FMD_B_FALSE);
234 fmd_serd_eng_fired(fmd_serd_eng_t *sgp)
236 return (sgp->sg_flags & FMD_SERD_FIRED);
240 fmd_serd_eng_empty(fmd_serd_eng_t *sgp)
242 return (sgp->sg_count == 0);
245 void
246 fmd_serd_eng_reset(fmd_serd_eng_t *sgp)
248 while (sgp->sg_count != 0)
249 fmd_serd_eng_discard(sgp, fmd_list_next(&sgp->sg_list));
251 sgp->sg_flags &= ~FMD_SERD_FIRED;
252 sgp->sg_flags |= FMD_SERD_DIRTY;
255 void
256 fmd_serd_eng_gc(fmd_serd_eng_t *sgp)
258 fmd_serd_elem_t *sep, *nep;
259 hrtime_t hrt;
261 if (sgp->sg_count == 0 || (sgp->sg_flags & FMD_SERD_FIRED))
262 return; /* no garbage collection needed if empty or fired */
264 sep = fmd_list_prev(&sgp->sg_list);
265 hrt = fmd_event_hrtime(sep->se_event) - sgp->sg_t;
267 for (sep = fmd_list_next(&sgp->sg_list); sep != NULL; sep = nep) {
268 if (fmd_event_hrtime(sep->se_event) >= hrt)
269 break; /* sep and subsequent events are all within T */
271 nep = fmd_list_next(sep);
272 fmd_serd_eng_discard(sgp, sep);
273 sgp->sg_flags |= FMD_SERD_DIRTY;
277 void
278 fmd_serd_eng_commit(fmd_serd_eng_t *sgp)
280 fmd_serd_elem_t *sep;
282 if (!(sgp->sg_flags & FMD_SERD_DIRTY))
283 return; /* engine has not changed since last commit */
285 for (sep = fmd_list_next(&sgp->sg_list); sep != NULL;
286 sep = fmd_list_next(sep))
287 fmd_event_commit(sep->se_event);
289 sgp->sg_flags &= ~FMD_SERD_DIRTY;
292 void
293 fmd_serd_eng_clrdirty(fmd_serd_eng_t *sgp)
295 sgp->sg_flags &= ~FMD_SERD_DIRTY;