Ticket #1995: 0001-PR1995-RBTree-Successor-and-Predecessor_v1.patch
File 0001-PR1995-RBTree-Successor-and-Predecessor_v1.patch, 11.9 KB (added by Gedare Bloom, on 03/05/12 at 15:51:41) |
---|
-
cpukit/sapi/inline/rtems/rbtree.inl
From 572f092950452b943c9723c7a60c81bda12e1426 Mon Sep 17 00:00:00 2001 From: Gedare Bloom <gedare@rtems.org> Date: Mon, 5 Mar 2012 11:48:57 -0500 Subject: [PATCH] PR1995: RBTree Successor and Predecessor Added mutable and immutable _RBTree_Next functions with and without protection. These functions return the next in-order node from a given node, which will either by that node's predecessor or successor. _RBTree_Successor() and _RBTree_Predecessor() now use the new functions. --- cpukit/sapi/inline/rtems/rbtree.inl | 10 +- cpukit/score/Makefile.am | 2 +- cpukit/score/include/rtems/score/rbtree.h | 58 ++++++++++- cpukit/score/inline/rtems/score/rbtree.inl | 24 +--- cpukit/score/src/rbtreenext.c | 167 ++++++++++++++++++++++++++++ testsuites/sptests/sprbtree01/init.c | 4 +- 6 files changed, 239 insertions(+), 26 deletions(-) create mode 100644 cpukit/score/src/rbtreenext.c diff --git a/cpukit/sapi/inline/rtems/rbtree.inl b/cpukit/sapi/inline/rtems/rbtree.inl index 16a6e2a..f329726 100644
a b RTEMS_INLINE_ROUTINE rtems_rbtree_node* rtems_rbtree_find( 274 274 /** @brief Find the node's in-order predecessor 275 275 * 276 276 * This function returns a pointer to the in-order predecessor 277 * of @a the_node if it exists , and NULL if not.277 * of @a the_node if it exists in @a the_rbtree, and NULL if not. 278 278 */ 279 279 RTEMS_INLINE_ROUTINE rtems_rbtree_node* rtems_rbtree_predecessor( 280 rtems_rbtree_control *the_rbtree, 280 281 rtems_rbtree_node *the_node 281 282 ) 282 283 { 283 return _RBTree_Predecessor( the_ node );284 return _RBTree_Predecessor( the_rbtree, the_node ); 284 285 } 285 286 286 287 /** @brief Find the node's in-order successor 287 288 * 288 289 * This function returns a pointer to the in-order successor 289 * of @a the_node if it exists , and NULL if not.290 * of @a the_node if it exists in @a the_rbtree, and NULL if not. 290 291 */ 291 292 RTEMS_INLINE_ROUTINE rtems_rbtree_node* rtems_rbtree_successor( 293 rtems_rbtree_control *the_rbtree, 292 294 rtems_rbtree_node *the_node 293 295 ) 294 296 { 295 return _RBTree_Successor( the_ node );297 return _RBTree_Successor( the_rbtree, the_node ); 296 298 } 297 299 298 300 /** -
cpukit/score/Makefile.am
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index 597da3e..aa3d791 100644
a b libscore_a_SOURCES += src/pheapallocate.c \ 265 265 ## RBTREE_C_FILES 266 266 libscore_a_SOURCES += src/rbtree.c \ 267 267 src/rbtreeextract.c src/rbtreefind.c src/rbtreefindheader.c \ 268 src/rbtreeget.c src/rbtreeinsert.c src/rbtree peek.c268 src/rbtreeget.c src/rbtreeinsert.c src/rbtreenext.c src/rbtreepeek.c 269 269 270 270 ## THREAD_C_FILES 271 271 libscore_a_SOURCES += src/thread.c src/threadchangepriority.c \ -
cpukit/score/include/rtems/score/rbtree.h
diff --git a/cpukit/score/include/rtems/score/rbtree.h b/cpukit/score/include/rtems/score/rbtree.h index f0e3b4b..5e1ac0a 100644
a b RBTree_Node *_RBTree_Insert( 294 294 RBTree_Node *the_node 295 295 ); 296 296 297 298 297 /** 299 298 * @brief Extract a Node (unprotected) 300 299 * … … void _RBTree_Extract( 321 320 RBTree_Node *the_node 322 321 ); 323 322 323 /* 324 * @brief Return the next in-order node (predecessor/successor) 325 * 326 * This routine returns the next in-order node from @a the_node with 327 * @a the_rbtree. If @a dir is 0 (RBT_LEFT) the predecessor is returned, 328 * or @a dir is 1 (RBT_RIGHT) and the successor is returned. 329 * 330 * @return pointer to next in-order node in rbtree, NULL if no nodes available 331 * @note It disables interrupts to ensure atomicity. 332 */ 333 RBTree_Node *_RBTree_Next( 334 RBTree_Control *the_rbtree, 335 RBTree_Node *the_node, 336 RBTree_Direction dir 337 ); 338 339 /* 340 * @brief Unprotected version of _RBTree_Next 341 * 342 * @note It does NOT disable interrupts to ensure atomicity. 343 */ 344 RBTree_Node *_RBTree_Next_unprotected( 345 RBTree_Control *the_rbtree, 346 RBTree_Node *the_node, 347 RBTree_Direction dir 348 ); 349 350 /* 351 * _RBTree_Next_immutable_unprotected 352 * 353 * This routine returns const-pointer to the next in-order node from @a node 354 * in @a rbtree. If @a dir is 0 (RBT_LEFT) the predecessor is returned, 355 * or @a dir is 1 (RBT_RIGHT) and the successor is returned. 356 * 357 * @note It does NOT disable interrupts to ensure the atomicity 358 * of the next operation. 359 */ 360 const RBTree_Node *_RBTree_Next_immutable_unprotected( 361 const RBTree_Control *rbtree, 362 const RBTree_Node *node, 363 RBTree_Direction dir 364 ); 365 366 /* 367 * _RBTree_Next_immutable 368 * 369 * This routine returns const-pointer to the next in-order node from @a node 370 * in @a rbtree. If @a dir is 0 (RBT_LEFT) the predecessor is returned, 371 * or @a dir is 1 (RBT_RIGHT) and the successor is returned. 372 * 373 */ 374 const RBTree_Node *_RBTree_Next_immutable( 375 const RBTree_Control *rbtree, 376 const RBTree_Node *node, 377 RBTree_Direction dir 378 ); 379 324 380 #ifndef __RTEMS_APPLICATION__ 325 381 #include <rtems/score/rbtree.inl> 326 382 #endif -
cpukit/score/inline/rtems/score/rbtree.inl
diff --git a/cpukit/score/inline/rtems/score/rbtree.inl b/cpukit/score/inline/rtems/score/rbtree.inl index ef653e5..0212908 100644
a b RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_Find_unprotected( 359 359 /** @brief Find the nodes in-order predecessor 360 360 * 361 361 * This function returns a pointer to the in-order predecessor 362 * of @a the_node if it exists , and NULL if not.362 * of @a the_node if it exists in @a the_rbtree, and NULL if not. 363 363 */ 364 364 RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_Predecessor( 365 RBTree_Control *the_rbtree, 365 366 RBTree_Node *the_node 366 367 ) 367 368 { 368 RBTree_Node* iter_node; 369 if (!the_node) return NULL; 370 iter_node = the_node->child[RBT_LEFT]; 371 if (!iter_node) return NULL; 372 while (iter_node->child[RBT_RIGHT]) { 373 iter_node = iter_node->child[RBT_RIGHT]; 374 } 375 return iter_node; 369 return _RBTree_Next(the_rbtree, the_node, RBT_LEFT); 376 370 } 377 371 378 372 /** @brief Find the nodes in-order successor 379 373 * 380 374 * This function returns a pointer to the in-order successor 381 * of @a the_node if it exists , and NULL if not.375 * of @a the_node if it exists in @a the_rbtree, and NULL if not. 382 376 */ 383 377 RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_Successor( 378 RBTree_Control *the_rbtree, 384 379 RBTree_Node *the_node 385 380 ) 386 381 { 387 RBTree_Node* iter_node; 388 if (!the_node) return NULL; 389 iter_node = the_node->child[RBT_RIGHT]; 390 if (!iter_node) return NULL; 391 while (iter_node->child[RBT_LEFT]) { 392 iter_node = iter_node->child[RBT_LEFT]; 393 } 394 return iter_node; 382 return _RBTree_Next(the_rbtree, the_node, RBT_RIGHT); 395 383 } 396 384 397 385 /** @brief Get the First Node (unprotected) -
new file cpukit/score/src/rbtreenext.c
diff --git a/cpukit/score/src/rbtreenext.c b/cpukit/score/src/rbtreenext.c new file mode 100644 index 0000000..89a7b85
- + 1 /* 2 * Copyright (c) 2012 Gedare Bloom. 3 * 4 * The license and distribution terms for this file may be 5 * found in the file LICENSE in this distribution or at 6 * http://www.rtems.com/license/LICENSE. 7 * 8 * $Id$ 9 */ 10 11 #if HAVE_CONFIG_H 12 #include "config.h" 13 #endif 14 15 #include <rtems/system.h> 16 #include <rtems/score/address.h> 17 #include <rtems/score/rbtree.h> 18 #include <rtems/score/isr.h> 19 20 /** @brief Gets the next node (unprotected) 21 * 22 * This routine returns the next in-order node from @a the_node with 23 * @a the_rbtree. If @a dir is 0 (RBT_LEFT) the predecessor is returned, 24 * or @a dir is 1 (RBT_RIGHT) and the successor is returned. 25 * 26 * @note It does NOT disable interrupts to ensure the atomicity 27 * of the next operation. 28 */ 29 RBTree_Node *_RBTree_Next_unprotected( 30 RBTree_Control *the_rbtree, 31 RBTree_Node *the_node, 32 RBTree_Direction dir 33 ) 34 { 35 RBTree_Direction opp_dir = _RBTree_Opposite_direction( dir ); 36 RBTree_Node *current = the_node->child [dir]; 37 RBTree_Node *next = NULL; 38 39 if (current != NULL) { 40 next = current; 41 while ((current = current->child [opp_dir]) != NULL) { 42 next = current; 43 } 44 } else { 45 RBTree_Node *null = (RBTree_Node *) the_rbtree; 46 RBTree_Node *parent = the_node->parent; 47 48 if (parent != null && the_node == parent->child [opp_dir]) { 49 next = parent; 50 } else { 51 while (parent != null && the_node == parent->child [dir]) { 52 the_node = parent; 53 parent = the_node->parent; 54 } 55 56 if (parent != null) { 57 next = parent; 58 } 59 } 60 } 61 62 return next; 63 } 64 65 /* 66 * _RBTree_Next_immutable_unprotected 67 * 68 * This routine returns const-pointer to the next in-order node from @a node 69 * in @a rbtree. If @a dir is 0 (RBT_LEFT) the predecessor is returned, 70 * or @a dir is 1 (RBT_RIGHT) and the successor is returned. 71 * 72 * @note It does NOT disable interrupts to ensure the atomicity 73 * of the next operation. 74 */ 75 const RBTree_Node *_RBTree_Next_immutable_unprotected( 76 const RBTree_Control *the_rbtree, 77 const RBTree_Node *the_node, 78 RBTree_Direction dir 79 ) 80 { 81 RBTree_Direction opp_dir = _RBTree_Opposite_direction( dir ); 82 const RBTree_Node *current = the_node->child [dir]; 83 const RBTree_Node *next = NULL; 84 85 if (current != NULL) { 86 next = current; 87 while ((current = current->child [opp_dir]) != NULL) { 88 next = current; 89 } 90 } else { 91 const RBTree_Node *null = (const RBTree_Node *) the_rbtree; 92 const RBTree_Node *parent = the_node->parent; 93 94 if (parent != null && the_node == parent->child [opp_dir]) { 95 next = parent; 96 } else { 97 while (parent != null && the_node == parent->child [dir]) { 98 the_node = parent; 99 parent = the_node->parent; 100 } 101 102 if (parent != null) { 103 next = parent; 104 } 105 } 106 } 107 108 return next; 109 } 110 111 /* 112 * _RBTree_Next 113 * 114 * This kernel routine returns a pointer to the next in-order node 115 * in the tree, which is either the predecessor or successor node, 116 * without removing that node. 117 * 118 * Input parameters: 119 * the_rbtree - pointer to rbtree header 120 * the_node - pointer to current node in the tree 121 * dir - specifies whether to return the predecessor (0) or successor (1) 122 * 123 * Output parameters: 124 * return_node - pointer to node in rbtree, NULL if no nodes available 125 * 126 * INTERRUPT LATENCY: 127 */ 128 129 RBTree_Node *_RBTree_Next( 130 RBTree_Control *the_rbtree, 131 RBTree_Node *the_node, 132 RBTree_Direction dir 133 ) 134 { 135 ISR_Level level; 136 RBTree_Node *return_node; 137 138 _ISR_Disable( level ); 139 return_node = _RBTree_Next_unprotected( the_rbtree, the_node, dir ); 140 _ISR_Enable( level ); 141 return return_node; 142 } 143 144 145 /* 146 * _RBTree_Next_immutable 147 * 148 * This routine returns const-pointer to the next in-order node from @a node 149 * in @a rbtree. If @a dir is 0 (RBT_LEFT) the predecessor is returned, 150 * or @a dir is 1 (RBT_RIGHT) and the successor is returned. 151 * 152 */ 153 const RBTree_Node *_RBTree_Next_immutable( 154 const RBTree_Control *rbtree, 155 const RBTree_Node *node, 156 RBTree_Direction dir 157 ) 158 { 159 ISR_Level level; 160 const RBTree_Node *immutable_node; 161 162 _ISR_Disable( level ); 163 immutable_node = _RBTree_Next_immutable_unprotected( rbtree, node, dir ); 164 _ISR_Enable( level ); 165 return immutable_node; 166 } 167 -
testsuites/sptests/sprbtree01/init.c
diff --git a/testsuites/sptests/sprbtree01/init.c b/testsuites/sptests/sprbtree01/init.c index 38badc9..4661f62 100644
a b rtems_task Init( 442 442 } 443 443 444 444 puts( "INIT - Verify rtems_rbtree_predecessor/successor"); 445 p = rtems_rbtree_predecessor( p);445 p = rtems_rbtree_predecessor(&rbtree1, p); 446 446 if(p && rtems_rbtree_container_of(p,test_node,Node)->id != 29) { 447 447 puts ("INIT - ERROR ON RBTREE ID MISMATCH"); 448 448 rtems_test_exit(0); 449 449 } 450 450 p = rtems_rbtree_find(&rbtree1, &search_node.Node); 451 p = rtems_rbtree_successor( p);451 p = rtems_rbtree_successor(&rbtree1, p); 452 452 if(p && rtems_rbtree_container_of(p,test_node,Node)->id != 31) { 453 453 puts ("INIT - ERROR ON RBTREE ID MISMATCH"); 454 454 rtems_test_exit(0);