xref: /onnv-gate/usr/src/cmd/isns/isnsd/sched.c (revision 7836:4e95154b5b7a)
1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM 
22*7836SJohn.Forte@Sun.COM /*
23*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
25*7836SJohn.Forte@Sun.COM  */
26*7836SJohn.Forte@Sun.COM 
27*7836SJohn.Forte@Sun.COM #include <stdio.h>
28*7836SJohn.Forte@Sun.COM #include <stdlib.h>
29*7836SJohn.Forte@Sun.COM #include <string.h>
30*7836SJohn.Forte@Sun.COM #include <unistd.h>
31*7836SJohn.Forte@Sun.COM #include <pthread.h>
32*7836SJohn.Forte@Sun.COM 
33*7836SJohn.Forte@Sun.COM #include "isns_server.h"
34*7836SJohn.Forte@Sun.COM #include "isns_protocol.h"
35*7836SJohn.Forte@Sun.COM #include "isns_log.h"
36*7836SJohn.Forte@Sun.COM #include "isns_sched.h"
37*7836SJohn.Forte@Sun.COM #include "isns_scn.h"
38*7836SJohn.Forte@Sun.COM #include "isns_esi.h"
39*7836SJohn.Forte@Sun.COM 
40*7836SJohn.Forte@Sun.COM /*
41*7836SJohn.Forte@Sun.COM  * extern variables.
42*7836SJohn.Forte@Sun.COM  */
43*7836SJohn.Forte@Sun.COM 
44*7836SJohn.Forte@Sun.COM /*
45*7836SJohn.Forte@Sun.COM  * global variables.
46*7836SJohn.Forte@Sun.COM  */
47*7836SJohn.Forte@Sun.COM pthread_mutex_t el_mtx = PTHREAD_MUTEX_INITIALIZER;
48*7836SJohn.Forte@Sun.COM 
49*7836SJohn.Forte@Sun.COM /*
50*7836SJohn.Forte@Sun.COM  * local variables.
51*7836SJohn.Forte@Sun.COM  */
52*7836SJohn.Forte@Sun.COM static el_key_t **il;
53*7836SJohn.Forte@Sun.COM static int icurr = 0;
54*7836SJohn.Forte@Sun.COM static el_notice_t *curr = NULL;
55*7836SJohn.Forte@Sun.COM 
56*7836SJohn.Forte@Sun.COM static uint32_t DU;
57*7836SJohn.Forte@Sun.COM static uint32_t DT;
58*7836SJohn.Forte@Sun.COM static uint32_t LB;
59*7836SJohn.Forte@Sun.COM static uint32_t NLIM;
60*7836SJohn.Forte@Sun.COM 
61*7836SJohn.Forte@Sun.COM /*
62*7836SJohn.Forte@Sun.COM  * external variables.
63*7836SJohn.Forte@Sun.COM  */
64*7836SJohn.Forte@Sun.COM 
65*7836SJohn.Forte@Sun.COM /*
66*7836SJohn.Forte@Sun.COM  * local functions.
67*7836SJohn.Forte@Sun.COM  */
68*7836SJohn.Forte@Sun.COM 
69*7836SJohn.Forte@Sun.COM /*
70*7836SJohn.Forte@Sun.COM  * ****************************************************************************
71*7836SJohn.Forte@Sun.COM  *
72*7836SJohn.Forte@Sun.COM  * il_shift:
73*7836SJohn.Forte@Sun.COM  *	Shift the indexed-list to the most current time.
74*7836SJohn.Forte@Sun.COM  *
75*7836SJohn.Forte@Sun.COM  * t	- most current time.
76*7836SJohn.Forte@Sun.COM  *
77*7836SJohn.Forte@Sun.COM  * ****************************************************************************
78*7836SJohn.Forte@Sun.COM  */
79*7836SJohn.Forte@Sun.COM static void
il_shift(uint32_t t)80*7836SJohn.Forte@Sun.COM il_shift(
81*7836SJohn.Forte@Sun.COM 	uint32_t t
82*7836SJohn.Forte@Sun.COM )
83*7836SJohn.Forte@Sun.COM {
84*7836SJohn.Forte@Sun.COM 	el_notice_t *fn, *n;
85*7836SJohn.Forte@Sun.COM 	el_key_t *fk, *k;
86*7836SJohn.Forte@Sun.COM 	uint32_t nt;
87*7836SJohn.Forte@Sun.COM 	int c;
88*7836SJohn.Forte@Sun.COM 
89*7836SJohn.Forte@Sun.COM 	k = il[icurr];
90*7836SJohn.Forte@Sun.COM 	while (k->time < t) {
91*7836SJohn.Forte@Sun.COM 		fk = k;
92*7836SJohn.Forte@Sun.COM 		fn = k->notice;
93*7836SJohn.Forte@Sun.COM 		/* remove the dummy key and dummy notice */
94*7836SJohn.Forte@Sun.COM 		fk->left->right = fk->right;
95*7836SJohn.Forte@Sun.COM 		fk->right->left = fk->left;
96*7836SJohn.Forte@Sun.COM 		fn->pred->sucd = fn->sucd;
97*7836SJohn.Forte@Sun.COM 		fn->sucd->pred = fn->pred;
98*7836SJohn.Forte@Sun.COM 
99*7836SJohn.Forte@Sun.COM 		/* find the place where the dummy goes to */
100*7836SJohn.Forte@Sun.COM 		k = il[(icurr + DU - 1) % DU];
101*7836SJohn.Forte@Sun.COM 		if (k->time < INFINITY - DT) {
102*7836SJohn.Forte@Sun.COM 			nt = k->time + DT; /* next key time */
103*7836SJohn.Forte@Sun.COM 		} else {
104*7836SJohn.Forte@Sun.COM 			nt = INFINITY - 1; /* the last second */
105*7836SJohn.Forte@Sun.COM 		}
106*7836SJohn.Forte@Sun.COM 		while (k->time < nt) {
107*7836SJohn.Forte@Sun.COM 			k = k->right;
108*7836SJohn.Forte@Sun.COM 		}
109*7836SJohn.Forte@Sun.COM 		n = k->notice->pred;
110*7836SJohn.Forte@Sun.COM 		c = 1;
111*7836SJohn.Forte@Sun.COM 		while (n->time >= nt) {
112*7836SJohn.Forte@Sun.COM 			c ++;
113*7836SJohn.Forte@Sun.COM 			n = n->pred;
114*7836SJohn.Forte@Sun.COM 		}
115*7836SJohn.Forte@Sun.COM 		n = n->sucd;
116*7836SJohn.Forte@Sun.COM 
117*7836SJohn.Forte@Sun.COM 		/* update lower bound */
118*7836SJohn.Forte@Sun.COM 		LB = fk->time;
119*7836SJohn.Forte@Sun.COM 
120*7836SJohn.Forte@Sun.COM 		/* insert the dummy key */
121*7836SJohn.Forte@Sun.COM 		fk->time = nt;
122*7836SJohn.Forte@Sun.COM 		fk->count = k->count - c + 1;
123*7836SJohn.Forte@Sun.COM 		fk->left = k->left;
124*7836SJohn.Forte@Sun.COM 		fk->right = k;
125*7836SJohn.Forte@Sun.COM 		k->left->right = fk;
126*7836SJohn.Forte@Sun.COM 		k->left = fk;
127*7836SJohn.Forte@Sun.COM 		k->count = c;
128*7836SJohn.Forte@Sun.COM 		/* insert the dummy notice */
129*7836SJohn.Forte@Sun.COM 		fn->time = nt;
130*7836SJohn.Forte@Sun.COM 		fn->pred = n->pred;
131*7836SJohn.Forte@Sun.COM 		fn->sucd = n;
132*7836SJohn.Forte@Sun.COM 		n->pred->sucd = fn;
133*7836SJohn.Forte@Sun.COM 		n->pred = fn;
134*7836SJohn.Forte@Sun.COM 
135*7836SJohn.Forte@Sun.COM 		/* shift the current index */
136*7836SJohn.Forte@Sun.COM 		icurr = (icurr + 1) % DU;
137*7836SJohn.Forte@Sun.COM 		k = il[icurr];
138*7836SJohn.Forte@Sun.COM 	}
139*7836SJohn.Forte@Sun.COM }
140*7836SJohn.Forte@Sun.COM 
141*7836SJohn.Forte@Sun.COM /*
142*7836SJohn.Forte@Sun.COM  * global functions.
143*7836SJohn.Forte@Sun.COM  */
144*7836SJohn.Forte@Sun.COM 
145*7836SJohn.Forte@Sun.COM /*
146*7836SJohn.Forte@Sun.COM  * ****************************************************************************
147*7836SJohn.Forte@Sun.COM  *
148*7836SJohn.Forte@Sun.COM  * el_init:
149*7836SJohn.Forte@Sun.COM  *	Initialize the element list.
150*7836SJohn.Forte@Sun.COM  *
151*7836SJohn.Forte@Sun.COM  * du	- Number of uint in the indexed-list.
152*7836SJohn.Forte@Sun.COM  * dt	- Time interval of the indexed-list.
153*7836SJohn.Forte@Sun.COM  * nlim	- Limit number of each notice.
154*7836SJohn.Forte@Sun.COM  * return - 0: successful, otherwise failed.
155*7836SJohn.Forte@Sun.COM  *
156*7836SJohn.Forte@Sun.COM  * ****************************************************************************
157*7836SJohn.Forte@Sun.COM  */
158*7836SJohn.Forte@Sun.COM int
el_init(uint32_t du,uint32_t dt,uint32_t nlim)159*7836SJohn.Forte@Sun.COM el_init(
160*7836SJohn.Forte@Sun.COM 	uint32_t du,
161*7836SJohn.Forte@Sun.COM 	uint32_t dt,
162*7836SJohn.Forte@Sun.COM 	uint32_t nlim
163*7836SJohn.Forte@Sun.COM )
164*7836SJohn.Forte@Sun.COM {
165*7836SJohn.Forte@Sun.COM 	el_key_t *k, *kleft;
166*7836SJohn.Forte@Sun.COM 	el_notice_t *n, *npred;
167*7836SJohn.Forte@Sun.COM 
168*7836SJohn.Forte@Sun.COM 	uint32_t t = 0;
169*7836SJohn.Forte@Sun.COM 
170*7836SJohn.Forte@Sun.COM 	int i;
171*7836SJohn.Forte@Sun.COM 
172*7836SJohn.Forte@Sun.COM 	if (du < 1 || dt < 1 || nlim < 1) {
173*7836SJohn.Forte@Sun.COM 		return (1);
174*7836SJohn.Forte@Sun.COM 	}
175*7836SJohn.Forte@Sun.COM 
176*7836SJohn.Forte@Sun.COM 	DU = du;
177*7836SJohn.Forte@Sun.COM 	DT = dt;
178*7836SJohn.Forte@Sun.COM 	LB = 0;
179*7836SJohn.Forte@Sun.COM 	NLIM = nlim;
180*7836SJohn.Forte@Sun.COM 
181*7836SJohn.Forte@Sun.COM 	/*
182*7836SJohn.Forte@Sun.COM 	 * initialize the event set
183*7836SJohn.Forte@Sun.COM 	 */
184*7836SJohn.Forte@Sun.COM 
185*7836SJohn.Forte@Sun.COM 	/* first dummy notice */
186*7836SJohn.Forte@Sun.COM 	n = (el_notice_t *)malloc(sizeof (el_notice_t));
187*7836SJohn.Forte@Sun.COM 	if (n == NULL) {
188*7836SJohn.Forte@Sun.COM 		return (1);
189*7836SJohn.Forte@Sun.COM 	}
190*7836SJohn.Forte@Sun.COM 	n->time = LB;
191*7836SJohn.Forte@Sun.COM 	n->event = NULL;
192*7836SJohn.Forte@Sun.COM 	n->isdummy = 1;
193*7836SJohn.Forte@Sun.COM 	n->pred = NULL;
194*7836SJohn.Forte@Sun.COM 	npred = n;
195*7836SJohn.Forte@Sun.COM 
196*7836SJohn.Forte@Sun.COM 	/* first dummy key */
197*7836SJohn.Forte@Sun.COM 	k = (el_key_t *)malloc(sizeof (el_key_t));
198*7836SJohn.Forte@Sun.COM 	if (k == NULL) {
199*7836SJohn.Forte@Sun.COM 		return (1);
200*7836SJohn.Forte@Sun.COM 	}
201*7836SJohn.Forte@Sun.COM 	k->time = LB;
202*7836SJohn.Forte@Sun.COM 	k->count = 1;
203*7836SJohn.Forte@Sun.COM 	k->notice = n;
204*7836SJohn.Forte@Sun.COM 	k->left = NULL;
205*7836SJohn.Forte@Sun.COM 	kleft = k;
206*7836SJohn.Forte@Sun.COM 
207*7836SJohn.Forte@Sun.COM 	n->key = k;
208*7836SJohn.Forte@Sun.COM 
209*7836SJohn.Forte@Sun.COM 	/* index list */
210*7836SJohn.Forte@Sun.COM 	il = (el_key_t **)malloc((DU + 1) * sizeof (el_key_t *));
211*7836SJohn.Forte@Sun.COM 	if (il == NULL) {
212*7836SJohn.Forte@Sun.COM 		return (1);
213*7836SJohn.Forte@Sun.COM 	}
214*7836SJohn.Forte@Sun.COM 
215*7836SJohn.Forte@Sun.COM 	/* create notice list, key list & index list */
216*7836SJohn.Forte@Sun.COM 	for (i = 0; i < DU; i++) {
217*7836SJohn.Forte@Sun.COM 		t += DT;
218*7836SJohn.Forte@Sun.COM 
219*7836SJohn.Forte@Sun.COM 		n = (el_notice_t *)malloc(sizeof (el_notice_t));
220*7836SJohn.Forte@Sun.COM 		if (n == NULL) {
221*7836SJohn.Forte@Sun.COM 			return (1);
222*7836SJohn.Forte@Sun.COM 		}
223*7836SJohn.Forte@Sun.COM 		n->time = t;
224*7836SJohn.Forte@Sun.COM 		n->event = NULL;
225*7836SJohn.Forte@Sun.COM 		n->isdummy = 1;
226*7836SJohn.Forte@Sun.COM 		n->pred = npred;
227*7836SJohn.Forte@Sun.COM 		npred->sucd = n;
228*7836SJohn.Forte@Sun.COM 		npred = n;
229*7836SJohn.Forte@Sun.COM 
230*7836SJohn.Forte@Sun.COM 		k = (el_key_t *)malloc(sizeof (el_key_t));
231*7836SJohn.Forte@Sun.COM 		if (k == NULL) {
232*7836SJohn.Forte@Sun.COM 			return (1);
233*7836SJohn.Forte@Sun.COM 		}
234*7836SJohn.Forte@Sun.COM 		k->time = t;
235*7836SJohn.Forte@Sun.COM 		k->count = 1;
236*7836SJohn.Forte@Sun.COM 		k->notice = n;
237*7836SJohn.Forte@Sun.COM 		k->left = kleft;
238*7836SJohn.Forte@Sun.COM 		kleft->right = k;
239*7836SJohn.Forte@Sun.COM 		kleft = k;
240*7836SJohn.Forte@Sun.COM 
241*7836SJohn.Forte@Sun.COM 		n->key = k;
242*7836SJohn.Forte@Sun.COM 
243*7836SJohn.Forte@Sun.COM 		il[i] = k;
244*7836SJohn.Forte@Sun.COM 	}
245*7836SJohn.Forte@Sun.COM 
246*7836SJohn.Forte@Sun.COM 	/* last dummy notice */
247*7836SJohn.Forte@Sun.COM 	n = (el_notice_t *)malloc(sizeof (el_notice_t));
248*7836SJohn.Forte@Sun.COM 	if (n == NULL) {
249*7836SJohn.Forte@Sun.COM 		return (1);
250*7836SJohn.Forte@Sun.COM 	}
251*7836SJohn.Forte@Sun.COM 	n->time = INFINITY; /* the end of the world */
252*7836SJohn.Forte@Sun.COM 	n->event = NULL;
253*7836SJohn.Forte@Sun.COM 	n->isdummy = 1;
254*7836SJohn.Forte@Sun.COM 	n->pred = npred;
255*7836SJohn.Forte@Sun.COM 	n->sucd = NULL;
256*7836SJohn.Forte@Sun.COM 	npred->sucd = n;
257*7836SJohn.Forte@Sun.COM 
258*7836SJohn.Forte@Sun.COM 	/* last dummy key */
259*7836SJohn.Forte@Sun.COM 	k = (el_key_t *)malloc(sizeof (el_key_t));
260*7836SJohn.Forte@Sun.COM 	if (k == NULL) {
261*7836SJohn.Forte@Sun.COM 		return (1);
262*7836SJohn.Forte@Sun.COM 	}
263*7836SJohn.Forte@Sun.COM 	k->time = INFINITY; /* the end of the world */
264*7836SJohn.Forte@Sun.COM 	k->count = 1;
265*7836SJohn.Forte@Sun.COM 	k->notice = n;
266*7836SJohn.Forte@Sun.COM 	k->left = kleft;
267*7836SJohn.Forte@Sun.COM 	k->right = NULL;
268*7836SJohn.Forte@Sun.COM 	kleft->right = k;
269*7836SJohn.Forte@Sun.COM 
270*7836SJohn.Forte@Sun.COM 	n->key = k;
271*7836SJohn.Forte@Sun.COM 
272*7836SJohn.Forte@Sun.COM 	/* last index */
273*7836SJohn.Forte@Sun.COM 	il[DU] = k;
274*7836SJohn.Forte@Sun.COM 
275*7836SJohn.Forte@Sun.COM 	return (0);
276*7836SJohn.Forte@Sun.COM }
277*7836SJohn.Forte@Sun.COM 
278*7836SJohn.Forte@Sun.COM /*
279*7836SJohn.Forte@Sun.COM  * ****************************************************************************
280*7836SJohn.Forte@Sun.COM  *
281*7836SJohn.Forte@Sun.COM  * el_add:
282*7836SJohn.Forte@Sun.COM  *	Add an event to the element list with it's execution time.
283*7836SJohn.Forte@Sun.COM  *	It might not actually put the event to the list if the event
284*7836SJohn.Forte@Sun.COM  *	is the most current one for execution.
285*7836SJohn.Forte@Sun.COM  *
286*7836SJohn.Forte@Sun.COM  * ev	- The Event.
287*7836SJohn.Forte@Sun.COM  * t	- The time when the event is scheduled at.
288*7836SJohn.Forte@Sun.COM  * evp	- Pointer of event for returning.
289*7836SJohn.Forte@Sun.COM  * return - Error code.
290*7836SJohn.Forte@Sun.COM  *
291*7836SJohn.Forte@Sun.COM  * ****************************************************************************
292*7836SJohn.Forte@Sun.COM  */
293*7836SJohn.Forte@Sun.COM int
el_add(void * ev,uint32_t t,void ** evp)294*7836SJohn.Forte@Sun.COM el_add(
295*7836SJohn.Forte@Sun.COM 	void *ev,
296*7836SJohn.Forte@Sun.COM 	uint32_t t,
297*7836SJohn.Forte@Sun.COM 	void **evp
298*7836SJohn.Forte@Sun.COM )
299*7836SJohn.Forte@Sun.COM {
300*7836SJohn.Forte@Sun.COM 	int ec = 0;
301*7836SJohn.Forte@Sun.COM 
302*7836SJohn.Forte@Sun.COM 	uint32_t t1 = 0;
303*7836SJohn.Forte@Sun.COM 
304*7836SJohn.Forte@Sun.COM 	int i, j;
305*7836SJohn.Forte@Sun.COM 	el_key_t *k;
306*7836SJohn.Forte@Sun.COM 	el_notice_t *n;
307*7836SJohn.Forte@Sun.COM 
308*7836SJohn.Forte@Sun.COM 	el_key_t *y;
309*7836SJohn.Forte@Sun.COM 	el_notice_t *x;
310*7836SJohn.Forte@Sun.COM 
311*7836SJohn.Forte@Sun.COM 	/* lock the event set */
312*7836SJohn.Forte@Sun.COM 	(void) pthread_mutex_lock(&el_mtx);
313*7836SJohn.Forte@Sun.COM 
314*7836SJohn.Forte@Sun.COM 	/* strip it off from the event list which is being handled */
315*7836SJohn.Forte@Sun.COM 	if (evf_again(ev) != 0) {
316*7836SJohn.Forte@Sun.COM 		/* if it is rescheduling an event and the event */
317*7836SJohn.Forte@Sun.COM 		/* was waiting for execution after idle finishes */
318*7836SJohn.Forte@Sun.COM 		if (evf_rem(ev) == 0 &&
319*7836SJohn.Forte@Sun.COM 		    evp != NULL &&
320*7836SJohn.Forte@Sun.COM 		    (curr == NULL || t <= curr->time)) {
321*7836SJohn.Forte@Sun.COM 			/* no need to reschedule it */
322*7836SJohn.Forte@Sun.COM 			*evp = ev;
323*7836SJohn.Forte@Sun.COM 			goto add_done;
324*7836SJohn.Forte@Sun.COM 		}
325*7836SJohn.Forte@Sun.COM 		evl_strip(ev);
326*7836SJohn.Forte@Sun.COM 		/* if it is marked as a removed event, do not add it */
327*7836SJohn.Forte@Sun.COM 		if (evf_rem(ev) != 0) {
328*7836SJohn.Forte@Sun.COM 			ev_free(ev);
329*7836SJohn.Forte@Sun.COM 			goto add_done;
330*7836SJohn.Forte@Sun.COM 		}
331*7836SJohn.Forte@Sun.COM 	}
332*7836SJohn.Forte@Sun.COM 
333*7836SJohn.Forte@Sun.COM 	/* get the index in the il */
334*7836SJohn.Forte@Sun.COM 	if (t == 0) {
335*7836SJohn.Forte@Sun.COM 		t = ev_intval(ev);
336*7836SJohn.Forte@Sun.COM 		/* not initialization time */
337*7836SJohn.Forte@Sun.COM 		if (evf_init(ev) || evf_again(ev)) {
338*7836SJohn.Forte@Sun.COM 			t1 = get_stopwatch(evf_wakeup(ev));
339*7836SJohn.Forte@Sun.COM 			/* make il up to date */
340*7836SJohn.Forte@Sun.COM 			il_shift(t1);
341*7836SJohn.Forte@Sun.COM 			/* avoid overflow */
342*7836SJohn.Forte@Sun.COM 			if (t1 >= INFINITY - t) {
343*7836SJohn.Forte@Sun.COM 				/* the last second */
344*7836SJohn.Forte@Sun.COM 				t1 = INFINITY - t1 - 1;
345*7836SJohn.Forte@Sun.COM 			}
346*7836SJohn.Forte@Sun.COM 		}
347*7836SJohn.Forte@Sun.COM 		t += t1;
348*7836SJohn.Forte@Sun.COM 	}
349*7836SJohn.Forte@Sun.COM 	i = (t - LB) / DT;
350*7836SJohn.Forte@Sun.COM 	if (i >= DU) {
351*7836SJohn.Forte@Sun.COM 		i = DU;
352*7836SJohn.Forte@Sun.COM 	} else {
353*7836SJohn.Forte@Sun.COM 		i = (i + icurr) % DU;
354*7836SJohn.Forte@Sun.COM 	}
355*7836SJohn.Forte@Sun.COM 
356*7836SJohn.Forte@Sun.COM 	/* find the right key */
357*7836SJohn.Forte@Sun.COM 	k = (il[i])->left;
358*7836SJohn.Forte@Sun.COM 	while (k->time > t) {
359*7836SJohn.Forte@Sun.COM 		k = k->left;
360*7836SJohn.Forte@Sun.COM 	}
361*7836SJohn.Forte@Sun.COM 	k = k->right;
362*7836SJohn.Forte@Sun.COM 
363*7836SJohn.Forte@Sun.COM 	/* need to split */
364*7836SJohn.Forte@Sun.COM 	if (k->count == NLIM) {
365*7836SJohn.Forte@Sun.COM 		/* insert a new key */
366*7836SJohn.Forte@Sun.COM 		y = (el_key_t *)malloc(sizeof (el_key_t));
367*7836SJohn.Forte@Sun.COM 		if (y == NULL) {
368*7836SJohn.Forte@Sun.COM 			ec = ISNS_RSP_INTERNAL_ERROR;
369*7836SJohn.Forte@Sun.COM 			goto add_done;
370*7836SJohn.Forte@Sun.COM 		}
371*7836SJohn.Forte@Sun.COM 		k->count = NLIM / 2;
372*7836SJohn.Forte@Sun.COM 		x = k->notice;
373*7836SJohn.Forte@Sun.COM 		for (j = 1; j <= NLIM / 2; j++) {
374*7836SJohn.Forte@Sun.COM 			x = x->pred;
375*7836SJohn.Forte@Sun.COM 		}
376*7836SJohn.Forte@Sun.COM 		y->time = x->time;
377*7836SJohn.Forte@Sun.COM 		y->count = NLIM - NLIM / 2;
378*7836SJohn.Forte@Sun.COM 		y->notice = x;
379*7836SJohn.Forte@Sun.COM 		y->right = k;
380*7836SJohn.Forte@Sun.COM 		y->left = k->left;
381*7836SJohn.Forte@Sun.COM 		k->left->right = y;
382*7836SJohn.Forte@Sun.COM 		k->left = y;
383*7836SJohn.Forte@Sun.COM 
384*7836SJohn.Forte@Sun.COM 		/* update the key */
385*7836SJohn.Forte@Sun.COM 		x->key = y;
386*7836SJohn.Forte@Sun.COM 
387*7836SJohn.Forte@Sun.COM 		/* shift */
388*7836SJohn.Forte@Sun.COM 		if (y->time > t) {
389*7836SJohn.Forte@Sun.COM 			k = y;
390*7836SJohn.Forte@Sun.COM 		}
391*7836SJohn.Forte@Sun.COM 	}
392*7836SJohn.Forte@Sun.COM 
393*7836SJohn.Forte@Sun.COM 	/* make a new notice */
394*7836SJohn.Forte@Sun.COM 	x = (el_notice_t *)malloc(sizeof (el_notice_t));
395*7836SJohn.Forte@Sun.COM 	if (x == NULL) {
396*7836SJohn.Forte@Sun.COM 		ec = ISNS_RSP_INTERNAL_ERROR;
397*7836SJohn.Forte@Sun.COM 		goto add_done;
398*7836SJohn.Forte@Sun.COM 	}
399*7836SJohn.Forte@Sun.COM 	x->time = t;
400*7836SJohn.Forte@Sun.COM 	x->event = ev;
401*7836SJohn.Forte@Sun.COM 	x->isdummy = 0;
402*7836SJohn.Forte@Sun.COM 	x->key = NULL;
403*7836SJohn.Forte@Sun.COM 
404*7836SJohn.Forte@Sun.COM 	/* insert it */
405*7836SJohn.Forte@Sun.COM 	n = k->notice;
406*7836SJohn.Forte@Sun.COM 	while (n->time > t) {
407*7836SJohn.Forte@Sun.COM 		n = n->pred;
408*7836SJohn.Forte@Sun.COM 	}
409*7836SJohn.Forte@Sun.COM 	x->pred = n;
410*7836SJohn.Forte@Sun.COM 	x->sucd = n->sucd;
411*7836SJohn.Forte@Sun.COM 	n->sucd->pred = x;
412*7836SJohn.Forte@Sun.COM 	n->sucd = x;
413*7836SJohn.Forte@Sun.COM 
414*7836SJohn.Forte@Sun.COM 	/* increase number of notice */
415*7836SJohn.Forte@Sun.COM 	k->count ++;
416*7836SJohn.Forte@Sun.COM 
417*7836SJohn.Forte@Sun.COM 	/* reset current notice and wake up idle */
418*7836SJohn.Forte@Sun.COM 	if (curr == NULL || curr->time > t) {
419*7836SJohn.Forte@Sun.COM 		curr = x;
420*7836SJohn.Forte@Sun.COM 	}
421*7836SJohn.Forte@Sun.COM 
422*7836SJohn.Forte@Sun.COM 	/* clear event flags */
423*7836SJohn.Forte@Sun.COM 	evf_zero(ev);
424*7836SJohn.Forte@Sun.COM 
425*7836SJohn.Forte@Sun.COM 	isnslog(LOG_DEBUG, "el_add", "%s [%d] is scheduled at %d.",
426*7836SJohn.Forte@Sun.COM 	    ((ev_t *)ev)->type == EV_ESI ? "ESI" : "REG_EXP",
427*7836SJohn.Forte@Sun.COM 	    ((ev_t *)ev)->uid,
428*7836SJohn.Forte@Sun.COM 	    t);
429*7836SJohn.Forte@Sun.COM 
430*7836SJohn.Forte@Sun.COM add_done:
431*7836SJohn.Forte@Sun.COM 	/* unlock the event set */
432*7836SJohn.Forte@Sun.COM 	(void) pthread_mutex_unlock(&el_mtx);
433*7836SJohn.Forte@Sun.COM 
434*7836SJohn.Forte@Sun.COM 	/* failed, free it */
435*7836SJohn.Forte@Sun.COM 	if (ec != 0) {
436*7836SJohn.Forte@Sun.COM 		ev_free(ev);
437*7836SJohn.Forte@Sun.COM 		isnslog(LOG_DEBUG, "el_add", "failed, no memory.");
438*7836SJohn.Forte@Sun.COM 	}
439*7836SJohn.Forte@Sun.COM 
440*7836SJohn.Forte@Sun.COM 	return (ec);
441*7836SJohn.Forte@Sun.COM }
442*7836SJohn.Forte@Sun.COM 
443*7836SJohn.Forte@Sun.COM /*
444*7836SJohn.Forte@Sun.COM  * ****************************************************************************
445*7836SJohn.Forte@Sun.COM  *
446*7836SJohn.Forte@Sun.COM  * el_remove:
447*7836SJohn.Forte@Sun.COM  *	Remove or update an event from the element list. If the event is
448*7836SJohn.Forte@Sun.COM  *	currently not in the element list, it must be in a queue which
449*7836SJohn.Forte@Sun.COM  *	contains all of event which are being executing at the moment.
450*7836SJohn.Forte@Sun.COM  *	So it seeks the event from the list prior to the element list.
451*7836SJohn.Forte@Sun.COM  *
452*7836SJohn.Forte@Sun.COM  * id1	- The event ID.
453*7836SJohn.Forte@Sun.COM  * id2	- The second ID for the event update.
454*7836SJohn.Forte@Sun.COM  * pending - Do not actually remove, mark it for removal pending.
455*7836SJohn.Forte@Sun.COM  * return - Error code.
456*7836SJohn.Forte@Sun.COM  *
457*7836SJohn.Forte@Sun.COM  * ****************************************************************************
458*7836SJohn.Forte@Sun.COM  */
459*7836SJohn.Forte@Sun.COM int
el_remove(uint32_t id1,uint32_t id2,int pending)460*7836SJohn.Forte@Sun.COM el_remove(
461*7836SJohn.Forte@Sun.COM 	uint32_t id1,
462*7836SJohn.Forte@Sun.COM 	uint32_t id2,
463*7836SJohn.Forte@Sun.COM 	int pending
464*7836SJohn.Forte@Sun.COM )
465*7836SJohn.Forte@Sun.COM {
466*7836SJohn.Forte@Sun.COM 	el_key_t *k, *kl, *kr;
467*7836SJohn.Forte@Sun.COM 	el_notice_t *n, *n2;
468*7836SJohn.Forte@Sun.COM 
469*7836SJohn.Forte@Sun.COM 	(void) pthread_mutex_lock(&el_mtx);
470*7836SJohn.Forte@Sun.COM 
471*7836SJohn.Forte@Sun.COM 	/* search the event from the event list which is being handled */
472*7836SJohn.Forte@Sun.COM 	if (evl_remove(id1, id2, pending) != 0) {
473*7836SJohn.Forte@Sun.COM 		(void) pthread_mutex_unlock(&el_mtx);
474*7836SJohn.Forte@Sun.COM 		return (0);
475*7836SJohn.Forte@Sun.COM 	}
476*7836SJohn.Forte@Sun.COM 
477*7836SJohn.Forte@Sun.COM 	/* search the notice starting from current */
478*7836SJohn.Forte@Sun.COM 	n = curr;
479*7836SJohn.Forte@Sun.COM 	while (n != NULL) {
480*7836SJohn.Forte@Sun.COM 		/* found the match notice */
481*7836SJohn.Forte@Sun.COM 		if (!n->isdummy && ev_match(n->event, id1) != 0) {
482*7836SJohn.Forte@Sun.COM 			if (ev_remove(n->event, id2, 1, pending) == 0) {
483*7836SJohn.Forte@Sun.COM 				/* update the key of the match notice */
484*7836SJohn.Forte@Sun.COM 				k = n->key;
485*7836SJohn.Forte@Sun.COM 				if (k != NULL && k->count == 1) {
486*7836SJohn.Forte@Sun.COM 					/* no more notice */
487*7836SJohn.Forte@Sun.COM 					k->left->right = k->right;
488*7836SJohn.Forte@Sun.COM 					k->right->left = k->left;
489*7836SJohn.Forte@Sun.COM 					free(k);
490*7836SJohn.Forte@Sun.COM 				} else {
491*7836SJohn.Forte@Sun.COM 					if (k != NULL) {
492*7836SJohn.Forte@Sun.COM 						k->notice = n->pred;
493*7836SJohn.Forte@Sun.COM 						k->notice->key = k;
494*7836SJohn.Forte@Sun.COM 						k->time = k->notice->time;
495*7836SJohn.Forte@Sun.COM 					}
496*7836SJohn.Forte@Sun.COM 					n2 = n;
497*7836SJohn.Forte@Sun.COM 					k = n2->key;
498*7836SJohn.Forte@Sun.COM 					while (k == NULL) {
499*7836SJohn.Forte@Sun.COM 						n2 = n2->sucd;
500*7836SJohn.Forte@Sun.COM 						k = n2->key;
501*7836SJohn.Forte@Sun.COM 					}
502*7836SJohn.Forte@Sun.COM 					/* decrease the count by one */
503*7836SJohn.Forte@Sun.COM 					k->count --;
504*7836SJohn.Forte@Sun.COM 					/* merge the keys */
505*7836SJohn.Forte@Sun.COM 					kl = k->left;
506*7836SJohn.Forte@Sun.COM 					kr = k->right;
507*7836SJohn.Forte@Sun.COM 					if (!kl->notice->isdummy &&
508*7836SJohn.Forte@Sun.COM 					    (kl->count + k->count) <= NLIM) {
509*7836SJohn.Forte@Sun.COM 						/* delete the left key */
510*7836SJohn.Forte@Sun.COM 						k->count += kl->count;
511*7836SJohn.Forte@Sun.COM 						k->left = kl->left;
512*7836SJohn.Forte@Sun.COM 						k->left->right = k;
513*7836SJohn.Forte@Sun.COM 						kl->notice->key = NULL;
514*7836SJohn.Forte@Sun.COM 						free(kl);
515*7836SJohn.Forte@Sun.COM 					} else if (!k->notice->isdummy &&
516*7836SJohn.Forte@Sun.COM 					    (kr->count + k->count) <= NLIM) {
517*7836SJohn.Forte@Sun.COM 						/* delete this key */
518*7836SJohn.Forte@Sun.COM 						kr->count += k->count;
519*7836SJohn.Forte@Sun.COM 						kr->left = k->left;
520*7836SJohn.Forte@Sun.COM 						kr->left->right = kr;
521*7836SJohn.Forte@Sun.COM 						k->notice->key = NULL;
522*7836SJohn.Forte@Sun.COM 						free(k);
523*7836SJohn.Forte@Sun.COM 					}
524*7836SJohn.Forte@Sun.COM 				}
525*7836SJohn.Forte@Sun.COM 				/* delete the match notice */
526*7836SJohn.Forte@Sun.COM 				n->pred->sucd = n->sucd;
527*7836SJohn.Forte@Sun.COM 				n->sucd->pred = n->pred;
528*7836SJohn.Forte@Sun.COM 				/* update current */
529*7836SJohn.Forte@Sun.COM 				if (n == curr) {
530*7836SJohn.Forte@Sun.COM 					n2 = n->sucd;
531*7836SJohn.Forte@Sun.COM 					while (n2 != NULL && n2->isdummy) {
532*7836SJohn.Forte@Sun.COM 						n2 = n2->sucd;
533*7836SJohn.Forte@Sun.COM 					}
534*7836SJohn.Forte@Sun.COM 					curr = n2;
535*7836SJohn.Forte@Sun.COM 				}
536*7836SJohn.Forte@Sun.COM 				free(n);
537*7836SJohn.Forte@Sun.COM 			}
538*7836SJohn.Forte@Sun.COM 			break; /* exit while loop */
539*7836SJohn.Forte@Sun.COM 		}
540*7836SJohn.Forte@Sun.COM 		n = n->sucd;
541*7836SJohn.Forte@Sun.COM 	}
542*7836SJohn.Forte@Sun.COM 
543*7836SJohn.Forte@Sun.COM 	(void) pthread_mutex_unlock(&el_mtx);
544*7836SJohn.Forte@Sun.COM 
545*7836SJohn.Forte@Sun.COM 	return (0);
546*7836SJohn.Forte@Sun.COM }
547*7836SJohn.Forte@Sun.COM 
548*7836SJohn.Forte@Sun.COM /*
549*7836SJohn.Forte@Sun.COM  * ****************************************************************************
550*7836SJohn.Forte@Sun.COM  *
551*7836SJohn.Forte@Sun.COM  * el_first:
552*7836SJohn.Forte@Sun.COM  *	Fetch the first event from the element list.
553*7836SJohn.Forte@Sun.COM  *
554*7836SJohn.Forte@Sun.COM  * t	- Pointer of time of the event for returning.
555*7836SJohn.Forte@Sun.COM  * return - The event.
556*7836SJohn.Forte@Sun.COM  *
557*7836SJohn.Forte@Sun.COM  * ****************************************************************************
558*7836SJohn.Forte@Sun.COM  */
559*7836SJohn.Forte@Sun.COM void *
el_first(uint32_t * t)560*7836SJohn.Forte@Sun.COM el_first(
561*7836SJohn.Forte@Sun.COM 	uint32_t *t
562*7836SJohn.Forte@Sun.COM )
563*7836SJohn.Forte@Sun.COM {
564*7836SJohn.Forte@Sun.COM 	void *p = NULL;
565*7836SJohn.Forte@Sun.COM 
566*7836SJohn.Forte@Sun.COM 	el_notice_t *n;
567*7836SJohn.Forte@Sun.COM 	el_key_t *k;
568*7836SJohn.Forte@Sun.COM 
569*7836SJohn.Forte@Sun.COM 	(void) pthread_mutex_lock(&el_mtx);
570*7836SJohn.Forte@Sun.COM 
571*7836SJohn.Forte@Sun.COM 	if (curr != NULL) {
572*7836SJohn.Forte@Sun.COM 		/* remove current from the event set */
573*7836SJohn.Forte@Sun.COM 		curr->pred->sucd = curr->sucd;
574*7836SJohn.Forte@Sun.COM 		curr->sucd->pred = curr->pred;
575*7836SJohn.Forte@Sun.COM 
576*7836SJohn.Forte@Sun.COM 		/* decrease number of notice */
577*7836SJohn.Forte@Sun.COM 		n = curr;
578*7836SJohn.Forte@Sun.COM 		while (n->key == NULL) {
579*7836SJohn.Forte@Sun.COM 			n = n->sucd;
580*7836SJohn.Forte@Sun.COM 		}
581*7836SJohn.Forte@Sun.COM 		k = n->key;
582*7836SJohn.Forte@Sun.COM 		k->count --;
583*7836SJohn.Forte@Sun.COM 
584*7836SJohn.Forte@Sun.COM 		/* empty not-dummy key */
585*7836SJohn.Forte@Sun.COM 		if (k->count == 0) {
586*7836SJohn.Forte@Sun.COM 			k->left->right = k->right;
587*7836SJohn.Forte@Sun.COM 			k->right->left = k->left;
588*7836SJohn.Forte@Sun.COM 			free(k);
589*7836SJohn.Forte@Sun.COM 		}
590*7836SJohn.Forte@Sun.COM 
591*7836SJohn.Forte@Sun.COM 		/* get next notice */
592*7836SJohn.Forte@Sun.COM 		n = curr->sucd;
593*7836SJohn.Forte@Sun.COM 		while (n != NULL && n->isdummy) {
594*7836SJohn.Forte@Sun.COM 			n = n->sucd;
595*7836SJohn.Forte@Sun.COM 		}
596*7836SJohn.Forte@Sun.COM 
597*7836SJohn.Forte@Sun.COM 		/* return the time */
598*7836SJohn.Forte@Sun.COM 		*t = curr->time;
599*7836SJohn.Forte@Sun.COM 		/* reset current notice */
600*7836SJohn.Forte@Sun.COM 		p = curr->event;
601*7836SJohn.Forte@Sun.COM 		free(curr);
602*7836SJohn.Forte@Sun.COM 		curr = n;
603*7836SJohn.Forte@Sun.COM 	}
604*7836SJohn.Forte@Sun.COM 
605*7836SJohn.Forte@Sun.COM 	/* the one that is being handled by esi_proc */
606*7836SJohn.Forte@Sun.COM 	if (p) {
607*7836SJohn.Forte@Sun.COM 		evl_append(p);
608*7836SJohn.Forte@Sun.COM 	}
609*7836SJohn.Forte@Sun.COM 
610*7836SJohn.Forte@Sun.COM 	(void) pthread_mutex_unlock(&el_mtx);
611*7836SJohn.Forte@Sun.COM 
612*7836SJohn.Forte@Sun.COM 	if (p) {
613*7836SJohn.Forte@Sun.COM 		isnslog(LOG_DEBUG, "el_first", "%s [%d] is fetched.",
614*7836SJohn.Forte@Sun.COM 		    ((ev_t *)p)->type == EV_ESI ? "ESI" : "REG_EXP",
615*7836SJohn.Forte@Sun.COM 		    ((ev_t *)p)->uid);
616*7836SJohn.Forte@Sun.COM 	}
617*7836SJohn.Forte@Sun.COM 
618*7836SJohn.Forte@Sun.COM 	return (p);
619*7836SJohn.Forte@Sun.COM }
620