cl_event_wheel.c revision 285830
167754Smsmith/* 267754Smsmith * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved. 377424Smsmith * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 467754Smsmith * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 567754Smsmith * 667754Smsmith * This software is available to you under a choice of one of two 7217365Sjkim * licenses. You may choose to be licensed under the terms of the GNU 8281075Sdim * General Public License (GPL) Version 2, available from the file 970243Smsmith * COPYING in the main directory of this source tree, or the 1067754Smsmith * OpenIB.org BSD license below: 11217365Sjkim * 12217365Sjkim * Redistribution and use in source and binary forms, with or 13217365Sjkim * without modification, are permitted provided that the following 14217365Sjkim * conditions are met: 15217365Sjkim * 16217365Sjkim * - Redistributions of source code must retain the above 17217365Sjkim * copyright notice, this list of conditions and the following 18217365Sjkim * disclaimer. 19217365Sjkim * 20217365Sjkim * - Redistributions in binary form must reproduce the above 21217365Sjkim * copyright notice, this list of conditions and the following 22217365Sjkim * disclaimer in the documentation and/or other materials 23217365Sjkim * provided with the distribution. 24217365Sjkim * 2567754Smsmith * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26217365Sjkim * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27217365Sjkim * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28217365Sjkim * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2967754Smsmith * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30217365Sjkim * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31217365Sjkim * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32217365Sjkim * SOFTWARE. 33217365Sjkim * 34217365Sjkim */ 35217365Sjkim 36217365Sjkim#if HAVE_CONFIG_H 37217365Sjkim# include <config.h> 38217365Sjkim#endif /* HAVE_CONFIG_H */ 39217365Sjkim 40217365Sjkim#include <math.h> 41217365Sjkim#include <stdlib.h> 42217365Sjkim#include <complib/cl_event_wheel.h> 4367754Smsmith#include <complib/cl_debug.h> 44193341Sjkim 45193341Sjkim#define CL_DBG(fmt, arg...) 46193341Sjkim 4767754Smsmithstatic cl_status_t 4877424Smsmith__event_will_age_before(IN const cl_list_item_t * const p_list_item, 4991116Smsmith IN void *context) 5067754Smsmith{ 5167754Smsmith uint64_t aging_time = *((uint64_t *) context); 52281075Sdim cl_event_wheel_reg_info_t *p_event; 5383174Smsmith 54151937Sjkim p_event = 5567754Smsmith PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); 56151937Sjkim 57151937Sjkim if (p_event->aging_time < aging_time) 58151937Sjkim return CL_SUCCESS; 59151937Sjkim else 6067754Smsmith return CL_NOT_FOUND; 61151937Sjkim} 62151937Sjkim 63151937Sjkimstatic void __cl_event_wheel_callback(IN void *context) 64151937Sjkim{ 6567754Smsmith cl_event_wheel_t *p_event_wheel = (cl_event_wheel_t *) context; 66151937Sjkim cl_list_item_t *p_list_item, *p_prev_event_list_item; 67151937Sjkim cl_list_item_t *p_list_next_item; 68151937Sjkim cl_event_wheel_reg_info_t *p_event; 69151937Sjkim uint64_t current_time; 7083174Smsmith uint64_t next_aging_time; 71151937Sjkim uint32_t new_timeout; 72151937Sjkim cl_status_t cl_status; 73151937Sjkim 74151937Sjkim /* might be during closing ... */ 7583174Smsmith if (p_event_wheel->closing) 76151937Sjkim return; 77151937Sjkim 78151937Sjkim current_time = cl_get_time_stamp(); 79151937Sjkim 8067754Smsmith if (NULL != p_event_wheel->p_external_lock) 81151937Sjkim 82151937Sjkim /* Take care of the order of acquiring locks to avoid the deadlock! 83151937Sjkim * The external lock goes first. 8467754Smsmith */ 85151937Sjkim cl_spinlock_acquire(p_event_wheel->p_external_lock); 86151937Sjkim 87151937Sjkim cl_spinlock_acquire(&p_event_wheel->lock); 88151937Sjkim 8967754Smsmith p_list_item = cl_qlist_head(&p_event_wheel->events_wheel); 90151937Sjkim if (p_list_item == cl_qlist_end(&p_event_wheel->events_wheel)) 91228110Sjkim /* the list is empty - nothing to do */ 92228110Sjkim goto Exit; 93228110Sjkim 94228110Sjkim /* we found such an item. get the p_event */ 95228110Sjkim p_event = 96151937Sjkim PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); 97151937Sjkim 98151937Sjkim while (p_event->aging_time <= current_time) { 9967754Smsmith /* this object has aged - invoke it's callback */ 100151937Sjkim if (p_event->pfn_aged_callback) 101151937Sjkim next_aging_time = 102151937Sjkim p_event->pfn_aged_callback(p_event->key, 103151937Sjkim p_event->num_regs, 10467754Smsmith p_event->context); 105151937Sjkim else 106151937Sjkim next_aging_time = 0; 107151937Sjkim 10867754Smsmith /* point to the next object in the wheel */ 109151937Sjkim p_list_next_item = cl_qlist_next(p_list_item); 110151937Sjkim 111151937Sjkim /* We need to retire the event if the next aging time passed */ 11267754Smsmith if (next_aging_time < current_time) { 113151937Sjkim /* remove it from the map */ 114151937Sjkim cl_qmap_remove_item(&p_event_wheel->events_map, 115151937Sjkim &(p_event->map_item)); 116151937Sjkim 11767754Smsmith /* pop p_event from the wheel */ 11867754Smsmith cl_qlist_remove_head(&p_event_wheel->events_wheel); 11967754Smsmith 12067754Smsmith /* delete the event info object - allocated by cl_event_wheel_reg */ 121151937Sjkim free(p_event); 12267754Smsmith } else { 123245582Sjkim /* update the required aging time */ 124245582Sjkim p_event->aging_time = next_aging_time; 12567754Smsmith p_event->num_regs++; 12677424Smsmith 12767754Smsmith /* do not remove from the map - but remove from the list head and 128245582Sjkim place in the correct position */ 12967754Smsmith 13067754Smsmith /* pop p_event from the wheel */ 13167754Smsmith cl_qlist_remove_head(&p_event_wheel->events_wheel); 132151937Sjkim 133151937Sjkim /* find the event that ages just before */ 134151937Sjkim p_prev_event_list_item = 135151937Sjkim cl_qlist_find_from_tail(&p_event_wheel-> 13667754Smsmith events_wheel, 137167802Sjkim __event_will_age_before, 138167802Sjkim &p_event->aging_time); 139151937Sjkim 140151937Sjkim /* insert just after */ 14167754Smsmith cl_qlist_insert_next(&p_event_wheel->events_wheel, 14267754Smsmith p_prev_event_list_item, 143151937Sjkim &p_event->list_item); 14483174Smsmith 145151937Sjkim /* as we have modified the list - restart from first item: */ 14683174Smsmith p_list_next_item = 147151937Sjkim cl_qlist_head(&p_event_wheel->events_wheel); 14867754Smsmith } 149151937Sjkim 150167802Sjkim /* advance to next event */ 151151937Sjkim p_list_item = p_list_next_item; 15267754Smsmith if (p_list_item == cl_qlist_end(&p_event_wheel->events_wheel)) 153151937Sjkim /* the list is empty - nothing to do */ 154151937Sjkim break; 155151937Sjkim 156151937Sjkim /* get the p_event */ 157151937Sjkim p_event = 158151937Sjkim PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, 159151937Sjkim list_item); 160151937Sjkim } 161151937Sjkim 162151937Sjkim /* We need to restart the timer only if the list is not empty now */ 163151937Sjkim if (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) { 16467754Smsmith /* get the p_event */ 165151937Sjkim p_event = 16667754Smsmith PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, 167151937Sjkim list_item); 168250838Sjkim 169167802Sjkim /* start the timer to the timeout [msec] */ 170151937Sjkim new_timeout = 17167754Smsmith (uint32_t) (((p_event->aging_time - current_time) / 1000) + 172151937Sjkim 0.5); 173250838Sjkim CL_DBG("__cl_event_wheel_callback: Restart timer in: " 174167802Sjkim "%u [msec]\n", new_timeout); 175151937Sjkim cl_status = cl_timer_start(&p_event_wheel->timer, new_timeout); 17667754Smsmith if (cl_status != CL_SUCCESS) { 177151937Sjkim CL_DBG("__cl_event_wheel_callback : ERR 6100: " 17867754Smsmith "Failed to start timer\n"); 179151937Sjkim } 180250838Sjkim } 181228110Sjkim 182228110Sjkim /* release the lock */ 183228110SjkimExit: 184228110Sjkim cl_spinlock_release(&p_event_wheel->lock); 185228110Sjkim if (NULL != p_event_wheel->p_external_lock) 186228110Sjkim cl_spinlock_release(p_event_wheel->p_external_lock); 187228110Sjkim} 188228110Sjkim 189228110Sjkim/* 190151937Sjkim * Construct and Initialize 19183174Smsmith */ 192151937Sjkimvoid cl_event_wheel_construct(IN cl_event_wheel_t * const p_event_wheel) 193250838Sjkim{ 194167802Sjkim cl_spinlock_construct(&(p_event_wheel->lock)); 195151937Sjkim cl_timer_construct(&(p_event_wheel->timer)); 19683174Smsmith} 197151937Sjkim 198250838Sjkimcl_status_t 199167802Sjkimcl_event_wheel_init(IN cl_event_wheel_t * const p_event_wheel) 200151937Sjkim{ 20167754Smsmith cl_status_t cl_status = CL_SUCCESS; 202151937Sjkim 203252279Sjkim /* initialize */ 204167802Sjkim p_event_wheel->p_external_lock = NULL; 205151937Sjkim p_event_wheel->closing = FALSE; 20667754Smsmith cl_status = cl_spinlock_init(&(p_event_wheel->lock)); 207151937Sjkim if (cl_status != CL_SUCCESS) 20867754Smsmith return cl_status; 209151937Sjkim cl_qlist_init(&p_event_wheel->events_wheel); 210250838Sjkim cl_qmap_init(&p_event_wheel->events_map); 211167802Sjkim 212167802Sjkim /* init the timer with timeout */ 213151937Sjkim cl_status = cl_timer_init(&p_event_wheel->timer, __cl_event_wheel_callback, p_event_wheel); /* cb context */ 21467754Smsmith 215151937Sjkim return cl_status; 216250838Sjkim} 217167802Sjkim 218167802Sjkimcl_status_t 219151937Sjkimcl_event_wheel_init_ex(IN cl_event_wheel_t * const p_event_wheel, 22067754Smsmith IN cl_spinlock_t * p_external_lock) 221228110Sjkim{ 222250838Sjkim cl_status_t cl_status; 223228110Sjkim 224228110Sjkim cl_status = cl_event_wheel_init(p_event_wheel); 225228110Sjkim if (CL_SUCCESS != cl_status) 226228110Sjkim return cl_status; 227151937Sjkim 228151937Sjkim p_event_wheel->p_external_lock = p_external_lock; 229151937Sjkim return cl_status; 230151937Sjkim} 231151937Sjkim 232151937Sjkimvoid cl_event_wheel_dump(IN cl_event_wheel_t * const p_event_wheel) 233151937Sjkim{ 234151937Sjkim cl_list_item_t *p_list_item; 235167802Sjkim cl_event_wheel_reg_info_t *p_event; 236151937Sjkim 237151937Sjkim p_list_item = cl_qlist_head(&p_event_wheel->events_wheel); 23867754Smsmith 239228110Sjkim while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) { 240228110Sjkim p_event = 241228110Sjkim PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, 242228110Sjkim list_item); 243228110Sjkim CL_DBG("cl_event_wheel_dump: Found event key:<0x%" 244228110Sjkim PRIx64 ">, aging time:%" PRIu64 "\n", 245228110Sjkim p_event->key, p_event->aging_time); 246228110Sjkim p_list_item = cl_qlist_next(p_list_item); 247228110Sjkim } 248228110Sjkim} 249228110Sjkim 250228110Sjkimvoid cl_event_wheel_destroy(IN cl_event_wheel_t * const p_event_wheel) 251228110Sjkim{ 252151937Sjkim cl_list_item_t *p_list_item; 253151937Sjkim cl_map_item_t *p_map_item; 254151937Sjkim cl_event_wheel_reg_info_t *p_event; 255151937Sjkim 256151937Sjkim /* we need to get a lock */ 257151937Sjkim cl_spinlock_acquire(&p_event_wheel->lock); 258151937Sjkim 259167802Sjkim cl_event_wheel_dump(p_event_wheel); 260151937Sjkim 261151937Sjkim /* go over all the items in the list and remove them */ 26267754Smsmith p_list_item = cl_qlist_remove_head(&p_event_wheel->events_wheel); 263151937Sjkim while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) { 264151937Sjkim p_event = 265151937Sjkim PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, 266151937Sjkim list_item); 267151937Sjkim 268151937Sjkim CL_DBG("cl_event_wheel_destroy: Found outstanding event" 269151937Sjkim " key:<0x%" PRIx64 ">\n", p_event->key); 270167802Sjkim 271167802Sjkim /* remove it from the map */ 272151937Sjkim p_map_item = &(p_event->map_item); 273151937Sjkim cl_qmap_remove_item(&p_event_wheel->events_map, p_map_item); 27467754Smsmith free(p_event); /* allocated by cl_event_wheel_reg */ 275228110Sjkim p_list_item = 276228110Sjkim cl_qlist_remove_head(&p_event_wheel->events_wheel); 277228110Sjkim } 278228110Sjkim 279228110Sjkim /* destroy the timer */ 280228110Sjkim cl_timer_destroy(&p_event_wheel->timer); 281228110Sjkim 282228110Sjkim /* destroy the lock (this should be done without releasing - we don't want 283228110Sjkim any other run to grab the lock at this point. */ 284228110Sjkim cl_spinlock_release(&p_event_wheel->lock); 285228110Sjkim cl_spinlock_destroy(&(p_event_wheel->lock)); 286228110Sjkim} 287151937Sjkim 288151937Sjkimcl_status_t 289151937Sjkimcl_event_wheel_reg(IN cl_event_wheel_t * const p_event_wheel, 290151937Sjkim IN const uint64_t key, 291167802Sjkim IN const uint64_t aging_time_usec, 292151937Sjkim IN cl_pfn_event_aged_cb_t pfn_callback, 29367754Smsmith IN void *const context) 294151937Sjkim{ 295151937Sjkim cl_event_wheel_reg_info_t *p_event; 296151937Sjkim uint64_t timeout; 297151937Sjkim uint32_t to; 298167802Sjkim cl_status_t cl_status = CL_SUCCESS; 299151937Sjkim cl_list_item_t *prev_event_list_item; 30067754Smsmith cl_map_item_t *p_map_item; 301151937Sjkim 302250838Sjkim /* Get the lock on the manager */ 303151937Sjkim cl_spinlock_acquire(&(p_event_wheel->lock)); 304151937Sjkim 305151937Sjkim cl_event_wheel_dump(p_event_wheel); 306151937Sjkim 30767754Smsmith /* Make sure such a key does not exists */ 308151937Sjkim p_map_item = cl_qmap_get(&p_event_wheel->events_map, key); 309151937Sjkim if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) { 310151937Sjkim CL_DBG("cl_event_wheel_reg: Already exists key:0x%" 31167754Smsmith PRIx64 "\n", key); 31267754Smsmith 31367754Smsmith /* already there - remove it from the list as it is getting a new time */ 31467754Smsmith p_event = 31567754Smsmith PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, 316151937Sjkim map_item); 31767754Smsmith 318151937Sjkim /* remove the item from the qlist */ 31967754Smsmith cl_qlist_remove_item(&p_event_wheel->events_wheel, 320151937Sjkim &p_event->list_item); 32167754Smsmith /* and the qmap */ 322151937Sjkim cl_qmap_remove_item(&p_event_wheel->events_map, 323151937Sjkim &p_event->map_item); 32467754Smsmith } else { 32567754Smsmith /* make a new one */ 32667754Smsmith p_event = (cl_event_wheel_reg_info_t *) 327151937Sjkim malloc(sizeof(cl_event_wheel_reg_info_t)); 328151937Sjkim p_event->num_regs = 0; 329151937Sjkim } 33067754Smsmith 33191116Smsmith p_event->key = key; 33283174Smsmith p_event->aging_time = aging_time_usec; 33383174Smsmith p_event->pfn_aged_callback = pfn_callback; 334151937Sjkim p_event->context = context; 335151937Sjkim p_event->num_regs++; 336151937Sjkim 337151937Sjkim CL_DBG("cl_event_wheel_reg: Registering event key:0x%" PRIx64 33867754Smsmith " aging in %u [msec]\n", p_event->key, 339151937Sjkim (uint32_t) ((p_event->aging_time - 340151937Sjkim cl_get_time_stamp()) / 1000)); 34167754Smsmith 342151937Sjkim /* If the list is empty - need to start the timer */ 343151937Sjkim if (cl_is_qlist_empty(&p_event_wheel->events_wheel)) { 344151937Sjkim /* Edward Bortnikov 03/29/2003 34567754Smsmith * ++TBD Consider moving the timer manipulation behind the list manipulation. 34667754Smsmith */ 34767754Smsmith 34867754Smsmith /* calculate the new timeout */ 34967754Smsmith timeout = 350151937Sjkim (p_event->aging_time - cl_get_time_stamp() + 500) / 1000; 35167754Smsmith 352151937Sjkim /* stop the timer if it is running */ 35367754Smsmith 35477424Smsmith /* Edward Bortnikov 03/29/2003 35567754Smsmith * Don't call cl_timer_stop() because it spins forever. 356151937Sjkim * cl_timer_start() will invoke cl_timer_stop() by itself. 357151937Sjkim * 35867754Smsmith * The problematic scenario is when __cl_event_wheel_callback() 35967754Smsmith * is in race condition with this code. It sets timer.in_timer_cb 36067754Smsmith * to TRUE and then blocks on p_event_wheel->lock. Following this, 361151937Sjkim * the call to cl_timer_stop() hangs. Following this, the whole system 362151937Sjkim * enters into a deadlock. 363151937Sjkim * 36467754Smsmith * cl_timer_stop(&p_event_wheel->timer); 36591116Smsmith */ 36683174Smsmith 36783174Smsmith /* The timeout for the cl_timer_start should be given as uint32_t. 368151937Sjkim if there is an overflow - warn about it. */ 36967754Smsmith to = (uint32_t) timeout; 370151937Sjkim if (timeout > (uint32_t) timeout) { 37167754Smsmith to = 0xffffffff; /* max 32 bit timer */ 37291116Smsmith CL_DBG("cl_event_wheel_reg: timeout requested is " 37367754Smsmith "too large. Using timeout: %u\n", to); 374151937Sjkim } 37567754Smsmith 37667754Smsmith /* start the timer to the timeout [msec] */ 37791116Smsmith cl_status = cl_timer_start(&p_event_wheel->timer, to); 37867754Smsmith if (cl_status != CL_SUCCESS) { 379151937Sjkim CL_DBG("cl_event_wheel_reg : ERR 6103: " 38067754Smsmith "Failed to start timer\n"); 38167754Smsmith goto Exit; 38291116Smsmith } 38367754Smsmith } 384151937Sjkim 38567754Smsmith /* insert the object to the qlist and the qmap */ 38667754Smsmith 38767754Smsmith /* BUT WE MUST INSERT IT IN A SORTED MANNER */ 38867754Smsmith prev_event_list_item = 389151937Sjkim cl_qlist_find_from_tail(&p_event_wheel->events_wheel, 390151937Sjkim __event_will_age_before, 391151937Sjkim &p_event->aging_time); 39267754Smsmith 39367754Smsmith cl_qlist_insert_next(&p_event_wheel->events_wheel, 394151937Sjkim prev_event_list_item, &p_event->list_item); 39567754Smsmith 396151937Sjkim cl_qmap_insert(&p_event_wheel->events_map, key, &(p_event->map_item)); 39767754Smsmith 39867754SmsmithExit: 39967754Smsmith cl_spinlock_release(&p_event_wheel->lock); 40067754Smsmith 40167754Smsmith return cl_status; 402151937Sjkim} 40367754Smsmith 404151937Sjkimvoid 40567754Smsmithcl_event_wheel_unreg(IN cl_event_wheel_t * const p_event_wheel, IN uint64_t key) 40677424Smsmith{ 40767754Smsmith cl_event_wheel_reg_info_t *p_event; 408151937Sjkim cl_map_item_t *p_map_item; 40967754Smsmith 41067754Smsmith CL_DBG("cl_event_wheel_unreg: " "Removing key:0x%" PRIx64 "\n", key); 41167754Smsmith 41267754Smsmith cl_spinlock_acquire(&p_event_wheel->lock); 413151937Sjkim p_map_item = cl_qmap_get(&p_event_wheel->events_map, key); 414151937Sjkim if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) { 41567754Smsmith /* we found such an item. */ 416151937Sjkim p_event = 417151937Sjkim PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, 41867754Smsmith map_item); 41967754Smsmith 42091116Smsmith /* remove the item from the qlist */ 42183174Smsmith cl_qlist_remove_item(&p_event_wheel->events_wheel, 42283174Smsmith &(p_event->list_item)); 423245582Sjkim /* remove the item from the qmap */ 424245582Sjkim cl_qmap_remove_item(&p_event_wheel->events_map, 425245582Sjkim &(p_event->map_item)); 42667754Smsmith 427151937Sjkim CL_DBG("cl_event_wheel_unreg: Removed key:0x%" PRIx64 "\n", 428151937Sjkim key); 42967754Smsmith 430151937Sjkim /* free the item */ 43167754Smsmith free(p_event); 432151937Sjkim } else { 433151937Sjkim CL_DBG("cl_event_wheel_unreg: did not find key:0x%" PRIx64 434151937Sjkim "\n", key); 435151937Sjkim } 43667754Smsmith 437151937Sjkim cl_spinlock_release(&p_event_wheel->lock); 43867754Smsmith} 439151937Sjkim 440151937Sjkimuint32_t 441114237Snjlcl_event_wheel_num_regs(IN cl_event_wheel_t * const p_event_wheel, 442151937Sjkim IN uint64_t key) 443151937Sjkim{ 444151937Sjkim 445151937Sjkim cl_event_wheel_reg_info_t *p_event; 446114237Snjl cl_map_item_t *p_map_item; 447114237Snjl uint32_t num_regs = 0; 448246849Sjkim 449246849Sjkim /* try to find the key in the map */ 450246849Sjkim CL_DBG("cl_event_wheel_num_regs: Looking for key:0x%" 451246849Sjkim PRIx64 "\n", key); 452246849Sjkim 453246849Sjkim cl_spinlock_acquire(&p_event_wheel->lock); 454246849Sjkim p_map_item = cl_qmap_get(&p_event_wheel->events_map, key); 455246849Sjkim if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) { 456246849Sjkim /* ok so we can simply return it's num_regs */ 457151937Sjkim p_event = 45867754Smsmith PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, 459228110Sjkim map_item); 460228110Sjkim num_regs = p_event->num_regs; 461228110Sjkim } 462228110Sjkim 463228110Sjkim cl_spinlock_release(&p_event_wheel->lock); 464228110Sjkim return (num_regs); 465228110Sjkim} 466228110Sjkim 467228110Sjkim#ifdef __CL_EVENT_WHEEL_TEST__ 468228110Sjkim 46967754Smsmith/* Dump out the complete state of the event wheel */ 470151937Sjkimvoid __cl_event_wheel_dump(IN cl_event_wheel_t * const p_event_wheel) 47167754Smsmith{ 472228110Sjkim cl_list_item_t *p_list_item; 47367754Smsmith cl_map_item_t *p_map_item; 474151937Sjkim cl_event_wheel_reg_info_t *p_event; 47567754Smsmith 476151937Sjkim printf("************** Event Wheel Dump ***********************\n"); 47767754Smsmith printf("Event Wheel List has %u items:\n", 47867754Smsmith cl_qlist_count(&p_event_wheel->events_wheel)); 47967754Smsmith 48067754Smsmith p_list_item = cl_qlist_head(&p_event_wheel->events_wheel); 48167754Smsmith while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) { 482151937Sjkim p_event = 48377424Smsmith PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, 484151937Sjkim list_item); 48577424Smsmith printf("Event key:0x%" PRIx64 " Context:%s NumRegs:%u\n", 48677424Smsmith p_event->key, (char *)p_event->context, 48777424Smsmith p_event->num_regs); 488151937Sjkim 48977424Smsmith /* next */ 49077424Smsmith p_list_item = cl_qlist_next(p_list_item); 49177424Smsmith } 49277424Smsmith 493151937Sjkim printf("Event Map has %u items:\n", 494151937Sjkim cl_qmap_count(&p_event_wheel->events_map)); 49577424Smsmith 496151937Sjkim p_map_item = cl_qmap_head(&p_event_wheel->events_map); 497151937Sjkim while (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) { 49877424Smsmith p_event = 49977424Smsmith PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, 50091116Smsmith map_item); 50183174Smsmith printf("Event key:0x%" PRIx64 " Context:%s NumRegs:%u\n", 50283174Smsmith p_event->key, (char *)p_event->context, 503245582Sjkim p_event->num_regs); 504245582Sjkim 505245582Sjkim /* next */ 50677424Smsmith p_map_item = cl_qmap_next(p_map_item); 50777424Smsmith } 50877424Smsmith 50977424Smsmith} 510151937Sjkim 51177424Smsmith/* The callback for aging event */ 512151937Sjkim/* We assume we pass a text context */ 51377424Smsmithvoid __test_event_aging(uint64_t key, void *context) 514151937Sjkim{ 515151937Sjkim printf("*****************************************************\n"); 516151937Sjkim printf("Aged key: 0x%" PRIx64 " Context:%s\n", key, (char *)context); 517151937Sjkim} 51877424Smsmith 519167802Sjkimint main() 520167802Sjkim{ 52177424Smsmith cl_event_wheel_t event_wheel; 52277424Smsmith /* uint64_t key; */ 52377424Smsmith 52477424Smsmith /* construct */ 52577424Smsmith cl_event_wheel_construct(&event_wheel); 52677424Smsmith 527151937Sjkim /* init */ 52867754Smsmith cl_event_wheel_init(&event_wheel); 529151937Sjkim 530151937Sjkim /* Start Playing */ 53167754Smsmith cl_event_wheel_reg(&event_wheel, 1, /* key */ 53277424Smsmith cl_get_time_stamp() + 3000000, /* 3 sec lifetime */ 53367754Smsmith __test_event_aging, /* cb */ 534151937Sjkim "The first Aging Event"); 535151937Sjkim 53667754Smsmith cl_event_wheel_reg(&event_wheel, 2, /* key */ 53767754Smsmith cl_get_time_stamp() + 3000000, /* 3 sec lifetime */ 53867754Smsmith __test_event_aging, /* cb */ 539151937Sjkim "The Second Aging Event"); 540151937Sjkim 541151937Sjkim cl_event_wheel_reg(&event_wheel, 3, /* key */ 542151937Sjkim cl_get_time_stamp() + 3500000, /* 3 sec lifetime */ 54367754Smsmith __test_event_aging, /* cb */ 544167802Sjkim "The Third Aging Event"); 545167802Sjkim 546167802Sjkim __cl_event_wheel_dump(&event_wheel); 547167802Sjkim 548167802Sjkim sleep(2); 549167802Sjkim cl_event_wheel_reg(&event_wheel, 2, /* key */ 550151937Sjkim cl_get_time_stamp() + 8000000, /* 3 sec lifetime */ 55167754Smsmith __test_event_aging, /* cb */ 552151937Sjkim "The Second Aging Event Moved"); 553151937Sjkim 554151937Sjkim __cl_event_wheel_dump(&event_wheel); 555151937Sjkim 556151937Sjkim sleep(1); 557151937Sjkim /* remove the third event */ 558151937Sjkim cl_event_wheel_unreg(&event_wheel, 3); /* key */ 55967754Smsmith 560151937Sjkim /* get the number of registrations for the keys */ 561151937Sjkim printf("Event 1 Registered: %u\n", 562151937Sjkim cl_event_wheel_num_regs(&event_wheel, 1)); 563151937Sjkim printf("Event 2 Registered: %u\n", 564151937Sjkim cl_event_wheel_num_regs(&event_wheel, 2)); 565151937Sjkim 566151937Sjkim sleep(5); 56783174Smsmith /* destroy */ 568151937Sjkim cl_event_wheel_destroy(&event_wheel); 569151937Sjkim 570151937Sjkim return (0); 571151937Sjkim} 572151937Sjkim 573151937Sjkim#endif /* __CL_EVENT_WHEEL_TEST__ */ 574151937Sjkim