7146250754
Split up the doubled assignment in visor_charqueue_create() into two separate assignments. Signed-off-by: Benjamin Romer <benjamin.romer@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
130 lines
3.1 KiB
C
130 lines
3.1 KiB
C
/* charqueue.c
|
|
*
|
|
* Copyright (C) 2010 - 2013 UNISYS CORPORATION
|
|
* All rights reserved.
|
|
*
|
|
* 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, GOOD TITLE or
|
|
* NON INFRINGEMENT. See the GNU General Public License for more
|
|
* details.
|
|
*/
|
|
|
|
/*
|
|
* Simple character queue implementation for Linux kernel mode.
|
|
*/
|
|
|
|
#include "charqueue.h"
|
|
|
|
#define MYDRVNAME "charqueue"
|
|
|
|
#define IS_EMPTY(charqueue) (charqueue->head == charqueue->tail)
|
|
|
|
struct charqueue {
|
|
int alloc_size;
|
|
int nslots;
|
|
spinlock_t lock;
|
|
int head, tail;
|
|
unsigned char buf[0];
|
|
};
|
|
|
|
struct charqueue *visor_charqueue_create(ulong nslots)
|
|
{
|
|
int alloc_size = sizeof(struct charqueue) + nslots + 1;
|
|
struct charqueue *cq = kmalloc(alloc_size, GFP_KERNEL|__GFP_NORETRY);
|
|
|
|
if (cq == NULL) {
|
|
ERRDRV("visor_charqueue_create allocation failed (alloc_size=%d)",
|
|
alloc_size);
|
|
return NULL;
|
|
}
|
|
cq->alloc_size = alloc_size;
|
|
cq->nslots = nslots;
|
|
cq->head = 0;
|
|
cq->tail = 0;
|
|
spin_lock_init(&cq->lock);
|
|
return cq;
|
|
}
|
|
EXPORT_SYMBOL_GPL(visor_charqueue_create);
|
|
|
|
void visor_charqueue_enqueue(struct charqueue *charqueue, unsigned char c)
|
|
{
|
|
int alloc_slots = charqueue->nslots+1; /* 1 slot is always empty */
|
|
|
|
spin_lock(&charqueue->lock);
|
|
charqueue->head = (charqueue->head+1) % alloc_slots;
|
|
if (charqueue->head == charqueue->tail)
|
|
/* overflow; overwrite the oldest entry */
|
|
charqueue->tail = (charqueue->tail+1) % alloc_slots;
|
|
charqueue->buf[charqueue->head] = c;
|
|
spin_unlock(&charqueue->lock);
|
|
}
|
|
EXPORT_SYMBOL_GPL(visor_charqueue_enqueue);
|
|
|
|
BOOL visor_charqueue_is_empty(struct charqueue *charqueue)
|
|
{
|
|
BOOL b;
|
|
|
|
spin_lock(&charqueue->lock);
|
|
b = IS_EMPTY(charqueue);
|
|
spin_unlock(&charqueue->lock);
|
|
return b;
|
|
}
|
|
EXPORT_SYMBOL_GPL(visor_charqueue_is_empty);
|
|
|
|
static int charqueue_dequeue_1(struct charqueue *charqueue)
|
|
{
|
|
int alloc_slots = charqueue->nslots + 1; /* 1 slot is always empty */
|
|
|
|
if (IS_EMPTY(charqueue))
|
|
return -1;
|
|
charqueue->tail = (charqueue->tail+1) % alloc_slots;
|
|
return charqueue->buf[charqueue->tail];
|
|
}
|
|
|
|
int charqueue_dequeue(struct charqueue *charqueue)
|
|
{
|
|
int rc;
|
|
|
|
spin_lock(&charqueue->lock);
|
|
rc = charqueue_dequeue_1(charqueue);
|
|
spin_unlock(&charqueue->lock);
|
|
return rc;
|
|
}
|
|
|
|
int visor_charqueue_dequeue_n(struct charqueue *charqueue, unsigned char *buf,
|
|
int n)
|
|
{
|
|
int rc, counter = 0, c;
|
|
|
|
spin_lock(&charqueue->lock);
|
|
for (;;) {
|
|
if (n <= 0)
|
|
break; /* no more buffer space */
|
|
c = charqueue_dequeue_1(charqueue);
|
|
if (c < 0)
|
|
break; /* no more input */
|
|
*buf = (unsigned char)(c);
|
|
buf++;
|
|
n--;
|
|
counter++;
|
|
}
|
|
rc = counter;
|
|
spin_unlock(&charqueue->lock);
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL_GPL(visor_charqueue_dequeue_n);
|
|
|
|
void visor_charqueue_destroy(struct charqueue *charqueue)
|
|
{
|
|
if (charqueue == NULL)
|
|
return;
|
|
kfree(charqueue);
|
|
}
|
|
EXPORT_SYMBOL_GPL(visor_charqueue_destroy);
|