[PATCH] Power5,Power6 BSR driver
Sonny Rao
sonnyrao at us.ibm.com
Wed Jun 18 16:53:46 EST 2008
On Mon, Jun 16, 2008 at 01:53:44PM -0500, jschopp at austin.ibm.com wrote:
> From: Sonny Rao <sonnyrao at linux.vnet.ibm.com>
>
> 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;
}
More information about the Linuxppc-dev
mailing list