Functions | |
static __inline tm_type * | tm_block_to_type (tm_block *b) |
Returns the tm_type of a tm_block. | |
static __inline tm_block * | tm_ptr_to_block (char *p) |
Returns the potential tm_block of a potential pointer. | |
static __inline tm_node * | tm_pure_ptr_to_node (void *_p) |
Returns the tm_node of a pointer. | |
static __inline void * | tm_node_to_ptr (tm_node *n) |
Returns the data pointer of a tm_node. | |
static __inline tm_block * | tm_node_to_block (tm_node *n) |
Returns the tm_block of a tm_node. | |
static __inline tm_node * | tm_ptr_to_node (void *p) |
Returns the tm_node of a potential pointer. | |
static __inline tm_type * | tm_node_to_type (tm_node *n) |
Returns the tm_type of a tm_node. |
Returns the tm_block of a tm_node.
Definition at line 130 of file ptr.h.
References tm_node_to_ptr(), and tm_ptr_to_block().
Referenced by _tm_check_sweep_error(), _tm_free_inner(), _tm_node_mark(), _tm_node_scan(), _tm_node_scan_some(), _tm_node_sweep_some(), _tm_node_sweep_some_for_type(), _tm_node_unmark_some(), _tm_type_alloc_node_from_free_list(), and tm_write_barrier_node().
00131 { 00132 return tm_ptr_to_block(tm_node_to_ptr(n)); 00133 }
static __inline void* tm_node_to_ptr | ( | tm_node * | n | ) | [static] |
Returns the data pointer of a tm_node.
Adds the tm_node header size to the tm_node address.
Definition at line 120 of file ptr.h.
Referenced by _tm_check_sweep_error(), _tm_node_sweep(), _tm_type_alloc_node_from_free_list(), and tm_node_to_block().
Returns the tm_type of a tm_node.
Definition at line 296 of file ptr.h.
References _tm_block_validate, tm_ptr_to_block(), and tm_block::type.
Referenced by _tm_realloc_inner().
00297 { 00298 tm_block *b = tm_ptr_to_block((char*) n); 00299 _tm_block_validate(b); 00300 return b->type; 00301 }
static __inline tm_block* tm_ptr_to_block | ( | char * | p | ) | [static] |
Returns the potential tm_block of a potential pointer.
FIXME: This code does not work for blocks bigger than tm_block_SIZE.
If tm_ptr_AT_END_IS_VALID is true, A pointer directly at the end of tm_block should be considered a pointer into the tm_block before it, because there may be a node allocated contigiously before tm_block header.
Example:
... ----------------+----------------------------- ... tm_block a | tm_block b | node | node | tm_block HDR | node | node | ... ----------------+------------------------------... ^ ^ | | p! p?
Code behaving like this might be pathological, but is valid:
int *p = tm_alloc(sizeof(p[0]) * 10); int i = 10; while ( -- i >= 0 ) { *(p ++) = i; some_function_that_calls_tm_alloc(); // // when i == 0, p is (just) past end of tm_alloc() data space and a GC happens. // There are no live pointers to the original tm_alloc() data space. // } p -= 10; // p goes back original tm_alloc() data space, // but p has been reclaimed!
If tm_ptr_AT_END_IS_VALID is false, Mask off the tm_block_SIZE bits from the address.
Definition at line 31 of file ptr.h.
References tm_block_SIZE, tm_block_SIZE_MASK, and tm_msg().
Referenced by tm_node_to_block(), tm_node_to_type(), and tm_ptr_to_node().
00032 { 00033 /** 00034 * If tm_ptr_AT_END_IS_VALID is true, 00035 * A pointer directly at the end of tm_block should be considered 00036 * a pointer into the tm_block before it, 00037 * because there may be a node allocated contigiously before 00038 * tm_block header. 00039 * 00040 * Example: 00041 * 00042 * <pre> 00043 * 00044 * ... ----------------+----------------------------- ... 00045 * tm_block a | tm_block b 00046 * | node | node | tm_block HDR | node | node | 00047 * ... ----------------+------------------------------... 00048 * ^ ^ 00049 * | | 00050 * p! p? 00051 * 00052 * </pre> 00053 * 00054 * Code behaving like this might be pathological, but is valid: 00055 * 00056 * <pre> 00057 * 00058 * int *p = tm_alloc(sizeof(p[0]) * 10); 00059 * int i = 10; 00060 * while ( -- i >= 0 ) { 00061 * *(p ++) = i; 00062 * some_function_that_calls_tm_alloc(); 00063 * // 00064 * // when i == 0, p is (just) past end of tm_alloc() data space and a GC happens. 00065 * // There are no live pointers to the original tm_alloc() data space. 00066 * // 00067 * } 00068 * p -= 10; 00069 * // p goes back original tm_alloc() data space, 00070 * // but p has been reclaimed! 00071 * 00072 * </pre> 00073 */ 00074 00075 #if tm_ptr_AT_END_IS_VALID 00076 char *b; /*!< The pptr aligned to the tm_block_SIZE. */ 00077 size_t offset; /*! The offset of the pptr in a tm_block. */ 00078 00079 /*! Find the offset of p in an aligned tm_block. */ 00080 offset = (((unsigned long) p) % tm_block_SIZE); 00081 b = p - offset; 00082 /*! If the pptr is directly at the beginning of the block, */ 00083 if ( offset == 0 && p ) { 00084 /*! Assume its in the previous block, by subtracting tm_block_SIZE. */ 00085 b -= tm_block_SIZE; 00086 tm_msg("P bb p%p b%p\n", (void*) p, (void*) b); 00087 // tm_stop(); 00088 } 00089 00090 return (void*) b; 00091 #else 00092 /** 00093 * If tm_ptr_AT_END_IS_VALID is false, 00094 * Mask off the tm_block_SIZE bits from the address. 00095 */ 00096 return (void*) ((unsigned long) p & tm_block_SIZE_MASK); 00097 #endif /* tm_ptr_AT_END_IS_VALID */ 00098 }
static __inline tm_node* tm_ptr_to_node | ( | void * | p | ) | [static] |
Returns the tm_node of a potential pointer.
If tm_ptr_AT_END_IS_VALID is true, A pointer directly at the end of block should be considered a pointer into the block before it. See tm_ptr_to_block().
Avoid pointers into pages not marked in use.
Get the block and type.
Avoid untyped blocks.
Avoid references to block headers or outsize the allocated space.
Normalize p to node head by using its tm_type size.
If tm_ptr_AT_END_IS_VALID is true, If the pointer is directly after a node boundary assume it's a pointer to the node before.
node0 node1 +---------------...-+---------------...-+... | tm_node | t->size | tm_node | t->size | +---------------...-+---------------...-+... ^ ^ | | new pp pp
Translate the pointer back to the tm_block header.
If the pointer is in the node header, it's not a pointer into the node data.
node0 node1 +---------------...-+---------------...-+... | tm_node | t->size | tm_node | t->size | +---------------...-+---------------...-+... ^ | pp
Remove intra-node offset.
node0 node1 +---------------...-+---------------...-+... | tm_node | t->size | tm_node | t->size | +---------------...-+---------------...-+... ^ ^ | | new pp pp
Translate back to block header.
It's a node.
Avoid references to free nodes.
Return a node.
Definition at line 140 of file ptr.h.
References _tm_block_validate, _tm_page_in_use(), tm_type::n, tm_block_HDR_SIZE, tm_block_node_begin, tm_block_node_next_parcel, tm_block_node_size, tm_msg(), tm_node_color, tm_node_HDR_SIZE, tm_ptr_h, tm_ptr_is_aligned_to_block, tm_ptr_l, tm_ptr_to_block(), tm_WHITE, and tm_block::type.
Referenced by __tm_write_barrier(), _tm_alloc_type_inner(), and _tm_mark_possible_ptr().
00141 { 00142 tm_block *b; 00143 00144 #if 0 00145 /*! If p is 0, it is not a pointer to a tm_node. */ 00146 if ( ! p ) 00147 return 0; 00148 #endif 00149 00150 /** 00151 * If tm_ptr_AT_END_IS_VALID is true, 00152 * A pointer directly at the end of block should be considered 00153 * a pointer into the block before it. 00154 * See tm_ptr_to_block(). 00155 */ 00156 #if tm_ptr_AT_END_IS_VALID 00157 if ( tm_ptr_is_aligned_to_block(p) ) { 00158 /*! This allows _tm_page_in_use(p) to pass. */ 00159 p = p - 1; 00160 } 00161 #endif 00162 00163 #if 1 00164 /*! Avoid pointers into pages not marked in use. */ 00165 if ( ! _tm_page_in_use(p) ) 00166 return 0; 00167 #else 00168 /*! Avoid out of range pointers. */ 00169 if ( ! (tm_ptr_l <= p && p <= tm_ptr_h) ) 00170 return 0; 00171 #endif 00172 00173 /*! Get the block and type. */ 00174 b = tm_ptr_to_block(p); 00175 00176 _tm_block_validate(b); 00177 00178 /*! Avoid untyped blocks. */ 00179 if ( ! b->type ) 00180 return 0; 00181 00182 /*! Avoid references to block headers or outsize the allocated space. */ 00183 if ( p > tm_block_node_next_parcel(b) ) 00184 return 0; 00185 00186 if ( p < tm_block_node_begin(b) ) 00187 return 0; 00188 00189 /*! Normalize p to node head by using its tm_type size. */ 00190 { 00191 unsigned long pp = (unsigned long) p; 00192 unsigned long node_size = tm_block_node_size(b); 00193 tm_node *n; 00194 00195 /* 00196 ** Translate away the block header. 00197 */ 00198 pp -= (unsigned long) b + tm_block_HDR_SIZE; 00199 00200 00201 { 00202 unsigned long node_off = pp % node_size; 00203 00204 /** 00205 * If tm_ptr_AT_END_IS_VALID is true, 00206 * If the pointer is directly after a node boundary 00207 * assume it's a pointer to the node before. 00208 * 00209 * <pre> 00210 * 00211 * node0 node1 00212 * +---------------...-+---------------...-+... 00213 * | tm_node | t->size | tm_node | t->size | 00214 * +---------------...-+---------------...-+... 00215 * ^ ^ 00216 * | | 00217 * new pp pp 00218 * 00219 * </pre> 00220 * 00221 * Translate the pointer back to the tm_block header. 00222 */ 00223 #if tm_ptr_AT_END_IS_VALID 00224 if ( node_off == 0 && pp ) { 00225 pp -= node_size; 00226 pp += (unsigned long) b + tm_block_HDR_SIZE; 00227 00228 #if 0 00229 tm_msg("P nb p%p p0%p\n", (void*) p, (void*) pp); 00230 #endif 00231 } else 00232 #endif 00233 00234 /** 00235 * If the pointer is in the node header, 00236 * it's not a pointer into the node data. 00237 * 00238 * <pre> 00239 * node0 node1 00240 * +---------------...-+---------------...-+... 00241 * | tm_node | t->size | tm_node | t->size | 00242 * +---------------...-+---------------...-+... 00243 * ^ 00244 * | 00245 * pp 00246 * </pre> 00247 * 00248 */ 00249 if ( node_off < tm_node_HDR_SIZE ) { 00250 return 0; 00251 } 00252 00253 /** 00254 * Remove intra-node offset. 00255 * 00256 * <pre> 00257 * 00258 * node0 node1 00259 * +---------------...-+---------------...-+... 00260 * | tm_node | t->size | tm_node | t->size | 00261 * +---------------...-+---------------...-+... 00262 * ^ ^ 00263 * | | 00264 * new pp pp 00265 * 00266 * </pre> 00267 * 00268 */ 00269 else { 00270 pp -= node_off; 00271 00272 /** 00273 * Translate back to block header. 00274 */ 00275 pp += (unsigned long) b + tm_block_HDR_SIZE; 00276 } 00277 } 00278 00279 /*! It's a node. */ 00280 n = (tm_node*) pp; 00281 00282 /*! Avoid references to free nodes. */ 00283 if ( tm_node_color(n) == tm_WHITE ) 00284 return 0; 00285 00286 /*! Return a node. */ 00287 return n; 00288 } 00289 }
static __inline tm_node* tm_pure_ptr_to_node | ( | void * | _p | ) | [static] |
Returns the tm_node of a pointer.
Subtracts the tm_node header size from the pointer.
Definition at line 107 of file ptr.h.
Referenced by __tm_write_barrier_pure(), _tm_free_inner(), and _tm_realloc_inner().
00108 { 00109 // return (tm_node*) (((char*) _p) - tm_node_HDR_SIZE); 00110 return ((tm_node*) _p) - 1; 00111 }