cregit-Linux how code gets into the kernel

Release 4.11 sound/core/seq/seq_fifo.c

Directory: sound/core/seq
/*
 *   ALSA sequencer FIFO
 *   Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
 *
 *
 *   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
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */

#include <sound/core.h>
#include <linux/slab.h>
#include <linux/sched/signal.h>

#include "seq_fifo.h"
#include "seq_lock.h"


/* FIFO */

/* create new fifo */

struct snd_seq_fifo *snd_seq_fifo_new(int poolsize) { struct snd_seq_fifo *f; f = kzalloc(sizeof(*f), GFP_KERNEL); if (!f) return NULL; f->pool = snd_seq_pool_new(poolsize); if (f->pool == NULL) { kfree(f); return NULL; } if (snd_seq_pool_init(f->pool) < 0) { snd_seq_pool_delete(&f->pool); kfree(f); return NULL; } spin_lock_init(&f->lock); snd_use_lock_init(&f->use_lock); init_waitqueue_head(&f->input_sleep); atomic_set(&f->overflow, 0); f->head = NULL; f->tail = NULL; f->cells = 0; return f; }

Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela14195.92%240.00%
Takashi Iwai64.08%360.00%
Total147100.00%5100.00%


void snd_seq_fifo_delete(struct snd_seq_fifo **fifo) { struct snd_seq_fifo *f; if (snd_BUG_ON(!fifo)) return; f = *fifo; if (snd_BUG_ON(!f)) return; *fifo = NULL; if (f->pool) snd_seq_pool_mark_closing(f->pool); snd_seq_fifo_clear(f); /* wake up clients if any */ if (waitqueue_active(&f->input_sleep)) wake_up(&f->input_sleep); /* release resources...*/ /*....................*/ if (f->pool) { snd_seq_pool_done(f->pool); snd_seq_pool_delete(&f->pool); } kfree(f); }

Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela8072.07%125.00%
Takashi Iwai3127.93%375.00%
Total111100.00%4100.00%

static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f); /* clear queue */
void snd_seq_fifo_clear(struct snd_seq_fifo *f) { struct snd_seq_event_cell *cell; unsigned long flags; /* clear overflow flag */ atomic_set(&f->overflow, 0); snd_use_lock_sync(&f->use_lock); spin_lock_irqsave(&f->lock, flags); /* drain the fifo */ while ((cell = fifo_cell_out(f)) != NULL) { snd_seq_cell_free(cell); } spin_unlock_irqrestore(&f->lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela7594.94%150.00%
Takashi Iwai45.06%150.00%
Total79100.00%2100.00%

/* enqueue event to fifo */
int snd_seq_fifo_event_in(struct snd_seq_fifo *f, struct snd_seq_event *event) { struct snd_seq_event_cell *cell; unsigned long flags; int err; if (snd_BUG_ON(!f)) return -EINVAL; snd_use_lock_use(&f->use_lock); err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL); /* always non-blocking */ if (err < 0) { if ((err == -ENOMEM) || (err == -EAGAIN)) atomic_inc(&f->overflow); snd_use_lock_free(&f->use_lock); return err; } /* append new cells to fifo */ spin_lock_irqsave(&f->lock, flags); if (f->tail != NULL) f->tail->next = cell; f->tail = cell; if (f->head == NULL) f->head = cell; cell->next = NULL; f->cells++; spin_unlock_irqrestore(&f->lock, flags); /* wakeup client */ if (waitqueue_active(&f->input_sleep)) wake_up(&f->input_sleep); snd_use_lock_free(&f->use_lock); return 0; /* success */ }

Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela17785.10%120.00%
Takashi Iwai2210.58%360.00%
Adam Goode94.33%120.00%
Total208100.00%5100.00%

/* dequeue cell from fifo */
static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f) { struct snd_seq_event_cell *cell; if ((cell = f->head) != NULL) { f->head = cell->next; /* reset tail if this was the last element */ if (f->tail == cell) f->tail = NULL; cell->next = NULL; f->cells--; } return cell; }

Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela6391.30%150.00%
Takashi Iwai68.70%150.00%
Total69100.00%2100.00%

/* dequeue cell from fifo and copy on user space */
int snd_seq_fifo_cell_out(struct snd_seq_fifo *f, struct snd_seq_event_cell **cellp, int nonblock) { struct snd_seq_event_cell *cell; unsigned long flags; wait_queue_t wait; if (snd_BUG_ON(!f)) return -EINVAL; *cellp = NULL; init_waitqueue_entry(&wait, current); spin_lock_irqsave(&f->lock, flags); while ((cell = fifo_cell_out(f)) == NULL) { if (nonblock) { /* non-blocking - return immediately */ spin_unlock_irqrestore(&f->lock, flags); return -EAGAIN; } set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&f->input_sleep, &wait); spin_unlock_irq(&f->lock); schedule(); spin_lock_irq(&f->lock); remove_wait_queue(&f->input_sleep, &wait); if (signal_pending(current)) { spin_unlock_irqrestore(&f->lock, flags); return -ERESTARTSYS; } } spin_unlock_irqrestore(&f->lock, flags); *cellp = cell; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela17391.53%360.00%
Takashi Iwai168.47%240.00%
Total189100.00%5100.00%


void snd_seq_fifo_cell_putback(struct snd_seq_fifo *f, struct snd_seq_event_cell *cell) { unsigned long flags; if (cell) { spin_lock_irqsave(&f->lock, flags); cell->next = f->head; f->head = cell; if (!f->tail) f->tail = cell; f->cells++; spin_unlock_irqrestore(&f->lock, flags); } }

Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela6077.92%133.33%
Takashi Iwai1722.08%266.67%
Total77100.00%3100.00%

/* polling; return non-zero if queue is available */
int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file, poll_table *wait) { poll_wait(file, &f->input_sleep, wait); return (f->cells > 0); }

Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela3895.00%150.00%
Takashi Iwai25.00%150.00%
Total40100.00%2100.00%

/* change the size of pool; all old events are removed */
int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize) { unsigned long flags; struct snd_seq_pool *newpool, *oldpool; struct snd_seq_event_cell *cell, *next, *oldhead; if (snd_BUG_ON(!f || !f->pool)) return -EINVAL; /* allocate new pool */ newpool = snd_seq_pool_new(poolsize); if (newpool == NULL) return -ENOMEM; if (snd_seq_pool_init(newpool) < 0) { snd_seq_pool_delete(&newpool); return -ENOMEM; } spin_lock_irqsave(&f->lock, flags); /* remember old pool */ oldpool = f->pool; oldhead = f->head; /* exchange pools */ f->pool = newpool; f->head = NULL; f->tail = NULL; f->cells = 0; /* NOTE: overflow flag is not cleared */ spin_unlock_irqrestore(&f->lock, flags); /* close the old pool and wait until all users are gone */ snd_seq_pool_mark_closing(oldpool); snd_use_lock_sync(&f->use_lock); /* release cells in old pool */ for (cell = oldhead; cell; cell = next) { next = cell->next; snd_seq_cell_free(cell); } snd_seq_pool_delete(&oldpool); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela16582.50%125.00%
Takashi Iwai3517.50%375.00%
Total200100.00%4100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela100186.59%640.00%
Takashi Iwai14312.37%746.67%
Adam Goode90.78%16.67%
Ingo Molnar30.26%16.67%
Total1156100.00%15100.00%
Directory: sound/core/seq
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.