[Cbe-oss-dev] [PATCH 3/3] libspe: add image open library

Dirk Herrendoerfer d.herrendoerfer at de.ibm.com
Thu Jul 16 23:38:03 EST 2009


Patch to add spe_image_open_library function and to change  
spe_image_close
enabling loading an SPE executable image from a dynamic shared object  
library.
This includes a testimageopenlibrary test case along with building and  
using
the libtest.so dynamic shared object library. This patch includes  
enhanced
documentation of these functions. Also the Ada interface definition was
extended, but not tested.

Signed-off-by: Brian Watt <bwatt at us.ibm.com>
Acked-by: Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot]  
com>

diff -uprN libspe2.orig/ada/libspe2.ads libspe2.add_image_open_library/ 
ada/libspe2.ads
--- libspe2.orig/ada/libspe2.ads	2009-06-25 15:11:41.000000000 -0500
+++ libspe2.add_image_open_library/ada/libspe2.ads	2009-06-23  
16:50:59.000000000 -0500
@@ -69,6 +69,15 @@ package libspe2 is
    pragma Import (C, spe_image_open, "spe_image_open");

  --
+-- spe_image_open_library
+--
+  function spe_image_open_library
+    (library  : char_array;
+     entry    : char_array)
+    return spe_program_handle_t;
+  pragma Import (C, spe_image_open_library, "spe_image_open_library");
+
+--
  -- spe_image_close
  --
    function spe_image_close
diff -uprN libspe2.orig/libspe2.c libspe2.add_image_open_library/ 
libspe2.c
--- libspe2.orig/libspe2.c	2009-06-25 15:22:26.000000000 -0500
+++ libspe2.add_image_open_library/libspe2.c	2009-06-23  
16:51:02.000000000 -0500
@@ -132,6 +132,15 @@ spe_program_handle_t * spe_image_open (c
  }

  /*
+ * spe_image_open_library
+ */
+
+spe_program_handle_t * spe_image_open_library (const char *library,  
const char *entry)
+{
+	return _base_spe_image_open_library(library, entry);
+}
+
+/*
   * spe_image_close
   */

diff -uprN libspe2.orig/libspe2.h libspe2.add_image_open_library/ 
libspe2.h
--- libspe2.orig/libspe2.h	2009-06-25 15:18:11.000000000 -0500
+++ libspe2.add_image_open_library/libspe2.h	2009-06-23  
16:51:02.000000000 -0500
@@ -85,6 +85,11 @@ int spe_gang_context_destroy (spe_gang_c
  spe_program_handle_t * spe_image_open (const char *filename);

  /*
+ * spe_image_open_library
+ */
+spe_program_handle_t * spe_image_open_library (const char *library,  
const char *entry);
+
+/*
   * spe_image_close
   */
  int spe_image_close (spe_program_handle_t *program);
diff -uprN libspe2.orig/Makefile libspe2.add_image_open_library/Makefile
--- libspe2.orig/Makefile	2009-06-25 15:52:51.000000000 -0500
+++ libspe2.add_image_open_library/Makefile	2009-06-26  
12:20:20.000000000 -0500
@@ -107,7 +107,7 @@ libspe2.pc: Makefile $(TOP)/libspe2.pc.i
  	@mv $@.tmp $@

  $(libspe2_SO): $(libspe2_OBJS) base-all  event-all libspe2.pc
-	$(CC) $(CFLAGS) -shared -o $@ $(libspe2_OBJS) spebase/*.o speevent/ 
*.o -lrt -lpthread -Wl,--soname=${libspe2_SONAME}
+	$(CC) $(CFLAGS) -shared -o $@ $(libspe2_OBJS) spebase/*.o speevent/ 
*.o -lrt -lpthread -ldl -Wl,--soname=${libspe2_SONAME}

  $(libspe2_A): $(libspe2_OBJS) base-all  event-all
  	 $(CROSS)ar -r $(libspe2_A) $(libspe2_OBJS) spebase/*.o speevent/ 
*.o $(libspe2_OBJS)
diff -uprN libspe2.orig/spebase/image.c libspe2.add_image_open_library/ 
spebase/image.c
--- libspe2.orig/spebase/image.c	2009-06-25 15:17:03.000000000 -0500
+++ libspe2.add_image_open_library/spebase/image.c	2009-06-25  
17:33:14.000000000 -0500
@@ -19,6 +19,7 @@

  #include <errno.h>
  #include <fcntl.h>
+#include <stdio.h>
  #include <stdlib.h>

  #include <sys/mman.h>
@@ -26,12 +27,23 @@

  #include <unistd.h>

+#include <dlfcn.h>
+
  #include "elf_loader.h"
  #include "spebase.h"

+typedef enum _SPE_IMAGE_TYPE {
+	SPE_IMAGE_TYPE_FILE = 0,
+	SPE_IMAGE_TYPE_LIB = 1,
+} SPE_IMAGE_TYPE;
+
  struct image_handle {
  	spe_program_handle_t speh;
-	unsigned int map_size;
+	SPE_IMAGE_TYPE image_type;
+	union {
+		unsigned int map_size;
+		void *lib_handle;
+	};
  };

  spe_program_handle_t *_base_spe_image_open(const char *filename)
@@ -49,6 +61,7 @@ spe_program_handle_t *_base_spe_image_op
  	ret->speh.elf_image = MAP_FAILED;
  	ret->speh.handle_size = sizeof(spe_program_handle_t);
  	ret->speh.toe_shadow = NULL;
+  ret->image_type = SPE_IMAGE_TYPE_FILE;

  	binfd = open(filename, O_RDONLY);
  	if (binfd < 0)
@@ -96,6 +109,69 @@ ret_err:
  	return NULL;
  }

+spe_program_handle_t *_base_spe_image_open_library(const char  
*library, const char *entry)
+{
+  /* allocate an extra integer in the spe handle to keep the mapped  
size information */
+  struct image_handle *ret;
+  spe_program_handle_t *tmp;
+
+  ret = (struct image_handle *)malloc(sizeof(struct image_handle));
+  if (ret == NULL) {
+    return NULL;
+  }
+
+	ret->speh.elf_image = NULL;
+  ret->speh.handle_size = sizeof(spe_program_handle_t);
+  ret->speh.toe_shadow = NULL;
+  ret->image_type = SPE_IMAGE_TYPE_LIB;
+
+  /* load the library */
+  dlerror(); // purge previous error
+  ret->lib_handle = dlopen(library, RTLD_NOW | RTLD_GLOBAL);
+  if (ret->lib_handle == NULL) {
+  	DEBUG_PRINTF("dlopen failed: %s\n",dlerror());
+  	errno=ELIBACC;
+  	goto ret_err;
+  }
+
+  /* find the executable symbol in the library */
+  tmp = (spe_program_handle_t *)dlsym(ret->lib_handle, entry);
+  if (tmp == NULL) {
+  	DEBUG_PRINTF("dlsym failed: %s\n",dlerror());
+  	errno=ENOENT;
+    goto ret_err;
+  }
+
+	/* Sanity: handle_sizes must match */
+	if (ret->speh.handle_size != tmp->handle_size) {
+		errno=EINVAL;
+	  goto ret_err;
+	}
+	
+  /* copy existing spe_program_handle_t structure members from the  
loaded code to the malloc'ed space */
+  ret->speh.elf_image = tmp->elf_image;
+  ret->speh.toe_shadow = tmp->toe_shadow;
+
+  /*Verify that this is a valid SPE ELF object */
+  if ((_base_spe_verify_spe_elf_image((spe_program_handle_t *) ret)) ! 
= 0) {
+    goto ret_err;
+  }
+
+	if (_base_spe_toe_ear(&ret->speh))
+		goto ret_err;
+
+  /* ok */
+  return (spe_program_handle_t *) ret;
+
+  /* err & cleanup */
+ret_err:
+	if (ret->lib_handle != NULL) {
+		dlclose(ret->lib_handle);
+	}
+  free(ret);
+  return NULL;
+}
+
  int _base_spe_image_close(spe_program_handle_t *handle)
  {
  	int ret = 0;
@@ -108,15 +184,39 @@ int _base_spe_image_close(spe_program_ha
  	
  	ih = (struct image_handle *)handle;

-	if (!ih->speh.elf_image || !ih->map_size) {
+	if (!ih->speh.elf_image) {
  		errno = EINVAL;
  		return -1;
  	}
-
+	
  	if (ih->speh.toe_shadow)
  		free(ih->speh.toe_shadow);

-	ret = munmap(ih->speh.elf_image, ih->map_size );
+	switch(ih->image_type) {
+		case SPE_IMAGE_TYPE_FILE:
+			if (!ih->map_size) {
+				errno = EINVAL;
+				return -1;
+			}
+			ret = munmap(ih->speh.elf_image, ih->map_size );
+		break;
+		case SPE_IMAGE_TYPE_LIB:
+			if (!ih->lib_handle) {
+				errno = EINVAL;
+				return -1;
+			}
+			dlerror(); // purge previous error
+			if (dlclose(ih->lib_handle) != 0) {
+				DEBUG_PRINTF("dlclose failed: %s\n",dlerror());
+				return -1;
+			}
+		break;
+		default:
+		  errno = EINVAL;
+		  return -1;
+		break;
+  }
+	
  	free(handle);

  	return ret;
diff -uprN libspe2.orig/spebase/Makefile  
libspe2.add_image_open_library/spebase/Makefile
--- libspe2.orig/spebase/Makefile	2008-11-12 16:32:03.000000000 -0600
+++ libspe2.add_image_open_library/spebase/Makefile	2009-06-26  
12:20:19.000000000 -0500
@@ -51,7 +51,7 @@ clean:
  	rm -rf $(libspebase_A) $(libspebase_OBJS) $(libspebase_SO)

  $(libspebase_SO): $(libspebase_OBJS)
-	$(CC) $(CFLAGS) -shared -o $@ $^ -lrt -lpthread -Wl,--soname=$ 
{libspebase_SONAME}
+	$(CC) $(CFLAGS) -shared -o $@ $^ -lrt -lpthread -ldl -Wl,--soname=$ 
{libspebase_SONAME}

  $(libspebase_A): $(libspebase_OBJS)
  	 $(CROSS)ar -r $(libspebase_A) $(libspebase_OBJS)
diff -uprN libspe2.orig/spebase/spebase.h  
libspe2.add_image_open_library/spebase/spebase.h
--- libspe2.orig/spebase/spebase.h	2009-06-25 17:30:22.000000000 -0500
+++ libspe2.add_image_open_library/spebase/spebase.h	2009-06-26  
15:16:05.000000000 -0500
@@ -28,6 +28,7 @@ extern "C"
  #endif

  #include <pthread.h>
+#include <stdio.h>

  #include "libspe2-types.h"

@@ -257,21 +258,26 @@ extern int _base_spe_context_run(spe_con
  					unsigned int runflags, void *argp, void *envp, spe_stop_info_t  
*stopinfo);

  /**
- * _base_spe_image_close unmaps an SPE ELF object that was previously  
mapped using
- * spe_image_open.
- * @param handle handle to open file
+ * _base_spe_image_close Closes an SPE ELF object that was previously  
opened using
+ * spe_image_open or spe_image_open_library. For spe_image_open the  
image is unmapped
+ * and closed. For spe_image_open_library the dynamic shared object  
library is closed.
   *
- * @retval 0 On success, spe_close_image returns 0.
+ * @param handle A valid address of an SPE program.
+ *
+ * @retval 0 On success, spe_image_close returns 0.
   * @retval -1 On failure, -1 is returned and errno is set  
appropriately.\n
   * Possible values for errno:\n
- * EINVAL From spe_close_image, this indicates that the file,  
specified by
- * filename, was not previously mapped by a call to spe_image_open.
+ * EINVAL	The specified address of the SPE program is invalid.
+ * A number of other errno values could be returned by the munmap(2)  
close(2),
+ * or dlclose(2) system calls which may be utilized by the  
spe_image_close function.
+ *
+ * @sa spe_image_open, spe_image_open_library
   */
  extern int _base_spe_image_close(spe_program_handle_t *handle);

  /**
   * _base_spe_image_open maps an SPE ELF executable indicated by  
filename into system
- * memory and returns the mapped address appropriate for use by the  
spe_create_thread
+ * memory and returns the mapped address appropriate for use by the  
spe_program_load
   * API. It is often more convenient/appropriate to use the loading  
methodologies
   * where SPE ELF objects are converted to PPE static or shared  
libraries with
   * symbols which point to the SPE ELF objects after these special  
libraries are
@@ -297,11 +303,44 @@ extern int _base_spe_image_close(spe_pro
   * A number of other errno values could be returned by the open(2),  
fstat(2),
   * mmap(2), munmap(2), or close(2) system calls which may be  
utilized by the
   * spe_image_open or spe_image_close functions.
- * @sa spe_create_thread
+ *
+ * @sa spe_image_open_library, spe_program_load, spe_image_close
   */
  extern spe_program_handle_t *_base_spe_image_open(const char  
*filename);

  /**
+ * _base_spe_image_open_library opens a PPE dynamic shared object  
library
+ * specified by library and loads it into system memory. It then  
searches for the
+ * entry as a symbol within this library. The result is a pointer to  
an SPE
+ * program handle which can then be used with spe_program_load to  
load this SPE main
+ * program into the local store of an SPE before running it with  
spe_context_run.
+ *
+ * The image_library is a PPE shared object library containing any  
number of PPE
+ * object files that were created as the result of the ppu_embedspu  
script.
+ *
+ * @param library Specifies a string pointer that is the library name  
to be
+ * dynamically loaded into system memory. If the pointer is NULL,  
then the
+ * standard dlopen conventions are followed as described in its man- 
page.
+ * @param entry Specifies the name of an SPE ELF executable that is  
in the
+ * library. This symbol is the name specified in the ppu-embedspu  
command.
+ *
+ * @return On success, a non-null handle to the SPE ELF object is  
returned.
+ * On failure, NULL is returned and errno is set to indicate the error.
+ * Possible values for errno include:\n
+ * ELIBACC The library could not be opened.\n
+ * ENOENT The entry symbol could not be found in the library.\n
+ * EFAULT The library or entry parameter points to an address that  
was not
+ * contained in the calling process`s address space.
+ *
+ * A number of other errno values could be returned by the dlopen(2),
+ * and dlsym(2) system calls which may be utilized by the
+ * spe_image_open_library function.
+ *
+ * @sa spe_image_open, spe_image_close
+ */
+extern spe_program_handle_t *_base_spe_image_open_library(const char  
*library, const char *entry);
+
+/**
   * The _base_spe_mfcio_put function places a put DMA command on the  
proxy command queue
   * of the SPE thread specified by speid. The put command transfers  
size bytes of
   * data starting at the local store address specified by ls to the  
effective
diff -uprN libspe2.orig/tests/libspe2.basic/Makefile  
libspe2.add_image_open_library/tests/libspe2.basic/Makefile
--- libspe2.orig/tests/libspe2.basic/Makefile	2009-06-25  
15:21:37.000000000 -0500
+++ libspe2.add_image_open_library/tests/libspe2.basic/Makefile	 
2009-06-24 12:43:27.000000000 -0500
@@ -33,10 +33,14 @@ main_progs = \
  	testhandler.elf \
  	testevent1.elf \
  	testevent2.elf \
-	testmbox.elf
+	testmbox.elf \
+	testimageopenlibrary.elf

  ppu_progs =

+ppu_libs = \
+	libtest.so
+
  spu_progs = \
  	helloworld.spu.elf \
  	hellointr.spu.elf \
@@ -47,3 +51,6 @@ extra_main_progs = \
  	testmap1.elf

  include $(TEST_TOP)/make.rules
+
+libtest.so: helloworld.embed.o
+	$(CC) -shared $(filter %.o,$^) -o $@ $(LDFLAGS)
diff -uprN libspe2.orig/tests/libspe2.basic/testimageopenlibrary.c  
libspe2.add_image_open_library/tests/libspe2.basic/ 
testimageopenlibrary.c
--- libspe2.orig/tests/libspe2.basic/testimageopenlibrary.c	1969-12-31  
18:00:00.000000000 -0600
+++ libspe2.add_image_open_library/tests/libspe2.basic/ 
testimageopenlibrary.c	2009-06-24 16:43:57.000000000 -0500
@@ -0,0 +1,40 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "libspe2.h"
+
+int main(void)
+{
+	spe_context_ptr_t ctx;
+	int flags = 0;
+	unsigned int entry = SPE_DEFAULT_ENTRY;
+	void * argp = NULL;
+	void * envp = NULL;
+	spe_program_handle_t * program;
+	spe_stop_info_t stop_info;
+	int rc;
+	
+	program = spe_image_open_library("./libtest.so","helloworld");
+	if (!program) {
+		perror("spe_image_open_library");
+		return -1;
+	}
+	
+	ctx = spe_context_create(flags, NULL);
+	if (ctx == NULL) {
+		perror("spe_context_create");
+		return -2;
+	}
+	if (spe_program_load(ctx, program)) {
+		perror("spe_program_load");
+		return -3;
+	}
+	rc = spe_context_run(ctx, &entry, 0, argp, envp, &stop_info);
+	if (rc < 0)
+		perror("spe_context_run");
+	
+	spe_context_destroy(ctx);
+
+	return 0;
+}
+
diff -uprN libspe2.orig/tests/make.rules  
libspe2.add_image_open_library/tests/make.rules
--- libspe2.orig/tests/make.rules	2009-06-25 15:17:34.000000000 -0500
+++ libspe2.add_image_open_library/tests/make.rules	2009-06-24  
12:48:25.000000000 -0500
@@ -29,7 +29,7 @@ spu_elfs = $(filter %.elf,$(spu_progs))

  .PHONY: all check clean distclean $(checks)

-all: $(main_progs) $(extra_main_progs) $(ppu_progs) $(spu_progs)
+all: $(ppu_libs) $(main_progs) $(extra_main_progs) $(ppu_progs) $ 
(spu_progs)

  check:
  	@passed=""; \
@@ -56,7 +56,7 @@ $(checks): check-%: %
  	fi

  clean:
-	-$(RM) *.elf *.o *.tmp `find . -maxdepth 1 -type l`
+	-$(RM) *.elf *.o *.tmp *.so `find . -maxdepth 1 -type l`

  distclean: clean
  	-$(RM) *~



More information about the cbe-oss-dev mailing list