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