Beispiel #1
0
/*
 * Pop up to IDA_PCPU_BATCH_MOVE IDs off the global freelist, and push them onto
 * our percpu freelist:
 */
static inline void alloc_global_tags(struct percpu_ida *pool,
				     struct percpu_ida_cpu *tags)
{
	move_tags(tags->freelist, &tags->nr_free,
		  pool->freelist, &pool->nr_free,
		  min(pool->nr_free, pool->percpu_batch_size));
}
/*
 * Pop up to IDA_PCPU_BATCH_MOVE IDs off the global freelist, and push them onto
 * our percpu freelist:
 */
static inline void alloc_global_tags(struct percpu_ida *pool,
				     struct percpu_ida_cpu *tags)
{
	move_tags(tags->freelist, &tags->nr_free,
		  pool->freelist, &pool->nr_free,
		  min(pool->nr_free, IDA_PCPU_BATCH_MOVE));
}
/**
 * percpu_ida_free - free a tag
 * @pool: pool @tag was allocated from
 * @tag: a tag previously allocated with percpu_ida_alloc()
 *
 * Safe to be called from interrupt context.
 */
void percpu_ida_free(struct percpu_ida *pool, unsigned tag)
{
	struct percpu_ida_cpu *tags;
	unsigned long flags;
	unsigned nr_free;

	BUG_ON(tag >= pool->nr_tags);

	local_irq_save(flags);
	tags = this_cpu_ptr(pool->tag_cpu);

	spin_lock(&tags->lock);
	tags->freelist[tags->nr_free++] = tag;

	nr_free = tags->nr_free;
	spin_unlock(&tags->lock);

	if (nr_free == 1) {
		cpumask_set_cpu(smp_processor_id(),
				&pool->cpus_have_tags);
		wake_up(&pool->wait);
	}

	if (nr_free == pool->percpu_max_size) {
		spin_lock(&pool->lock);

		/*
		 * Global lock held and irqs disabled, don't need percpu
		 * lock
		 */
		if (tags->nr_free == pool->percpu_max_size) {
			move_tags(pool->freelist, &pool->nr_free,
				  tags->freelist, &tags->nr_free,
				  pool->percpu_batch_size);

			wake_up(&pool->wait);
		}
		spin_unlock(&pool->lock);
	}

	local_irq_restore(flags);
}
Beispiel #4
0
/**
 * percpu_ida_free - free a tag
 * @pool: pool @tag was allocated from
 * @tag: a tag previously allocated with percpu_ida_alloc()
 *
 * Safe to be called from interrupt context.
 */
void percpu_ida_free(struct percpu_ida *pool, unsigned tag)
{
	struct percpu_ida_cpu *tags;
	unsigned long flags;
	unsigned nr_free;

	BUG_ON(tag >= pool->nr_tags);

	tags = raw_cpu_ptr(pool->tag_cpu);

	spin_lock_irqsave(&tags->lock, flags);
	tags->freelist[tags->nr_free++] = tag;

	nr_free = tags->nr_free;

	if (nr_free == 1) {
		cpumask_set_cpu(smp_processor_id(),
				&pool->cpus_have_tags);
		wake_up(&pool->wait);
	}
	spin_unlock_irqrestore(&tags->lock, flags);

	if (nr_free == pool->percpu_max_size) {
		spin_lock_irqsave(&pool->lock, flags);
		spin_lock(&tags->lock);

		if (tags->nr_free == pool->percpu_max_size) {
			move_tags(pool->freelist, &pool->nr_free,
				  tags->freelist, &tags->nr_free,
				  pool->percpu_batch_size);

			wake_up(&pool->wait);
		}
		spin_unlock(&tags->lock);
		spin_unlock_irqrestore(&pool->lock, flags);
	}
}