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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
33 #include "isns_server.h"
34 #include "isns_protocol.h"
36 #include "isns_sched.h"
47 pthread_mutex_t el_mtx
= PTHREAD_MUTEX_INITIALIZER
;
54 static el_notice_t
*curr
= NULL
;
70 * ****************************************************************************
73 * Shift the indexed-list to the most current time.
75 * t - most current time.
77 * ****************************************************************************
93 /* remove the dummy key and dummy notice */
94 fk
->left
->right
= fk
->right
;
95 fk
->right
->left
= fk
->left
;
96 fn
->pred
->sucd
= fn
->sucd
;
97 fn
->sucd
->pred
= fn
->pred
;
99 /* find the place where the dummy goes to */
100 k
= il
[(icurr
+ DU
- 1) % DU
];
101 if (k
->time
< INFINITY
- DT
) {
102 nt
= k
->time
+ DT
; /* next key time */
104 nt
= INFINITY
- 1; /* the last second */
106 while (k
->time
< nt
) {
111 while (n
->time
>= nt
) {
117 /* update lower bound */
120 /* insert the dummy key */
122 fk
->count
= k
->count
- c
+ 1;
128 /* insert the dummy notice */
135 /* shift the current index */
136 icurr
= (icurr
+ 1) % DU
;
146 * ****************************************************************************
149 * Initialize the element list.
151 * du - Number of uint in the indexed-list.
152 * dt - Time interval of the indexed-list.
153 * nlim - Limit number of each notice.
154 * return - 0: successful, otherwise failed.
156 * ****************************************************************************
166 el_notice_t
*n
, *npred
;
172 if (du
< 1 || dt
< 1 || nlim
< 1) {
182 * initialize the event set
185 /* first dummy notice */
186 n
= (el_notice_t
*)malloc(sizeof (el_notice_t
));
196 /* first dummy key */
197 k
= (el_key_t
*)malloc(sizeof (el_key_t
));
210 il
= (el_key_t
**)malloc((DU
+ 1) * sizeof (el_key_t
*));
215 /* create notice list, key list & index list */
216 for (i
= 0; i
< DU
; i
++) {
219 n
= (el_notice_t
*)malloc(sizeof (el_notice_t
));
230 k
= (el_key_t
*)malloc(sizeof (el_key_t
));
246 /* last dummy notice */
247 n
= (el_notice_t
*)malloc(sizeof (el_notice_t
));
251 n
->time
= INFINITY
; /* the end of the world */
259 k
= (el_key_t
*)malloc(sizeof (el_key_t
));
263 k
->time
= INFINITY
; /* the end of the world */
279 * ****************************************************************************
282 * Add an event to the element list with it's execution time.
283 * It might not actually put the event to the list if the event
284 * is the most current one for execution.
287 * t - The time when the event is scheduled at.
288 * evp - Pointer of event for returning.
289 * return - Error code.
291 * ****************************************************************************
311 /* lock the event set */
312 (void) pthread_mutex_lock(&el_mtx
);
314 /* strip it off from the event list which is being handled */
315 if (evf_again(ev
) != 0) {
316 /* if it is rescheduling an event and the event */
317 /* was waiting for execution after idle finishes */
318 if (evf_rem(ev
) == 0 &&
320 (curr
== NULL
|| t
<= curr
->time
)) {
321 /* no need to reschedule it */
326 /* if it is marked as a removed event, do not add it */
327 if (evf_rem(ev
) != 0) {
333 /* get the index in the il */
336 /* not initialization time */
337 if (evf_init(ev
) || evf_again(ev
)) {
338 t1
= get_stopwatch(evf_wakeup(ev
));
339 /* make il up to date */
342 if (t1
>= INFINITY
- t
) {
343 /* the last second */
344 t1
= INFINITY
- t1
- 1;
353 i
= (i
+ icurr
) % DU
;
356 /* find the right key */
358 while (k
->time
> t
) {
364 if (k
->count
== NLIM
) {
365 /* insert a new key */
366 y
= (el_key_t
*)malloc(sizeof (el_key_t
));
368 ec
= ISNS_RSP_INTERNAL_ERROR
;
373 for (j
= 1; j
<= NLIM
/ 2; j
++) {
377 y
->count
= NLIM
- NLIM
/ 2;
393 /* make a new notice */
394 x
= (el_notice_t
*)malloc(sizeof (el_notice_t
));
396 ec
= ISNS_RSP_INTERNAL_ERROR
;
406 while (n
->time
> t
) {
414 /* increase number of notice */
417 /* reset current notice and wake up idle */
418 if (curr
== NULL
|| curr
->time
> t
) {
422 /* clear event flags */
425 isnslog(LOG_DEBUG
, "el_add", "%s [%d] is scheduled at %d.",
426 ((ev_t
*)ev
)->type
== EV_ESI
? "ESI" : "REG_EXP",
431 /* unlock the event set */
432 (void) pthread_mutex_unlock(&el_mtx
);
434 /* failed, free it */
437 isnslog(LOG_DEBUG
, "el_add", "failed, no memory.");
444 * ****************************************************************************
447 * Remove or update an event from the element list. If the event is
448 * currently not in the element list, it must be in a queue which
449 * contains all of event which are being executing at the moment.
450 * So it seeks the event from the list prior to the element list.
452 * id1 - The event ID.
453 * id2 - The second ID for the event update.
454 * pending - Do not actually remove, mark it for removal pending.
455 * return - Error code.
457 * ****************************************************************************
466 el_key_t
*k
, *kl
, *kr
;
469 (void) pthread_mutex_lock(&el_mtx
);
471 /* search the event from the event list which is being handled */
472 if (evl_remove(id1
, id2
, pending
) != 0) {
473 (void) pthread_mutex_unlock(&el_mtx
);
477 /* search the notice starting from current */
480 /* found the match notice */
481 if (!n
->isdummy
&& ev_match(n
->event
, id1
) != 0) {
482 if (ev_remove(n
->event
, id2
, 1, pending
) == 0) {
483 /* update the key of the match notice */
485 if (k
!= NULL
&& k
->count
== 1) {
487 k
->left
->right
= k
->right
;
488 k
->right
->left
= k
->left
;
494 k
->time
= k
->notice
->time
;
502 /* decrease the count by one */
507 if (!kl
->notice
->isdummy
&&
508 (kl
->count
+ k
->count
) <= NLIM
) {
509 /* delete the left key */
510 k
->count
+= kl
->count
;
513 kl
->notice
->key
= NULL
;
515 } else if (!k
->notice
->isdummy
&&
516 (kr
->count
+ k
->count
) <= NLIM
) {
517 /* delete this key */
518 kr
->count
+= k
->count
;
520 kr
->left
->right
= kr
;
521 k
->notice
->key
= NULL
;
525 /* delete the match notice */
526 n
->pred
->sucd
= n
->sucd
;
527 n
->sucd
->pred
= n
->pred
;
531 while (n2
!= NULL
&& n2
->isdummy
) {
538 break; /* exit while loop */
543 (void) pthread_mutex_unlock(&el_mtx
);
549 * ****************************************************************************
552 * Fetch the first event from the element list.
554 * t - Pointer of time of the event for returning.
555 * return - The event.
557 * ****************************************************************************
569 (void) pthread_mutex_lock(&el_mtx
);
572 /* remove current from the event set */
573 curr
->pred
->sucd
= curr
->sucd
;
574 curr
->sucd
->pred
= curr
->pred
;
576 /* decrease number of notice */
578 while (n
->key
== NULL
) {
584 /* empty not-dummy key */
586 k
->left
->right
= k
->right
;
587 k
->right
->left
= k
->left
;
591 /* get next notice */
593 while (n
!= NULL
&& n
->isdummy
) {
597 /* return the time */
599 /* reset current notice */
605 /* the one that is being handled by esi_proc */
610 (void) pthread_mutex_unlock(&el_mtx
);
613 isnslog(LOG_DEBUG
, "el_first", "%s [%d] is fetched.",
614 ((ev_t
*)p
)->type
== EV_ESI
? "ESI" : "REG_EXP",