Thread (11 messages) flat view 11 messages, 5 authors, 2008-07-08

Re: [PATCH] Power5,Power6 BSR driver

From: Sonny Rao <hidden>
Date: 2008-06-18 07:15:30

On Mon, Jun 16, 2008 at 01:53:44PM -0500, jschopp@austin.ibm.com wrote:
From: Sonny Rao <redacted>

Adds a character driver for BSR support on IBM POWER systems including 
Power5 and Power6.  The BSR is an optional processor facility not currently 
implemented by any other processors.  It's primary purpose is large SMP 
synchronization.  More details on the BSR are in comments to the code which 
follows.

Here's a basic, quick n' dirty testcase I have
Remember to link w/ -lpthread


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <pthread.h>

static void rw_test(char *map, unsigned bytes)
{
	unsigned i;
	printf("reading current bsr values\n");
	for (i=0 ; i < bytes;i++) {
		printf("bsr[%u] = 0x%x\n",
		       i, map[i]);
	}
	printf("writing all 1s into bsr\n");
	for (i=0; i< bytes; i++) {
		map[i] = 0xff;
	}
	printf("reading current bsr values\n");
	for (i=0 ; i < bytes;i++) {
		printf("bsr[%u] = 0x%x\n",
		       i, map[i]);
	}
	printf("writing all byte numbers into bsr\n");
	for (i=0; i< bytes; i++) {
		map[i] = i;
	}
	printf("reading current bsr values\n");
	for (i=0 ; i < bytes;i++) {
		printf("bsr[%u] = 0x%x\n",
		       i, map[i]);
	}

}

struct thread_data {
	pthread_t thread;
	volatile char *map;
	unsigned id;
	uint64_t counter;
};

#define be_busy(cycles) do { \
  __asm__ __volatile__ ("1: addic. %0,%0,-1\n" \
			"   bne 1b\n" : :"r" (cycles) : "cr0"); } while(0)
#define  __sync() do { \
  __asm__ __volatile__ ("sync\n" ::: "memory"); } while(0)

static
void * thread_fn(void * data)
{
	struct thread_data *mydata = data;

	__sync();
	mydata->map[mydata->id]++;
	__sync();
	while (mydata->map[0] == 0) {
		/* be_busy(10); */
		mydata->counter++;
	}
	return NULL;
}

static
void pthread_test(volatile char *map, unsigned num)
{
	struct thread_data *pthreads;
	unsigned i;

	pthreads = malloc(sizeof(struct thread_data) * num);
	if (!pthreads) {
		perror("malloc");
		return;
	}
	for (i=0; i<num; i++) {
		map[i] = 0;
	}
	__sync();
	for (i=1; i< num;i++) {
		struct thread_data *cur = &pthreads[i];
		cur->map = map;
		cur->id  = i;
		if (pthread_create(&cur->thread, NULL, thread_fn, cur)) {
			perror("pthread_create");
			exit(1);
		}
	}
	for (i=1; i<num;i++) {
		char status;
		do {
			status = map[i];
		} while(status == 0);
	}
	__sync();
	map[0] = 1;
	__sync();
	for (i=1; i<num;i++) {
		if (pthread_join(pthreads[i].thread, NULL)) {
			perror("pthread_join");
		}
		printf("%03u %llu\n", pthreads[i].id, pthreads[i].counter);
	}
	free(pthreads);
}

int main (int argc, char *argv[])
{
	char *file;
	int fd;
	char *map;
	int pagesize = getpagesize();
	unsigned  bytes;

	if (argc < 3) {
		fprintf(stderr, "usage: <bsr dev> <num bytes>\n");
		return 1;
	}
	file = argv[1];
	bytes = strtoul(argv[2], NULL, 0);
	fd = open(file, O_RDWR);
	if (fd < 0) {
		perror("open");
		return 1;
	}
	map = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (!map) {
		perror("mmap");
		close(fd);
		return 1;
	}

	rw_test(map, bytes);
	pthread_test(map, bytes);
	close(fd);
	return 0;
}
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help