1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
7 #include <sound/core.h>
8 #include <linux/slab.h>
9 #include <linux/sched/signal.h>
18 struct snd_seq_fifo
*snd_seq_fifo_new(int poolsize
)
20 struct snd_seq_fifo
*f
;
22 f
= kzalloc(sizeof(*f
), GFP_KERNEL
);
26 f
->pool
= snd_seq_pool_new(poolsize
);
27 if (f
->pool
== NULL
) {
31 if (snd_seq_pool_init(f
->pool
) < 0) {
32 snd_seq_pool_delete(&f
->pool
);
37 spin_lock_init(&f
->lock
);
38 snd_use_lock_init(&f
->use_lock
);
39 init_waitqueue_head(&f
->input_sleep
);
40 atomic_set(&f
->overflow
, 0);
49 void snd_seq_fifo_delete(struct snd_seq_fifo
**fifo
)
51 struct snd_seq_fifo
*f
;
53 if (snd_BUG_ON(!fifo
))
61 snd_seq_pool_mark_closing(f
->pool
);
63 snd_seq_fifo_clear(f
);
65 /* wake up clients if any */
66 if (waitqueue_active(&f
->input_sleep
))
67 wake_up(&f
->input_sleep
);
69 /* release resources...*/
70 /*....................*/
73 snd_seq_pool_done(f
->pool
);
74 snd_seq_pool_delete(&f
->pool
);
80 static struct snd_seq_event_cell
*fifo_cell_out(struct snd_seq_fifo
*f
);
83 void snd_seq_fifo_clear(struct snd_seq_fifo
*f
)
85 struct snd_seq_event_cell
*cell
;
87 /* clear overflow flag */
88 atomic_set(&f
->overflow
, 0);
90 snd_use_lock_sync(&f
->use_lock
);
91 spin_lock_irq(&f
->lock
);
93 while ((cell
= fifo_cell_out(f
)) != NULL
) {
94 snd_seq_cell_free(cell
);
96 spin_unlock_irq(&f
->lock
);
100 /* enqueue event to fifo */
101 int snd_seq_fifo_event_in(struct snd_seq_fifo
*f
,
102 struct snd_seq_event
*event
)
104 struct snd_seq_event_cell
*cell
;
111 snd_use_lock_use(&f
->use_lock
);
112 err
= snd_seq_event_dup(f
->pool
, event
, &cell
, 1, NULL
, NULL
); /* always non-blocking */
114 if ((err
== -ENOMEM
) || (err
== -EAGAIN
))
115 atomic_inc(&f
->overflow
);
116 snd_use_lock_free(&f
->use_lock
);
120 /* append new cells to fifo */
121 spin_lock_irqsave(&f
->lock
, flags
);
123 f
->tail
->next
= cell
;
129 spin_unlock_irqrestore(&f
->lock
, flags
);
132 if (waitqueue_active(&f
->input_sleep
))
133 wake_up(&f
->input_sleep
);
135 snd_use_lock_free(&f
->use_lock
);
137 return 0; /* success */
141 /* dequeue cell from fifo */
142 static struct snd_seq_event_cell
*fifo_cell_out(struct snd_seq_fifo
*f
)
144 struct snd_seq_event_cell
*cell
;
146 if ((cell
= f
->head
) != NULL
) {
147 f
->head
= cell
->next
;
149 /* reset tail if this was the last element */
160 /* dequeue cell from fifo and copy on user space */
161 int snd_seq_fifo_cell_out(struct snd_seq_fifo
*f
,
162 struct snd_seq_event_cell
**cellp
, int nonblock
)
164 struct snd_seq_event_cell
*cell
;
166 wait_queue_entry_t wait
;
172 init_waitqueue_entry(&wait
, current
);
173 spin_lock_irqsave(&f
->lock
, flags
);
174 while ((cell
= fifo_cell_out(f
)) == NULL
) {
176 /* non-blocking - return immediately */
177 spin_unlock_irqrestore(&f
->lock
, flags
);
180 set_current_state(TASK_INTERRUPTIBLE
);
181 add_wait_queue(&f
->input_sleep
, &wait
);
182 spin_unlock_irqrestore(&f
->lock
, flags
);
184 spin_lock_irqsave(&f
->lock
, flags
);
185 remove_wait_queue(&f
->input_sleep
, &wait
);
186 if (signal_pending(current
)) {
187 spin_unlock_irqrestore(&f
->lock
, flags
);
191 spin_unlock_irqrestore(&f
->lock
, flags
);
198 void snd_seq_fifo_cell_putback(struct snd_seq_fifo
*f
,
199 struct snd_seq_event_cell
*cell
)
204 spin_lock_irqsave(&f
->lock
, flags
);
205 cell
->next
= f
->head
;
210 spin_unlock_irqrestore(&f
->lock
, flags
);
215 /* polling; return non-zero if queue is available */
216 int snd_seq_fifo_poll_wait(struct snd_seq_fifo
*f
, struct file
*file
,
219 poll_wait(file
, &f
->input_sleep
, wait
);
220 return (f
->cells
> 0);
223 /* change the size of pool; all old events are removed */
224 int snd_seq_fifo_resize(struct snd_seq_fifo
*f
, int poolsize
)
226 struct snd_seq_pool
*newpool
, *oldpool
;
227 struct snd_seq_event_cell
*cell
, *next
, *oldhead
;
229 if (snd_BUG_ON(!f
|| !f
->pool
))
232 /* allocate new pool */
233 newpool
= snd_seq_pool_new(poolsize
);
236 if (snd_seq_pool_init(newpool
) < 0) {
237 snd_seq_pool_delete(&newpool
);
241 spin_lock_irq(&f
->lock
);
242 /* remember old pool */
250 /* NOTE: overflow flag is not cleared */
251 spin_unlock_irq(&f
->lock
);
253 /* close the old pool and wait until all users are gone */
254 snd_seq_pool_mark_closing(oldpool
);
255 snd_use_lock_sync(&f
->use_lock
);
257 /* release cells in old pool */
258 for (cell
= oldhead
; cell
; cell
= next
) {
260 snd_seq_cell_free(cell
);
262 snd_seq_pool_delete(&oldpool
);
267 /* get the number of unused cells safely */
268 int snd_seq_fifo_unused_cells(struct snd_seq_fifo
*f
)
276 snd_use_lock_use(&f
->use_lock
);
277 spin_lock_irqsave(&f
->lock
, flags
);
278 cells
= snd_seq_unused_cells(f
->pool
);
279 spin_unlock_irqrestore(&f
->lock
, flags
);
280 snd_use_lock_free(&f
->use_lock
);