summaryrefslogtreecommitdiffstats
path: root/src/h_timer.h
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2016-12-07 15:24:38 +0200
committerHanoh Haim <hhaim@cisco.com>2016-12-21 13:01:05 +0200
commiteae78d4356b8834b78a91c52d869a7949f8f3e90 (patch)
tree184156f8e653adfa33eb0e70838f45d2a92355d0 /src/h_timer.h
parent539de1c6af63071c1da9ed5db668c500f8993a03 (diff)
improve Stateful scheduler
Signed-off-by: Hanoh Haim <hhaim@cisco.com>
Diffstat (limited to 'src/h_timer.h')
-rw-r--r--src/h_timer.h288
1 files changed, 288 insertions, 0 deletions
diff --git a/src/h_timer.h b/src/h_timer.h
new file mode 100644
index 00000000..1d57640b
--- /dev/null
+++ b/src/h_timer.h
@@ -0,0 +1,288 @@
+#ifndef H_TIMER_WHEEL_H
+#define H_TIMER_WHEEL_H
+/*
+ Hanoh Haim
+ Cisco Systems, Inc.
+*/
+
+/*
+Copyright (c) 2015-2015 Cisco Systems, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <common/basic_utils.h>
+#include <stdint.h>
+#include <assert.h>
+#include <rte_prefetch.h>
+#include "pal_utl.h"
+#include "mbuf.h"
+
+
+
+typedef enum {
+ RC_HTW_OK = 0,
+ RC_HTW_ERR_NO_RESOURCES = -1,
+ RC_HTW_ERR_TIMER_IS_ON = -2,
+ RC_HTW_ERR_NO_LOG2 = -3,
+ RC_HTW_ERR_MAX_WHEELS = -4,
+ RC_HTW_ERR_NOT_ENOUGH_BITS = -5,
+
+} RC_HTW_t;
+
+
+
+
+
+class CHTimerWheelLink {
+
+public:
+ CHTimerWheelLink * m_next;
+ CHTimerWheelLink * m_prev;
+
+public:
+ void reset(){
+ m_next = 0;
+ m_prev = 0;
+ }
+ void set_self(){
+ m_next=this;
+ m_prev=this;
+ }
+
+ bool is_self(){
+ if (m_next == this) {
+ return (true);
+ }
+ return (false);
+ }
+
+ void append(CHTimerWheelLink * obj){
+ obj->m_next = this;
+ obj->m_prev = m_prev;
+
+ m_prev->m_next = obj;
+ m_prev = obj;
+ }
+
+ void detach(void){
+ #ifdef HTW_DEBUG
+ assert(m_next);
+ #endif
+ CHTimerWheelLink *next;
+
+ next = m_next;
+ next->m_prev = m_prev;
+ m_prev->m_next = next;
+ m_next=0;
+ m_prev=0;
+ }
+} ;
+
+typedef uint32_t htw_ticks_t;
+
+class CHTimerObj : public CHTimerWheelLink {
+
+public:
+ inline void reset(void){
+ CHTimerWheelLink::reset();
+ m_ticks_left=0;
+ m_wheel=0;
+ }
+
+ inline bool is_running(){
+ if (m_next != 0) {
+ return (true);
+ }
+ return (false);
+ }
+
+
+ void Dump(FILE *fd);
+
+public:
+ /* CACHE LINE 0*/
+ htw_ticks_t m_ticks_left; /* abs ticks left */
+ uint32_t m_wheel;
+
+ uint32_t m_pad[2]; /* aging time in ticks */
+} ;
+
+typedef void (*htw_on_tick_cb_t)(void *userdata,CHTimerObj *tmr);
+
+class CHTimerOneWheel {
+
+public:
+ CHTimerOneWheel(){
+ reset();
+ }
+
+ RC_HTW_t Create(uint32_t wheel_size);
+
+ RC_HTW_t Delete();
+
+ inline RC_HTW_t timer_start(CHTimerObj *tmr,
+ htw_ticks_t ticks){
+
+ #ifdef HTW_DEBUG
+ if ( tmr->is_running() ){
+ return( RC_HTW_ERR_TIMER_IS_ON);
+ }
+ #endif
+
+ append( tmr, ticks);
+ return (RC_HTW_OK);
+ }
+
+ RC_HTW_t timer_stop (CHTimerObj *tmr);
+
+ inline bool check_timer_tick_cycle(){
+ return (m_tick_done);
+ }
+
+
+ inline bool timer_tick(){
+
+ m_ticks++;
+ m_bucket_index++;
+
+ if (m_tick_done) {
+ m_tick_done=false;
+ }
+ if ( m_bucket_index == m_wheel_size ) {
+ m_bucket_index = 0;
+ m_tick_done=true;
+ }
+ m_active_bucket = &m_buckets[m_bucket_index];
+ return (m_tick_done);
+ }
+
+
+ inline CHTimerObj * pop_event(void) {
+
+ if ( m_active_bucket->is_self() ){
+ return ((CHTimerObj *)0);
+ }
+
+ CHTimerWheelLink * first = m_active_bucket->m_next;
+
+ rte_prefetch0(first->m_next);
+
+ first->detach();
+ return ((CHTimerObj *)first);
+ }
+
+
+
+public:
+
+ void dump_link_list(uint32_t bucket_index,
+ void *userdata,
+ htw_on_tick_cb_t cb,
+ FILE *fd);
+
+
+ uint32_t get_bucket_index(void){
+ return ( m_bucket_index);
+ }
+
+private:
+
+ inline void reset(void){
+ m_buckets=0;
+ m_active_bucket=0;
+ m_ticks=0;
+ m_wheel_size=0;
+ m_wheel_mask=0;
+ m_bucket_index=0;
+ m_tick_done=false;
+ }
+
+
+ inline void append (CHTimerObj *tmr,
+ uint32_t ticks) {
+ CHTimerWheelLink *cur;
+
+ uint32_t cursor = ((m_bucket_index + ticks) & m_wheel_mask);
+ cur = &m_buckets[cursor];
+
+ cur->append((CHTimerWheelLink *)tmr);
+ }
+
+private:
+ CHTimerWheelLink * m_buckets;
+ CHTimerWheelLink * m_active_bucket; /* point to the current bucket m_buckets[m_bucket_index] */
+
+ htw_ticks_t m_ticks;
+ uint32_t m_wheel_size; //e.g. 256
+ uint32_t m_wheel_mask; // 256-1
+ uint32_t m_bucket_index;
+ bool m_tick_done;
+};
+
+
+
+
+#define MAX_H_TIMER_WHEELS (4)
+
+class CHTimerWheel {
+
+public:
+ CHTimerWheel(){
+ reset();
+ }
+
+ RC_HTW_t Create(uint32_t wheel_size,
+ uint32_t num_wheels);
+
+ RC_HTW_t Delete();
+
+ inline RC_HTW_t timer_start(CHTimerObj *tmr,
+ htw_ticks_t ticks){
+ m_total_events++;
+ if (likely(ticks<m_wheel_size)) {
+ tmr->m_ticks_left=0;
+ tmr->m_wheel=0;
+ return (m_timer_w[0].timer_start(tmr,ticks));
+ }
+ return ( timer_start_rest(tmr, ticks));
+ }
+
+ RC_HTW_t timer_stop (CHTimerObj *tmr);
+
+ void on_tick(void *userdata,htw_on_tick_cb_t cb);
+
+ bool is_any_events_left(){
+ return(m_total_events>0?true:false);
+ }
+
+
+
+private:
+ void reset(void);
+
+ RC_HTW_t timer_start_rest(CHTimerObj *tmr,
+ htw_ticks_t ticks);
+
+private:
+ htw_ticks_t m_ticks;
+ uint32_t m_num_wheels;
+ uint32_t m_wheel_size; //e.g. 256
+ uint32_t m_wheel_mask; //e.g 256-1
+ uint32_t m_wheel_shift; // e.g 8
+ uint64_t m_total_events;
+ CHTimerOneWheel m_timer_w[MAX_H_TIMER_WHEELS];
+} ;
+
+
+#endif