#ifndef _LINUX_PERCPU_COUNTER_H
#define _LINUX_PERCPU_COUNTER_H
#include <linux/spinlock.h>
#include <linux/smp.h>
#include <linux/list.h>
#include <linux/threads.h>
#include <linux/percpu.h>
#include <linux/types.h>
#define PERCPU_COUNTER_LOCAL_BATCH …
#ifdef CONFIG_SMP
struct percpu_counter { … };
extern int percpu_counter_batch;
int __percpu_counter_init_many(struct percpu_counter *fbc, s64 amount,
gfp_t gfp, u32 nr_counters,
struct lock_class_key *key);
#define percpu_counter_init_many(fbc, value, gfp, nr_counters) …
#define percpu_counter_init(fbc, value, gfp) …
void percpu_counter_destroy_many(struct percpu_counter *fbc, u32 nr_counters);
static inline void percpu_counter_destroy(struct percpu_counter *fbc)
{ … }
void percpu_counter_set(struct percpu_counter *fbc, s64 amount);
void percpu_counter_add_batch(struct percpu_counter *fbc, s64 amount,
s32 batch);
s64 __percpu_counter_sum(struct percpu_counter *fbc);
int __percpu_counter_compare(struct percpu_counter *fbc, s64 rhs, s32 batch);
bool __percpu_counter_limited_add(struct percpu_counter *fbc, s64 limit,
s64 amount, s32 batch);
void percpu_counter_sync(struct percpu_counter *fbc);
static inline int percpu_counter_compare(struct percpu_counter *fbc, s64 rhs)
{ … }
static inline void percpu_counter_add(struct percpu_counter *fbc, s64 amount)
{ … }
static inline bool
percpu_counter_limited_add(struct percpu_counter *fbc, s64 limit, s64 amount)
{ … }
static inline void
percpu_counter_add_local(struct percpu_counter *fbc, s64 amount)
{ … }
static inline s64 percpu_counter_sum_positive(struct percpu_counter *fbc)
{ … }
static inline s64 percpu_counter_sum(struct percpu_counter *fbc)
{ … }
static inline s64 percpu_counter_read(struct percpu_counter *fbc)
{ … }
static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc)
{ … }
static inline bool percpu_counter_initialized(struct percpu_counter *fbc)
{ … }
#else
struct percpu_counter {
s64 count;
};
static inline int percpu_counter_init_many(struct percpu_counter *fbc,
s64 amount, gfp_t gfp,
u32 nr_counters)
{
u32 i;
for (i = 0; i < nr_counters; i++)
fbc[i].count = amount;
return 0;
}
static inline int percpu_counter_init(struct percpu_counter *fbc, s64 amount,
gfp_t gfp)
{
return percpu_counter_init_many(fbc, amount, gfp, 1);
}
static inline void percpu_counter_destroy_many(struct percpu_counter *fbc,
u32 nr_counters)
{
}
static inline void percpu_counter_destroy(struct percpu_counter *fbc)
{
}
static inline void percpu_counter_set(struct percpu_counter *fbc, s64 amount)
{
fbc->count = amount;
}
static inline int percpu_counter_compare(struct percpu_counter *fbc, s64 rhs)
{
if (fbc->count > rhs)
return 1;
else if (fbc->count < rhs)
return -1;
else
return 0;
}
static inline int
__percpu_counter_compare(struct percpu_counter *fbc, s64 rhs, s32 batch)
{
return percpu_counter_compare(fbc, rhs);
}
static inline void
percpu_counter_add(struct percpu_counter *fbc, s64 amount)
{
unsigned long flags;
local_irq_save(flags);
fbc->count += amount;
local_irq_restore(flags);
}
static inline bool
percpu_counter_limited_add(struct percpu_counter *fbc, s64 limit, s64 amount)
{
unsigned long flags;
bool good = false;
s64 count;
if (amount == 0)
return true;
local_irq_save(flags);
count = fbc->count + amount;
if ((amount > 0 && count <= limit) ||
(amount < 0 && count >= limit)) {
fbc->count = count;
good = true;
}
local_irq_restore(flags);
return good;
}
static inline void
percpu_counter_add_local(struct percpu_counter *fbc, s64 amount)
{
percpu_counter_add(fbc, amount);
}
static inline void
percpu_counter_add_batch(struct percpu_counter *fbc, s64 amount, s32 batch)
{
percpu_counter_add(fbc, amount);
}
static inline s64 percpu_counter_read(struct percpu_counter *fbc)
{
return fbc->count;
}
static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc)
{
return fbc->count;
}
static inline s64 percpu_counter_sum_positive(struct percpu_counter *fbc)
{
return percpu_counter_read_positive(fbc);
}
static inline s64 percpu_counter_sum(struct percpu_counter *fbc)
{
return percpu_counter_read(fbc);
}
static inline bool percpu_counter_initialized(struct percpu_counter *fbc)
{
return true;
}
static inline void percpu_counter_sync(struct percpu_counter *fbc)
{
}
#endif
static inline void percpu_counter_inc(struct percpu_counter *fbc)
{ … }
static inline void percpu_counter_dec(struct percpu_counter *fbc)
{ … }
static inline void percpu_counter_sub(struct percpu_counter *fbc, s64 amount)
{ … }
static inline void
percpu_counter_sub_local(struct percpu_counter *fbc, s64 amount)
{ … }
#endif