提交 498d319b 编写于 作者: S Stefani Seibold 提交者: Linus Torvalds

kfifo API type safety

This patch enhances the type safety for the kfifo API.  It is now safe
to put const data into a non const FIFO and the API will now generate a
compiler warning when reading from the fifo where the destination
address is pointing to a const variable.

As a side effect the kfifo_put() does now expect the value of an element
instead a pointer to the element.  This was suggested Russell King.  It
make the handling of the kfifo_put easier since there is no need to
create a helper variable for getting the address of a pointer or to pass
integers of different sizes.

IMHO the API break is okay, since there are currently only six users of
kfifo_put().

The code is also cleaner by kicking out the "if (0)" expressions.

[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: NStefani Seibold <stefani@seibold.net>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Hauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 a019e48c
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
*/ */
void drm_flip_work_queue(struct drm_flip_work *work, void *val) void drm_flip_work_queue(struct drm_flip_work *work, void *val)
{ {
if (kfifo_put(&work->fifo, (const void **)&val)) { if (kfifo_put(&work->fifo, val)) {
atomic_inc(&work->pending); atomic_inc(&work->pending);
} else { } else {
DRM_ERROR("%s fifo full!\n", work->name); DRM_ERROR("%s fifo full!\n", work->name);
......
...@@ -56,7 +56,7 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) ...@@ -56,7 +56,7 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
ev.id = ev_code; ev.id = ev_code;
ev.timestamp = timestamp; ev.timestamp = timestamp;
copied = kfifo_put(&ev_int->det_events, &ev); copied = kfifo_put(&ev_int->det_events, ev);
if (copied != 0) if (copied != 0)
wake_up_locked_poll(&ev_int->wait, POLLIN); wake_up_locked_poll(&ev_int->wait, POLLIN);
} }
......
...@@ -446,7 +446,7 @@ static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) ...@@ -446,7 +446,7 @@ static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
break; break;
if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) { if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) {
rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n"); rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
break; break;
} }
......
...@@ -164,7 +164,7 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, ...@@ -164,7 +164,7 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
valid = rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID); valid = rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID);
if (valid) { if (valid) {
if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status)) if (!kfifo_put(&rt2x00dev->txstatus_fifo, tx_status))
rt2x00_warn(rt2x00dev, "TX status FIFO overrun\n"); rt2x00_warn(rt2x00dev, "TX status FIFO overrun\n");
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
......
...@@ -574,7 +574,7 @@ void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, ...@@ -574,7 +574,7 @@ void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
}; };
spin_lock_irqsave(&aer_recover_ring_lock, flags); spin_lock_irqsave(&aer_recover_ring_lock, flags);
if (kfifo_put(&aer_recover_ring, &entry)) if (kfifo_put(&aer_recover_ring, entry))
schedule_work(&aer_recover_work); schedule_work(&aer_recover_work);
else else
pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n", pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n",
......
/* /*
* A generic kernel FIFO implementation * A generic kernel FIFO implementation
* *
* Copyright (C) 2009/2010 Stefani Seibold <stefani@seibold.net> * Copyright (C) 2013 Stefani Seibold <stefani@seibold.net>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -67,9 +67,10 @@ struct __kfifo { ...@@ -67,9 +67,10 @@ struct __kfifo {
union { \ union { \
struct __kfifo kfifo; \ struct __kfifo kfifo; \
datatype *type; \ datatype *type; \
const datatype *const_type; \
char (*rectype)[recsize]; \ char (*rectype)[recsize]; \
ptrtype *ptr; \ ptrtype *ptr; \
const ptrtype *ptr_const; \ ptrtype const *ptr_const; \
} }
#define __STRUCT_KFIFO(type, size, recsize, ptrtype) \ #define __STRUCT_KFIFO(type, size, recsize, ptrtype) \
...@@ -386,16 +387,12 @@ __kfifo_int_must_check_helper( \ ...@@ -386,16 +387,12 @@ __kfifo_int_must_check_helper( \
#define kfifo_put(fifo, val) \ #define kfifo_put(fifo, val) \
({ \ ({ \
typeof((fifo) + 1) __tmp = (fifo); \ typeof((fifo) + 1) __tmp = (fifo); \
typeof((val) + 1) __val = (val); \ typeof(*__tmp->const_type) __val = (val); \
unsigned int __ret; \ unsigned int __ret; \
const size_t __recsize = sizeof(*__tmp->rectype); \ size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \ struct __kfifo *__kfifo = &__tmp->kfifo; \
if (0) { \
typeof(__tmp->ptr_const) __dummy __attribute__ ((unused)); \
__dummy = (typeof(__val))NULL; \
} \
if (__recsize) \ if (__recsize) \
__ret = __kfifo_in_r(__kfifo, __val, sizeof(*__val), \ __ret = __kfifo_in_r(__kfifo, &__val, sizeof(__val), \
__recsize); \ __recsize); \
else { \ else { \
__ret = !kfifo_is_full(__tmp); \ __ret = !kfifo_is_full(__tmp); \
...@@ -404,7 +401,7 @@ __kfifo_int_must_check_helper( \ ...@@ -404,7 +401,7 @@ __kfifo_int_must_check_helper( \
((typeof(__tmp->type))__kfifo->data) : \ ((typeof(__tmp->type))__kfifo->data) : \
(__tmp->buf) \ (__tmp->buf) \
)[__kfifo->in & __tmp->kfifo.mask] = \ )[__kfifo->in & __tmp->kfifo.mask] = \
*(typeof(__tmp->type))__val; \ (typeof(*__tmp->type))__val; \
smp_wmb(); \ smp_wmb(); \
__kfifo->in++; \ __kfifo->in++; \
} \ } \
...@@ -415,7 +412,7 @@ __kfifo_int_must_check_helper( \ ...@@ -415,7 +412,7 @@ __kfifo_int_must_check_helper( \
/** /**
* kfifo_get - get data from the fifo * kfifo_get - get data from the fifo
* @fifo: address of the fifo to be used * @fifo: address of the fifo to be used
* @val: the var where to store the data to be added * @val: address where to store the data
* *
* This macro reads the data from the fifo. * This macro reads the data from the fifo.
* It returns 0 if the fifo was empty. Otherwise it returns the number * It returns 0 if the fifo was empty. Otherwise it returns the number
...@@ -428,12 +425,10 @@ __kfifo_int_must_check_helper( \ ...@@ -428,12 +425,10 @@ __kfifo_int_must_check_helper( \
__kfifo_uint_must_check_helper( \ __kfifo_uint_must_check_helper( \
({ \ ({ \
typeof((fifo) + 1) __tmp = (fifo); \ typeof((fifo) + 1) __tmp = (fifo); \
typeof((val) + 1) __val = (val); \ typeof(__tmp->ptr) __val = (val); \
unsigned int __ret; \ unsigned int __ret; \
const size_t __recsize = sizeof(*__tmp->rectype); \ const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \ struct __kfifo *__kfifo = &__tmp->kfifo; \
if (0) \
__val = (typeof(__tmp->ptr))0; \
if (__recsize) \ if (__recsize) \
__ret = __kfifo_out_r(__kfifo, __val, sizeof(*__val), \ __ret = __kfifo_out_r(__kfifo, __val, sizeof(*__val), \
__recsize); \ __recsize); \
...@@ -456,7 +451,7 @@ __kfifo_uint_must_check_helper( \ ...@@ -456,7 +451,7 @@ __kfifo_uint_must_check_helper( \
/** /**
* kfifo_peek - get data from the fifo without removing * kfifo_peek - get data from the fifo without removing
* @fifo: address of the fifo to be used * @fifo: address of the fifo to be used
* @val: the var where to store the data to be added * @val: address where to store the data
* *
* This reads the data from the fifo without removing it from the fifo. * This reads the data from the fifo without removing it from the fifo.
* It returns 0 if the fifo was empty. Otherwise it returns the number * It returns 0 if the fifo was empty. Otherwise it returns the number
...@@ -469,12 +464,10 @@ __kfifo_uint_must_check_helper( \ ...@@ -469,12 +464,10 @@ __kfifo_uint_must_check_helper( \
__kfifo_uint_must_check_helper( \ __kfifo_uint_must_check_helper( \
({ \ ({ \
typeof((fifo) + 1) __tmp = (fifo); \ typeof((fifo) + 1) __tmp = (fifo); \
typeof((val) + 1) __val = (val); \ typeof(__tmp->ptr) __val = (val); \
unsigned int __ret; \ unsigned int __ret; \
const size_t __recsize = sizeof(*__tmp->rectype); \ const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \ struct __kfifo *__kfifo = &__tmp->kfifo; \
if (0) \
__val = (typeof(__tmp->ptr))NULL; \
if (__recsize) \ if (__recsize) \
__ret = __kfifo_out_peek_r(__kfifo, __val, sizeof(*__val), \ __ret = __kfifo_out_peek_r(__kfifo, __val, sizeof(*__val), \
__recsize); \ __recsize); \
...@@ -508,14 +501,10 @@ __kfifo_uint_must_check_helper( \ ...@@ -508,14 +501,10 @@ __kfifo_uint_must_check_helper( \
#define kfifo_in(fifo, buf, n) \ #define kfifo_in(fifo, buf, n) \
({ \ ({ \
typeof((fifo) + 1) __tmp = (fifo); \ typeof((fifo) + 1) __tmp = (fifo); \
typeof((buf) + 1) __buf = (buf); \ typeof(__tmp->ptr_const) __buf = (buf); \
unsigned long __n = (n); \ unsigned long __n = (n); \
const size_t __recsize = sizeof(*__tmp->rectype); \ const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \ struct __kfifo *__kfifo = &__tmp->kfifo; \
if (0) { \
typeof(__tmp->ptr_const) __dummy __attribute__ ((unused)); \
__dummy = (typeof(__buf))NULL; \
} \
(__recsize) ?\ (__recsize) ?\
__kfifo_in_r(__kfifo, __buf, __n, __recsize) : \ __kfifo_in_r(__kfifo, __buf, __n, __recsize) : \
__kfifo_in(__kfifo, __buf, __n); \ __kfifo_in(__kfifo, __buf, __n); \
...@@ -561,14 +550,10 @@ __kfifo_uint_must_check_helper( \ ...@@ -561,14 +550,10 @@ __kfifo_uint_must_check_helper( \
__kfifo_uint_must_check_helper( \ __kfifo_uint_must_check_helper( \
({ \ ({ \
typeof((fifo) + 1) __tmp = (fifo); \ typeof((fifo) + 1) __tmp = (fifo); \
typeof((buf) + 1) __buf = (buf); \ typeof(__tmp->ptr) __buf = (buf); \
unsigned long __n = (n); \ unsigned long __n = (n); \
const size_t __recsize = sizeof(*__tmp->rectype); \ const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \ struct __kfifo *__kfifo = &__tmp->kfifo; \
if (0) { \
typeof(__tmp->ptr) __dummy = NULL; \
__buf = __dummy; \
} \
(__recsize) ?\ (__recsize) ?\
__kfifo_out_r(__kfifo, __buf, __n, __recsize) : \ __kfifo_out_r(__kfifo, __buf, __n, __recsize) : \
__kfifo_out(__kfifo, __buf, __n); \ __kfifo_out(__kfifo, __buf, __n); \
...@@ -773,14 +758,10 @@ __kfifo_uint_must_check_helper( \ ...@@ -773,14 +758,10 @@ __kfifo_uint_must_check_helper( \
__kfifo_uint_must_check_helper( \ __kfifo_uint_must_check_helper( \
({ \ ({ \
typeof((fifo) + 1) __tmp = (fifo); \ typeof((fifo) + 1) __tmp = (fifo); \
typeof((buf) + 1) __buf = (buf); \ typeof(__tmp->ptr) __buf = (buf); \
unsigned long __n = (n); \ unsigned long __n = (n); \
const size_t __recsize = sizeof(*__tmp->rectype); \ const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \ struct __kfifo *__kfifo = &__tmp->kfifo; \
if (0) { \
typeof(__tmp->ptr) __dummy __attribute__ ((unused)) = NULL; \
__buf = __dummy; \
} \
(__recsize) ? \ (__recsize) ? \
__kfifo_out_peek_r(__kfifo, __buf, __n, __recsize) : \ __kfifo_out_peek_r(__kfifo, __buf, __n, __recsize) : \
__kfifo_out_peek(__kfifo, __buf, __n); \ __kfifo_out_peek(__kfifo, __buf, __n); \
......
...@@ -1269,7 +1269,7 @@ void memory_failure_queue(unsigned long pfn, int trapno, int flags) ...@@ -1269,7 +1269,7 @@ void memory_failure_queue(unsigned long pfn, int trapno, int flags)
mf_cpu = &get_cpu_var(memory_failure_cpu); mf_cpu = &get_cpu_var(memory_failure_cpu);
spin_lock_irqsave(&mf_cpu->lock, proc_flags); spin_lock_irqsave(&mf_cpu->lock, proc_flags);
if (kfifo_put(&mf_cpu->fifo, &entry)) if (kfifo_put(&mf_cpu->fifo, entry))
schedule_work_on(smp_processor_id(), &mf_cpu->work); schedule_work_on(smp_processor_id(), &mf_cpu->work);
else else
pr_err("Memory failure: buffer overflow when queuing memory failure at %#lx\n", pr_err("Memory failure: buffer overflow when queuing memory failure at %#lx\n",
......
...@@ -64,7 +64,7 @@ static int __init testfunc(void) ...@@ -64,7 +64,7 @@ static int __init testfunc(void)
/* put values into the fifo */ /* put values into the fifo */
for (i = 0; i != 10; i++) for (i = 0; i != 10; i++)
kfifo_put(&test, &i); kfifo_put(&test, i);
/* show the number of used elements */ /* show the number of used elements */
printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test)); printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));
...@@ -85,7 +85,7 @@ static int __init testfunc(void) ...@@ -85,7 +85,7 @@ static int __init testfunc(void)
kfifo_skip(&test); kfifo_skip(&test);
/* put values into the fifo until is full */ /* put values into the fifo until is full */
for (i = 20; kfifo_put(&test, &i); i++) for (i = 20; kfifo_put(&test, i); i++)
; ;
printk(KERN_INFO "queue len: %u\n", kfifo_len(&test)); printk(KERN_INFO "queue len: %u\n", kfifo_len(&test));
......
...@@ -39,7 +39,7 @@ static int __init example_init(void) ...@@ -39,7 +39,7 @@ static int __init example_init(void)
kfifo_in(&fifo, "test", 4); kfifo_in(&fifo, "test", 4);
for (i = 0; i != 9; i++) for (i = 0; i != 9; i++)
kfifo_put(&fifo, &i); kfifo_put(&fifo, i);
/* kick away first byte */ /* kick away first byte */
kfifo_skip(&fifo); kfifo_skip(&fifo);
......
...@@ -61,7 +61,7 @@ static int __init testfunc(void) ...@@ -61,7 +61,7 @@ static int __init testfunc(void)
/* put values into the fifo */ /* put values into the fifo */
for (i = 0; i != 10; i++) for (i = 0; i != 10; i++)
kfifo_put(&test, &i); kfifo_put(&test, i);
/* show the number of used elements */ /* show the number of used elements */
printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test)); printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));
...@@ -78,7 +78,7 @@ static int __init testfunc(void) ...@@ -78,7 +78,7 @@ static int __init testfunc(void)
kfifo_skip(&test); kfifo_skip(&test);
/* put values into the fifo until is full */ /* put values into the fifo until is full */
for (i = 20; kfifo_put(&test, &i); i++) for (i = 20; kfifo_put(&test, i); i++)
; ;
printk(KERN_INFO "queue len: %u\n", kfifo_len(&test)); printk(KERN_INFO "queue len: %u\n", kfifo_len(&test));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册