| File: | root/firefox-clang/third_party/rust/glslopt/glsl-optimizer/src/compiler/glsl/list.h |
| Warning: | line 151, column 18 Access to field 'prev' results in a dereference of a null pointer (loaded from field 'next') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* | |||
| 2 | * Copyright © 2011 Intel Corporation | |||
| 3 | * | |||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | |||
| 5 | * copy of this software and associated documentation files (the "Software"), | |||
| 6 | * to deal in the Software without restriction, including without limitation | |||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | |||
| 9 | * Software is furnished to do so, subject to the following conditions: | |||
| 10 | * | |||
| 11 | * The above copyright notice and this permission notice (including the next | |||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | |||
| 13 | * Software. | |||
| 14 | * | |||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| 21 | * DEALINGS IN THE SOFTWARE. | |||
| 22 | */ | |||
| 23 | ||||
| 24 | /** | |||
| 25 | * \file ir_function_detect_recursion.cpp | |||
| 26 | * Determine whether a shader contains static recursion. | |||
| 27 | * | |||
| 28 | * Consider the (possibly disjoint) graph of function calls in a shader. If a | |||
| 29 | * program contains recursion, this graph will contain a cycle. If a function | |||
| 30 | * is part of a cycle, it will have a caller and it will have a callee (it | |||
| 31 | * calls another function). | |||
| 32 | * | |||
| 33 | * To detect recursion, the function call graph is constructed. The graph is | |||
| 34 | * repeatedly reduced by removing any function that either has no callees | |||
| 35 | * (leaf functions) or has no caller. Eventually the only functions that | |||
| 36 | * remain will be the functions in the cycles. | |||
| 37 | * | |||
| 38 | * The GLSL spec is a bit wishy-washy about recursion. | |||
| 39 | * | |||
| 40 | * From page 39 (page 45 of the PDF) of the GLSL 1.10 spec: | |||
| 41 | * | |||
| 42 | * "Behavior is undefined if recursion is used. Recursion means having any | |||
| 43 | * function appearing more than once at any one time in the run-time stack | |||
| 44 | * of function calls. That is, a function may not call itself either | |||
| 45 | * directly or indirectly. Compilers may give diagnostic messages when | |||
| 46 | * this is detectable at compile time, but not all such cases can be | |||
| 47 | * detected at compile time." | |||
| 48 | * | |||
| 49 | * From page 79 (page 85 of the PDF): | |||
| 50 | * | |||
| 51 | * "22) Should recursion be supported? | |||
| 52 | * | |||
| 53 | * DISCUSSION: Probably not necessary, but another example of limiting | |||
| 54 | * the language based on how it would directly map to hardware. One | |||
| 55 | * thought is that recursion would benefit ray tracing shaders. On the | |||
| 56 | * other hand, many recursion operations can also be implemented with the | |||
| 57 | * user managing the recursion through arrays. RenderMan doesn't support | |||
| 58 | * recursion. This could be added at a later date, if it proved to be | |||
| 59 | * necessary. | |||
| 60 | * | |||
| 61 | * RESOLVED on September 10, 2002: Implementations are not required to | |||
| 62 | * support recursion. | |||
| 63 | * | |||
| 64 | * CLOSED on September 10, 2002." | |||
| 65 | * | |||
| 66 | * From page 79 (page 85 of the PDF): | |||
| 67 | * | |||
| 68 | * "56) Is it an error for an implementation to support recursion if the | |||
| 69 | * specification says recursion is not supported? | |||
| 70 | * | |||
| 71 | * ADDED on September 10, 2002. | |||
| 72 | * | |||
| 73 | * DISCUSSION: This issues is related to Issue (22). If we say that | |||
| 74 | * recursion (or some other piece of functionality) is not supported, is | |||
| 75 | * it an error for an implementation to support it? Perhaps the | |||
| 76 | * specification should remain silent on these kind of things so that they | |||
| 77 | * could be gracefully added later as an extension or as part of the | |||
| 78 | * standard. | |||
| 79 | * | |||
| 80 | * RESOLUTION: Languages, in general, have programs that are not | |||
| 81 | * well-formed in ways a compiler cannot detect. Portability is only | |||
| 82 | * ensured for well-formed programs. Detecting recursion is an example of | |||
| 83 | * this. The language will say a well-formed program may not recurse, but | |||
| 84 | * compilers are not forced to detect that recursion may happen. | |||
| 85 | * | |||
| 86 | * CLOSED: November 29, 2002." | |||
| 87 | * | |||
| 88 | * In GLSL 1.10 the behavior of recursion is undefined. Compilers don't have | |||
| 89 | * to reject shaders (at compile-time or link-time) that contain recursion. | |||
| 90 | * Instead they could work, or crash, or kill a kitten. | |||
| 91 | * | |||
| 92 | * From page 44 (page 50 of the PDF) of the GLSL 1.20 spec: | |||
| 93 | * | |||
| 94 | * "Recursion is not allowed, not even statically. Static recursion is | |||
| 95 | * present if the static function call graph of the program contains | |||
| 96 | * cycles." | |||
| 97 | * | |||
| 98 | * This langauge clears things up a bit, but it still leaves a lot of | |||
| 99 | * questions unanswered. | |||
| 100 | * | |||
| 101 | * - Is the error generated at compile-time or link-time? | |||
| 102 | * | |||
| 103 | * - Is it an error to have a recursive function that is never statically | |||
| 104 | * called by main or any function called directly or indirectly by main? | |||
| 105 | * Technically speaking, such a function is not in the "static function | |||
| 106 | * call graph of the program" at all. | |||
| 107 | * | |||
| 108 | * \bug | |||
| 109 | * If a shader has multiple cycles, this algorithm may erroneously complain | |||
| 110 | * about functions that aren't in any cycle, but are in the part of the call | |||
| 111 | * tree that connects them. For example, if the call graph consists of a | |||
| 112 | * cycle between A and B, and a cycle between D and E, and B also calls C | |||
| 113 | * which calls D, then this algorithm will report C as a function which "has | |||
| 114 | * static recursion" even though it is not part of any cycle. | |||
| 115 | * | |||
| 116 | * A better algorithm for cycle detection that doesn't have this drawback can | |||
| 117 | * be found here: | |||
| 118 | * | |||
| 119 | * http://en.wikipedia.org/wiki/Tarjan%E2%80%99s_strongly_connected_components_algorithm | |||
| 120 | * | |||
| 121 | * \author Ian Romanick <ian.d.romanick@intel.com> | |||
| 122 | */ | |||
| 123 | #include "ir.h" | |||
| 124 | #include "glsl_parser_extras.h" | |||
| 125 | #include "linker.h" | |||
| 126 | #include "util/hash_table.h" | |||
| 127 | #include "program.h" | |||
| 128 | ||||
| 129 | namespace { | |||
| 130 | ||||
| 131 | struct call_node : public exec_node { | |||
| 132 | class function *func; | |||
| 133 | }; | |||
| 134 | ||||
| 135 | class function { | |||
| 136 | public: | |||
| 137 | function(ir_function_signature *sig) | |||
| 138 | : sig(sig) | |||
| 139 | { | |||
| 140 | /* empty */ | |||
| 141 | } | |||
| 142 | ||||
| 143 | DECLARE_RALLOC_CXX_OPERATORS(function)private: static void _ralloc_destructor(void *p) { reinterpret_cast <function *>(p)->function::~function(); } public: static void* operator new(size_t size, void *mem_ctx) { void *p = ralloc_size (mem_ctx, size); (static_cast <bool> (p != __null) ? void (0) : __assert_fail ("p != NULL", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); if (!__has_trivial_destructor (function)) ralloc_set_destructor(p, _ralloc_destructor); return p; } static void operator delete(void *p) { if (!__has_trivial_destructor (function)) ralloc_set_destructor(p, __null); ralloc_free(p); } | |||
| 144 | ||||
| 145 | ir_function_signature *sig; | |||
| 146 | ||||
| 147 | /** List of functions called by this function. */ | |||
| 148 | exec_list callees; | |||
| 149 | ||||
| 150 | /** List of functions that call this function. */ | |||
| 151 | exec_list callers; | |||
| 152 | }; | |||
| 153 | ||||
| 154 | class has_recursion_visitor : public ir_hierarchical_visitor { | |||
| 155 | public: | |||
| 156 | has_recursion_visitor() | |||
| 157 | : current(NULL__null) | |||
| 158 | { | |||
| 159 | progress = false; | |||
| 160 | this->mem_ctx = ralloc_context(NULL__null); | |||
| 161 | this->function_hash = _mesa_pointer_hash_table_create(NULL__null); | |||
| 162 | } | |||
| 163 | ||||
| 164 | ~has_recursion_visitor() | |||
| 165 | { | |||
| 166 | _mesa_hash_table_destroy(this->function_hash, NULL__null); | |||
| 167 | ralloc_free(this->mem_ctx); | |||
| 168 | } | |||
| 169 | ||||
| 170 | function *get_function(ir_function_signature *sig) | |||
| 171 | { | |||
| 172 | function *f; | |||
| 173 | hash_entry *entry = _mesa_hash_table_search(this->function_hash, sig); | |||
| 174 | if (entry == NULL__null) { | |||
| 175 | f = new(mem_ctx) function(sig); | |||
| 176 | _mesa_hash_table_insert(this->function_hash, sig, f); | |||
| 177 | } else { | |||
| 178 | f = (function *) entry->data; | |||
| 179 | } | |||
| 180 | ||||
| 181 | return f; | |||
| 182 | } | |||
| 183 | ||||
| 184 | virtual ir_visitor_status visit_enter(ir_function_signature *sig) | |||
| 185 | { | |||
| 186 | this->current = this->get_function(sig); | |||
| 187 | return visit_continue; | |||
| 188 | } | |||
| 189 | ||||
| 190 | virtual ir_visitor_status visit_leave(ir_function_signature *sig) | |||
| 191 | { | |||
| 192 | (void) sig; | |||
| 193 | this->current = NULL__null; | |||
| 194 | return visit_continue; | |||
| 195 | } | |||
| 196 | ||||
| 197 | virtual ir_visitor_status visit_enter(ir_call *call) | |||
| 198 | { | |||
| 199 | /* At global scope this->current will be NULL. Since there is no way to | |||
| 200 | * call global scope, it can never be part of a cycle. Don't bother | |||
| 201 | * adding calls from global scope to the graph. | |||
| 202 | */ | |||
| 203 | if (this->current == NULL__null) | |||
| 204 | return visit_continue; | |||
| 205 | ||||
| 206 | function *const target = this->get_function(call->callee); | |||
| 207 | ||||
| 208 | /* Create a link from the caller to the callee. | |||
| 209 | */ | |||
| 210 | call_node *node = new(mem_ctx) call_node; | |||
| 211 | node->func = target; | |||
| 212 | this->current->callees.push_tail(node); | |||
| 213 | ||||
| 214 | /* Create a link from the callee to the caller. | |||
| 215 | */ | |||
| 216 | node = new(mem_ctx) call_node; | |||
| 217 | node->func = this->current; | |||
| 218 | target->callers.push_tail(node); | |||
| 219 | return visit_continue; | |||
| 220 | } | |||
| 221 | ||||
| 222 | function *current; | |||
| 223 | struct hash_table *function_hash; | |||
| 224 | void *mem_ctx; | |||
| 225 | bool progress; | |||
| 226 | }; | |||
| 227 | ||||
| 228 | } /* anonymous namespace */ | |||
| 229 | ||||
| 230 | static void | |||
| 231 | destroy_links(exec_list *list, function *f) | |||
| 232 | { | |||
| 233 | foreach_in_list_safe(call_node, node, list)for (call_node *node = (!exec_node_is_tail_sentinel((list)-> head_sentinel.next) ? (call_node *) ((list)->head_sentinel .next) : __null), *__next = (node) ? (!exec_node_is_tail_sentinel ((list)->head_sentinel.next->next) ? (call_node *) ((list )->head_sentinel.next->next) : __null) : __null; (node) != __null; (node) = __next, __next = __next ? (!exec_node_is_tail_sentinel (__next->next) ? (call_node *) (__next->next) : __null) : __null) { | |||
| 234 | /* If this is the right function, remove it. Note that the loop cannot | |||
| 235 | * terminate now. There can be multiple links to a function if it is | |||
| 236 | * either called multiple times or calls multiple times. | |||
| 237 | */ | |||
| 238 | if (node->func == f) | |||
| 239 | node->remove(); | |||
| 240 | } | |||
| 241 | } | |||
| 242 | ||||
| 243 | ||||
| 244 | /** | |||
| 245 | * Remove a function if it has either no in or no out links | |||
| 246 | */ | |||
| 247 | static void | |||
| 248 | remove_unlinked_functions(const void *key, void *data, void *closure) | |||
| 249 | { | |||
| 250 | has_recursion_visitor *visitor = (has_recursion_visitor *) closure; | |||
| 251 | function *f = (function *) data; | |||
| 252 | ||||
| 253 | if (f->callers.is_empty() || f->callees.is_empty()) { | |||
| 254 | while (!f->callers.is_empty()) { | |||
| 255 | struct call_node *n = (struct call_node *) f->callers.pop_head(); | |||
| 256 | destroy_links(& n->func->callees, f); | |||
| 257 | } | |||
| 258 | ||||
| 259 | while (!f->callees.is_empty()) { | |||
| 260 | struct call_node *n = (struct call_node *) f->callees.pop_head(); | |||
| 261 | destroy_links(& n->func->callers, f); | |||
| 262 | } | |||
| 263 | ||||
| 264 | hash_entry *entry = _mesa_hash_table_search(visitor->function_hash, key); | |||
| 265 | _mesa_hash_table_remove(visitor->function_hash, entry); | |||
| 266 | visitor->progress = true; | |||
| 267 | } | |||
| 268 | } | |||
| 269 | ||||
| 270 | ||||
| 271 | static void | |||
| 272 | emit_errors_unlinked(const void *key, void *data, void *closure) | |||
| 273 | { | |||
| 274 | struct _mesa_glsl_parse_state *state = | |||
| 275 | (struct _mesa_glsl_parse_state *) closure; | |||
| 276 | function *f = (function *) data; | |||
| 277 | YYLTYPE loc; | |||
| 278 | ||||
| 279 | (void) key; | |||
| 280 | ||||
| 281 | char *proto = prototype_string(f->sig->return_type, | |||
| 282 | f->sig->function_name(), | |||
| 283 | &f->sig->parameters); | |||
| 284 | ||||
| 285 | memset(&loc, 0, sizeof(loc)); | |||
| 286 | _mesa_glsl_error(&loc, state, | |||
| 287 | "function `%s' has static recursion", | |||
| 288 | proto); | |||
| 289 | ralloc_free(proto); | |||
| 290 | } | |||
| 291 | ||||
| 292 | ||||
| 293 | static void | |||
| 294 | emit_errors_linked(const void *key, void *data, void *closure) | |||
| 295 | { | |||
| 296 | struct gl_shader_program *prog = | |||
| 297 | (struct gl_shader_program *) closure; | |||
| 298 | function *f = (function *) data; | |||
| 299 | ||||
| 300 | (void) key; | |||
| 301 | ||||
| 302 | char *proto = prototype_string(f->sig->return_type, | |||
| 303 | f->sig->function_name(), | |||
| 304 | &f->sig->parameters); | |||
| 305 | ||||
| 306 | linker_error(prog, "function `%s' has static recursion.\n", proto); | |||
| 307 | ralloc_free(proto); | |||
| 308 | } | |||
| 309 | ||||
| 310 | ||||
| 311 | void | |||
| 312 | detect_recursion_unlinked(struct _mesa_glsl_parse_state *state, | |||
| 313 | exec_list *instructions) | |||
| 314 | { | |||
| 315 | has_recursion_visitor v; | |||
| 316 | ||||
| 317 | /* Collect all of the information about which functions call which other | |||
| 318 | * functions. | |||
| 319 | */ | |||
| 320 | v.run(instructions); | |||
| 321 | ||||
| 322 | /* Remove from the set all of the functions that either have no caller or | |||
| 323 | * call no other functions. Repeat until no functions are removed. | |||
| 324 | */ | |||
| 325 | do { | |||
| 326 | v.progress = false; | |||
| 327 | hash_table_call_foreach(v.function_hash, remove_unlinked_functions, & v); | |||
| 328 | } while (v.progress); | |||
| 329 | ||||
| 330 | ||||
| 331 | /* At this point any functions still in the hash must be part of a cycle. | |||
| 332 | */ | |||
| 333 | hash_table_call_foreach(v.function_hash, emit_errors_unlinked, state); | |||
| 334 | } | |||
| 335 | ||||
| 336 | ||||
| 337 | void | |||
| 338 | detect_recursion_linked(struct gl_shader_program *prog, | |||
| 339 | exec_list *instructions) | |||
| 340 | { | |||
| 341 | has_recursion_visitor v; | |||
| 342 | ||||
| 343 | /* Collect all of the information about which functions call which other | |||
| 344 | * functions. | |||
| 345 | */ | |||
| 346 | v.run(instructions); | |||
| 347 | ||||
| 348 | /* Remove from the set all of the functions that either have no caller or | |||
| 349 | * call no other functions. Repeat until no functions are removed. | |||
| 350 | */ | |||
| 351 | do { | |||
| 352 | v.progress = false; | |||
| 353 | hash_table_call_foreach(v.function_hash, remove_unlinked_functions, & v); | |||
| ||||
| 354 | } while (v.progress); | |||
| 355 | ||||
| 356 | ||||
| 357 | /* At this point any functions still in the hash must be part of a cycle. | |||
| 358 | */ | |||
| 359 | hash_table_call_foreach(v.function_hash, emit_errors_linked, prog); | |||
| 360 | } |
| 1 | /* |
| 2 | * Copyright © 2009,2012 Intel Corporation |
| 3 | * |
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), |
| 6 | * to deal in the Software without restriction, including without limitation |
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 8 | * and/or sell copies of the Software, and to permit persons to whom the |
| 9 | * Software is furnished to do so, subject to the following conditions: |
| 10 | * |
| 11 | * The above copyright notice and this permission notice (including the next |
| 12 | * paragraph) shall be included in all copies or substantial portions of the |
| 13 | * Software. |
| 14 | * |
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 21 | * IN THE SOFTWARE. |
| 22 | * |
| 23 | * Authors: |
| 24 | * Eric Anholt <eric@anholt.net> |
| 25 | * |
| 26 | */ |
| 27 | |
| 28 | #ifndef _HASH_TABLE_H |
| 29 | #define _HASH_TABLE_H |
| 30 | |
| 31 | #include <stdlib.h> |
| 32 | #include <inttypes.h> |
| 33 | #include <stdbool.h> |
| 34 | #include "c99_compat.h" |
| 35 | #include "fnv1a.h" |
| 36 | #include "macros.h" |
| 37 | |
| 38 | #ifdef __cplusplus201703L |
| 39 | extern "C" { |
| 40 | #endif |
| 41 | |
| 42 | struct hash_entry { |
| 43 | uint32_t hash; |
| 44 | const void *key; |
| 45 | void *data; |
| 46 | }; |
| 47 | |
| 48 | struct hash_table { |
| 49 | struct hash_entry *table; |
| 50 | uint32_t (*key_hash_function)(const void *key); |
| 51 | bool (*key_equals_function)(const void *a, const void *b); |
| 52 | const void *deleted_key; |
| 53 | uint32_t size; |
| 54 | uint32_t rehash; |
| 55 | uint64_t size_magic; |
| 56 | uint64_t rehash_magic; |
| 57 | uint32_t max_entries; |
| 58 | uint32_t size_index; |
| 59 | uint32_t entries; |
| 60 | uint32_t deleted_entries; |
| 61 | }; |
| 62 | |
| 63 | struct hash_table * |
| 64 | _mesa_hash_table_create(void *mem_ctx, |
| 65 | uint32_t (*key_hash_function)(const void *key), |
| 66 | bool (*key_equals_function)(const void *a, |
| 67 | const void *b)); |
| 68 | |
| 69 | bool |
| 70 | _mesa_hash_table_init(struct hash_table *ht, |
| 71 | void *mem_ctx, |
| 72 | uint32_t (*key_hash_function)(const void *key), |
| 73 | bool (*key_equals_function)(const void *a, |
| 74 | const void *b)); |
| 75 | |
| 76 | struct hash_table * |
| 77 | _mesa_hash_table_clone(struct hash_table *src, void *dst_mem_ctx); |
| 78 | void _mesa_hash_table_destroy(struct hash_table *ht, |
| 79 | void (*delete_function)(struct hash_entry *entry)); |
| 80 | void _mesa_hash_table_clear(struct hash_table *ht, |
| 81 | void (*delete_function)(struct hash_entry *entry)); |
| 82 | void _mesa_hash_table_set_deleted_key(struct hash_table *ht, |
| 83 | const void *deleted_key); |
| 84 | |
| 85 | static inline uint32_t _mesa_hash_table_num_entries(struct hash_table *ht) |
| 86 | { |
| 87 | return ht->entries; |
| 88 | } |
| 89 | |
| 90 | struct hash_entry * |
| 91 | _mesa_hash_table_insert(struct hash_table *ht, const void *key, void *data); |
| 92 | struct hash_entry * |
| 93 | _mesa_hash_table_insert_pre_hashed(struct hash_table *ht, uint32_t hash, |
| 94 | const void *key, void *data); |
| 95 | struct hash_entry * |
| 96 | _mesa_hash_table_search(struct hash_table *ht, const void *key); |
| 97 | struct hash_entry * |
| 98 | _mesa_hash_table_search_pre_hashed(struct hash_table *ht, uint32_t hash, |
| 99 | const void *key); |
| 100 | void _mesa_hash_table_remove(struct hash_table *ht, |
| 101 | struct hash_entry *entry); |
| 102 | void _mesa_hash_table_remove_key(struct hash_table *ht, |
| 103 | const void *key); |
| 104 | |
| 105 | struct hash_entry *_mesa_hash_table_next_entry(struct hash_table *ht, |
| 106 | struct hash_entry *entry); |
| 107 | struct hash_entry * |
| 108 | _mesa_hash_table_random_entry(struct hash_table *ht, |
| 109 | bool (*predicate)(struct hash_entry *entry)); |
| 110 | |
| 111 | uint32_t _mesa_hash_data(const void *data, size_t size); |
| 112 | |
| 113 | uint32_t _mesa_hash_int(const void *key); |
| 114 | uint32_t _mesa_hash_uint(const void *key); |
| 115 | uint32_t _mesa_hash_u32(const void *key); |
| 116 | uint32_t _mesa_hash_string(const void *key); |
| 117 | uint32_t _mesa_hash_pointer(const void *pointer); |
| 118 | |
| 119 | bool _mesa_key_int_equal(const void *a, const void *b); |
| 120 | bool _mesa_key_uint_equal(const void *a, const void *b); |
| 121 | bool _mesa_key_u32_equal(const void *a, const void *b); |
| 122 | bool _mesa_key_string_equal(const void *a, const void *b); |
| 123 | bool _mesa_key_pointer_equal(const void *a, const void *b); |
| 124 | |
| 125 | struct hash_table * |
| 126 | _mesa_pointer_hash_table_create(void *mem_ctx); |
| 127 | |
| 128 | /** |
| 129 | * This foreach function is safe against deletion (which just replaces |
| 130 | * an entry's data with the deleted marker), but not against insertion |
| 131 | * (which may rehash the table, making entry a dangling pointer). |
| 132 | */ |
| 133 | #define hash_table_foreach(ht, entry)for (struct hash_entry *entry = _mesa_hash_table_next_entry(ht , __null); entry != __null; entry = _mesa_hash_table_next_entry (ht, entry)) \ |
| 134 | for (struct hash_entry *entry = _mesa_hash_table_next_entry(ht, NULL__null); \ |
| 135 | entry != NULL__null; \ |
| 136 | entry = _mesa_hash_table_next_entry(ht, entry)) |
| 137 | |
| 138 | static inline void |
| 139 | hash_table_call_foreach(struct hash_table *ht, |
| 140 | void (*callback)(const void *key, |
| 141 | void *data, |
| 142 | void *closure), |
| 143 | void *closure) |
| 144 | { |
| 145 | hash_table_foreach(ht, entry)for (struct hash_entry *entry = _mesa_hash_table_next_entry(ht , __null); entry != __null; entry = _mesa_hash_table_next_entry (ht, entry)) |
| 146 | callback(entry->key, entry->data, closure); |
| 147 | } |
| 148 | |
| 149 | /** |
| 150 | * Hash table wrapper which supports 64-bit keys. |
| 151 | */ |
| 152 | struct hash_table_u64 { |
| 153 | struct hash_table *table; |
| 154 | void *freed_key_data; |
| 155 | void *deleted_key_data; |
| 156 | }; |
| 157 | |
| 158 | struct hash_table_u64 * |
| 159 | _mesa_hash_table_u64_create(void *mem_ctx); |
| 160 | |
| 161 | void |
| 162 | _mesa_hash_table_u64_destroy(struct hash_table_u64 *ht, |
| 163 | void (*delete_function)(struct hash_entry *entry)); |
| 164 | |
| 165 | void |
| 166 | _mesa_hash_table_u64_insert(struct hash_table_u64 *ht, uint64_t key, |
| 167 | void *data); |
| 168 | |
| 169 | void * |
| 170 | _mesa_hash_table_u64_search(struct hash_table_u64 *ht, uint64_t key); |
| 171 | |
| 172 | void |
| 173 | _mesa_hash_table_u64_remove(struct hash_table_u64 *ht, uint64_t key); |
| 174 | |
| 175 | void |
| 176 | _mesa_hash_table_u64_clear(struct hash_table_u64 *ht, |
| 177 | void (*delete_function)(struct hash_entry *entry)); |
| 178 | |
| 179 | #ifdef __cplusplus201703L |
| 180 | } /* extern C */ |
| 181 | #endif |
| 182 | |
| 183 | #endif /* _HASH_TABLE_H */ |
| 1 | /* | ||||||
| 2 | * Copyright © 2008, 2010 Intel Corporation | ||||||
| 3 | * | ||||||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||||||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||||||
| 6 | * to deal in the Software without restriction, including without limitation | ||||||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||||||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||||||
| 10 | * | ||||||
| 11 | * The above copyright notice and this permission notice (including the next | ||||||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||||||
| 13 | * Software. | ||||||
| 14 | * | ||||||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||||||
| 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||||
| 21 | * DEALINGS IN THE SOFTWARE. | ||||||
| 22 | */ | ||||||
| 23 | |||||||
| 24 | /** | ||||||
| 25 | * \file list.h | ||||||
| 26 | * \brief Doubly-linked list abstract container type. | ||||||
| 27 | * | ||||||
| 28 | * Each doubly-linked list has a sentinel head and tail node. These nodes | ||||||
| 29 | * contain no data. The head sentinel can be identified by its \c prev | ||||||
| 30 | * pointer being \c NULL. The tail sentinel can be identified by its | ||||||
| 31 | * \c next pointer being \c NULL. | ||||||
| 32 | * | ||||||
| 33 | * A list is empty if either the head sentinel's \c next pointer points to the | ||||||
| 34 | * tail sentinel or the tail sentinel's \c prev poiner points to the head | ||||||
| 35 | * sentinel. The head sentinel and tail sentinel nodes are allocated within the | ||||||
| 36 | * list structure. | ||||||
| 37 | * | ||||||
| 38 | * Do note that this means that the list nodes will contain pointers into the | ||||||
| 39 | * list structure itself and as a result you may not \c realloc() an \c | ||||||
| 40 | * exec_list or any structure in which an \c exec_list is embedded. | ||||||
| 41 | */ | ||||||
| 42 | |||||||
| 43 | #ifndef LIST_CONTAINER_H | ||||||
| 44 | #define LIST_CONTAINER_H | ||||||
| 45 | |||||||
| 46 | #ifndef __cplusplus201703L | ||||||
| 47 | #include <stddef.h> | ||||||
| 48 | #endif | ||||||
| 49 | #include <assert.h> | ||||||
| 50 | |||||||
| 51 | #include "util/ralloc.h" | ||||||
| 52 | |||||||
| 53 | struct exec_node { | ||||||
| 54 | struct exec_node *next; | ||||||
| 55 | struct exec_node *prev; | ||||||
| 56 | |||||||
| 57 | #ifdef __cplusplus201703L | ||||||
| 58 | DECLARE_RZALLOC_CXX_OPERATORS(exec_node)private: static void _ralloc_destructor(void *p) { reinterpret_cast <exec_node *>(p)->exec_node::~exec_node(); } public: static void* operator new(size_t size, void *mem_ctx) { void *p = rzalloc_size(mem_ctx, size); (static_cast <bool> ( p != __null) ? void (0) : __assert_fail ("p != NULL", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); if (!__has_trivial_destructor(exec_node)) ralloc_set_destructor (p, _ralloc_destructor); return p; } static void operator delete (void *p) { if (!__has_trivial_destructor(exec_node)) ralloc_set_destructor (p, __null); ralloc_free(p); } | ||||||
| 59 | |||||||
| 60 | exec_node() : next(NULL__null), prev(NULL__null) | ||||||
| 61 | { | ||||||
| 62 | /* empty */ | ||||||
| 63 | } | ||||||
| 64 | |||||||
| 65 | const exec_node *get_next() const; | ||||||
| 66 | exec_node *get_next(); | ||||||
| 67 | |||||||
| 68 | const exec_node *get_prev() const; | ||||||
| 69 | exec_node *get_prev(); | ||||||
| 70 | |||||||
| 71 | void remove(); | ||||||
| 72 | |||||||
| 73 | /** | ||||||
| 74 | * Link a node with itself | ||||||
| 75 | * | ||||||
| 76 | * This creates a sort of degenerate list that is occasionally useful. | ||||||
| 77 | */ | ||||||
| 78 | void self_link(); | ||||||
| 79 | |||||||
| 80 | /** | ||||||
| 81 | * Insert a node in the list after the current node | ||||||
| 82 | */ | ||||||
| 83 | void insert_after(exec_node *after); | ||||||
| 84 | |||||||
| 85 | /** | ||||||
| 86 | * Insert another list in the list after the current node | ||||||
| 87 | */ | ||||||
| 88 | void insert_after(struct exec_list *after); | ||||||
| 89 | |||||||
| 90 | /** | ||||||
| 91 | * Insert a node in the list before the current node | ||||||
| 92 | */ | ||||||
| 93 | void insert_before(exec_node *before); | ||||||
| 94 | |||||||
| 95 | /** | ||||||
| 96 | * Insert another list in the list before the current node | ||||||
| 97 | */ | ||||||
| 98 | void insert_before(struct exec_list *before); | ||||||
| 99 | |||||||
| 100 | /** | ||||||
| 101 | * Replace the current node with the given node. | ||||||
| 102 | */ | ||||||
| 103 | void replace_with(exec_node *replacement); | ||||||
| 104 | |||||||
| 105 | /** | ||||||
| 106 | * Is this the sentinel at the tail of the list? | ||||||
| 107 | */ | ||||||
| 108 | bool is_tail_sentinel() const; | ||||||
| 109 | |||||||
| 110 | /** | ||||||
| 111 | * Is this the sentinel at the head of the list? | ||||||
| 112 | */ | ||||||
| 113 | bool is_head_sentinel() const; | ||||||
| 114 | #endif | ||||||
| 115 | }; | ||||||
| 116 | |||||||
| 117 | static inline void | ||||||
| 118 | exec_node_init(struct exec_node *n) | ||||||
| 119 | { | ||||||
| 120 | n->next = NULL__null; | ||||||
| 121 | n->prev = NULL__null; | ||||||
| 122 | } | ||||||
| 123 | |||||||
| 124 | static inline const struct exec_node * | ||||||
| 125 | exec_node_get_next_const(const struct exec_node *n) | ||||||
| 126 | { | ||||||
| 127 | return n->next; | ||||||
| 128 | } | ||||||
| 129 | |||||||
| 130 | static inline struct exec_node * | ||||||
| 131 | exec_node_get_next(struct exec_node *n) | ||||||
| 132 | { | ||||||
| 133 | return n->next; | ||||||
| 134 | } | ||||||
| 135 | |||||||
| 136 | static inline const struct exec_node * | ||||||
| 137 | exec_node_get_prev_const(const struct exec_node *n) | ||||||
| 138 | { | ||||||
| 139 | return n->prev; | ||||||
| 140 | } | ||||||
| 141 | |||||||
| 142 | static inline struct exec_node * | ||||||
| 143 | exec_node_get_prev(struct exec_node *n) | ||||||
| 144 | { | ||||||
| 145 | return n->prev; | ||||||
| 146 | } | ||||||
| 147 | |||||||
| 148 | static inline void | ||||||
| 149 | exec_node_remove(struct exec_node *n) | ||||||
| 150 | { | ||||||
| 151 | n->next->prev = n->prev; | ||||||
| |||||||
| 152 | n->prev->next = n->next; | ||||||
| 153 | n->next = NULL__null; | ||||||
| 154 | n->prev = NULL__null; | ||||||
| 155 | } | ||||||
| 156 | |||||||
| 157 | static inline void | ||||||
| 158 | exec_node_self_link(struct exec_node *n) | ||||||
| 159 | { | ||||||
| 160 | n->next = n; | ||||||
| 161 | n->prev = n; | ||||||
| 162 | } | ||||||
| 163 | |||||||
| 164 | static inline void | ||||||
| 165 | exec_node_insert_after(struct exec_node *n, struct exec_node *after) | ||||||
| 166 | { | ||||||
| 167 | after->next = n->next; | ||||||
| 168 | after->prev = n; | ||||||
| 169 | |||||||
| 170 | n->next->prev = after; | ||||||
| 171 | n->next = after; | ||||||
| 172 | } | ||||||
| 173 | |||||||
| 174 | static inline void | ||||||
| 175 | exec_node_insert_node_before(struct exec_node *n, struct exec_node *before) | ||||||
| 176 | { | ||||||
| 177 | before->next = n; | ||||||
| 178 | before->prev = n->prev; | ||||||
| 179 | |||||||
| 180 | n->prev->next = before; | ||||||
| 181 | n->prev = before; | ||||||
| 182 | } | ||||||
| 183 | |||||||
| 184 | static inline void | ||||||
| 185 | exec_node_replace_with(struct exec_node *n, struct exec_node *replacement) | ||||||
| 186 | { | ||||||
| 187 | replacement->prev = n->prev; | ||||||
| 188 | replacement->next = n->next; | ||||||
| 189 | |||||||
| 190 | n->prev->next = replacement; | ||||||
| 191 | n->next->prev = replacement; | ||||||
| 192 | } | ||||||
| 193 | |||||||
| 194 | static inline bool | ||||||
| 195 | exec_node_is_tail_sentinel(const struct exec_node *n) | ||||||
| 196 | { | ||||||
| 197 | return n->next == NULL__null; | ||||||
| 198 | } | ||||||
| 199 | |||||||
| 200 | static inline bool | ||||||
| 201 | exec_node_is_head_sentinel(const struct exec_node *n) | ||||||
| 202 | { | ||||||
| 203 | return n->prev == NULL__null; | ||||||
| 204 | } | ||||||
| 205 | |||||||
| 206 | #ifdef __cplusplus201703L | ||||||
| 207 | inline const exec_node *exec_node::get_next() const | ||||||
| 208 | { | ||||||
| 209 | return exec_node_get_next_const(this); | ||||||
| 210 | } | ||||||
| 211 | |||||||
| 212 | inline exec_node *exec_node::get_next() | ||||||
| 213 | { | ||||||
| 214 | return exec_node_get_next(this); | ||||||
| 215 | } | ||||||
| 216 | |||||||
| 217 | inline const exec_node *exec_node::get_prev() const | ||||||
| 218 | { | ||||||
| 219 | return exec_node_get_prev_const(this); | ||||||
| 220 | } | ||||||
| 221 | |||||||
| 222 | inline exec_node *exec_node::get_prev() | ||||||
| 223 | { | ||||||
| 224 | return exec_node_get_prev(this); | ||||||
| 225 | } | ||||||
| 226 | |||||||
| 227 | inline void exec_node::remove() | ||||||
| 228 | { | ||||||
| 229 | exec_node_remove(this); | ||||||
| 230 | } | ||||||
| 231 | |||||||
| 232 | inline void exec_node::self_link() | ||||||
| 233 | { | ||||||
| 234 | exec_node_self_link(this); | ||||||
| 235 | } | ||||||
| 236 | |||||||
| 237 | inline void exec_node::insert_after(exec_node *after) | ||||||
| 238 | { | ||||||
| 239 | exec_node_insert_after(this, after); | ||||||
| 240 | } | ||||||
| 241 | |||||||
| 242 | inline void exec_node::insert_before(exec_node *before) | ||||||
| 243 | { | ||||||
| 244 | exec_node_insert_node_before(this, before); | ||||||
| 245 | } | ||||||
| 246 | |||||||
| 247 | inline void exec_node::replace_with(exec_node *replacement) | ||||||
| 248 | { | ||||||
| 249 | exec_node_replace_with(this, replacement); | ||||||
| 250 | } | ||||||
| 251 | |||||||
| 252 | inline bool exec_node::is_tail_sentinel() const | ||||||
| 253 | { | ||||||
| 254 | return exec_node_is_tail_sentinel(this); | ||||||
| 255 | } | ||||||
| 256 | |||||||
| 257 | inline bool exec_node::is_head_sentinel() const | ||||||
| 258 | { | ||||||
| 259 | return exec_node_is_head_sentinel(this); | ||||||
| 260 | } | ||||||
| 261 | #endif | ||||||
| 262 | |||||||
| 263 | #ifdef __cplusplus201703L | ||||||
| 264 | /* This macro will not work correctly if `t' uses virtual inheritance. If you | ||||||
| 265 | * are using virtual inheritance, you deserve a slow and painful death. Enjoy! | ||||||
| 266 | */ | ||||||
| 267 | #define exec_list_offsetof(t, f, p)(((char *) &((t *) p)->f) - ((char *) p)) \ | ||||||
| 268 | (((char *) &((t *) p)->f) - ((char *) p)) | ||||||
| 269 | #else | ||||||
| 270 | #define exec_list_offsetof(t, f, p)(((char *) &((t *) p)->f) - ((char *) p)) offsetof(t, f)__builtin_offsetof(t, f) | ||||||
| 271 | #endif | ||||||
| 272 | |||||||
| 273 | /** | ||||||
| 274 | * Get a pointer to the structure containing an exec_node | ||||||
| 275 | * | ||||||
| 276 | * Given a pointer to an \c exec_node embedded in a structure, get a pointer to | ||||||
| 277 | * the containing structure. | ||||||
| 278 | * | ||||||
| 279 | * \param type Base type of the structure containing the node | ||||||
| 280 | * \param node Pointer to the \c exec_node | ||||||
| 281 | * \param field Name of the field in \c type that is the embedded \c exec_node | ||||||
| 282 | */ | ||||||
| 283 | #define exec_node_data(type, node, field)((type *) (((uintptr_t) node) - (((char *) &((type *) node )->field) - ((char *) node)))) \ | ||||||
| 284 | ((type *) (((uintptr_t) node) - exec_list_offsetof(type, field, node)(((char *) &((type *) node)->field) - ((char *) node)))) | ||||||
| 285 | |||||||
| 286 | #ifdef __cplusplus201703L | ||||||
| 287 | struct exec_node; | ||||||
| 288 | #endif | ||||||
| 289 | |||||||
| 290 | struct exec_list { | ||||||
| 291 | struct exec_node head_sentinel; | ||||||
| 292 | struct exec_node tail_sentinel; | ||||||
| 293 | |||||||
| 294 | #ifdef __cplusplus201703L | ||||||
| 295 | DECLARE_RALLOC_CXX_OPERATORS(exec_list)private: static void _ralloc_destructor(void *p) { reinterpret_cast <exec_list *>(p)->exec_list::~exec_list(); } public: static void* operator new(size_t size, void *mem_ctx) { void *p = ralloc_size(mem_ctx, size); (static_cast <bool> ( p != __null) ? void (0) : __assert_fail ("p != NULL", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); if (!__has_trivial_destructor(exec_list)) ralloc_set_destructor (p, _ralloc_destructor); return p; } static void operator delete (void *p) { if (!__has_trivial_destructor(exec_list)) ralloc_set_destructor (p, __null); ralloc_free(p); } | ||||||
| 296 | |||||||
| 297 | exec_list() | ||||||
| 298 | { | ||||||
| 299 | make_empty(); | ||||||
| 300 | } | ||||||
| 301 | |||||||
| 302 | void make_empty(); | ||||||
| 303 | |||||||
| 304 | bool is_empty() const; | ||||||
| 305 | |||||||
| 306 | const exec_node *get_head() const; | ||||||
| 307 | exec_node *get_head(); | ||||||
| 308 | const exec_node *get_head_raw() const; | ||||||
| 309 | exec_node *get_head_raw(); | ||||||
| 310 | |||||||
| 311 | const exec_node *get_tail() const; | ||||||
| 312 | exec_node *get_tail(); | ||||||
| 313 | const exec_node *get_tail_raw() const; | ||||||
| 314 | exec_node *get_tail_raw(); | ||||||
| 315 | |||||||
| 316 | unsigned length() const; | ||||||
| 317 | |||||||
| 318 | void push_head(exec_node *n); | ||||||
| 319 | void push_tail(exec_node *n); | ||||||
| 320 | void push_degenerate_list_at_head(exec_node *n); | ||||||
| 321 | |||||||
| 322 | /** | ||||||
| 323 | * Remove the first node from a list and return it | ||||||
| 324 | * | ||||||
| 325 | * \return | ||||||
| 326 | * The first node in the list or \c NULL if the list is empty. | ||||||
| 327 | * | ||||||
| 328 | * \sa exec_list::get_head | ||||||
| 329 | */ | ||||||
| 330 | exec_node *pop_head(); | ||||||
| 331 | |||||||
| 332 | /** | ||||||
| 333 | * Move all of the nodes from this list to the target list | ||||||
| 334 | */ | ||||||
| 335 | void move_nodes_to(exec_list *target); | ||||||
| 336 | |||||||
| 337 | /** | ||||||
| 338 | * Append all nodes from the source list to the end of the target list | ||||||
| 339 | */ | ||||||
| 340 | void append_list(exec_list *source); | ||||||
| 341 | |||||||
| 342 | /** | ||||||
| 343 | * Prepend all nodes from the source list to the beginning of the target | ||||||
| 344 | * list | ||||||
| 345 | */ | ||||||
| 346 | void prepend_list(exec_list *source); | ||||||
| 347 | #endif | ||||||
| 348 | }; | ||||||
| 349 | |||||||
| 350 | static inline void | ||||||
| 351 | exec_list_make_empty(struct exec_list *list) | ||||||
| 352 | { | ||||||
| 353 | list->head_sentinel.next = &list->tail_sentinel; | ||||||
| 354 | list->head_sentinel.prev = NULL__null; | ||||||
| 355 | list->tail_sentinel.next = NULL__null; | ||||||
| 356 | list->tail_sentinel.prev = &list->head_sentinel; | ||||||
| 357 | } | ||||||
| 358 | |||||||
| 359 | static inline bool | ||||||
| 360 | exec_list_is_empty(const struct exec_list *list) | ||||||
| 361 | { | ||||||
| 362 | /* There are three ways to test whether a list is empty or not. | ||||||
| 363 | * | ||||||
| 364 | * - Check to see if the head sentinel's \c next is the tail sentinel. | ||||||
| 365 | * - Check to see if the tail sentinel's \c prev is the head sentinel. | ||||||
| 366 | * - Check to see if the head is the sentinel node by test whether its | ||||||
| 367 | * \c next pointer is \c NULL. | ||||||
| 368 | * | ||||||
| 369 | * The first two methods tend to generate better code on modern systems | ||||||
| 370 | * because they save a pointer dereference. | ||||||
| 371 | */ | ||||||
| 372 | return list->head_sentinel.next == &list->tail_sentinel; | ||||||
| 373 | } | ||||||
| 374 | |||||||
| 375 | static inline bool | ||||||
| 376 | exec_list_is_singular(const struct exec_list *list) | ||||||
| 377 | { | ||||||
| 378 | return !exec_list_is_empty(list) && | ||||||
| 379 | list->head_sentinel.next->next == &list->tail_sentinel; | ||||||
| 380 | } | ||||||
| 381 | |||||||
| 382 | static inline const struct exec_node * | ||||||
| 383 | exec_list_get_head_const(const struct exec_list *list) | ||||||
| 384 | { | ||||||
| 385 | return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL__null; | ||||||
| 386 | } | ||||||
| 387 | |||||||
| 388 | static inline struct exec_node * | ||||||
| 389 | exec_list_get_head(struct exec_list *list) | ||||||
| 390 | { | ||||||
| 391 | return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL__null; | ||||||
| 392 | } | ||||||
| 393 | |||||||
| 394 | static inline const struct exec_node * | ||||||
| 395 | exec_list_get_head_raw_const(const struct exec_list *list) | ||||||
| 396 | { | ||||||
| 397 | return list->head_sentinel.next; | ||||||
| 398 | } | ||||||
| 399 | |||||||
| 400 | static inline struct exec_node * | ||||||
| 401 | exec_list_get_head_raw(struct exec_list *list) | ||||||
| 402 | { | ||||||
| 403 | return list->head_sentinel.next; | ||||||
| 404 | } | ||||||
| 405 | |||||||
| 406 | static inline const struct exec_node * | ||||||
| 407 | exec_list_get_tail_const(const struct exec_list *list) | ||||||
| 408 | { | ||||||
| 409 | return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL__null; | ||||||
| 410 | } | ||||||
| 411 | |||||||
| 412 | static inline struct exec_node * | ||||||
| 413 | exec_list_get_tail(struct exec_list *list) | ||||||
| 414 | { | ||||||
| 415 | return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL__null; | ||||||
| 416 | } | ||||||
| 417 | |||||||
| 418 | static inline const struct exec_node * | ||||||
| 419 | exec_list_get_tail_raw_const(const struct exec_list *list) | ||||||
| 420 | { | ||||||
| 421 | return list->tail_sentinel.prev; | ||||||
| 422 | } | ||||||
| 423 | |||||||
| 424 | static inline struct exec_node * | ||||||
| 425 | exec_list_get_tail_raw(struct exec_list *list) | ||||||
| 426 | { | ||||||
| 427 | return list->tail_sentinel.prev; | ||||||
| 428 | } | ||||||
| 429 | |||||||
| 430 | static inline unsigned | ||||||
| 431 | exec_list_length(const struct exec_list *list) | ||||||
| 432 | { | ||||||
| 433 | unsigned size = 0; | ||||||
| 434 | struct exec_node *node; | ||||||
| 435 | |||||||
| 436 | for (node = list->head_sentinel.next; node->next != NULL__null; node = node->next) { | ||||||
| 437 | size++; | ||||||
| 438 | } | ||||||
| 439 | |||||||
| 440 | return size; | ||||||
| 441 | } | ||||||
| 442 | |||||||
| 443 | static inline void | ||||||
| 444 | exec_list_push_head(struct exec_list *list, struct exec_node *n) | ||||||
| 445 | { | ||||||
| 446 | n->next = list->head_sentinel.next; | ||||||
| 447 | n->prev = &list->head_sentinel; | ||||||
| 448 | |||||||
| 449 | n->next->prev = n; | ||||||
| 450 | list->head_sentinel.next = n; | ||||||
| 451 | } | ||||||
| 452 | |||||||
| 453 | static inline void | ||||||
| 454 | exec_list_push_tail(struct exec_list *list, struct exec_node *n) | ||||||
| 455 | { | ||||||
| 456 | n->next = &list->tail_sentinel; | ||||||
| 457 | n->prev = list->tail_sentinel.prev; | ||||||
| 458 | |||||||
| 459 | n->prev->next = n; | ||||||
| 460 | list->tail_sentinel.prev = n; | ||||||
| 461 | } | ||||||
| 462 | |||||||
| 463 | static inline void | ||||||
| 464 | exec_list_push_degenerate_list_at_head(struct exec_list *list, struct exec_node *n) | ||||||
| 465 | { | ||||||
| 466 | assert(n->prev->next == n)(static_cast <bool> (n->prev->next == n) ? void ( 0) : __assert_fail ("n->prev->next == n", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); | ||||||
| 467 | |||||||
| 468 | n->prev->next = list->head_sentinel.next; | ||||||
| 469 | list->head_sentinel.next->prev = n->prev; | ||||||
| 470 | n->prev = &list->head_sentinel; | ||||||
| 471 | list->head_sentinel.next = n; | ||||||
| 472 | } | ||||||
| 473 | |||||||
| 474 | static inline struct exec_node * | ||||||
| 475 | exec_list_pop_head(struct exec_list *list) | ||||||
| 476 | { | ||||||
| 477 | struct exec_node *const n = exec_list_get_head(list); | ||||||
| 478 | if (n
| ||||||
| 479 | exec_node_remove(n); | ||||||
| 480 | |||||||
| 481 | return n; | ||||||
| 482 | } | ||||||
| 483 | |||||||
| 484 | static inline void | ||||||
| 485 | exec_list_move_nodes_to(struct exec_list *list, struct exec_list *target) | ||||||
| 486 | { | ||||||
| 487 | if (exec_list_is_empty(list)) { | ||||||
| 488 | exec_list_make_empty(target); | ||||||
| 489 | } else { | ||||||
| 490 | target->head_sentinel.next = list->head_sentinel.next; | ||||||
| 491 | target->head_sentinel.prev = NULL__null; | ||||||
| 492 | target->tail_sentinel.next = NULL__null; | ||||||
| 493 | target->tail_sentinel.prev = list->tail_sentinel.prev; | ||||||
| 494 | |||||||
| 495 | target->head_sentinel.next->prev = &target->head_sentinel; | ||||||
| 496 | target->tail_sentinel.prev->next = &target->tail_sentinel; | ||||||
| 497 | |||||||
| 498 | exec_list_make_empty(list); | ||||||
| 499 | } | ||||||
| 500 | } | ||||||
| 501 | |||||||
| 502 | static inline void | ||||||
| 503 | exec_list_append(struct exec_list *list, struct exec_list *source) | ||||||
| 504 | { | ||||||
| 505 | if (exec_list_is_empty(source)) | ||||||
| 506 | return; | ||||||
| 507 | |||||||
| 508 | /* Link the first node of the source with the last node of the target list. | ||||||
| 509 | */ | ||||||
| 510 | list->tail_sentinel.prev->next = source->head_sentinel.next; | ||||||
| 511 | source->head_sentinel.next->prev = list->tail_sentinel.prev; | ||||||
| 512 | |||||||
| 513 | /* Make the tail of the source list be the tail of the target list. | ||||||
| 514 | */ | ||||||
| 515 | list->tail_sentinel.prev = source->tail_sentinel.prev; | ||||||
| 516 | list->tail_sentinel.prev->next = &list->tail_sentinel; | ||||||
| 517 | |||||||
| 518 | /* Make the source list empty for good measure. | ||||||
| 519 | */ | ||||||
| 520 | exec_list_make_empty(source); | ||||||
| 521 | } | ||||||
| 522 | |||||||
| 523 | static inline void | ||||||
| 524 | exec_node_insert_list_after(struct exec_node *n, struct exec_list *after) | ||||||
| 525 | { | ||||||
| 526 | if (exec_list_is_empty(after)) | ||||||
| 527 | return; | ||||||
| 528 | |||||||
| 529 | after->tail_sentinel.prev->next = n->next; | ||||||
| 530 | after->head_sentinel.next->prev = n; | ||||||
| 531 | |||||||
| 532 | n->next->prev = after->tail_sentinel.prev; | ||||||
| 533 | n->next = after->head_sentinel.next; | ||||||
| 534 | |||||||
| 535 | exec_list_make_empty(after); | ||||||
| 536 | } | ||||||
| 537 | |||||||
| 538 | static inline void | ||||||
| 539 | exec_list_prepend(struct exec_list *list, struct exec_list *source) | ||||||
| 540 | { | ||||||
| 541 | exec_list_append(source, list); | ||||||
| 542 | exec_list_move_nodes_to(source, list); | ||||||
| 543 | } | ||||||
| 544 | |||||||
| 545 | static inline void | ||||||
| 546 | exec_node_insert_list_before(struct exec_node *n, struct exec_list *before) | ||||||
| 547 | { | ||||||
| 548 | if (exec_list_is_empty(before)) | ||||||
| 549 | return; | ||||||
| 550 | |||||||
| 551 | before->tail_sentinel.prev->next = n; | ||||||
| 552 | before->head_sentinel.next->prev = n->prev; | ||||||
| 553 | |||||||
| 554 | n->prev->next = before->head_sentinel.next; | ||||||
| 555 | n->prev = before->tail_sentinel.prev; | ||||||
| 556 | |||||||
| 557 | exec_list_make_empty(before); | ||||||
| 558 | } | ||||||
| 559 | |||||||
| 560 | static inline void | ||||||
| 561 | exec_list_validate(const struct exec_list *list) | ||||||
| 562 | { | ||||||
| 563 | const struct exec_node *node; | ||||||
| 564 | |||||||
| 565 | assert(list->head_sentinel.next->prev == &list->head_sentinel)(static_cast <bool> (list->head_sentinel.next->prev == &list->head_sentinel) ? void (0) : __assert_fail ( "list->head_sentinel.next->prev == &list->head_sentinel" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | ||||||
| 566 | assert(list->head_sentinel.prev == NULL)(static_cast <bool> (list->head_sentinel.prev == __null ) ? void (0) : __assert_fail ("list->head_sentinel.prev == NULL" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | ||||||
| 567 | assert(list->tail_sentinel.next == NULL)(static_cast <bool> (list->tail_sentinel.next == __null ) ? void (0) : __assert_fail ("list->tail_sentinel.next == NULL" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | ||||||
| 568 | assert(list->tail_sentinel.prev->next == &list->tail_sentinel)(static_cast <bool> (list->tail_sentinel.prev->next == &list->tail_sentinel) ? void (0) : __assert_fail ( "list->tail_sentinel.prev->next == &list->tail_sentinel" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | ||||||
| 569 | |||||||
| 570 | /* We could try to use one of the interators below for this but they all | ||||||
| 571 | * either require C++ or assume the exec_node is embedded in a structure | ||||||
| 572 | * which is not the case for this function. | ||||||
| 573 | */ | ||||||
| 574 | for (node = list->head_sentinel.next; node->next != NULL__null; node = node->next) { | ||||||
| 575 | assert(node->next->prev == node)(static_cast <bool> (node->next->prev == node) ? void (0) : __assert_fail ("node->next->prev == node", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); | ||||||
| 576 | assert(node->prev->next == node)(static_cast <bool> (node->prev->next == node) ? void (0) : __assert_fail ("node->prev->next == node", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); | ||||||
| 577 | } | ||||||
| 578 | } | ||||||
| 579 | |||||||
| 580 | #ifdef __cplusplus201703L | ||||||
| 581 | inline void exec_list::make_empty() | ||||||
| 582 | { | ||||||
| 583 | exec_list_make_empty(this); | ||||||
| 584 | } | ||||||
| 585 | |||||||
| 586 | inline bool exec_list::is_empty() const | ||||||
| 587 | { | ||||||
| 588 | return exec_list_is_empty(this); | ||||||
| 589 | } | ||||||
| 590 | |||||||
| 591 | inline const exec_node *exec_list::get_head() const | ||||||
| 592 | { | ||||||
| 593 | return exec_list_get_head_const(this); | ||||||
| 594 | } | ||||||
| 595 | |||||||
| 596 | inline exec_node *exec_list::get_head() | ||||||
| 597 | { | ||||||
| 598 | return exec_list_get_head(this); | ||||||
| 599 | } | ||||||
| 600 | |||||||
| 601 | inline const exec_node *exec_list::get_head_raw() const | ||||||
| 602 | { | ||||||
| 603 | return exec_list_get_head_raw_const(this); | ||||||
| 604 | } | ||||||
| 605 | |||||||
| 606 | inline exec_node *exec_list::get_head_raw() | ||||||
| 607 | { | ||||||
| 608 | return exec_list_get_head_raw(this); | ||||||
| 609 | } | ||||||
| 610 | |||||||
| 611 | inline const exec_node *exec_list::get_tail() const | ||||||
| 612 | { | ||||||
| 613 | return exec_list_get_tail_const(this); | ||||||
| 614 | } | ||||||
| 615 | |||||||
| 616 | inline exec_node *exec_list::get_tail() | ||||||
| 617 | { | ||||||
| 618 | return exec_list_get_tail(this); | ||||||
| 619 | } | ||||||
| 620 | |||||||
| 621 | inline const exec_node *exec_list::get_tail_raw() const | ||||||
| 622 | { | ||||||
| 623 | return exec_list_get_tail_raw_const(this); | ||||||
| 624 | } | ||||||
| 625 | |||||||
| 626 | inline exec_node *exec_list::get_tail_raw() | ||||||
| 627 | { | ||||||
| 628 | return exec_list_get_tail_raw(this); | ||||||
| 629 | } | ||||||
| 630 | |||||||
| 631 | inline unsigned exec_list::length() const | ||||||
| 632 | { | ||||||
| 633 | return exec_list_length(this); | ||||||
| 634 | } | ||||||
| 635 | |||||||
| 636 | inline void exec_list::push_head(exec_node *n) | ||||||
| 637 | { | ||||||
| 638 | exec_list_push_head(this, n); | ||||||
| 639 | } | ||||||
| 640 | |||||||
| 641 | inline void exec_list::push_tail(exec_node *n) | ||||||
| 642 | { | ||||||
| 643 | exec_list_push_tail(this, n); | ||||||
| 644 | } | ||||||
| 645 | |||||||
| 646 | inline void exec_list::push_degenerate_list_at_head(exec_node *n) | ||||||
| 647 | { | ||||||
| 648 | exec_list_push_degenerate_list_at_head(this, n); | ||||||
| 649 | } | ||||||
| 650 | |||||||
| 651 | inline exec_node *exec_list::pop_head() | ||||||
| 652 | { | ||||||
| 653 | return exec_list_pop_head(this); | ||||||
| 654 | } | ||||||
| 655 | |||||||
| 656 | inline void exec_list::move_nodes_to(exec_list *target) | ||||||
| 657 | { | ||||||
| 658 | exec_list_move_nodes_to(this, target); | ||||||
| 659 | } | ||||||
| 660 | |||||||
| 661 | inline void exec_list::append_list(exec_list *source) | ||||||
| 662 | { | ||||||
| 663 | exec_list_append(this, source); | ||||||
| 664 | } | ||||||
| 665 | |||||||
| 666 | inline void exec_node::insert_after(exec_list *after) | ||||||
| 667 | { | ||||||
| 668 | exec_node_insert_list_after(this, after); | ||||||
| 669 | } | ||||||
| 670 | |||||||
| 671 | inline void exec_list::prepend_list(exec_list *source) | ||||||
| 672 | { | ||||||
| 673 | exec_list_prepend(this, source); | ||||||
| 674 | } | ||||||
| 675 | |||||||
| 676 | inline void exec_node::insert_before(exec_list *before) | ||||||
| 677 | { | ||||||
| 678 | exec_node_insert_list_before(this, before); | ||||||
| 679 | } | ||||||
| 680 | #endif | ||||||
| 681 | |||||||
| 682 | #define exec_node_typed_forward(__node, __type)(!exec_node_is_tail_sentinel(__node) ? (__type) (__node) : __null ) \ | ||||||
| 683 | (!exec_node_is_tail_sentinel(__node) ? (__type) (__node) : NULL__null) | ||||||
| 684 | |||||||
| 685 | #define exec_node_typed_backward(__node, __type)(!exec_node_is_head_sentinel(__node) ? (__type) (__node) : __null ) \ | ||||||
| 686 | (!exec_node_is_head_sentinel(__node) ? (__type) (__node) : NULL__null) | ||||||
| 687 | |||||||
| 688 | #define foreach_in_list(__type, __inst, __list)for (__type *__inst = (!exec_node_is_tail_sentinel((__list)-> head_sentinel.next) ? (__type *) ((__list)->head_sentinel. next) : __null); (__inst) != __null; (__inst) = (!exec_node_is_tail_sentinel ((__inst)->next) ? (__type *) ((__inst)->next) : __null )) \ | ||||||
| 689 | for (__type *__inst = exec_node_typed_forward((__list)->head_sentinel.next, __type *)(!exec_node_is_tail_sentinel((__list)->head_sentinel.next) ? (__type *) ((__list)->head_sentinel.next) : __null); \ | ||||||
| 690 | (__inst) != NULL__null; \ | ||||||
| 691 | (__inst) = exec_node_typed_forward((__inst)->next, __type *)(!exec_node_is_tail_sentinel((__inst)->next) ? (__type *) ( (__inst)->next) : __null)) | ||||||
| 692 | |||||||
| 693 | #define foreach_in_list_reverse(__type, __inst, __list)for (__type *__inst = (!exec_node_is_head_sentinel((__list)-> tail_sentinel.prev) ? (__type *) ((__list)->tail_sentinel. prev) : __null); (__inst) != __null; (__inst) = (!exec_node_is_head_sentinel ((__inst)->prev) ? (__type *) ((__inst)->prev) : __null )) \ | ||||||
| 694 | for (__type *__inst = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *)(!exec_node_is_head_sentinel((__list)->tail_sentinel.prev) ? (__type *) ((__list)->tail_sentinel.prev) : __null); \ | ||||||
| 695 | (__inst) != NULL__null; \ | ||||||
| 696 | (__inst) = exec_node_typed_backward((__inst)->prev, __type *)(!exec_node_is_head_sentinel((__inst)->prev) ? (__type *) ( (__inst)->prev) : __null)) | ||||||
| 697 | |||||||
| 698 | /** | ||||||
| 699 | * This version is safe even if the current node is removed. | ||||||
| 700 | */ | ||||||
| 701 | |||||||
| 702 | #define foreach_in_list_safe(__type, __node, __list)for (__type *__node = (!exec_node_is_tail_sentinel((__list)-> head_sentinel.next) ? (__type *) ((__list)->head_sentinel. next) : __null), *__next = (__node) ? (!exec_node_is_tail_sentinel ((__list)->head_sentinel.next->next) ? (__type *) ((__list )->head_sentinel.next->next) : __null) : __null; (__node ) != __null; (__node) = __next, __next = __next ? (!exec_node_is_tail_sentinel (__next->next) ? (__type *) (__next->next) : __null) : __null ) \ | ||||||
| 703 | for (__type *__node = exec_node_typed_forward((__list)->head_sentinel.next, __type *)(!exec_node_is_tail_sentinel((__list)->head_sentinel.next) ? (__type *) ((__list)->head_sentinel.next) : __null), \ | ||||||
| 704 | *__next = (__node) ? exec_node_typed_forward((__list)->head_sentinel.next->next, __type *)(!exec_node_is_tail_sentinel((__list)->head_sentinel.next-> next) ? (__type *) ((__list)->head_sentinel.next->next) : __null) : NULL__null; \ | ||||||
| 705 | (__node) != NULL__null; \ | ||||||
| 706 | (__node) = __next, __next = __next ? exec_node_typed_forward(__next->next, __type *)(!exec_node_is_tail_sentinel(__next->next) ? (__type *) (__next ->next) : __null) : NULL__null) | ||||||
| 707 | |||||||
| 708 | #define foreach_in_list_reverse_safe(__type, __node, __list)for (__type *__node = (!exec_node_is_head_sentinel((__list)-> tail_sentinel.prev) ? (__type *) ((__list)->tail_sentinel. prev) : __null), *__prev = (__node) ? (!exec_node_is_head_sentinel ((__list)->tail_sentinel.prev->prev) ? (__type *) ((__list )->tail_sentinel.prev->prev) : __null) : __null; (__node ) != __null; (__node) = __prev, __prev = __prev ? (!exec_node_is_head_sentinel (__prev->prev) ? (__type *) (__prev->prev) : __null) : __null ) \ | ||||||
| 709 | for (__type *__node = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *)(!exec_node_is_head_sentinel((__list)->tail_sentinel.prev) ? (__type *) ((__list)->tail_sentinel.prev) : __null), \ | ||||||
| 710 | *__prev = (__node) ? exec_node_typed_backward((__list)->tail_sentinel.prev->prev, __type *)(!exec_node_is_head_sentinel((__list)->tail_sentinel.prev-> prev) ? (__type *) ((__list)->tail_sentinel.prev->prev) : __null) : NULL__null; \ | ||||||
| 711 | (__node) != NULL__null; \ | ||||||
| 712 | (__node) = __prev, __prev = __prev ? exec_node_typed_backward(__prev->prev, __type *)(!exec_node_is_head_sentinel(__prev->prev) ? (__type *) (__prev ->prev) : __null) : NULL__null) | ||||||
| 713 | |||||||
| 714 | #define foreach_in_list_use_after(__type, __inst, __list)__type *__inst; for ((__inst) = (!exec_node_is_tail_sentinel( (__list)->head_sentinel.next) ? (__type *) ((__list)->head_sentinel .next) : __null); (__inst) != __null; (__inst) = (!exec_node_is_tail_sentinel ((__inst)->next) ? (__type *) ((__inst)->next) : __null )) \ | ||||||
| 715 | __type *__inst; \ | ||||||
| 716 | for ((__inst) = exec_node_typed_forward((__list)->head_sentinel.next, __type *)(!exec_node_is_tail_sentinel((__list)->head_sentinel.next) ? (__type *) ((__list)->head_sentinel.next) : __null); \ | ||||||
| 717 | (__inst) != NULL__null; \ | ||||||
| 718 | (__inst) = exec_node_typed_forward((__inst)->next, __type *)(!exec_node_is_tail_sentinel((__inst)->next) ? (__type *) ( (__inst)->next) : __null)) | ||||||
| 719 | |||||||
| 720 | /** | ||||||
| 721 | * Iterate through two lists at once. Stops at the end of the shorter list. | ||||||
| 722 | * | ||||||
| 723 | * This is safe against either current node being removed or replaced. | ||||||
| 724 | */ | ||||||
| 725 | #define foreach_two_lists(__node1, __list1, __node2, __list2)for (struct exec_node * __node1 = (__list1)->head_sentinel .next, * __node2 = (__list2)->head_sentinel.next, * __next1 = __node1->next, * __next2 = __node2->next ; __next1 != __null && __next2 != __null ; __node1 = __next1, __node2 = __next2, __next1 = __next1->next, __next2 = __next2-> next) \ | ||||||
| 726 | for (struct exec_node * __node1 = (__list1)->head_sentinel.next, \ | ||||||
| 727 | * __node2 = (__list2)->head_sentinel.next, \ | ||||||
| 728 | * __next1 = __node1->next, \ | ||||||
| 729 | * __next2 = __node2->next \ | ||||||
| 730 | ; __next1 != NULL__null && __next2 != NULL__null \ | ||||||
| 731 | ; __node1 = __next1, \ | ||||||
| 732 | __node2 = __next2, \ | ||||||
| 733 | __next1 = __next1->next, \ | ||||||
| 734 | __next2 = __next2->next) | ||||||
| 735 | |||||||
| 736 | #define exec_node_data_forward(type, node, field)(!exec_node_is_tail_sentinel(node) ? ((type *) (((uintptr_t) node ) - (((char *) &((type *) node)->field) - ((char *) node )))) : __null) \ | ||||||
| 737 | (!exec_node_is_tail_sentinel(node) ? exec_node_data(type, node, field)((type *) (((uintptr_t) node) - (((char *) &((type *) node )->field) - ((char *) node)))) : NULL__null) | ||||||
| 738 | |||||||
| 739 | #define exec_node_data_backward(type, node, field)(!exec_node_is_head_sentinel(node) ? ((type *) (((uintptr_t) node ) - (((char *) &((type *) node)->field) - ((char *) node )))) : __null) \ | ||||||
| 740 | (!exec_node_is_head_sentinel(node) ? exec_node_data(type, node, field)((type *) (((uintptr_t) node) - (((char *) &((type *) node )->field) - ((char *) node)))) : NULL__null) | ||||||
| 741 | |||||||
| 742 | #define foreach_list_typed(__type, __node, __field, __list)for (__type * __node = (!exec_node_is_tail_sentinel((__list)-> head_sentinel.next) ? ((__type *) (((uintptr_t) (__list)-> head_sentinel.next) - (((char *) &((__type *) (__list)-> head_sentinel.next)->__field) - ((char *) (__list)->head_sentinel .next)))) : __null); (__node) != __null; (__node) = (!exec_node_is_tail_sentinel ((__node)->__field.next) ? ((__type *) (((uintptr_t) (__node )->__field.next) - (((char *) &((__type *) (__node)-> __field.next)->__field) - ((char *) (__node)->__field.next )))) : __null)) \ | ||||||
| 743 | for (__type * __node = \ | ||||||
| 744 | exec_node_data_forward(__type, (__list)->head_sentinel.next, __field)(!exec_node_is_tail_sentinel((__list)->head_sentinel.next) ? ((__type *) (((uintptr_t) (__list)->head_sentinel.next) - (((char *) &((__type *) (__list)->head_sentinel.next )->__field) - ((char *) (__list)->head_sentinel.next))) ) : __null); \ | ||||||
| 745 | (__node) != NULL__null; \ | ||||||
| 746 | (__node) = exec_node_data_forward(__type, (__node)->__field.next, __field)(!exec_node_is_tail_sentinel((__node)->__field.next) ? ((__type *) (((uintptr_t) (__node)->__field.next) - (((char *) & ((__type *) (__node)->__field.next)->__field) - ((char * ) (__node)->__field.next)))) : __null)) | ||||||
| 747 | |||||||
| 748 | #define foreach_list_typed_from(__type, __node, __field, __list, __start)for (__type * __node = (!exec_node_is_tail_sentinel((__start) ) ? ((__type *) (((uintptr_t) (__start)) - (((char *) &(( __type *) (__start))->__field) - ((char *) (__start))))) : __null); (__node) != __null; (__node) = (!exec_node_is_tail_sentinel ((__node)->__field.next) ? ((__type *) (((uintptr_t) (__node )->__field.next) - (((char *) &((__type *) (__node)-> __field.next)->__field) - ((char *) (__node)->__field.next )))) : __null)) \ | ||||||
| 749 | for (__type * __node = exec_node_data_forward(__type, (__start), __field)(!exec_node_is_tail_sentinel((__start)) ? ((__type *) (((uintptr_t ) (__start)) - (((char *) &((__type *) (__start))->__field ) - ((char *) (__start))))) : __null); \ | ||||||
| 750 | (__node) != NULL__null; \ | ||||||
| 751 | (__node) = exec_node_data_forward(__type, (__node)->__field.next, __field)(!exec_node_is_tail_sentinel((__node)->__field.next) ? ((__type *) (((uintptr_t) (__node)->__field.next) - (((char *) & ((__type *) (__node)->__field.next)->__field) - ((char * ) (__node)->__field.next)))) : __null)) | ||||||
| 752 | |||||||
| 753 | #define foreach_list_typed_reverse(__type, __node, __field, __list)for (__type * __node = (!exec_node_is_head_sentinel((__list)-> tail_sentinel.prev) ? ((__type *) (((uintptr_t) (__list)-> tail_sentinel.prev) - (((char *) &((__type *) (__list)-> tail_sentinel.prev)->__field) - ((char *) (__list)->tail_sentinel .prev)))) : __null); (__node) != __null; (__node) = (!exec_node_is_head_sentinel ((__node)->__field.prev) ? ((__type *) (((uintptr_t) (__node )->__field.prev) - (((char *) &((__type *) (__node)-> __field.prev)->__field) - ((char *) (__node)->__field.prev )))) : __null)) \ | ||||||
| 754 | for (__type * __node = \ | ||||||
| 755 | exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field)(!exec_node_is_head_sentinel((__list)->tail_sentinel.prev) ? ((__type *) (((uintptr_t) (__list)->tail_sentinel.prev) - (((char *) &((__type *) (__list)->tail_sentinel.prev )->__field) - ((char *) (__list)->tail_sentinel.prev))) ) : __null); \ | ||||||
| 756 | (__node) != NULL__null; \ | ||||||
| 757 | (__node) = exec_node_data_backward(__type, (__node)->__field.prev, __field)(!exec_node_is_head_sentinel((__node)->__field.prev) ? ((__type *) (((uintptr_t) (__node)->__field.prev) - (((char *) & ((__type *) (__node)->__field.prev)->__field) - ((char * ) (__node)->__field.prev)))) : __null)) | ||||||
| 758 | |||||||
| 759 | #define foreach_list_typed_safe(__type, __node, __field, __list)for (__type * __node = (!exec_node_is_tail_sentinel((__list)-> head_sentinel.next) ? ((__type *) (((uintptr_t) (__list)-> head_sentinel.next) - (((char *) &((__type *) (__list)-> head_sentinel.next)->__field) - ((char *) (__list)->head_sentinel .next)))) : __null), * __next = (__node) ? (!exec_node_is_tail_sentinel ((__node)->__field.next) ? ((__type *) (((uintptr_t) (__node )->__field.next) - (((char *) &((__type *) (__node)-> __field.next)->__field) - ((char *) (__node)->__field.next )))) : __null) : __null; (__node) != __null; (__node) = __next , __next = (__next && (__next)->__field.next) ? (! exec_node_is_tail_sentinel((__next)->__field.next) ? ((__type *) (((uintptr_t) (__next)->__field.next) - (((char *) & ((__type *) (__next)->__field.next)->__field) - ((char * ) (__next)->__field.next)))) : __null) : __null) \ | ||||||
| 760 | for (__type * __node = \ | ||||||
| 761 | exec_node_data_forward(__type, (__list)->head_sentinel.next, __field)(!exec_node_is_tail_sentinel((__list)->head_sentinel.next) ? ((__type *) (((uintptr_t) (__list)->head_sentinel.next) - (((char *) &((__type *) (__list)->head_sentinel.next )->__field) - ((char *) (__list)->head_sentinel.next))) ) : __null), \ | ||||||
| 762 | * __next = (__node) ? \ | ||||||
| 763 | exec_node_data_forward(__type, (__node)->__field.next, __field)(!exec_node_is_tail_sentinel((__node)->__field.next) ? ((__type *) (((uintptr_t) (__node)->__field.next) - (((char *) & ((__type *) (__node)->__field.next)->__field) - ((char * ) (__node)->__field.next)))) : __null) : NULL__null; \ | ||||||
| 764 | (__node) != NULL__null; \ | ||||||
| 765 | (__node) = __next, __next = (__next && (__next)->__field.next) ? \ | ||||||
| 766 | exec_node_data_forward(__type, (__next)->__field.next, __field)(!exec_node_is_tail_sentinel((__next)->__field.next) ? ((__type *) (((uintptr_t) (__next)->__field.next) - (((char *) & ((__type *) (__next)->__field.next)->__field) - ((char * ) (__next)->__field.next)))) : __null) : NULL__null) | ||||||
| 767 | |||||||
| 768 | #define foreach_list_typed_reverse_safe(__type, __node, __field, __list)for (__type * __node = (!exec_node_is_head_sentinel((__list)-> tail_sentinel.prev) ? ((__type *) (((uintptr_t) (__list)-> tail_sentinel.prev) - (((char *) &((__type *) (__list)-> tail_sentinel.prev)->__field) - ((char *) (__list)->tail_sentinel .prev)))) : __null), * __prev = (__node) ? (!exec_node_is_head_sentinel ((__node)->__field.prev) ? ((__type *) (((uintptr_t) (__node )->__field.prev) - (((char *) &((__type *) (__node)-> __field.prev)->__field) - ((char *) (__node)->__field.prev )))) : __null) : __null; (__node) != __null; (__node) = __prev , __prev = (__prev && (__prev)->__field.prev) ? (! exec_node_is_head_sentinel((__prev)->__field.prev) ? ((__type *) (((uintptr_t) (__prev)->__field.prev) - (((char *) & ((__type *) (__prev)->__field.prev)->__field) - ((char * ) (__prev)->__field.prev)))) : __null) : __null) \ | ||||||
| 769 | for (__type * __node = \ | ||||||
| 770 | exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field)(!exec_node_is_head_sentinel((__list)->tail_sentinel.prev) ? ((__type *) (((uintptr_t) (__list)->tail_sentinel.prev) - (((char *) &((__type *) (__list)->tail_sentinel.prev )->__field) - ((char *) (__list)->tail_sentinel.prev))) ) : __null), \ | ||||||
| 771 | * __prev = (__node) ? \ | ||||||
| 772 | exec_node_data_backward(__type, (__node)->__field.prev, __field)(!exec_node_is_head_sentinel((__node)->__field.prev) ? ((__type *) (((uintptr_t) (__node)->__field.prev) - (((char *) & ((__type *) (__node)->__field.prev)->__field) - ((char * ) (__node)->__field.prev)))) : __null) : NULL__null; \ | ||||||
| 773 | (__node) != NULL__null; \ | ||||||
| 774 | (__node) = __prev, __prev = (__prev && (__prev)->__field.prev) ? \ | ||||||
| 775 | exec_node_data_backward(__type, (__prev)->__field.prev, __field)(!exec_node_is_head_sentinel((__prev)->__field.prev) ? ((__type *) (((uintptr_t) (__prev)->__field.prev) - (((char *) & ((__type *) (__prev)->__field.prev)->__field) - ((char * ) (__prev)->__field.prev)))) : __null) : NULL__null) | ||||||
| 776 | |||||||
| 777 | #endif /* LIST_CONTAINER_H */ |