|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
This file is provided under a dual BSD/GPLv2 license. When using or
|
|
Packit |
961e70 |
redistributing this file, you may do so under either license.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
GPL LICENSE SUMMARY
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
Copyright(c) 2015 Intel Corporation.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
This program is free software; you can redistribute it and/or modify
|
|
Packit |
961e70 |
it under the terms of version 2 of the GNU General Public License as
|
|
Packit |
961e70 |
published by the Free Software Foundation.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
This program is distributed in the hope that it will be useful, but
|
|
Packit |
961e70 |
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
961e70 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
961e70 |
General Public License for more details.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
Contact Information:
|
|
Packit |
961e70 |
Intel Corporation, www.intel.com
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
BSD LICENSE
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
Copyright(c) 2015 Intel Corporation.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
Redistribution and use in source and binary forms, with or without
|
|
Packit |
961e70 |
modification, are permitted provided that the following conditions
|
|
Packit |
961e70 |
are met:
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
* Redistributions of source code must retain the above copyright
|
|
Packit |
961e70 |
notice, this list of conditions and the following disclaimer.
|
|
Packit |
961e70 |
* Redistributions in binary form must reproduce the above copyright
|
|
Packit |
961e70 |
notice, this list of conditions and the following disclaimer in
|
|
Packit |
961e70 |
the documentation and/or other materials provided with the
|
|
Packit |
961e70 |
distribution.
|
|
Packit |
961e70 |
* Neither the name of Intel Corporation nor the names of its
|
|
Packit |
961e70 |
contributors may be used to endorse or promote products derived
|
|
Packit |
961e70 |
from this software without specific prior written permission.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit |
961e70 |
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit |
961e70 |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
Packit |
961e70 |
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
Packit |
961e70 |
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
Packit |
961e70 |
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
Packit |
961e70 |
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
Packit |
961e70 |
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
Packit |
961e70 |
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
Packit |
961e70 |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
Packit |
961e70 |
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Copyright (c) 2003-2014 Intel Corporation. All rights reserved. */
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
#include "psm_user.h"
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
#if PSMI_TIMER_STATS
|
|
Packit |
961e70 |
# define PSMI_TIMER_STATS_ADD_INSERTION(ctrl) ((ctrl)->num_insertions++)
|
|
Packit |
961e70 |
# define PSMI_TIMER_STATS_ADD_TRAVERSAL(ctrl) ((ctrl)->num_traversals++)
|
|
Packit |
961e70 |
#else
|
|
Packit |
961e70 |
# define PSMI_TIMER_STATS_ADD_INSERTION(ctrl)
|
|
Packit |
961e70 |
# define PSMI_TIMER_STATS_ADD_TRAVERSAL(ctrl)
|
|
Packit |
961e70 |
#endif
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
psm2_error_t psmi_timer_init(struct psmi_timer_ctrl *ctrl)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
ctrl->t_cyc_next_expire = PSMI_TIMER_INFINITE;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
#if PSMI_TIMER_STATS
|
|
Packit |
961e70 |
ctrl->num_insertions = 0;
|
|
Packit |
961e70 |
ctrl->num_traversals = 0;
|
|
Packit |
961e70 |
#endif
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
TAILQ_INIT(&ctrl->timerq);
|
|
Packit |
961e70 |
return PSM2_OK;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
psm2_error_t psmi_timer_fini(struct psmi_timer_ctrl *ctrl)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
#if PSMI_TIMER_STATS
|
|
Packit |
961e70 |
if (ctrl->num_insertions > 0) {
|
|
Packit |
961e70 |
_HFI_INFO("avg elem traversals/insertion = %3.2f %%\n",
|
|
Packit |
961e70 |
100.0 * (double)ctrl->num_traversals /
|
|
Packit |
961e70 |
ctrl->num_insertions);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
#endif
|
|
Packit |
961e70 |
return PSM2_OK;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
void
|
|
Packit |
961e70 |
psmi_timer_request_always(struct psmi_timer_ctrl *ctrl,
|
|
Packit |
961e70 |
struct psmi_timer *t_insert, uint64_t t_cyc_expire)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct psmi_timer *t_cursor;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
psmi_assert(!(t_insert->flags & PSMI_TIMER_FLAG_PENDING));
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
t_insert->t_timeout = t_cyc_expire;
|
|
Packit |
961e70 |
t_insert->flags |= PSMI_TIMER_FLAG_PENDING;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* We keep the list from oldest (head) to newest (tail), with the
|
|
Packit |
961e70 |
* assumption that insert and remove occur much more often than search
|
|
Packit |
961e70 |
* (when the timer expires). Newly added timers are more likely to expire
|
|
Packit |
961e70 |
* later rather than sooner, which is why the head is older.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
PSMI_TIMER_STATS_ADD_INSERTION(ctrl);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (TAILQ_EMPTY(&ctrl->timerq)) { /* Common case */
|
|
Packit |
961e70 |
TAILQ_INSERT_TAIL(&ctrl->timerq, t_insert, timer);
|
|
Packit |
961e70 |
ctrl->t_cyc_next_expire = t_cyc_expire;
|
|
Packit |
961e70 |
PSMI_TIMER_STATS_ADD_TRAVERSAL(ctrl);
|
|
Packit |
961e70 |
return;
|
|
Packit |
961e70 |
} else if (t_cyc_expire > PSMI_TIMER_PRIO_LAST) {
|
|
Packit |
961e70 |
TAILQ_FOREACH(t_cursor, &ctrl->timerq, timer) {
|
|
Packit |
961e70 |
if (t_cursor->t_timeout <= t_cyc_expire) {
|
|
Packit |
961e70 |
TAILQ_INSERT_BEFORE(t_cursor, t_insert, timer);
|
|
Packit |
961e70 |
return;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
PSMI_TIMER_STATS_ADD_TRAVERSAL(ctrl);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
/* Got to the end of the list -- We're the next to expire */
|
|
Packit |
961e70 |
ctrl->t_cyc_next_expire = t_cyc_expire;
|
|
Packit |
961e70 |
TAILQ_INSERT_TAIL(&ctrl->timerq, t_insert, timer);
|
|
Packit |
961e70 |
return;
|
|
Packit |
961e70 |
} else {
|
|
Packit |
961e70 |
TAILQ_FOREACH_REVERSE(t_cursor, &ctrl->timerq, timerq, timer) {
|
|
Packit |
961e70 |
if (t_cursor->t_timeout >= t_cyc_expire) {
|
|
Packit |
961e70 |
TAILQ_INSERT_AFTER(&ctrl->timerq, t_cursor,
|
|
Packit |
961e70 |
t_insert, timer);
|
|
Packit |
961e70 |
ctrl->t_cyc_next_expire =
|
|
Packit |
961e70 |
min(t_cyc_expire, ctrl->t_cyc_next_expire);
|
|
Packit |
961e70 |
return;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
PSMI_TIMER_STATS_ADD_TRAVERSAL(ctrl);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
TAILQ_INSERT_HEAD(&ctrl->timerq, t_insert, timer);
|
|
Packit |
961e70 |
/* No need to check if we inserted last, given first branch case */
|
|
Packit |
961e70 |
/* if (TAILQ_LAST(&ctrl->timerq, timerq) == t_insert) */
|
|
Packit |
961e70 |
/* ctrl->t_cyc_next_expire = t_cyc_expire; */
|
|
Packit |
961e70 |
return;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
return;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
psm2_error_t
|
|
Packit |
961e70 |
psmi_timer_process_expired(struct psmi_timer_ctrl *ctrl, uint64_t t_cyc_expire)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
psm2_error_t err = PSM2_OK_NO_PROGRESS;
|
|
Packit |
961e70 |
struct psmi_timer *t_cursor = TAILQ_LAST(&ctrl->timerq, timerq);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
PSM2_LOG_MSG("entering");
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
while (t_cursor) {
|
|
Packit |
961e70 |
if (t_cursor->t_timeout > t_cyc_expire)
|
|
Packit |
961e70 |
break;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
err = PSM2_OK;
|
|
Packit |
961e70 |
psmi_assert(t_cursor->flags & PSMI_TIMER_FLAG_PENDING);
|
|
Packit |
961e70 |
t_cursor->flags &= ~PSMI_TIMER_FLAG_PENDING;
|
|
Packit |
961e70 |
TAILQ_REMOVE(&ctrl->timerq, t_cursor, timer);
|
|
Packit |
961e70 |
t_cursor->expire_callback(t_cursor, t_cyc_expire);
|
|
Packit |
961e70 |
t_cursor = TAILQ_PREV(t_cursor, timerq, timer);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (TAILQ_EMPTY(&ctrl->timerq))
|
|
Packit |
961e70 |
ctrl->t_cyc_next_expire = PSMI_TIMER_INFINITE;
|
|
Packit |
961e70 |
else
|
|
Packit |
961e70 |
ctrl->t_cyc_next_expire =
|
|
Packit |
961e70 |
TAILQ_LAST(&ctrl->timerq, timerq)->t_timeout;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
PSM2_LOG_MSG("leaving");
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
void
|
|
Packit |
961e70 |
psmi_timer_cancel_inner(struct psmi_timer_ctrl *ctrl,
|
|
Packit |
961e70 |
struct psmi_timer *t_remove)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
psmi_assert(t_remove->flags & PSMI_TIMER_FLAG_PENDING);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
t_remove->flags &= ~PSMI_TIMER_FLAG_PENDING;
|
|
Packit |
961e70 |
TAILQ_REMOVE(&ctrl->timerq, t_remove, timer);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* If we're removing the last entry, we need to reset the
|
|
Packit |
961e70 |
* expiration cycle time.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
if (TAILQ_EMPTY(&ctrl->timerq))
|
|
Packit |
961e70 |
ctrl->t_cyc_next_expire = PSMI_TIMER_INFINITE;
|
|
Packit |
961e70 |
else
|
|
Packit |
961e70 |
ctrl->t_cyc_next_expire =
|
|
Packit |
961e70 |
TAILQ_LAST(&ctrl->timerq, timerq)->t_timeout;
|
|
Packit |
961e70 |
return;
|
|
Packit |
961e70 |
}
|