diff options
| author | Stefani Seibold <stefani@seibold.net> | 2009-12-21 17:37:32 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-22 17:17:56 -0500 |
| commit | 86d4880313603810901f639ccb5c88ff13d4ad3c (patch) | |
| tree | c182d890b5c96a1143b70b00b93e3fc4a9263555 /include | |
| parent | a121f24accac1600bf5b6fb1e12eeabdfed7cb1a (diff) | |
kfifo: add record handling functions
Add kfifo_in_rec() - puts some record data into the FIFO
Add kfifo_out_rec() - gets some record data from the FIFO
Add kfifo_from_user_rec() - puts some data from user space into the FIFO
Add kfifo_to_user_rec() - gets data from the FIFO and write it to user space
Add kfifo_peek_rec() - gets the size of the next FIFO record field
Add kfifo_skip_rec() - skip the next fifo out record
Add kfifo_avail_rec() - determinate the number of bytes available in a record FIFO
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/kfifo.h | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index d3230fb08bc7..486e8ad3bb50 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h | |||
| @@ -278,4 +278,334 @@ static inline unsigned int __kfifo_off(struct kfifo *fifo, unsigned int off) | |||
| 278 | return off & (fifo->size - 1); | 278 | return off & (fifo->size - 1); |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | /** | ||
| 282 | * __kfifo_peek_n internal helper function for determinate the length of | ||
| 283 | * the next record in the fifo | ||
| 284 | */ | ||
| 285 | static inline unsigned int __kfifo_peek_n(struct kfifo *fifo, | ||
| 286 | unsigned int recsize) | ||
| 287 | { | ||
| 288 | #define __KFIFO_GET(fifo, off, shift) \ | ||
| 289 | ((fifo)->buffer[__kfifo_off((fifo), (fifo)->out+(off))] << (shift)) | ||
| 290 | |||
| 291 | unsigned int l; | ||
| 292 | |||
| 293 | l = __KFIFO_GET(fifo, 0, 0); | ||
| 294 | |||
| 295 | if (--recsize) | ||
| 296 | l |= __KFIFO_GET(fifo, 1, 8); | ||
| 297 | |||
| 298 | return l; | ||
| 299 | #undef __KFIFO_GET | ||
| 300 | } | ||
| 301 | |||
| 302 | /** | ||
| 303 | * __kfifo_poke_n internal helper function for storing the length of | ||
| 304 | * the next record into the fifo | ||
| 305 | */ | ||
| 306 | static inline void __kfifo_poke_n(struct kfifo *fifo, | ||
| 307 | unsigned int recsize, unsigned int n) | ||
| 308 | { | ||
| 309 | #define __KFIFO_PUT(fifo, off, val, shift) \ | ||
| 310 | ( \ | ||
| 311 | (fifo)->buffer[__kfifo_off((fifo), (fifo)->in+(off))] = \ | ||
| 312 | (unsigned char)((val) >> (shift)) \ | ||
| 313 | ) | ||
| 314 | |||
| 315 | __KFIFO_PUT(fifo, 0, n, 0); | ||
| 316 | |||
| 317 | if (--recsize) | ||
| 318 | __KFIFO_PUT(fifo, 1, n, 8); | ||
| 319 | #undef __KFIFO_PUT | ||
| 320 | } | ||
| 321 | |||
| 322 | /** | ||
| 323 | * __kfifo_in_... internal functions for put date into the fifo | ||
| 324 | * do not call it directly, use kfifo_in_rec() instead | ||
| 325 | */ | ||
| 326 | extern unsigned int __kfifo_in_n(struct kfifo *fifo, | ||
| 327 | const void *from, unsigned int n, unsigned int recsize); | ||
| 328 | |||
| 329 | extern unsigned int __kfifo_in_generic(struct kfifo *fifo, | ||
| 330 | const void *from, unsigned int n, unsigned int recsize); | ||
| 331 | |||
| 332 | static inline unsigned int __kfifo_in_rec(struct kfifo *fifo, | ||
| 333 | const void *from, unsigned int n, unsigned int recsize) | ||
| 334 | { | ||
| 335 | unsigned int ret; | ||
| 336 | |||
| 337 | ret = __kfifo_in_n(fifo, from, n, recsize); | ||
| 338 | |||
| 339 | if (likely(ret == 0)) { | ||
| 340 | if (recsize) | ||
| 341 | __kfifo_poke_n(fifo, recsize, n); | ||
| 342 | __kfifo_add_in(fifo, n + recsize); | ||
| 343 | } | ||
| 344 | return ret; | ||
| 345 | } | ||
| 346 | |||
| 347 | /** | ||
| 348 | * kfifo_in_rec - puts some record data into the FIFO | ||
| 349 | * @fifo: the fifo to be used. | ||
| 350 | * @from: the data to be added. | ||
| 351 | * @n: the length of the data to be added. | ||
| 352 | * @recsize: size of record field | ||
| 353 | * | ||
| 354 | * This function copies @n bytes from the @from into the FIFO and returns | ||
| 355 | * the number of bytes which cannot be copied. | ||
| 356 | * A returned value greater than the @n value means that the record doesn't | ||
| 357 | * fit into the buffer. | ||
| 358 | * | ||
| 359 | * Note that with only one concurrent reader and one concurrent | ||
| 360 | * writer, you don't need extra locking to use these functions. | ||
| 361 | */ | ||
| 362 | static inline __must_check unsigned int kfifo_in_rec(struct kfifo *fifo, | ||
| 363 | void *from, unsigned int n, unsigned int recsize) | ||
| 364 | { | ||
| 365 | if (!__builtin_constant_p(recsize)) | ||
| 366 | return __kfifo_in_generic(fifo, from, n, recsize); | ||
| 367 | return __kfifo_in_rec(fifo, from, n, recsize); | ||
| 368 | } | ||
| 369 | |||
| 370 | /** | ||
| 371 | * __kfifo_out_... internal functions for get date from the fifo | ||
| 372 | * do not call it directly, use kfifo_out_rec() instead | ||
| 373 | */ | ||
| 374 | extern unsigned int __kfifo_out_n(struct kfifo *fifo, | ||
| 375 | void *to, unsigned int reclen, unsigned int recsize); | ||
| 376 | |||
| 377 | extern unsigned int __kfifo_out_generic(struct kfifo *fifo, | ||
| 378 | void *to, unsigned int n, | ||
| 379 | unsigned int recsize, unsigned int *total); | ||
| 380 | |||
| 381 | static inline unsigned int __kfifo_out_rec(struct kfifo *fifo, | ||
| 382 | void *to, unsigned int n, unsigned int recsize, | ||
| 383 | unsigned int *total) | ||
| 384 | { | ||
| 385 | unsigned int l; | ||
| 386 | |||
| 387 | if (!recsize) { | ||
| 388 | l = n; | ||
| 389 | if (total) | ||
| 390 | *total = l; | ||
| 391 | } else { | ||
| 392 | l = __kfifo_peek_n(fifo, recsize); | ||
| 393 | if (total) | ||
| 394 | *total = l; | ||
| 395 | if (n < l) | ||
| 396 | return l; | ||
| 397 | } | ||
| 398 | |||
| 399 | return __kfifo_out_n(fifo, to, l, recsize); | ||
| 400 | } | ||
| 401 | |||
| 402 | /** | ||
| 403 | * kfifo_out_rec - gets some record data from the FIFO | ||
| 404 | * @fifo: the fifo to be used. | ||
| 405 | * @to: where the data must be copied. | ||
| 406 | * @n: the size of the destination buffer. | ||
| 407 | * @recsize: size of record field | ||
| 408 | * @total: pointer where the total number of to copied bytes should stored | ||
| 409 | * | ||
| 410 | * This function copies at most @n bytes from the FIFO to @to and returns the | ||
| 411 | * number of bytes which cannot be copied. | ||
| 412 | * A returned value greater than the @n value means that the record doesn't | ||
| 413 | * fit into the @to buffer. | ||
| 414 | * | ||
| 415 | * Note that with only one concurrent reader and one concurrent | ||
| 416 | * writer, you don't need extra locking to use these functions. | ||
| 417 | */ | ||
| 418 | static inline __must_check unsigned int kfifo_out_rec(struct kfifo *fifo, | ||
| 419 | void *to, unsigned int n, unsigned int recsize, | ||
| 420 | unsigned int *total) | ||
| 421 | |||
| 422 | { | ||
| 423 | if (!__builtin_constant_p(recsize)) | ||
| 424 | return __kfifo_out_generic(fifo, to, n, recsize, total); | ||
| 425 | return __kfifo_out_rec(fifo, to, n, recsize, total); | ||
| 426 | } | ||
| 427 | |||
| 428 | /** | ||
| 429 | * __kfifo_from_user_... internal functions for transfer from user space into | ||
| 430 | * the fifo. do not call it directly, use kfifo_from_user_rec() instead | ||
| 431 | */ | ||
| 432 | extern unsigned int __kfifo_from_user_n(struct kfifo *fifo, | ||
| 433 | const void __user *from, unsigned int n, unsigned int recsize); | ||
| 434 | |||
| 435 | extern unsigned int __kfifo_from_user_generic(struct kfifo *fifo, | ||
| 436 | const void __user *from, unsigned int n, unsigned int recsize); | ||
| 437 | |||
| 438 | static inline unsigned int __kfifo_from_user_rec(struct kfifo *fifo, | ||
| 439 | const void __user *from, unsigned int n, unsigned int recsize) | ||
| 440 | { | ||
| 441 | unsigned int ret; | ||
| 442 | |||
| 443 | ret = __kfifo_from_user_n(fifo, from, n, recsize); | ||
| 444 | |||
| 445 | if (likely(ret == 0)) { | ||
| 446 | if (recsize) | ||
| 447 | __kfifo_poke_n(fifo, recsize, n); | ||
| 448 | __kfifo_add_in(fifo, n + recsize); | ||
| 449 | } | ||
| 450 | return ret; | ||
| 451 | } | ||
| 452 | |||
| 453 | /** | ||
| 454 | * kfifo_from_user_rec - puts some data from user space into the FIFO | ||
| 455 | * @fifo: the fifo to be used. | ||
| 456 | * @from: pointer to the data to be added. | ||
| 457 | * @n: the length of the data to be added. | ||
| 458 | * @recsize: size of record field | ||
| 459 | * | ||
| 460 | * This function copies @n bytes from the @from into the | ||
| 461 | * FIFO and returns the number of bytes which cannot be copied. | ||
| 462 | * | ||
| 463 | * If the returned value is equal or less the @n value, the copy_from_user() | ||
| 464 | * functions has failed. Otherwise the record doesn't fit into the buffer. | ||
| 465 | * | ||
| 466 | * Note that with only one concurrent reader and one concurrent | ||
| 467 | * writer, you don't need extra locking to use these functions. | ||
| 468 | */ | ||
| 469 | static inline __must_check unsigned int kfifo_from_user_rec(struct kfifo *fifo, | ||
| 470 | const void __user *from, unsigned int n, unsigned int recsize) | ||
| 471 | { | ||
| 472 | if (!__builtin_constant_p(recsize)) | ||
| 473 | return __kfifo_from_user_generic(fifo, from, n, recsize); | ||
| 474 | return __kfifo_from_user_rec(fifo, from, n, recsize); | ||
| 475 | } | ||
| 476 | |||
| 477 | /** | ||
| 478 | * __kfifo_to_user_... internal functions for transfer fifo data into user space | ||
| 479 | * do not call it directly, use kfifo_to_user_rec() instead | ||
| 480 | */ | ||
| 481 | extern unsigned int __kfifo_to_user_n(struct kfifo *fifo, | ||
| 482 | void __user *to, unsigned int n, unsigned int reclen, | ||
| 483 | unsigned int recsize); | ||
| 484 | |||
| 485 | extern unsigned int __kfifo_to_user_generic(struct kfifo *fifo, | ||
| 486 | void __user *to, unsigned int n, unsigned int recsize, | ||
| 487 | unsigned int *total); | ||
| 488 | |||
| 489 | static inline unsigned int __kfifo_to_user_rec(struct kfifo *fifo, | ||
| 490 | void __user *to, unsigned int n, | ||
| 491 | unsigned int recsize, unsigned int *total) | ||
| 492 | { | ||
| 493 | unsigned int l; | ||
| 494 | |||
| 495 | if (!recsize) { | ||
| 496 | l = n; | ||
| 497 | if (total) | ||
| 498 | *total = l; | ||
| 499 | } else { | ||
| 500 | l = __kfifo_peek_n(fifo, recsize); | ||
| 501 | if (total) | ||
| 502 | *total = l; | ||
| 503 | if (n < l) | ||
| 504 | return l; | ||
| 505 | } | ||
| 506 | |||
| 507 | return __kfifo_to_user_n(fifo, to, n, l, recsize); | ||
| 508 | } | ||
| 509 | |||
| 510 | /** | ||
| 511 | * kfifo_to_user_rec - gets data from the FIFO and write it to user space | ||
| 512 | * @fifo: the fifo to be used. | ||
| 513 | * @to: where the data must be copied. | ||
| 514 | * @n: the size of the destination buffer. | ||
| 515 | * @recsize: size of record field | ||
| 516 | * @total: pointer where the total number of to copied bytes should stored | ||
| 517 | * | ||
| 518 | * This function copies at most @n bytes from the FIFO to the @to. | ||
| 519 | * In case of an error, the function returns the number of bytes which cannot | ||
| 520 | * be copied. | ||
| 521 | * If the returned value is equal or less the @n value, the copy_to_user() | ||
| 522 | * functions has failed. Otherwise the record doesn't fit into the @to buffer. | ||
| 523 | * | ||
| 524 | * Note that with only one concurrent reader and one concurrent | ||
| 525 | * writer, you don't need extra locking to use these functions. | ||
| 526 | */ | ||
| 527 | static inline __must_check unsigned int kfifo_to_user_rec(struct kfifo *fifo, | ||
| 528 | void __user *to, unsigned int n, unsigned int recsize, | ||
| 529 | unsigned int *total) | ||
| 530 | { | ||
| 531 | if (!__builtin_constant_p(recsize)) | ||
| 532 | return __kfifo_to_user_generic(fifo, to, n, recsize, total); | ||
| 533 | return __kfifo_to_user_rec(fifo, to, n, recsize, total); | ||
| 534 | } | ||
| 535 | |||
| 536 | /** | ||
| 537 | * __kfifo_peek_... internal functions for peek into the next fifo record | ||
| 538 | * do not call it directly, use kfifo_peek_rec() instead | ||
| 539 | */ | ||
| 540 | extern unsigned int __kfifo_peek_generic(struct kfifo *fifo, | ||
| 541 | unsigned int recsize); | ||
| 542 | |||
| 543 | /** | ||
| 544 | * kfifo_peek_rec - gets the size of the next FIFO record data | ||
| 545 | * @fifo: the fifo to be used. | ||
| 546 | * @recsize: size of record field | ||
| 547 | * | ||
| 548 | * This function returns the size of the next FIFO record in number of bytes | ||
| 549 | */ | ||
| 550 | static inline __must_check unsigned int kfifo_peek_rec(struct kfifo *fifo, | ||
| 551 | unsigned int recsize) | ||
| 552 | { | ||
| 553 | if (!__builtin_constant_p(recsize)) | ||
| 554 | return __kfifo_peek_generic(fifo, recsize); | ||
| 555 | if (!recsize) | ||
| 556 | return kfifo_len(fifo); | ||
| 557 | return __kfifo_peek_n(fifo, recsize); | ||
| 558 | } | ||
| 559 | |||
| 560 | /** | ||
| 561 | * __kfifo_skip_... internal functions for skip the next fifo record | ||
| 562 | * do not call it directly, use kfifo_skip_rec() instead | ||
| 563 | */ | ||
| 564 | extern void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize); | ||
| 565 | |||
| 566 | static inline void __kfifo_skip_rec(struct kfifo *fifo, | ||
| 567 | unsigned int recsize) | ||
| 568 | { | ||
| 569 | unsigned int l; | ||
| 570 | |||
| 571 | if (recsize) { | ||
| 572 | l = __kfifo_peek_n(fifo, recsize); | ||
| 573 | |||
| 574 | if (l + recsize <= kfifo_len(fifo)) { | ||
| 575 | __kfifo_add_out(fifo, l + recsize); | ||
| 576 | return; | ||
| 577 | } | ||
| 578 | } | ||
| 579 | kfifo_reset_out(fifo); | ||
| 580 | } | ||
| 581 | |||
| 582 | /** | ||
| 583 | * kfifo_skip_rec - skip the next fifo out record | ||
| 584 | * @fifo: the fifo to be used. | ||
| 585 | * @recsize: size of record field | ||
| 586 | * | ||
| 587 | * This function skips the next FIFO record | ||
| 588 | */ | ||
| 589 | static inline void kfifo_skip_rec(struct kfifo *fifo, | ||
| 590 | unsigned int recsize) | ||
| 591 | { | ||
| 592 | if (!__builtin_constant_p(recsize)) | ||
| 593 | __kfifo_skip_generic(fifo, recsize); | ||
| 594 | else | ||
| 595 | __kfifo_skip_rec(fifo, recsize); | ||
| 596 | } | ||
| 597 | |||
| 598 | /** | ||
| 599 | * kfifo_avail_rec - returns the number of bytes available in a record FIFO | ||
| 600 | * @fifo: the fifo to be used. | ||
| 601 | * @recsize: size of record field | ||
| 602 | */ | ||
| 603 | static inline __must_check unsigned int kfifo_avail_rec(struct kfifo *fifo, | ||
| 604 | unsigned int recsize) | ||
| 605 | { | ||
| 606 | unsigned int l = kfifo_size(fifo) - kfifo_len(fifo); | ||
| 607 | |||
| 608 | return (l > recsize) ? l - recsize : 0; | ||
| 609 | } | ||
| 610 | |||
| 281 | #endif | 611 | #endif |
