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/linux/kfifo.h | |
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/linux/kfifo.h')
-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 |