/* * Copyright (c) 2020 Red Hat, Inc. * * 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., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/kernel/limiter.h#2 $ */ #ifndef LIMITER_H #define LIMITER_H #include /* * A Limiter is a fancy counter used to limit resource usage. We have a * limit to number of resources that we are willing to use, and a Limiter * holds us to that limit. */ typedef struct limiter { // A spinlock controlling access to the contents of this struct spinlock_t lock; // The queue of threads waiting for a resource to become available wait_queue_head_t waiterQueue; // The number of resources in use uint32_t active; // The maximum number number of resources that have ever been in use uint32_t maximum; // The limit to the number of resources that are allowed to be used uint32_t limit; } Limiter; /** * Get the Limiter variable values (atomically under the lock) * * @param limiter The limiter * @param active The number of requests in progress * @param maximum The maximum number of requests that have ever been active **/ void getLimiterValuesAtomically(Limiter *limiter, uint32_t *active, uint32_t *maximum); /** * Initialize a Limiter * * @param limiter The limiter * @param limit The limit to the number of active resources **/ void initializeLimiter(Limiter *limiter, uint32_t limit); /** * Determine whether there are any active resources * * @param limiter The limiter * * @return true if there are no active resources **/ bool limiterIsIdle(Limiter *limiter); /** * Release resources, making them available for other uses * * @param limiter The limiter * @param count The number of resources to release **/ void limiterReleaseMany(Limiter *limiter, uint32_t count); /** * Release one resource, making it available for another use * * @param limiter The limiter **/ static inline void limiterRelease(Limiter *limiter) { limiterReleaseMany(limiter, 1); } /** * Wait until there are no active resources * * @param limiter The limiter **/ void limiterWaitForIdle(Limiter *limiter); /** * Prepare to start using one resource, waiting if there are too many resources * already in use. After returning from this routine, the caller may use the * resource, and must call limiterRelease after freeing the resource. * * @param limiter The limiter **/ void limiterWaitForOneFree(Limiter *limiter); /** * Attempt to reserve one resource, without waiting. After returning from this * routine, if allocation was successful, the caller may use the resource, and * must call limiterRelease after freeing the resource. * * @param limiter The limiter * * @return true iff the resource was allocated **/ bool limiterPoll(Limiter *limiter); #endif /* LIMITER_H */