1/* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Intel Corporation 3 */ 4 5#ifndef _OPDL_H_ 6#define _OPDL_H_ 7 8/** 9 * @file 10 * The "opdl_ring" is a data structure that contains a fixed number of slots, 11 * with each slot having the same, but configurable, size. Entries are input 12 * into the opdl_ring by copying into available slots. Once in the opdl_ring, 13 * an entry is processed by a number of stages, with the ordering of stage 14 * processing controlled by making stages dependent on one or more other stages. 15 * An entry is not available for a stage to process until it has been processed 16 * by that stages dependencies. Entries are always made available for 17 * processing in the same order that they were input in to the opdl_ring. 18 * Inputting is considered as a stage that depends on all other stages, 19 * and is also a dependency of all stages. 20 * 21 * Inputting and processing in a stage can support multi-threading. Note that 22 * multi-thread processing can also be done by making stages co-operate e.g. two 23 * stages where one processes the even packets and the other processes odd 24 * packets. 25 * 26 * A opdl_ring can be used as the basis for pipeline based applications. Instead 27 * of each stage in a pipeline dequeuing from a ring, processing and enqueuing 28 * to another ring, it can process entries in-place on the ring. If stages do 29 * not depend on each other, they can run in parallel. 30 * 31 * The opdl_ring works with entries of configurable size, these could be 32 * pointers to mbufs, pointers to mbufs with application specific meta-data, 33 * tasks etc. 34 */ 35 36#include <stdbool.h> 37#include <stdint.h> 38#include <stdio.h> 39 40#include <rte_eventdev.h> 41#ifdef __cplusplus 42extern "C" { 43#endif 44 45#ifndef OPDL_DISCLAIMS_PER_LCORE 46/** Multi-threaded processing allows one thread to process multiple batches in a 47 * stage, while another thread is processing a single large batch. This number 48 * controls how many non-contiguous batches one stage can process before being 49 * blocked by the other stage. 50 */ 51#define OPDL_DISCLAIMS_PER_LCORE 8 52#endif 53 54/** Opaque handle to a opdl_ring instance */ 55struct opdl_ring; 56 57/** Opaque handle to a single stage in a opdl_ring */ 58struct opdl_stage; 59 60/** 61 * Create a new instance of a opdl_ring. 62 * 63 * @param name 64 * String containing the name to give the new opdl_ring instance. 65 * @param num_slots 66 * How many slots the opdl_ring contains. Must be a power a 2! 67 * @param slot_size 68 * How many bytes in each slot. 69 * @param max_num_stages 70 * Maximum number of stages. 71 * @param socket 72 * The NUMA socket (or SOCKET_ID_ANY) to allocate the memory used for this 73 * opdl_ring instance. 74 * @param threadsafe 75 * Whether to support multiple threads inputting to the opdl_ring or not. 76 * Enabling this may have a negative impact on performance if only one thread 77 * will be inputting. 78 * 79 * @return 80 * A pointer to a new opdl_ring instance, or NULL on error. 81 */ 82struct opdl_ring * 83opdl_ring_create(const char *name, uint32_t num_slots, uint32_t slot_size, 84 uint32_t max_num_stages, int socket); 85 86/** 87 * Get pointer to individual slot in a opdl_ring. 88 * 89 * @param t 90 * The opdl_ring. 91 * @param index 92 * Index of slot. If greater than the number of slots it will be masked to be 93 * within correct range. 94 * 95 * @return 96 * A pointer to that slot. 97 */ 98void * 99opdl_ring_get_slot(const struct opdl_ring *t, uint32_t index); 100 101/** 102 * Get NUMA socket used by a opdl_ring. 103 * 104 * @param t 105 * The opdl_ring. 106 * 107 * @return 108 * NUMA socket. 109 */ 110int 111opdl_ring_get_socket(const struct opdl_ring *t); 112 113/** 114 * Get number of slots in a opdl_ring. 115 * 116 * @param t 117 * The opdl_ring. 118 * 119 * @return 120 * Number of slots. 121 */ 122uint32_t 123opdl_ring_get_num_slots(const struct opdl_ring *t); 124 125/** 126 * Get name of a opdl_ring. 127 * 128 * @param t 129 * The opdl_ring. 130 * 131 * @return 132 * Name string. 133 */ 134const char * 135opdl_ring_get_name(const struct opdl_ring *t); 136 137/** 138 * Adds a new processing stage to a specified opdl_ring instance. Adding a stage 139 * while there are entries in the opdl_ring being processed will cause undefined 140 * behaviour. 141 * 142 * @param t 143 * The opdl_ring to add the stage to. 144 * @param deps 145 * An array of pointers to other stages that this stage depends on. The other 146 * stages must be part of the same opdl_ring! Note that input is an implied 147 * dependency. This can be NULL if num_deps is 0. 148 * @param num_deps 149 * The size of the deps array. 150 * @param threadsafe 151 * Whether to support multiple threads processing this stage or not. 152 * Enabling this may have a negative impact on performance if only one thread 153 * will be processing this stage. 154 * @param is_input 155 * Indication to initialise the stage with all slots available or none 156 * 157 * @return 158 * A pointer to the new stage, or NULL on error. 159 */ 160struct opdl_stage * 161opdl_stage_add(struct opdl_ring *t, bool threadsafe, bool is_input); 162 163/** 164 * Returns the input stage of a opdl_ring to be used by other API functions. 165 * 166 * @param t 167 * The opdl_ring. 168 * 169 * @return 170 * A pointer to the input stage. 171 */ 172struct opdl_stage * 173opdl_ring_get_input_stage(const struct opdl_ring *t); 174 175/** 176 * Sets the dependencies for a stage (clears all the previous deps!). Changing 177 * dependencies while there are entries in the opdl_ring being processed will 178 * cause undefined behaviour. 179 * 180 * @param s 181 * The stage to set the dependencies for. 182 * @param deps 183 * An array of pointers to other stages that this stage will depends on. The 184 * other stages must be part of the same opdl_ring! 185 * @param num_deps 186 * The size of the deps array. This must be > 0. 187 * 188 * @return 189 * 0 on success, a negative value on error. 190 */ 191int 192opdl_stage_set_deps(struct opdl_stage *s, struct opdl_stage *deps[], 193 uint32_t num_deps); 194 195/** 196 * Returns the opdl_ring that a stage belongs to. 197 * 198 * @param s 199 * The stage 200 * 201 * @return 202 * A pointer to the opdl_ring that the stage belongs to. 203 */ 204struct opdl_ring * 205opdl_stage_get_opdl_ring(const struct opdl_stage *s); 206 207/** 208 * Inputs a new batch of entries into the opdl_ring. This function is only 209 * threadsafe (with the same opdl_ring parameter) if the threadsafe parameter of 210 * opdl_ring_create() was true. For performance reasons, this function does not 211 * check input parameters. 212 * 213 * @param t 214 * The opdl_ring to input entries in to. 215 * @param entries 216 * An array of entries that will be copied in to the opdl_ring. 217 * @param num_entries 218 * The size of the entries array. 219 * @param block 220 * If this is true, the function blocks until enough slots are available to 221 * input all the requested entries. If false, then the function inputs as 222 * many entries as currently possible. 223 * 224 * @return 225 * The number of entries successfully input. 226 */ 227uint32_t 228opdl_ring_input(struct opdl_ring *t, const void *entries, uint32_t num_entries, 229 bool block); 230 231/** 232 * Inputs a new batch of entries into a opdl stage. This function is only 233 * threadsafe (with the same opdl parameter) if the threadsafe parameter of 234 * opdl_create() was true. For performance reasons, this function does not 235 * check input parameters. 236 * 237 * @param t 238 * The opdl ring to input entries in to. 239 * @param s 240 * The stage to copy entries to. 241 * @param entries 242 * An array of entries that will be copied in to the opdl ring. 243 * @param num_entries 244 * The size of the entries array. 245 * @param block 246 * If this is true, the function blocks until enough slots are available to 247 * input all the requested entries. If false, then the function inputs as 248 * many entries as currently possible. 249 * 250 * @return 251 * The number of entries successfully input. 252 */ 253uint32_t 254opdl_ring_copy_from_burst(struct opdl_ring *t, struct opdl_stage *s, 255 const void *entries, uint32_t num_entries, bool block); 256 257/** 258 * Copy a batch of entries from the opdl ring. This function is only 259 * threadsafe (with the same opdl parameter) if the threadsafe parameter of 260 * opdl_create() was true. For performance reasons, this function does not 261 * check input parameters. 262 * 263 * @param t 264 * The opdl ring to copy entries from. 265 * @param s 266 * The stage to copy entries from. 267 * @param entries 268 * An array of entries that will be copied from the opdl ring. 269 * @param num_entries 270 * The size of the entries array. 271 * @param block 272 * If this is true, the function blocks until enough slots are available to 273 * input all the requested entries. If false, then the function inputs as 274 * many entries as currently possible. 275 * 276 * @return 277 * The number of entries successfully input. 278 */ 279uint32_t 280opdl_ring_copy_to_burst(struct opdl_ring *t, struct opdl_stage *s, 281 void *entries, uint32_t num_entries, bool block); 282 283/** 284 * Before processing a batch of entries, a stage must first claim them to get 285 * access. This function is threadsafe using same opdl_stage parameter if 286 * the stage was created with threadsafe set to true, otherwise it is only 287 * threadsafe with a different opdl_stage per thread. For performance 288 * reasons, this function does not check input parameters. 289 * 290 * @param s 291 * The opdl_ring stage to read entries in. 292 * @param entries 293 * An array of pointers to entries that will be filled in by this function. 294 * @param num_entries 295 * The number of entries to attempt to claim for processing (and the size of 296 * the entries array). 297 * @param seq 298 * If not NULL, this is set to the value of the internal stage sequence number 299 * associated with the first entry returned. 300 * @param block 301 * If this is true, the function blocks until num_entries slots are available 302 * to process. If false, then the function claims as many entries as 303 * currently possible. 304 * 305 * @param atomic 306 * if this is true, the function will return event according to event flow id 307 * @return 308 * The number of pointers to entries filled in to the entries array. 309 */ 310uint32_t 311opdl_stage_claim(struct opdl_stage *s, void *entries, 312 uint32_t num_entries, uint32_t *seq, bool block, bool atomic); 313 314uint32_t 315opdl_stage_deps_add(struct opdl_ring *t, struct opdl_stage *s, 316 uint32_t nb_instance, uint32_t instance_id, 317 struct opdl_stage *deps[], uint32_t num_deps); 318 319/** 320 * A function to check how many entries are ready to be claimed. 321 * 322 * @param entries 323 * An array of pointers to entries. 324 * @param num_entries 325 * Number of entries in an array. 326 * @param arg 327 * An opaque pointer to data passed to the claim function. 328 * @param block 329 * When set to true, the function should wait until num_entries are ready to 330 * be processed. Otherwise it should return immediately. 331 * 332 * @return 333 * Number of entries ready to be claimed. 334 */ 335typedef uint32_t (opdl_ring_check_entries_t)(void *entries[], 336 uint32_t num_entries, void *arg, bool block); 337 338/** 339 * Before processing a batch of entries, a stage must first claim them to get 340 * access. Each entry is checked by the passed check() function and depending 341 * on block value, it waits until num_entries are ready or returns immediately. 342 * This function is only threadsafe with a different opdl_stage per thread. 343 * 344 * @param s 345 * The opdl_ring stage to read entries in. 346 * @param entries 347 * An array of pointers to entries that will be filled in by this function. 348 * @param num_entries 349 * The number of entries to attempt to claim for processing (and the size of 350 * the entries array). 351 * @param seq 352 * If not NULL, this is set to the value of the internal stage sequence number 353 * associated with the first entry returned. 354 * @param block 355 * If this is true, the function blocks until num_entries ready slots are 356 * available to process. If false, then the function claims as many ready 357 * entries as currently possible. 358 * @param check 359 * Pointer to a function called to check entries. 360 * @param arg 361 * Opaque data passed to check() function. 362 * 363 * @return 364 * The number of pointers to ready entries filled in to the entries array. 365 */ 366uint32_t 367opdl_stage_claim_check(struct opdl_stage *s, void **entries, 368 uint32_t num_entries, uint32_t *seq, bool block, 369 opdl_ring_check_entries_t *check, void *arg); 370 371/** 372 * Before processing a batch of entries, a stage must first claim them to get 373 * access. This function is threadsafe using same opdl_stage parameter if 374 * the stage was created with threadsafe set to true, otherwise it is only 375 * threadsafe with a different opdl_stage per thread. 376 * 377 * The difference between this function and opdl_stage_claim() is that this 378 * function copies the entries from the opdl_ring. Note that any changes made to 379 * the copied entries will not be reflected back in to the entries in the 380 * opdl_ring, so this function probably only makes sense if the entries are 381 * pointers to other data. For performance reasons, this function does not check 382 * input parameters. 383 * 384 * @param s 385 * The opdl_ring stage to read entries in. 386 * @param entries 387 * An array of entries that will be filled in by this function. 388 * @param num_entries 389 * The number of entries to attempt to claim for processing (and the size of 390 * the entries array). 391 * @param seq 392 * If not NULL, this is set to the value of the internal stage sequence number 393 * associated with the first entry returned. 394 * @param block 395 * If this is true, the function blocks until num_entries slots are available 396 * to process. If false, then the function claims as many entries as 397 * currently possible. 398 * 399 * @return 400 * The number of entries copied in to the entries array. 401 */ 402uint32_t 403opdl_stage_claim_copy(struct opdl_stage *s, void *entries, 404 uint32_t num_entries, uint32_t *seq, bool block); 405 406/** 407 * This function must be called when a stage has finished its processing of 408 * entries, to make them available to any dependent stages. All entries that are 409 * claimed by the calling thread in the stage will be disclaimed. It is possible 410 * to claim multiple batches before disclaiming. For performance reasons, this 411 * function does not check input parameters. 412 * 413 * @param s 414 * The opdl_ring stage in which to disclaim all claimed entries. 415 * 416 * @param block 417 * Entries are always made available to a stage in the same order that they 418 * were input in the stage. If a stage is multithread safe, this may mean that 419 * full disclaiming of a batch of entries can not be considered complete until 420 * all earlier threads in the stage have disclaimed. If this parameter is true 421 * then the function blocks until all entries are fully disclaimed, otherwise 422 * it disclaims as many as currently possible, with non fully disclaimed 423 * batches stored until the next call to a claim or disclaim function for this 424 * stage on this thread. 425 * 426 * If a thread is not going to process any more entries in this stage, it 427 * *must* first call this function with this parameter set to true to ensure 428 * it does not block the entire opdl_ring. 429 * 430 * In a single threaded stage, this parameter has no effect. 431 */ 432int 433opdl_stage_disclaim(struct opdl_stage *s, uint32_t num_entries, 434 bool block); 435 436/** 437 * This function can be called when a stage has finished its processing of 438 * entries, to make them available to any dependent stages. The difference 439 * between this function and opdl_stage_disclaim() is that here only a 440 * portion of entries are disclaimed, not all of them. For performance reasons, 441 * this function does not check input parameters. 442 * 443 * @param s 444 * The opdl_ring stage in which to disclaim entries. 445 * 446 * @param num_entries 447 * The number of entries to disclaim. 448 * 449 * @param block 450 * Entries are always made available to a stage in the same order that they 451 * were input in the stage. If a stage is multithread safe, this may mean that 452 * full disclaiming of a batch of entries can not be considered complete until 453 * all earlier threads in the stage have disclaimed. If this parameter is true 454 * then the function blocks until the specified number of entries has been 455 * disclaimed (or there are no more entries to disclaim). Otherwise it 456 * disclaims as many claims as currently possible and an attempt to disclaim 457 * them is made the next time a claim or disclaim function for this stage on 458 * this thread is called. 459 * 460 * In a single threaded stage, this parameter has no effect. 461 */ 462void 463opdl_stage_disclaim_n(struct opdl_stage *s, uint32_t num_entries, 464 bool block); 465 466/** 467 * Check how many entries can be input. 468 * 469 * @param t 470 * The opdl_ring instance to check. 471 * 472 * @return 473 * The number of new entries currently allowed to be input. 474 */ 475uint32_t 476opdl_ring_available(struct opdl_ring *t); 477 478/** 479 * Check how many entries can be processed in a stage. 480 * 481 * @param s 482 * The stage to check. 483 * 484 * @return 485 * The number of entries currently available to be processed in this stage. 486 */ 487uint32_t 488opdl_stage_available(struct opdl_stage *s); 489 490/** 491 * Check how many entries are available to be processed. 492 * 493 * NOTE : DOES NOT CHANGE ANY STATE WITHIN THE STAGE 494 * 495 * @param s 496 * The stage to check. 497 * 498 * @param num_entries 499 * The number of entries to check for availability. 500 * 501 * @return 502 * The number of entries currently available to be processed in this stage. 503 */ 504uint32_t 505opdl_stage_find_num_available(struct opdl_stage *s, uint32_t num_entries); 506 507/** 508 * Create empty stage instance and return the pointer. 509 * 510 * @param t 511 * The pointer of opdl_ring. 512 * 513 * @param threadsafe 514 * enable multiple thread or not. 515 * @return 516 * The pointer of one empty stage instance. 517 */ 518struct opdl_stage * 519opdl_stage_create(struct opdl_ring *t, bool threadsafe); 520 521 522/** 523 * Set the internal queue id for each stage instance. 524 * 525 * @param s 526 * The pointer of stage instance. 527 * 528 * @param queue_id 529 * The value of internal queue id. 530 */ 531void 532opdl_stage_set_queue_id(struct opdl_stage *s, 533 uint32_t queue_id); 534 535/** 536 * Prints information on opdl_ring instance and all its stages 537 * 538 * @param t 539 * The stage to print info on. 540 * @param f 541 * Where to print the info. 542 */ 543void 544opdl_ring_dump(const struct opdl_ring *t, FILE *f); 545 546/** 547 * Blocks until all entries in a opdl_ring have been processed by all stages. 548 * 549 * @param t 550 * The opdl_ring instance to flush. 551 */ 552void 553opdl_ring_flush(struct opdl_ring *t); 554 555/** 556 * Deallocates all resources used by a opdl_ring instance 557 * 558 * @param t 559 * The opdl_ring instance to free. 560 */ 561void 562opdl_ring_free(struct opdl_ring *t); 563 564/** 565 * Search for a opdl_ring by its name 566 * 567 * @param name 568 * The name of the opdl_ring. 569 * @return 570 * The pointer to the opdl_ring matching the name, or NULL if not found. 571 * 572 */ 573struct opdl_ring * 574opdl_ring_lookup(const char *name); 575 576/** 577 * Set a opdl_stage to threadsafe variable. 578 * 579 * @param s 580 * The opdl_stage. 581 * @param threadsafe 582 * Threadsafe value. 583 */ 584void 585opdl_ring_set_stage_threadsafe(struct opdl_stage *s, bool threadsafe); 586 587 588/** 589 * Compare the event descriptor with original version in the ring. 590 * if key field event descriptor is changed by application, then 591 * update the slot in the ring otherwise do nothing with it. 592 * the key field is flow_id, priority, mbuf, impl_opaque 593 * 594 * @param s 595 * The opdl_stage. 596 * @param ev 597 * pointer of the event descriptor. 598 * @param index 599 * index of the event descriptor. 600 * @param atomic 601 * queue type associate with the stage. 602 * @return 603 * if the event key field is changed compare with previous record. 604 */ 605 606bool 607opdl_ring_cas_slot(struct opdl_stage *s, const struct rte_event *ev, 608 uint32_t index, bool atomic); 609 610#ifdef __cplusplus 611} 612#endif 613 614#endif /* _OPDL_H_ */ 615