|
||||
File indexing completed on 2025-01-18 10:01:16
0001 /* 0002 * Copyright © 2019-2023 Inria. All rights reserved. 0003 * See COPYING in top-level directory. 0004 */ 0005 0006 /** \file 0007 * \brief Memory node attributes. 0008 */ 0009 0010 #ifndef HWLOC_MEMATTR_H 0011 #define HWLOC_MEMATTR_H 0012 0013 #include "hwloc.h" 0014 0015 #ifdef __cplusplus 0016 extern "C" { 0017 #elif 0 0018 } 0019 #endif 0020 0021 /** \defgroup hwlocality_memattrs Comparing memory node attributes for finding where to allocate on 0022 * 0023 * Platforms with heterogeneous memory require ways to decide whether 0024 * a buffer should be allocated on "fast" memory (such as HBM), 0025 * "normal" memory (DDR) or even "slow" but large-capacity memory 0026 * (non-volatile memory). 0027 * These memory nodes are called "Targets" while the CPU accessing them 0028 * is called the "Initiator". Access performance depends on their 0029 * locality (NUMA platforms) as well as the intrinsic performance 0030 * of the targets (heterogeneous platforms). 0031 * 0032 * The following attributes describe the performance of memory accesses 0033 * from an Initiator to a memory Target, for instance their latency 0034 * or bandwidth. 0035 * Initiators performing these memory accesses are usually some PUs or Cores 0036 * (described as a CPU set). 0037 * Hence a Core may choose where to allocate a memory buffer by comparing 0038 * the attributes of different target memory nodes nearby. 0039 * 0040 * There are also some attributes that are system-wide. 0041 * Their value does not depend on a specific initiator performing 0042 * an access. 0043 * The memory node Capacity is an example of such attribute without 0044 * initiator. 0045 * 0046 * One way to use this API is to start with a cpuset describing the Cores where 0047 * a program is bound. The best target NUMA node for allocating memory in this 0048 * program on these Cores may be obtained by passing this cpuset as an initiator 0049 * to hwloc_memattr_get_best_target() with the relevant memory attribute. 0050 * For instance, if the code is latency limited, use the Latency attribute. 0051 * 0052 * A more flexible approach consists in getting the list of local NUMA nodes 0053 * by passing this cpuset to hwloc_get_local_numanode_objs(). 0054 * Attribute values for these nodes, if any, may then be obtained with 0055 * hwloc_memattr_get_value() and manually compared with the desired criteria. 0056 * 0057 * Memory attributes are also used internally to build Memory Tiers which provide 0058 * an easy way to distinguish NUMA nodes of different kinds, as explained 0059 * in \ref heteromem. 0060 * 0061 * \sa An example is available in doc/examples/memory-attributes.c in the source tree. 0062 * 0063 * \note The API also supports specific objects as initiator, 0064 * but it is currently not used internally by hwloc. 0065 * Users may for instance use it to provide custom performance 0066 * values for host memory accesses performed by GPUs. 0067 * 0068 * \note The interface actually also accepts targets that are not NUMA nodes. 0069 * @{ 0070 */ 0071 0072 /** \brief Memory node attributes. */ 0073 enum hwloc_memattr_id_e { 0074 /** \brief 0075 * The \"Capacity\" is returned in bytes (local_memory attribute in objects). 0076 * 0077 * Best capacity nodes are nodes with <b>higher capacity</b>. 0078 * 0079 * No initiator is involved when looking at this attribute. 0080 * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST. 0081 * \hideinitializer 0082 */ 0083 HWLOC_MEMATTR_ID_CAPACITY = 0, 0084 0085 /** \brief 0086 * The \"Locality\" is returned as the number of PUs in that locality 0087 * (e.g. the weight of its cpuset). 0088 * 0089 * Best locality nodes are nodes with <b>smaller locality</b> 0090 * (nodes that are local to very few PUs). 0091 * Poor locality nodes are nodes with larger locality 0092 * (nodes that are local to the entire machine). 0093 * 0094 * No initiator is involved when looking at this attribute. 0095 * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST. 0096 * \hideinitializer 0097 */ 0098 HWLOC_MEMATTR_ID_LOCALITY = 1, 0099 0100 /** \brief 0101 * The \"Bandwidth\" is returned in MiB/s, as seen from the given initiator location. 0102 * 0103 * Best bandwidth nodes are nodes with <b>higher bandwidth</b>. 0104 * 0105 * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST 0106 * and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR. 0107 * 0108 * This is the average bandwidth for read and write accesses. If the platform 0109 * provides individual read and write bandwidths but no explicit average value, 0110 * hwloc computes and returns the average. 0111 * \hideinitializer 0112 */ 0113 HWLOC_MEMATTR_ID_BANDWIDTH = 2, 0114 0115 /** \brief 0116 * The \"ReadBandwidth\" is returned in MiB/s, as seen from the given initiator location. 0117 * 0118 * Best bandwidth nodes are nodes with <b>higher bandwidth</b>. 0119 * 0120 * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST 0121 * and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR. 0122 * \hideinitializer 0123 */ 0124 HWLOC_MEMATTR_ID_READ_BANDWIDTH = 4, 0125 0126 /** \brief 0127 * The \"WriteBandwidth\" is returned in MiB/s, as seen from the given initiator location. 0128 * 0129 * Best bandwidth nodes are nodes with <b>higher bandwidth</b>. 0130 * 0131 * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST 0132 * and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR. 0133 * \hideinitializer 0134 */ 0135 HWLOC_MEMATTR_ID_WRITE_BANDWIDTH = 5, 0136 0137 /** \brief 0138 * The \"Latency\" is returned as nanoseconds, as seen from the given initiator location. 0139 * 0140 * Best latency nodes are nodes with <b>smaller latency</b>. 0141 * 0142 * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_LOWER_FIRST 0143 * and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR. 0144 * 0145 * This is the average latency for read and write accesses. If the platform 0146 * provides individual read and write latencies but no explicit average value, 0147 * hwloc computes and returns the average. 0148 * \hideinitializer 0149 */ 0150 HWLOC_MEMATTR_ID_LATENCY = 3, 0151 0152 /** \brief 0153 * The \"ReadLatency\" is returned as nanoseconds, as seen from the given initiator location. 0154 * 0155 * Best latency nodes are nodes with <b>smaller latency</b>. 0156 * 0157 * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_LOWER_FIRST 0158 * and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR. 0159 * \hideinitializer 0160 */ 0161 HWLOC_MEMATTR_ID_READ_LATENCY = 6, 0162 0163 /** \brief 0164 * The \"WriteLatency\" is returned as nanoseconds, as seen from the given initiator location. 0165 * 0166 * Best latency nodes are nodes with <b>smaller latency</b>. 0167 * 0168 * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_LOWER_FIRST 0169 * and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR. 0170 * \hideinitializer 0171 */ 0172 HWLOC_MEMATTR_ID_WRITE_LATENCY = 7, 0173 0174 /* TODO persistence? */ 0175 0176 HWLOC_MEMATTR_ID_MAX /**< \private Sentinel value */ 0177 }; 0178 0179 /** \brief A memory attribute identifier. 0180 * May be either one of ::hwloc_memattr_id_e or a new id returned by hwloc_memattr_register(). 0181 */ 0182 typedef unsigned hwloc_memattr_id_t; 0183 0184 /** \brief Return the identifier of the memory attribute with the given name. 0185 * 0186 * \return 0 on success. 0187 * \return -1 with errno set to \c EINVAL if no such attribute exists. 0188 */ 0189 HWLOC_DECLSPEC int 0190 hwloc_memattr_get_by_name(hwloc_topology_t topology, 0191 const char *name, 0192 hwloc_memattr_id_t *id); 0193 0194 0195 /** \brief Type of location. */ 0196 enum hwloc_location_type_e { 0197 /** \brief Location is given as a cpuset, in the location cpuset union field. \hideinitializer */ 0198 HWLOC_LOCATION_TYPE_CPUSET = 1, 0199 /** \brief Location is given as an object, in the location object union field. \hideinitializer */ 0200 HWLOC_LOCATION_TYPE_OBJECT = 0 0201 }; 0202 0203 /** \brief Where to measure attributes from. */ 0204 struct hwloc_location { 0205 /** \brief Type of location. */ 0206 enum hwloc_location_type_e type; 0207 /** \brief Actual location. */ 0208 union hwloc_location_u { 0209 /** \brief Location as a cpuset, when the location type is ::HWLOC_LOCATION_TYPE_CPUSET. */ 0210 hwloc_cpuset_t cpuset; 0211 /** \brief Location as an object, when the location type is ::HWLOC_LOCATION_TYPE_OBJECT. */ 0212 hwloc_obj_t object; 0213 } location; 0214 }; 0215 0216 0217 /** \brief Flags for selecting target NUMA nodes. */ 0218 enum hwloc_local_numanode_flag_e { 0219 /** \brief Select NUMA nodes whose locality is larger than the given cpuset. 0220 * For instance, if a single PU (or its cpuset) is given in \p initiator, 0221 * select all nodes close to the package that contains this PU. 0222 * \hideinitializer 0223 */ 0224 HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY = (1UL<<0), 0225 0226 /** \brief Select NUMA nodes whose locality is smaller than the given cpuset. 0227 * For instance, if a package (or its cpuset) is given in \p initiator, 0228 * also select nodes that are attached to only a half of that package. 0229 * \hideinitializer 0230 */ 0231 HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY = (1UL<<1), 0232 0233 /** \brief Select all NUMA nodes in the topology. 0234 * The initiator \p initiator is ignored. 0235 * \hideinitializer 0236 */ 0237 HWLOC_LOCAL_NUMANODE_FLAG_ALL = (1UL<<2) 0238 }; 0239 0240 /** \brief Return an array of local NUMA nodes. 0241 * 0242 * By default only select the NUMA nodes whose locality is exactly 0243 * the given \p location. More nodes may be selected if additional flags 0244 * are given as a OR'ed set of ::hwloc_local_numanode_flag_e. 0245 * 0246 * If \p location is given as an explicit object, its CPU set is used 0247 * to find NUMA nodes with the corresponding locality. 0248 * If the object does not have a CPU set (e.g. I/O object), the CPU 0249 * parent (where the I/O object is attached) is used. 0250 * 0251 * On input, \p nr points to the number of nodes that may be stored 0252 * in the \p nodes array. 0253 * On output, \p nr will be changed to the number of stored nodes, 0254 * or the number of nodes that would have been stored if there were 0255 * enough room. 0256 * 0257 * \return 0 on success or -1 on error. 0258 * 0259 * \note Some of these NUMA nodes may not have any memory attribute 0260 * values and hence not be reported as actual targets in other functions. 0261 * 0262 * \note The number of NUMA nodes in the topology (obtained by 0263 * hwloc_bitmap_weight() on the root object nodeset) may be used 0264 * to allocate the \p nodes array. 0265 * 0266 * \note When an object CPU set is given as locality, for instance a Package, 0267 * and when flags contain both ::HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY 0268 * and ::HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY, 0269 * the returned array corresponds to the nodeset of that object. 0270 */ 0271 HWLOC_DECLSPEC int 0272 hwloc_get_local_numanode_objs(hwloc_topology_t topology, 0273 struct hwloc_location *location, 0274 unsigned *nr, 0275 hwloc_obj_t *nodes, 0276 unsigned long flags); 0277 0278 0279 0280 /** \brief Return an attribute value for a specific target NUMA node. 0281 * 0282 * If the attribute does not relate to a specific initiator 0283 * (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR), 0284 * location \p initiator is ignored and may be \c NULL. 0285 * 0286 * \p flags must be \c 0 for now. 0287 * 0288 * \return 0 on success. 0289 * \return -1 on error, for instance with errno set to \c EINVAL if flags 0290 * are invalid or no such attribute exists. 0291 * 0292 * \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET 0293 * when refering to accesses performed by CPU cores. 0294 * ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc, 0295 * but users may for instance use it to provide custom information about 0296 * host memory accesses performed by GPUs. 0297 */ 0298 HWLOC_DECLSPEC int 0299 hwloc_memattr_get_value(hwloc_topology_t topology, 0300 hwloc_memattr_id_t attribute, 0301 hwloc_obj_t target_node, 0302 struct hwloc_location *initiator, 0303 unsigned long flags, 0304 hwloc_uint64_t *value); 0305 0306 /** \brief Return the best target NUMA node for the given attribute and initiator. 0307 * 0308 * If the attribute does not relate to a specific initiator 0309 * (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR), 0310 * location \p initiator is ignored and may be \c NULL. 0311 * 0312 * If \p value is non \c NULL, the corresponding value is returned there. 0313 * 0314 * If multiple targets have the same attribute values, only one is 0315 * returned (and there is no way to clarify how that one is chosen). 0316 * Applications that want to detect targets with identical/similar 0317 * values, or that want to look at values for multiple attributes, 0318 * should rather get all values using hwloc_memattr_get_value() 0319 * and manually select the target they consider the best. 0320 * 0321 * \p flags must be \c 0 for now. 0322 * 0323 * \return 0 on success. 0324 * \return -1 with errno set to \c ENOENT if there are no matching targets. 0325 * \return -1 with errno set to \c EINVAL if flags are invalid, 0326 * or no such attribute exists. 0327 * 0328 * \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET 0329 * when refering to accesses performed by CPU cores. 0330 * ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc, 0331 * but users may for instance use it to provide custom information about 0332 * host memory accesses performed by GPUs. 0333 */ 0334 HWLOC_DECLSPEC int 0335 hwloc_memattr_get_best_target(hwloc_topology_t topology, 0336 hwloc_memattr_id_t attribute, 0337 struct hwloc_location *initiator, 0338 unsigned long flags, 0339 hwloc_obj_t *best_target, hwloc_uint64_t *value); 0340 0341 /** \brief Return the best initiator for the given attribute and target NUMA node. 0342 * 0343 * If \p value is non \c NULL, the corresponding value is returned there. 0344 * 0345 * If multiple initiators have the same attribute values, only one is 0346 * returned (and there is no way to clarify how that one is chosen). 0347 * Applications that want to detect initiators with identical/similar 0348 * values, or that want to look at values for multiple attributes, 0349 * should rather get all values using hwloc_memattr_get_value() 0350 * and manually select the initiator they consider the best. 0351 * 0352 * The returned initiator should not be modified or freed, 0353 * it belongs to the topology. 0354 * 0355 * \p flags must be \c 0 for now. 0356 * 0357 * \return 0 on success. 0358 * \return -1 with errno set to \c ENOENT if there are no matching initiators. 0359 * \return -1 with errno set to \c EINVAL if the attribute does not relate to a specific initiator 0360 * (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR). 0361 */ 0362 HWLOC_DECLSPEC int 0363 hwloc_memattr_get_best_initiator(hwloc_topology_t topology, 0364 hwloc_memattr_id_t attribute, 0365 hwloc_obj_t target, 0366 unsigned long flags, 0367 struct hwloc_location *best_initiator, hwloc_uint64_t *value); 0368 0369 /** @} */ 0370 0371 0372 /** \defgroup hwlocality_memattrs_manage Managing memory attributes 0373 * @{ 0374 */ 0375 0376 /** \brief Return the name of a memory attribute. 0377 * 0378 * \return 0 on success. 0379 * \return -1 with errno set to \c EINVAL if the attribute does not exist. 0380 */ 0381 HWLOC_DECLSPEC int 0382 hwloc_memattr_get_name(hwloc_topology_t topology, 0383 hwloc_memattr_id_t attribute, 0384 const char **name); 0385 0386 /** \brief Return the flags of the given attribute. 0387 * 0388 * Flags are a OR'ed set of ::hwloc_memattr_flag_e. 0389 * 0390 * \return 0 on success. 0391 * \return -1 with errno set to \c EINVAL if the attribute does not exist. 0392 */ 0393 HWLOC_DECLSPEC int 0394 hwloc_memattr_get_flags(hwloc_topology_t topology, 0395 hwloc_memattr_id_t attribute, 0396 unsigned long *flags); 0397 0398 /** \brief Memory attribute flags. 0399 * Given to hwloc_memattr_register() and returned by hwloc_memattr_get_flags(). 0400 */ 0401 enum hwloc_memattr_flag_e { 0402 /** \brief The best nodes for this memory attribute are those with the higher values. 0403 * For instance Bandwidth. 0404 */ 0405 HWLOC_MEMATTR_FLAG_HIGHER_FIRST = (1UL<<0), 0406 /** \brief The best nodes for this memory attribute are those with the lower values. 0407 * For instance Latency. 0408 */ 0409 HWLOC_MEMATTR_FLAG_LOWER_FIRST = (1UL<<1), 0410 /** \brief The value returned for this memory attribute depends on the given initiator. 0411 * For instance Bandwidth and Latency, but not Capacity. 0412 */ 0413 HWLOC_MEMATTR_FLAG_NEED_INITIATOR = (1UL<<2) 0414 }; 0415 0416 /** \brief Register a new memory attribute. 0417 * 0418 * Add a specific memory attribute that is not defined in ::hwloc_memattr_id_e. 0419 * Flags are a OR'ed set of ::hwloc_memattr_flag_e. It must contain at least 0420 * one of ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST or ::HWLOC_MEMATTR_FLAG_LOWER_FIRST. 0421 * 0422 * \return 0 on success. 0423 * \return -1 with errno set to \c EBUSY if another attribute already uses this name. 0424 */ 0425 HWLOC_DECLSPEC int 0426 hwloc_memattr_register(hwloc_topology_t topology, 0427 const char *name, 0428 unsigned long flags, 0429 hwloc_memattr_id_t *id); 0430 0431 /** \brief Set an attribute value for a specific target NUMA node. 0432 * 0433 * If the attribute does not relate to a specific initiator 0434 * (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR), 0435 * location \p initiator is ignored and may be \c NULL. 0436 * 0437 * The initiator will be copied into the topology, 0438 * the caller should free anything allocated to store the initiator, 0439 * for instance the cpuset. 0440 * 0441 * \p flags must be \c 0 for now. 0442 * 0443 * \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET 0444 * when referring to accesses performed by CPU cores. 0445 * ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc, 0446 * but users may for instance use it to provide custom information about 0447 * host memory accesses performed by GPUs. 0448 * 0449 * \return 0 on success or -1 on error. 0450 */ 0451 HWLOC_DECLSPEC int 0452 hwloc_memattr_set_value(hwloc_topology_t topology, 0453 hwloc_memattr_id_t attribute, 0454 hwloc_obj_t target_node, 0455 struct hwloc_location *initiator, 0456 unsigned long flags, 0457 hwloc_uint64_t value); 0458 0459 /** \brief Return the target NUMA nodes that have some values for a given attribute. 0460 * 0461 * Return targets for the given attribute in the \p targets array 0462 * (for the given initiator if any). 0463 * If \p values is not \c NULL, the corresponding attribute values 0464 * are stored in the array it points to. 0465 * 0466 * On input, \p nr points to the number of targets that may be stored 0467 * in the array \p targets (and \p values). 0468 * On output, \p nr points to the number of targets (and values) that 0469 * were actually found, even if some of them couldn't be stored in the array. 0470 * Targets that couldn't be stored are ignored, but the function still 0471 * returns success (\c 0). The caller may find out by comparing the value pointed 0472 * by \p nr before and after the function call. 0473 * 0474 * The returned targets should not be modified or freed, 0475 * they belong to the topology. 0476 * 0477 * Argument \p initiator is ignored if the attribute does not relate to a specific 0478 * initiator (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR). 0479 * Otherwise \p initiator may be non \c NULL to report only targets 0480 * that have a value for that initiator. 0481 * 0482 * \p flags must be \c 0 for now. 0483 * 0484 * \note This function is meant for tools and debugging (listing internal information) 0485 * rather than for application queries. Applications should rather select useful 0486 * NUMA nodes with hwloc_get_local_numanode_objs() and then look at their attribute 0487 * values. 0488 * 0489 * \return 0 on success or -1 on error. 0490 * 0491 * \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET 0492 * when referring to accesses performed by CPU cores. 0493 * ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc, 0494 * but users may for instance use it to provide custom information about 0495 * host memory accesses performed by GPUs. 0496 */ 0497 HWLOC_DECLSPEC int 0498 hwloc_memattr_get_targets(hwloc_topology_t topology, 0499 hwloc_memattr_id_t attribute, 0500 struct hwloc_location *initiator, 0501 unsigned long flags, 0502 unsigned *nr, hwloc_obj_t *targets, hwloc_uint64_t *values); 0503 0504 /** \brief Return the initiators that have values for a given attribute for a specific target NUMA node. 0505 * 0506 * Return initiators for the given attribute and target node in the 0507 * \p initiators array. 0508 * If \p values is not \c NULL, the corresponding attribute values 0509 * are stored in the array it points to. 0510 * 0511 * On input, \p nr points to the number of initiators that may be stored 0512 * in the array \p initiators (and \p values). 0513 * On output, \p nr points to the number of initiators (and values) that 0514 * were actually found, even if some of them couldn't be stored in the array. 0515 * Initiators that couldn't be stored are ignored, but the function still 0516 * returns success (\c 0). The caller may find out by comparing the value pointed 0517 * by \p nr before and after the function call. 0518 * 0519 * The returned initiators should not be modified or freed, 0520 * they belong to the topology. 0521 * 0522 * \p flags must be \c 0 for now. 0523 * 0524 * If the attribute does not relate to a specific initiator 0525 * (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR), 0526 * no initiator is returned. 0527 * 0528 * \return 0 on success or -1 on error. 0529 * 0530 * \note This function is meant for tools and debugging (listing internal information) 0531 * rather than for application queries. Applications should rather select useful 0532 * NUMA nodes with hwloc_get_local_numanode_objs() and then look at their attribute 0533 * values for some relevant initiators. 0534 */ 0535 HWLOC_DECLSPEC int 0536 hwloc_memattr_get_initiators(hwloc_topology_t topology, 0537 hwloc_memattr_id_t attribute, 0538 hwloc_obj_t target_node, 0539 unsigned long flags, 0540 unsigned *nr, struct hwloc_location *initiators, hwloc_uint64_t *values); 0541 /** @} */ 0542 0543 #ifdef __cplusplus 0544 } /* extern "C" */ 0545 #endif 0546 0547 0548 #endif /* HWLOC_MEMATTR_H */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |