mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Huang Ying <ying.huang@intel.com>
To: Stefani Seibold <stefani@seibold.net>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [RFC] kfifo writer side lock-less support
Date: Wed, 09 Jun 2010 13:09:07 +0800	[thread overview]
Message-ID: <1276060147.3444.712.camel@yhuang-dev.sh.intel.com> (raw)
In-Reply-To: <1276023707.4499.12.camel@wall-e.seibold.net>

[-- Attachment #1: Type: text/plain, Size: 285 bytes --]

Hi, Stefani,

On Wed, 2010-06-09 at 03:01 +0800, Stefani Seibold wrote:
> Hi Huang,
> 
> it would be great if you could post an example code how to use your
> code.

The file attached is the testing code I used. Is it a good example from
your point of view?

Best Regards,
Huang Ying


[-- Attachment #2: kfifo_test.c --]
[-- Type: text/x-csrc, Size: 6243 bytes --]

/* kfifo_test.c */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kfifo.h>
#include <linux/random.h>
#include <linux/sched.h>
#include <linux/kthread.h>

#define KTPFX		"kfifo_test: "

#define FIFO_SIZE	PAGE_SIZE

#define IN_LEN_BITS	8
#define IN_LEN_MASK	((1<<IN_LEN_BITS) - 1)
#define IN_LEN_SHIFT	13
#define IN_LEN_MAX	(1<<IN_LEN_BITS)

#define IN_LEN_MEAN	(IN_LEN_MAX >> 1)

#define RECORDS_MEAN	(FIFO_SIZE / IN_LEN_MEAN)

#define IO_NUM_MAX	(RECORDS_MEAN * 3 / 2)

static char fifo_page[FIFO_SIZE];

static int test_intvl = 10;

static struct timer_list test_timer;
static int test_exiting;
static struct kfifo test_fifo;

static atomic_t test_added;
static atomic_t test_deled;
static atomic_t test_timer_added;
static atomic_t test_overlapped;

static atomic_t test_freezed;

static int test_ptr;

static unsigned int random_inl(void)
{
	u32 rand;

	rand = random32();

	rand = (rand >> IN_LEN_SHIFT) & IN_LEN_MASK;
	if (!rand)
		rand = 1;
	return rand;
}

static unsigned int random_io_num(void)
{
	u32 rand;

	rand = random32();
	rand = ((rand&0xff)<<24) | ((rand&0xff00)<<8) |
		((rand&0xff0000)>>8) | ((rand&0xff000000)>>24);
	return rand % IO_NUM_MAX;
}

static unsigned int kfifo_ll_in_one_random(struct kfifo *fifo)
{
	unsigned char in_buf[IN_LEN_MAX];
	unsigned int i, inl, rc;

	inl = random_inl();
	for (i = 0; i < inl; i++)
		in_buf[i] = inl;
	rc = kfifo_ll_in(fifo, in_buf, inl);
	if (rc)
		atomic_inc(&test_added);
	return rc;
}

static unsigned int kfifo_check_and_skip_one(struct kfifo *fifo)
{
	unsigned char out_buf[IN_LEN_MAX];
	unsigned int i, skipl, len;

	len = kfifo_len(fifo);
	if (!len)
		return 0;
	i = kfifo_out_peek(fifo, out_buf, 1, 0);
	skipl = out_buf[0];
	if (len < skipl) {
		pr_info(KTPFX "len: %u, skipl: %u\n", len, skipl);
		BUG();
	}
	i = kfifo_out_peek(fifo, out_buf, skipl, 0);
	for (i = 0; i < skipl; i++)
		BUG_ON(out_buf[i] != skipl);
	kfifo_skip(fifo, skipl);
	atomic_inc(&test_deled);

	return skipl;
}

#define kfifo_check_ptr(fifo, p)					\
	{								\
	if (p < fifo->buffer || p + *p > fifo->buffer + fifo->size) {	\
		pr_info(KTPFX "fifo->buffer: %p, p: %p, *p: %u\n",	\
			fifo->buffer, p, *p);				\
		BUG();							\
	}								\
}

static unsigned int kfifo_ll_in_one_random_ptr(struct kfifo *fifo)
{
	unsigned char *p;
	unsigned int i, inl;

	inl = random_inl();
	preempt_disable();
	p = kfifo_reserve_continuous_ptr(fifo, &inl);
	if (!p) {
		preempt_enable_no_resched();
		return 0;
	}
	for (i = 0; i < inl; i++)
		p[i] = inl;
	kfifo_commit_ptr(fifo, p);
	kfifo_check_ptr(fifo, p);
	preempt_enable_no_resched();
	atomic_inc(&test_added);
	return inl;
}

static unsigned int kfifo_check_and_skip_one_ptr(struct kfifo *fifo)
{
	unsigned char *p;
	unsigned int i;
	struct kfifo_iter iter;

	kfifo_iter_init(&iter, fifo);
	p = kfifo_iter_get_ptr(&iter);
	if (!p)
		return 0;
#if 1
	while (p) {
		kfifo_check_ptr(fifo, p);
		for (i = 1; i < *p; i++)
			BUG_ON(p[i] != *p);
		kfifo_iter_advance(&iter, *p);
		p = kfifo_iter_get_ptr(&iter);
	}
	kfifo_iter_init(&iter, fifo);
	p = kfifo_iter_get_ptr(&iter);
#else
	for (i = 0; i < *p; i++)
		BUG_ON(p[i] != *p);
#endif
	kfifo_skip(fifo, *p);

	atomic_inc(&test_deled);

	return *p;
}

static void test_round(struct kfifo *fifo)
{
	unsigned int i, numi, numo;
	unsigned int old_added, old_deled, full, empty;

	numi = random_io_num();
	numo = random_io_num();

	old_added = atomic_read(&test_added);
	old_deled = atomic_read(&test_deled);

	full = kfifo_avail(fifo) < IN_LEN_MAX / 2;

	if (test_ptr) {
		for (i = 0; i < numi; i++)
			kfifo_ll_in_one_random_ptr(fifo);
	} else {
		for (i = 0; i < numi; i++)
			kfifo_ll_in_one_random(fifo);
	}

	if (!full && numi && old_added == atomic_read(&test_added))
		atomic_inc(&test_freezed);

	empty = kfifo_len(fifo) == 0;

	if (test_ptr) {
		for (i = 0; i < numo; i++)
			kfifo_check_and_skip_one_ptr(fifo);
	} else {
		for (i = 0; i < numo; i++)
			kfifo_check_and_skip_one(fifo);
	}

	if (!empty && numo && old_deled == atomic_read(&test_deled))
		atomic_inc(&test_freezed);
}

void test_fifo_init(void)
{
	kfifo_init(&test_fifo, fifo_page, sizeof(fifo_page));
	test_fifo.in = test_fifo.out = test_fifo.reserve = (~0U - PAGE_SIZE);
}

static void simple_test(void)
{
	int i;

	test_fifo_init();
	for (i = 0; i < 100; i++) {
		test_round(&test_fifo);
		schedule();
	}
}

static void test_timer_func(unsigned long data)
{
	if (test_ptr)
		kfifo_ll_in_one_random_ptr(&test_fifo);
	else
		kfifo_ll_in_one_random(&test_fifo);

	if (test_fifo.reserve != test_fifo.in)
		atomic_inc(&test_overlapped);
	atomic_inc(&test_timer_added);
	if (!test_exiting) {
		test_timer.expires = jiffies + 1;
		add_timer_on(&test_timer, 1);
	}
}

static int test_thread1(void *data)
{
	unsigned long until;
	struct completion *comp = data;
	unsigned int i = 0;

	until = jiffies;
	until += msecs_to_jiffies(MSEC_PER_SEC * test_intvl);

	do {
		test_round(&test_fifo);
		if ((i & 0xf) == 0)
			schedule();
	} while ((long)(until - jiffies) > 0);

	complete(comp);

	return 0;
}

static void full_test(void)
{
	struct task_struct *thd;
	struct completion comp;

	atomic_set(&test_added, 0);
	atomic_set(&test_deled, 0);
	atomic_set(&test_timer_added, 0);
	atomic_set(&test_overlapped, 0);
	atomic_set(&test_freezed, 0);

	test_fifo_init();

	test_timer.expires = jiffies + 1;
	add_timer_on(&test_timer, 1);

	init_completion(&comp);
	thd = kthread_create(test_thread1, &comp, "kfifo_tester1");
	if (IS_ERR(thd)) {
		pr_err(KTPFX "Failed to create thread!\n");
		return;
	}
	kthread_bind(thd, 1);
	wake_up_process(thd);
	wait_for_completion(&comp);

	del_timer_sync(&test_timer);

	pr_info(KTPFX
	"%s: added: %u, deled: %u, overlapped: %u of %u, freezed: %u\n",
		test_ptr ? "ptr" : "nor",
		atomic_read(&test_added), atomic_read(&test_deled),
		atomic_read(&test_overlapped), atomic_read(&test_timer_added),
		atomic_read(&test_freezed));
}

static int kfifo_test_init(void)
{
	init_timer(&test_timer);
	test_timer.function = test_timer_func;

	test_ptr = 0;
	simple_test();
	test_ptr = 1;
	simple_test();

	test_ptr = 0;
	full_test();
	test_ptr = 1;
	full_test();

	return 0;
}

static void kfifo_test_exit(void)
{
}

module_init(kfifo_test_init);
module_exit(kfifo_test_exit);

MODULE_LICENSE("GPL");

      reply	other threads:[~2010-06-09  5:09 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-06-08  6:45 Huang Ying
2010-06-08 19:01 ` Stefani Seibold
2010-06-09  5:09   ` Huang Ying [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1276060147.3444.712.camel@yhuang-dev.sh.intel.com \
    --to=ying.huang@intel.com \
    --cc=akpm@linux-foundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stefani@seibold.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome