[Cbe-oss-dev] The use of __spe_context_update_event() is inefficient for the debugger

John DelSignore jdelsign at totalviewtech.com
Tue Feb 5 01:57:11 EST 2008


Hi,

The libspe1 and libspe2 libraries in SDK 2.1 (and in other SDK versions too) contain a function named __spe_context_update_event() that I believe is designed to help the debugger know when an an spe context has been updated. The interface seems to be quite simple: Whenever an image is loaded into an SPU context, or whenever an SPU context is destroyed, libspe calls a function named "__spe_context_update_event".  As far as I can tell, this event is not specific to a particular SPU context, and simply means that "some" SPU context has changed.  It's up to the debugger to figure out which one. I believe that this interface could be improved to help the efficiency of the debugger. I'll focus on two libspe2 problems for now, but libspe1 has similar problems.

Problem #1
==========

In libspe2 in SDK 2.1, spe_program_load() calls _base_spe_program_load(), which calls __spe_context_update_event(), after the SPU ELF file has been loaded into the spe context, and the base address of the SPU ELF image in the PPU address space is written to the spufs "object-id" file. The code looks like this:

accessors.c:
__attribute__ ((noinline)) void  __spe_context_update_event(void)
{
	return;
}

load.c:
int _base_spe_program_load(spe_context_ptr_t spe, spe_program_handle_t *program)
{
	int rc,objfd;
	struct spe_ld_info ld_info;

	rc = load_spe_elf (program, spe->base_private->mem_mmap_base, &ld_info);
	if (rc != 0) {
		DEBUG_PRINTF ("Load SPE ELF failed..\n");
		return -1;
	}
	
	/* Register SPE image start address as "object-id" for oprofile.  */
	objfd = openat (spe->base_private->fd_spe_dir,"object-id", O_RDWR);
	if (objfd >= 0) {
		char buf[100];
		sprintf (buf, "%p", program->elf_image);
		write (objfd, buf, strlen (buf) + 1);
		close (objfd);
	}
	
	__spe_context_update_event();	

	spe->base_private->entry=ld_info.entry;
	
	return 0;
}

The problem here is that when __spe_context_update_event() is called, the debugger cannot easily discover *which* spe context has been loaded. That means that the debugger must grovel around in all of the spe contexts to try to figure out which of them changed. And since it is possible to reload an existing context with the same image, which overwrites any breakpoints the debugger planted in the context and results in no visible change to the object-id file, every time any spe context is updated, the debugger must look at each spe context in the process, and at a minimum replant the breakpoints. This is very inefficient, especially in environments with a large number of spe threads, for example multi-process environments.

An easy fix for this would be to pass the spe directory file descriptor (spe->base_private->fd_spe_dir) to the spe context update event function. To preserve compatibility with older debuggers and allow for a transition to the new scheme, we'd probably want to add a function instead of replacing __spe_context_update_event(). and call both functions. For example, the above would become:

accessors.c:
__attribute__ ((noinline)) void  __spe_context_update_event(void)
{
	return;
}
__attribute__ ((noinline)) void  __spe_context_update_event_fd_spe_dir(int fd_spe_dir)
{
	__spe_context_update_event(); /* Compatibility with older debuggers */
	return;
}

load.c:
int _base_spe_program_load(spe_context_ptr_t spe, spe_program_handle_t *program)
{
	int rc,objfd;
	struct spe_ld_info ld_info;

	rc = load_spe_elf (program, spe->base_private->mem_mmap_base, &ld_info);
	if (rc != 0) {
		DEBUG_PRINTF ("Load SPE ELF failed..\n");
		return -1;
	}
	
	/* Register SPE image start address as "object-id" for oprofile.  */
	objfd = openat (spe->base_private->fd_spe_dir,"object-id", O_RDWR);
	if (objfd >= 0) {
		char buf[100];
		sprintf (buf, "%p", program->elf_image);
		write (objfd, buf, strlen (buf) + 1);
		close (objfd);
	}
	
	__spe_context_update_event_fd_spe_dir(spe->base_private->fd_spe_dir);	

	spe->base_private->entry=ld_info.entry;
	
	return 0;
}

This way, newer debuggers can look at the first argument to __spe_context_update_event_fd_spe_dir() to determine which spe context was updated, which will be much more efficient as the number of spe contexts in the target program grows.

Problem #2
==========

In libspe2 in SDK 2.1, spe_context_destroy() calls _base_spe_context_destroy(), which calls __spe_context_update_event(), *after* the spe context has been destroyed; the spufs "object-id" file is not reset to zero.  Note that by the time __spe_context_update_event() is called, the spe context has already been torn down, so there's nothing useful the debugger can do with this event.  In particular, as far as I can tell, there is no way to "unload" an spe context such that the spe context continues to exist, but the address space of the spe context is reset. Calling __spe_context_update_event() when a context is destroyed just slows down the debugger, so I would suggest not calling __spe_context_update_event() or if adopted, __spe_context_update_event_fd_spe_dir(). But, if someone thinks that the event is useful, calling __spe_context_update_event_fd_spe_dir() with the fd_spe_dir of the context that was just destroyed would be OK.

Comments?

Cheers, John D.
-- 
John V. DelSignore, Jr.                 jdelsign at totalviewtech.com
Chief Architect
TotalView Technologies                  WWW:   http://www.totalviewtech.com
24 Prime Parkway                        Phone: (508) 652-7730
Natick, MA 01760                        FAX:   (508) 652-7787




More information about the cbe-oss-dev mailing list