This patch moves the check for available free space for a new entry into a separate function. Existing callers that only check for a non-zero return value are unaffected. __ptr_ring_produce() now returns -EINVAL for a zero-size ring and -ENOSPC when full, whereas before both cases returned -ENOSPC. The new helper allows callers to determine in advance whether a single subsequent __ptr_ring_produce() call will succeed. This information can, for example, be used to temporarily stop producing until __ptr_ring_check_produce() indicates that space is available again. The return values are documented above the helper, as a caller that waits for space must distinguish the transient -ENOSPC from the permanent -EINVAL.
Unified · Split
| @@ -96,6 +96,26 @@ static inline bool ptr_ring_full_bh(struct ptr_ring *r) · 95 unmodified lines | |||
| 96 | return ret; | 96 | return ret; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | /* Report whether the next __ptr_ring_produce() has room for one entry: | ||
| 100 | * 0 means the single slot at r->queue[r->producer] is free, -ENOSPC means | ||
| 101 | * the ring is full, which is transient, and -EINVAL means r->size is 0, | ||
| 102 | * which is permanent. A caller that stops producing and waits for space | ||
| 103 | * must therefore do so only for -ENOSPC. | ||
| 104 | * | ||
| 105 | * Note: callers invoking this in a loop must use a compiler barrier, | ||
| 106 | * for example cpu_relax(). Callers must hold producer_lock. | ||
| 107 | */ | ||
| 108 | static inline int __ptr_ring_check_produce(struct ptr_ring *r) | ||
| 109 | { | ||
| 110 | if (unlikely(!r->size)) | ||
| 111 | return -EINVAL; | ||
| 112 | |||
| 113 | if (data_race(r->queue[r->producer])) | ||
| 114 | return -ENOSPC; | ||
| 115 | |||
| 116 | return 0; | ||
| 117 | } | ||
| 118 | |||
| 99 | /* Note: callers invoking this in a loop must use a compiler barrier, | 119 | /* Note: callers invoking this in a loop must use a compiler barrier, |
| 100 | * for example cpu_relax(). Callers must hold producer_lock. | 120 | * for example cpu_relax(). Callers must hold producer_lock. |
| 101 | * Callers are responsible for making sure pointer that is being queued | 121 | * Callers are responsible for making sure pointer that is being queued |
| @@ -103,8 +123,10 @@ static inline bool ptr_ring_full_bh(struct ptr_ring *r) · 1 unmodified line | |||
| 103 | */ | 123 | */ |
| 104 | static inline int __ptr_ring_produce(struct ptr_ring *r, void *ptr) | 124 | static inline int __ptr_ring_produce(struct ptr_ring *r, void *ptr) |
| 105 | { | 125 | { |
| 106 | if (unlikely(!r->size) || data_race(r->queue[r->producer])) | 126 | int ret = __ptr_ring_check_produce(r); |
| 107 | return -ENOSPC; | 127 | |
| 128 | if (ret) | ||
| 129 | return ret; | ||
| 108 | 130 | ||
| 109 | /* Make sure the pointer we are storing points to a valid data. */ | 131 | /* Make sure the pointer we are storing points to a valid data. */ |
| 110 | /* Pairs with the dependency ordering in __ptr_ring_consume. */ | 132 | /* Pairs with the dependency ordering in __ptr_ring_consume. */ |