Blame source/vdo/kernel/bufferPool.h

Packit Service 75d76b
/*
Packit Service 75d76b
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 75d76b
 *
Packit Service 75d76b
 * This program is free software; you can redistribute it and/or
Packit Service 75d76b
 * modify it under the terms of the GNU General Public License
Packit Service 75d76b
 * as published by the Free Software Foundation; either version 2
Packit Service 75d76b
 * of the License, or (at your option) any later version.
Packit Service 75d76b
 * 
Packit Service 75d76b
 * This program is distributed in the hope that it will be useful,
Packit Service 75d76b
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 75d76b
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 75d76b
 * GNU General Public License for more details.
Packit Service 75d76b
 * 
Packit Service 75d76b
 * You should have received a copy of the GNU General Public License
Packit Service 75d76b
 * along with this program; if not, write to the Free Software
Packit Service 75d76b
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 75d76b
 * 02110-1301, USA. 
Packit Service 75d76b
 *
Packit Service 75d76b
 * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/kernel/bufferPool.h#1 $
Packit Service 75d76b
 */
Packit Service 75d76b
#ifndef BUFFERPOOL_H
Packit Service 75d76b
#define BUFFERPOOL_H
Packit Service 75d76b
Packit Service 75d76b
/*
Packit Service 75d76b
 * We need bug.h because in 3.10, kernel.h (indirectly) defines
Packit Service 75d76b
 * ARRAY_SIZE as a macro which (indirectly and conditionally) uses
Packit Service 75d76b
 * BUILD_BUG_ON_ZERO, which is defined in bug.h, which is *not*
Packit Service 75d76b
 * included. In earlier versions like 3.2 it Just Worked.
Packit Service 75d76b
 */
Packit Service 75d76b
#include <linux/bug.h>
Packit Service 75d76b
#include <linux/kernel.h>
Packit Service 75d76b
#include <linux/types.h>
Packit Service 75d76b
Packit Service 75d76b
typedef struct bufferPool BufferPool;
Packit Service 75d76b
Packit Service 75d76b
typedef int BufferAllocateFunction(void *poolData, void **dataPtr);
Packit Service 75d76b
typedef void BufferFreeFunction(void *poolData, void *data);
Packit Service 75d76b
typedef void BufferDumpFunction(void *poolData, void *data);
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Creates a generic pool of buffer data. The elements in the pool are
Packit Service 75d76b
 * allocated up front and placed on a free list, which manages the
Packit Service 75d76b
 * reuse of the individual buffers in the pool.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param [in]  poolName         Name of the pool
Packit Service 75d76b
 * @param [in]  size             The number of elements to create for this pool
Packit Service 75d76b
 * @param [in]  allocateFunction The function to call to create the actual data
Packit Service 75d76b
 *                               for each element
Packit Service 75d76b
 * @param [in]  freeFunction     The function to call to free the actual data
Packit Service 75d76b
 *                               for each element
Packit Service 75d76b
 * @param [in]  dumpFunction     The function to call to dump the actual data
Packit Service 75d76b
 *                               for each element into the log
Packit Service 75d76b
 * @param [in]  poolData         A pointer to the pool's associated data
Packit Service 75d76b
 * @param [out] poolPtr          A pointer to hold the pool that was created
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return a success or error code
Packit Service 75d76b
 */
Packit Service 75d76b
int makeBufferPool(const char              *poolName,
Packit Service 75d76b
                   unsigned int             size,
Packit Service 75d76b
                   BufferAllocateFunction  *allocateFunction,
Packit Service 75d76b
                   BufferFreeFunction      *freeFunction,
Packit Service 75d76b
                   BufferDumpFunction      *dumpFunction,
Packit Service 75d76b
                   void                    *poolData,
Packit Service 75d76b
                   BufferPool             **poolPtr)
Packit Service 75d76b
  __attribute__((warn_unused_result));
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Free a buffer pool and null out the reference to it. This will free
Packit Service 75d76b
 * all the elements of the pool as well.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param [in]  poolPtr   The reference to the pool to free
Packit Service 75d76b
 **/
Packit Service 75d76b
void freeBufferPool(BufferPool **poolPtr);
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Dump a buffer pool to the log.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param [in] pool          The buffer pool to allocate from
Packit Service 75d76b
 * @param [in] dumpElements  True for complete output, or false for a
Packit Service 75d76b
 *                           one-line summary
Packit Service 75d76b
 **/
Packit Service 75d76b
void dumpBufferPool(BufferPool *pool, bool dumpElements);
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Acquires a free buffer from the free list of the pool and
Packit Service 75d76b
 * returns it's associated data.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param [in]  pool      The buffer pool to allocate from
Packit Service 75d76b
 * @param [out] dataPtr   A pointer to hold the buffer data
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return a success or error code
Packit Service 75d76b
 */
Packit Service 75d76b
int allocBufferFromPool(BufferPool *pool, void **dataPtr)
Packit Service 75d76b
  __attribute__((warn_unused_result));
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Returns a buffer to the free list of a pool
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param [in] pool   The buffer pool to return the buffer to
Packit Service 75d76b
 * @param [in] data   The buffer data to return
Packit Service 75d76b
 */
Packit Service 75d76b
void freeBufferToPool(BufferPool *pool, void *data);
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Returns a set of buffers to the free list of a pool
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param [in] pool   The buffer pool to return the buffer to
Packit Service 75d76b
 * @param [in] data   The buffer data to return
Packit Service 75d76b
 * @param [in] count  Number of entries in the data array
Packit Service 75d76b
 */
Packit Service 75d76b
void freeBuffersToPool(BufferPool *pool, void **data, int count);
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Control structure for freeing (releasing back to the pool) pointers
Packit Service 75d76b
 * in batches.
Packit Service 75d76b
 *
Packit Service 75d76b
 * Since the objects stored in a buffer pool are completely opaque,
Packit Service 75d76b
 * some external data structure is needed to manage a collection of
Packit Service 75d76b
 * them. This is a simple helper for doing that, since we're freeing
Packit Service 75d76b
 * batches of objects in a couple different places. Within the pool
Packit Service 75d76b
 * itself there's a pair of linked lists, but getting at them requires
Packit Service 75d76b
 * the locking that we're trying to minimize.
Packit Service 75d76b
 *
Packit Service 75d76b
 * We collect pointers until the array is full or until there are no
Packit Service 75d76b
 * more available, and we call freeBuffersToPool to release a batch
Packit Service 75d76b
 * all at once.
Packit Service 75d76b
 **/
Packit Service 75d76b
typedef struct freeBufferPointers {
Packit Service 75d76b
  BufferPool *pool;
Packit Service 75d76b
  int         index;
Packit Service 75d76b
  void       *pointers[30]; // size is arbitrary
Packit Service 75d76b
} FreeBufferPointers;
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Initialize the control structure for batching buffer pointers to be
Packit Service 75d76b
 * released to their pool.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param [out] fbp   The (caller-allocated) control structure
Packit Service 75d76b
 * @param [in]  pool  The buffer pool to return objects to.
Packit Service 75d76b
 **/
Packit Service 75d76b
static inline void initFreeBufferPointers(FreeBufferPointers *fbp,
Packit Service 75d76b
                                          BufferPool         *pool)
Packit Service 75d76b
{
Packit Service 75d76b
  fbp->index = 0;
Packit Service 75d76b
  fbp->pool  = pool;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Release any buffers left in the collection.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param [in]  fbp  The control structure
Packit Service 75d76b
 **/
Packit Service 75d76b
static inline void freeBufferPointers(FreeBufferPointers *fbp)
Packit Service 75d76b
{
Packit Service 75d76b
  freeBuffersToPool(fbp->pool, fbp->pointers, fbp->index);
Packit Service 75d76b
  fbp->index = 0;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Add another buffer pointer to the collection, and if we're full,
Packit Service 75d76b
 * release the whole batch to the pool.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param [in]  fbp      The control structure
Packit Service 75d76b
 * @param [in]  pointer  The buffer pointer to release
Packit Service 75d76b
 **/
Packit Service 75d76b
static inline void addFreeBufferPointer(FreeBufferPointers *fbp,
Packit Service 75d76b
                                        void               *pointer)
Packit Service 75d76b
{
Packit Service 75d76b
  fbp->pointers[fbp->index] = pointer;
Packit Service 75d76b
  fbp->index++;
Packit Service 75d76b
  if (fbp->index == ARRAY_SIZE(fbp->pointers)) {
Packit Service 75d76b
    freeBufferPointers(fbp);
Packit Service 75d76b
  }
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
#endif /* BUFFERPOOL_H */