[Cbe-oss-dev] [PATCH] libspe: support for new problem state mapping

Benjamin Herrenschmidt benh at kernel.crashing.org
Fri Sep 29 15:12:17 EST 2006


This patch modifies libspe to use the new problem state mapping "psmap"
file making it now work with kernels compiled with 64k base page size.
It also adds the missing mapping of the mss register while at it. It
should also be backward compatible with old kernels.

diff -urN ../sw/head/libspe/ps.c libspe/ps.c
--- ../sw/head/libspe/ps.c	2006-08-23 13:29:54.000000000 +1000
+++ libspe/ps.c	2006-09-26 15:21:01.000000000 +1000
@@ -39,18 +39,33 @@
 
 /* Internal function prototypes. only used internaly.
  */
-void *map_mfc_area(speid_t speid);
-void *map_cntl_area(speid_t speid);
-void *map_signal1_area(speid_t speid);
-void *map_signal2_area(speid_t speid);
 
-void *map_mfc_area(speid_t speid)
+static void *map_mss_area(speid_t speid)
+{
+	struct thread_store *spe = speid;
+
+	if (spe->mss_mmap_base == MAP_FAILED)
+	{
+		spe->mss_mmap_base = do_spe_map_ps_area(spe, 0,
+							spe->fd_mss, 0x1000);
+	}
+
+	if (spe->mss_mmap_base == MAP_FAILED)
+	{
+		return NULL;
+	}
+
+	return spe->mss_mmap_base;
+}
+
+static void *map_mfc_area(speid_t speid)
 {
 	struct thread_store *spe = speid;
 
 	if (spe->mfc_mmap_base == MAP_FAILED)
 	{
-		spe->mfc_mmap_base = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, spe->fd_mfc, 0);
+		spe->mfc_mmap_base = do_spe_map_ps_area(spe, 0x3000,
+							spe->fd_mfc, 0x1000); 
 	}
 	
 	if (spe->mfc_mmap_base == MAP_FAILED)
@@ -61,13 +76,14 @@
 	return spe->mfc_mmap_base;
 }
 
-void *map_cntl_area(speid_t speid)
+static void *map_cntl_area(speid_t speid)
 {
 	struct thread_store *spe = speid;
 
 	if (spe->cntl_mmap_base == MAP_FAILED)
 	{
-		spe->cntl_mmap_base = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, spe->fd_cntl, 0);
+		spe->cntl_mmap_base = do_spe_map_ps_area(spe, 0x4000,
+							 spe->fd_cntl, 0x1000); 
 	}
 	
 	if (spe->cntl_mmap_base == MAP_FAILED)
@@ -78,13 +94,14 @@
 	return spe->cntl_mmap_base;
 }
 
-void *map_signal1_area(speid_t speid)
+static void *map_signal1_area(speid_t speid)
 {
 	struct thread_store *spe = speid;
 
 	if (spe->signal1_mmap_base == MAP_FAILED)
 	{
-		spe->signal1_mmap_base = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, spe->fd_sig1, 0);
+		spe->signal1_mmap_base = do_spe_map_ps_area(spe, 0x14000,
+							    spe->fd_sig1, 0x1000); 
 	}
 
 	if (spe->signal1_mmap_base == MAP_FAILED)
@@ -95,13 +112,14 @@
 	return spe->signal1_mmap_base;
 }
 
-void *map_signal2_area(speid_t speid)
+static void *map_signal2_area(speid_t speid)
 {
 	struct thread_store *spe = speid;
 
 	if (spe->signal2_mmap_base == MAP_FAILED)
 	{
-		spe->signal2_mmap_base = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, spe->fd_sig2, 0);
+		spe->signal2_mmap_base = do_spe_map_ps_area(spe, 0x1c000,
+							    spe->fd_sig2, 0x1000); 
 	}
 
 	return spe->signal2_mmap_base;
@@ -218,50 +236,45 @@
 	}
 		
 	if ( area == SPE_MSSYNC_AREA ) {
-                fprintf(stderr,"spe_map_ps_area: internal error. mapping of the mss area is not supported.\n");
-                errno = ENOSYS;
-		return NULL;
+		base_addr = map_mss_area(speid);
+		if (base_addr == NULL) {
+			perror("spe_map_ps_area: internal error. cant map mss file.");
+			errno = EIO;
+			return NULL;
+		}
+		return base_addr;
 	} else if ( area == SPE_MFC_COMMAND_AREA ) {
 		base_addr = map_mfc_area(speid);
-
 		if (base_addr == NULL) {
                         perror("spe_map_ps_area: internal error. cant map mfc file.");
                         errno = EIO;
 			return NULL;
-		} else {
-			return base_addr ; 
 		}
-
+		return base_addr ;
 	} else if ( area == SPE_CONTROL_AREA ) {
 		base_addr = map_cntl_area(speid);
-
 		if (base_addr == NULL) {
                         perror("spe_map_ps_area: internal error. cant map control file.");
                         errno = EIO;
 			return NULL;
-		} else {
-			return base_addr ; 
 		}
+		return base_addr ;
 	} else if ( area == SPE_SIG_NOTIFY_1_AREA ) {
 		base_addr = map_signal1_area(speid);
-
 		if (base_addr == NULL) {
                         perror("spe_map_ps_area: internal error. cant map signal1 file.");
                         errno = EIO;
 			return NULL;
-		} else {
-			return base_addr; 
 		}
+		return base_addr; 
 	} else if ( area == SPE_SIG_NOTIFY_2_AREA ) {
 		base_addr = map_signal2_area(speid);
-
 		if (base_addr == NULL) {
                         perror("spe_map_ps_area: internal error. cant map signal2 file.");
                         errno = EIO;
 			return NULL;
-		} else {
-			return base_addr; 
 		}
+		return base_addr; 
 	}
 	
 	perror("spe_map_ps_area: Unsupported call of spe_map_ps_area.");
diff -urN ../sw/head/libspe/signal.c libspe/signal.c
--- ../sw/head/libspe/signal.c	2006-01-21 02:27:12.000000000 +1100
+++ libspe/signal.c	2006-09-26 13:40:51.000000000 +1000
@@ -24,7 +24,8 @@
 {
 	struct thread_store *thread_store = speid;
 	int fd;
-	void *base_addr;
+	void **base_addr;
+	off_t offset;
 
 	if (signo != 1 && signo != 2)
 	{
@@ -36,20 +37,21 @@
 	if (signo == 1)
 	{
 		fd = thread_store->fd_sig1;
-		base_addr = thread_store->signal1_mmap_base;
+		base_addr = &thread_store->signal1_mmap_base;
+		offset = 0x14000;
 	}
 	else
 	{
 		fd = thread_store->fd_sig2;
-		base_addr = thread_store->signal2_mmap_base;
+		base_addr = &thread_store->signal2_mmap_base;
+		offset = 0x1c000;
 	}
 
 
 	if ( base_addr == MAP_FAILED )
-	{	
-		base_addr=mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-		
-		if ( base_addr == MAP_FAILED )
+	{
+		*base_addr = do_spe_map_ps_area(thread_store, offset, fd, 0x1000);
+		if ( *base_addr == MAP_FAILED )
 		{	
 			perror("spe_signal_address: internal error. cant map signal file.");
 			errno = EIO;
@@ -58,6 +60,6 @@
 	}
 
 
-	return base_addr+0x0C;
+	return (*base_addr)+0x0C;
 }
 
diff -urN ../sw/head/libspe/spe.c libspe/spe.c
--- ../sw/head/libspe/spe.c	2006-09-14 15:01:23.000000000 +1000
+++ libspe/spe.c	2006-09-26 15:43:28.000000000 +1000
@@ -1,3 +1,4 @@
+
 /*
  * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS
  * Copyright (C) 2005 IBM Corp.
@@ -118,6 +119,11 @@
 	char filename[256];
 	int ret;
 	
+	/* this one mail fail */
+	sprintf(filename, "%s/psmap", pathname);
+	spe->fd_psmap = open(filename, O_RDWR);
+	spe->ps_mmap_base=MAP_FAILED;
+
 	sprintf(filename, "%s/mbox", pathname);
 	spe->fd_mbox = open(filename, O_RDONLY);
 
@@ -157,13 +163,21 @@
 	spe->fd_cntl = open(filename, O_RDWR);
 	spe->cntl_mmap_base=MAP_FAILED;
 
+	/* this one may fail */
+	sprintf(filename, "%s/mss", pathname);
+	spe->fd_mss = open(filename, O_RDWR);
+	spe->mss_mmap_base=MAP_FAILED;
+
 	ret=pipe(spe->ev_pipe);
+	if (ret)
+		spe->ev_pipe[0] = spe->ev_pipe[1] = -1;
 		
 	if (spe->fd_mbox      < 0 || spe->fd_ibox      < 0 || spe->fd_wbox      < 0 ||
 	    spe->fd_mbox_stat < 0 || spe->fd_ibox_stat < 0 || spe->fd_wbox_stat < 0 ||
 	    spe->fd_npc       < 0 || spe->fd_sig1      < 0 || spe->fd_sig2      < 0 || 
 	    ret ) {
 		DEBUG_PRINTF("Could not open all SPE files.\n");
+		close(spe->fd_psmap);
 		close(spe->fd_mbox);
 		close(spe->fd_mbox_stat);
 		close(spe->fd_ibox);
@@ -174,8 +188,8 @@
 		close(spe->fd_sig1);
 		close(spe->fd_sig2);
 		close(spe->fd_mfc);
-
 		close(spe->fd_cntl);
+		close(spe->fd_mss);
 		close(spe->ev_pipe[0]);
 		close(spe->ev_pipe[1]);
 		return -1;
@@ -406,21 +420,28 @@
 	close (thread_store->fd_wbox_stat);
 	close (thread_store->fd_npc);
 	
-	if (thread_store->signal1_mmap_base != MAP_FAILED)
-		munmap(thread_store->signal1_mmap_base,0x1000);
+	/* If psmap exists, unmap just that, else unmap individual bits */
+	if (thread_store->fd_psmap < 0) {
+		if (thread_store->signal1_mmap_base != MAP_FAILED)
+			munmap(thread_store->signal1_mmap_base,0x1000);
+		if (thread_store->signal2_mmap_base != MAP_FAILED)
+			munmap(thread_store->signal2_mmap_base,0x1000);
+		if (thread_store->mfc_mmap_base != MAP_FAILED)
+			munmap(thread_store->mfc_mmap_base,0x1000);
+		if (thread_store->cntl_mmap_base != MAP_FAILED)
+			munmap(thread_store->cntl_mmap_base,0x1000);
+		if (thread_store->mss_mmap_base != MAP_FAILED)
+			munmap(thread_store->mss_mmap_base,0x1000);
+	} else {
+		if (thread_store->ps_mmap_base != MAP_FAILED)
+			munmap(thread_store->ps_mmap_base, 0x20000);
+		close (thread_store->fd_psmap);
+	}
+	close (thread_store->fd_mss);
+	close (thread_store->fd_cntl);
+	close (thread_store->fd_mfc);
 	close (thread_store->fd_sig1);
-	
-	if (thread_store->signal2_mmap_base != MAP_FAILED)
-		munmap(thread_store->signal2_mmap_base,0x1000);
 	close (thread_store->fd_sig2);
-	
-	if (thread_store->mfc_mmap_base != MAP_FAILED)
-		munmap(thread_store->mfc_mmap_base,0x1000);
-	close (thread_store->fd_mfc);
-	
-	if (thread_store->cntl_mmap_base != MAP_FAILED)
-		munmap(thread_store->cntl_mmap_base,0x1000);
-	close (thread_store->fd_cntl);
 
 #ifndef SPE_NO_MMAP
 	munmap(thread_store->mem_mmap_base,LS_SIZE);
@@ -1097,6 +1118,36 @@
 	return rc;
 }
 
+/***
+ * do_spe_map_ps_area(spe, offset, fd, size)
+ *
+ * This is an internal function for mmapping part of the SPE problem state.
+ * it will use either the 128k single problem state mapping on recent kernels
+ * or the individual per-file mmap using the passed-in fd if the former is
+ * not available.
+ */
+void *do_spe_map_ps_area(struct thread_store *spe, off_t offset, int fd,
+			 size_t size)
+{
+	/* Check if 128k mapping is possible and not mapped yet */
+	if (spe->fd_psmap >= 0 && spe->ps_mmap_base == MAP_FAILED) {
+		spe->ps_mmap_base = mmap(0, 0x20000, PROT_READ | PROT_WRITE,
+					 MAP_SHARED, spe->fd_psmap, 0);
+		if (spe->ps_mmap_base == MAP_FAILED)
+			return MAP_FAILED;
+	}
+
+	/* If we have 128k mapping, return an offset within */
+	if (spe->ps_mmap_base != MAP_FAILED) {
+		if (offset > 0x20000 || (offset + size) > 0x20000)
+			return MAP_FAILED;
+		return spe->ps_mmap_base + offset;
+	}
+
+	/* Use the individual file mapping */
+	return mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+}
+
 /*
  * 
  */
diff -urN ../sw/head/libspe/spe.h libspe/spe.h
--- ../sw/head/libspe/spe.h	2006-09-22 10:44:44.000000000 +1000
+++ libspe/spe.h	2006-09-26 15:16:34.000000000 +1000
@@ -42,13 +42,15 @@
 	pthread_mutex_t event_lock;
         int 		fd_mem, fd_run, fd_mbox, fd_mbox_stat, fd_ibox, 
 			fd_ibox_stat, fd_wbox, fd_wbox_stat, fd_npc, fd_sig1, 
-			fd_sig2, fd_mfc, fd_cntl,
+			fd_sig2, fd_mfc, fd_cntl, fd_mss, fd_psmap,
 		 	policy, priority, affinity_mask, spe_flags,
 			npc, ret_status,event, ev_pipe[2];
         spe_gid_t 	group_id;
 	unsigned long	mask;
-	unsigned int    flags;
+	unsigned int    flags;	
         void 		*mem_mmap_base;
+	void		*ps_mmap_base;
+	void		*mss_mmap_base;
         void 		*mfc_mmap_base;
         void 		*cntl_mmap_base;
         void 		*signal1_mmap_base;
@@ -123,6 +125,8 @@
 extern int do_spe_run (void *spe);
 extern unsigned int set_npc (void *spe, unsigned int npc);
 extern int validatefd(struct poll_helper *phelper, int pos, int fd);
+extern void *do_spe_map_ps_area(struct thread_store *spe, off_t offset, int fd,
+				size_t size);
 
 extern void register_handler(void * handler, unsigned int callnum );
 extern int check_priority(int policy, int priority);





More information about the cbe-oss-dev mailing list