libspe2 0.9a
Data Structures | Defines | Enumerations | Functions
spebase.h File Reference
#include <pthread.h>
#include "libspe2-types.h"
Include dependency graph for spebase.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  spe_context_base_priv
struct  spe_gang_context_base_priv

Defines

#define __PRINTF(fmt, args...)   { fprintf(stderr,fmt , ## args); }
#define DEBUG_PRINTF(fmt, args...)
#define LS_SIZE   0x40000
#define PSMAP_SIZE   0x20000
#define MFC_SIZE   0x1000
#define MSS_SIZE   0x1000
#define CNTL_SIZE   0x1000
#define SIGNAL_SIZE   0x1000
#define MSSYNC_OFFSET   0x00000
#define MFC_OFFSET   0x03000
#define CNTL_OFFSET   0x04000
#define SIGNAL1_OFFSET   0x14000
#define SIGNAL2_OFFSET   0x1c000
#define SPE_EMULATE_PARAM_BUFFER   0x3e000
#define SPE_PROGRAM_NORMAL_END   0x2000
#define SPE_PROGRAM_LIBRARY_CALL   0x2100
#define SPE_PROGRAM_ISOLATED_STOP   0x2200
#define SPE_PROGRAM_ISO_LOAD_COMPLETE   0x2206

Enumerations

enum  fd_name {
  FD_MBOX, FD_MBOX_STAT, FD_IBOX, FD_IBOX_NB,
  FD_IBOX_STAT, FD_WBOX, FD_WBOX_NB, FD_WBOX_STAT,
  FD_SIG1, FD_SIG2, FD_MFC, FD_MSS,
  NUM_MBOX_FDS
}

Functions

spe_context_ptr_t _base_spe_context_create (unsigned int flags, spe_gang_context_ptr_t gctx, spe_context_ptr_t aff_spe)
spe_gang_context_ptr_t _base_spe_gang_context_create (unsigned int flags)
int _base_spe_program_load (spe_context_ptr_t spectx, spe_program_handle_t *program)
void _base_spe_program_load_complete (spe_context_ptr_t spectx)
int _base_spe_emulated_loader_present (void)
int _base_spe_context_destroy (spe_context_ptr_t spectx)
int _base_spe_gang_context_destroy (spe_gang_context_ptr_t gctx)
int _base_spe_context_run (spe_context_ptr_t spe, unsigned int *entry, unsigned int runflags, void *argp, void *envp, spe_stop_info_t *stopinfo)
int _base_spe_image_close (spe_program_handle_t *handle)
spe_program_handle_t_base_spe_image_open (const char *filename)
int _base_spe_mfcio_put (spe_context_ptr_t spectx, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid)
int _base_spe_mfcio_putb (spe_context_ptr_t spectx, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid)
int _base_spe_mfcio_putf (spe_context_ptr_t spectx, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid)
int _base_spe_mfcio_get (spe_context_ptr_t spectx, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid)
int _base_spe_mfcio_getb (spe_context_ptr_t spectx, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid)
int _base_spe_mfcio_getf (spe_context_ptr_t spectx, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid)
int _base_spe_out_mbox_read (spe_context_ptr_t spectx, unsigned int mbox_data[], int count)
int _base_spe_in_mbox_write (spe_context_ptr_t spectx, unsigned int mbox_data[], int count, int behavior_flag)
int _base_spe_in_mbox_status (spe_context_ptr_t spectx)
int _base_spe_out_mbox_status (spe_context_ptr_t spectx)
int _base_spe_out_intr_mbox_status (spe_context_ptr_t spectx)
int _base_spe_out_intr_mbox_read (spe_context_ptr_t spectx, unsigned int mbox_data[], int count, int behavior_flag)
int _base_spe_signal_write (spe_context_ptr_t spectx, unsigned int signal_reg, unsigned int data)
int _base_spe_callback_handler_register (void *handler, unsigned int callnum, unsigned int mode)
int _base_spe_callback_handler_deregister (unsigned int callnum)
void * _base_spe_callback_handler_query (unsigned int callnum)
int _base_spe_stop_reason_get (spe_context_ptr_t spectx)
int _base_spe_mfcio_tag_status_read (spe_context_ptr_t spectx, unsigned int mask, unsigned int behavior, unsigned int *tag_status)
int __base_spe_stop_event_source_get (spe_context_ptr_t spectx)
int __base_spe_stop_event_target_get (spe_context_ptr_t spectx)
int _base_spe_stop_status_get (spe_context_ptr_t spectx)
int __base_spe_event_source_acquire (struct spe_context *spectx, enum fd_name fdesc)
void __base_spe_event_source_release (struct spe_context *spectx, enum fd_name fdesc)
void * _base_spe_ps_area_get (struct spe_context *spectx, enum ps_area area)
int __base_spe_spe_dir_get (struct spe_context *spectx)
void * _base_spe_ls_area_get (struct spe_context *spectx)
int _base_spe_ls_size_get (spe_context_ptr_t spe)
void _base_spe_context_lock (spe_context_ptr_t spe, enum fd_name fd)
void _base_spe_context_unlock (spe_context_ptr_t spe, enum fd_name fd)
int _base_spe_cpu_info_get (int info_requested, int cpu_node)
void __spe_context_update_event (void)
int _base_spe_mssync_start (spe_context_ptr_t spectx)
int _base_spe_mssync_status (spe_context_ptr_t spectx)

Detailed Description

spebase.h contains the public API funtions

Definition in file spebase.h.


Define Documentation

#define __PRINTF (   fmt,
  args... 
)    { fprintf(stderr,fmt , ## args); }

Definition at line 34 of file spebase.h.

#define CNTL_OFFSET   0x04000

Definition at line 124 of file spebase.h.

Referenced by _base_spe_context_create().

#define CNTL_SIZE   0x1000

Definition at line 119 of file spebase.h.

Referenced by _base_spe_context_create().

#define DEBUG_PRINTF (   fmt,
  args... 
)

Definition at line 38 of file spebase.h.

#define LS_SIZE   0x40000

Definition at line 115 of file spebase.h.

#define MFC_OFFSET   0x03000

Definition at line 123 of file spebase.h.

Referenced by _base_spe_context_create().

#define MFC_SIZE   0x1000

Definition at line 117 of file spebase.h.

Referenced by _base_spe_context_create().

#define MSS_SIZE   0x1000

Definition at line 118 of file spebase.h.

Referenced by _base_spe_context_create().

#define MSSYNC_OFFSET   0x00000

Definition at line 122 of file spebase.h.

Referenced by _base_spe_context_create().

#define PSMAP_SIZE   0x20000

Definition at line 116 of file spebase.h.

Referenced by _base_spe_context_create().

#define SIGNAL1_OFFSET   0x14000

Definition at line 125 of file spebase.h.

Referenced by _base_spe_context_create().

#define SIGNAL2_OFFSET   0x1c000

Definition at line 126 of file spebase.h.

Referenced by _base_spe_context_create().

#define SIGNAL_SIZE   0x1000

Definition at line 120 of file spebase.h.

Referenced by _base_spe_context_create().

#define SPE_EMULATE_PARAM_BUFFER   0x3e000

Location of the PPE-assisted library call buffer for emulated isolation contexts.

Definition at line 132 of file spebase.h.

Referenced by _base_spe_handle_library_callback().

#define SPE_PROGRAM_ISO_LOAD_COMPLETE   0x2206

Definition at line 143 of file spebase.h.

Referenced by _base_spe_context_run().

#define SPE_PROGRAM_ISOLATED_STOP   0x2200

Isolated exit codes: 0x220x

Definition at line 142 of file spebase.h.

Referenced by _base_spe_context_run().

#define SPE_PROGRAM_LIBRARY_CALL   0x2100

Definition at line 137 of file spebase.h.

Referenced by _base_spe_context_run().

#define SPE_PROGRAM_NORMAL_END   0x2000

Definition at line 136 of file spebase.h.

Referenced by _base_spe_context_run().


Enumeration Type Documentation

enum fd_name

NOTE: NUM_MBOX_FDS must always be the last element in the enumeration

Enumerator:
FD_MBOX 
FD_MBOX_STAT 
FD_IBOX 
FD_IBOX_NB 
FD_IBOX_STAT 
FD_WBOX 
FD_WBOX_NB 
FD_WBOX_STAT 
FD_SIG1 
FD_SIG2 
FD_MFC 
FD_MSS 
NUM_MBOX_FDS 

Definition at line 42 of file spebase.h.


Function Documentation

int __base_spe_event_source_acquire ( struct spe_context spectx,
enum fd_name  fdesc 
)

__base_spe_event_source_acquire opens a file descriptor to the specified event source

Parameters:
spectxSpecifies the SPE context
fdescSpecifies the event source
void __base_spe_event_source_release ( struct spe_context spectx,
enum fd_name  fdesc 
)

__base_spe_event_source_release releases the file descriptor to the specified event source

Parameters:
spectxSpecifies the SPE context
fdescSpecifies the event source

Definition at line 79 of file accessors.c.

References _base_spe_close_if_open().

{
        _base_spe_close_if_open(spe, fdesc);
}

Here is the call graph for this function:

int __base_spe_spe_dir_get ( struct spe_context spectx)

__base_spe_spe_dir_get return the file descriptor of the SPE directory in spufs

Parameters:
spectxSpecifies the SPE context
int __base_spe_stop_event_source_get ( spe_context_ptr_t  spe)

__base_spe_stop_event_source_get

Parameters:
spectxSpecifies the SPE context

speevent users read from this end

Definition at line 92 of file accessors.c.

References spe_context::base_private, and spe_context_base_priv::ev_pipe.

{
        return spe->base_private->ev_pipe[1];
}
int __base_spe_stop_event_target_get ( spe_context_ptr_t  spe)

__base_spe_stop_event_target_get

Parameters:
spectxSpecifies the SPE context

speevent writes to this end

Definition at line 100 of file accessors.c.

References spe_context::base_private, and spe_context_base_priv::ev_pipe.

{
        return spe->base_private->ev_pipe[0];
}
void __spe_context_update_event ( void  )

__spe_context_update_event internal function for gdb notification.

Referenced by _base_spe_context_destroy(), and _base_spe_program_load_complete().

int _base_spe_callback_handler_deregister ( unsigned int  callnum)

unregister a handler function for the specified number NOTE: unregistering a handler from call zero and one is ignored.

Definition at line 78 of file lib_builtin.c.

References MAX_CALLNUM, and RESERVED.

{
        errno = 0;
        if (callnum > MAX_CALLNUM) {
                errno = EINVAL;
                return -1;
        }
        if (callnum < RESERVED) {
                errno = EACCES;
                return -1;
        }
        if (handlers[callnum] == NULL) {
                errno = ESRCH;
                return -1;
        }

        handlers[callnum] = NULL;
        return 0;
}
void* _base_spe_callback_handler_query ( unsigned int  callnum)

query a handler function for the specified number

Definition at line 98 of file lib_builtin.c.

References MAX_CALLNUM.

{
        errno = 0;

        if (callnum > MAX_CALLNUM) {
                errno = EINVAL;
                return NULL;
        }
        if (handlers[callnum] == NULL) {
                errno = ESRCH;
                return NULL;
        }
        return handlers[callnum];
}
int _base_spe_callback_handler_register ( void *  handler,
unsigned int  callnum,
unsigned int  mode 
)

register a handler function for the specified number NOTE: registering a handler to call zero and one is ignored.

Definition at line 40 of file lib_builtin.c.

References MAX_CALLNUM, RESERVED, SPE_CALLBACK_NEW, and SPE_CALLBACK_UPDATE.

{
        errno = 0;

        if (callnum > MAX_CALLNUM) {
                errno = EINVAL;
                return -1;
        }
        
        switch(mode){
        case SPE_CALLBACK_NEW:
                if (callnum < RESERVED) {
                        errno = EACCES;
                        return -1;
                }
                if (handlers[callnum] != NULL) {
                        errno = EACCES;
                        return -1;
                }
                handlers[callnum] = handler;
                break;

        case SPE_CALLBACK_UPDATE:
                if (handlers[callnum] == NULL) {
                        errno = ESRCH;
                        return -1;
                }
                handlers[callnum] = handler;
                break;
        default:
                errno = EINVAL;
                return -1;
                break;
        }
        return 0;

}
spe_context_ptr_t _base_spe_context_create ( unsigned int  flags,
spe_gang_context_ptr_t  gctx,
spe_context_ptr_t  aff_spe 
)

_base_spe_context_create creates a single SPE context, i.e., the corresponding directory is created in SPUFS either as a subdirectory of a gang or individually (maybe this is best considered a gang of one)

Parameters:
flags
gctxspecify NULL if not belonging to a gang
aff_spespecify NULL to skip affinity information

Definition at line 183 of file create.c.

References _base_spe_emulated_loader_present(), spe_gang_context::base_private, spe_context::base_private, spe_context_base_priv::cntl_mmap_base, CNTL_OFFSET, CNTL_SIZE, DEBUG_PRINTF, spe_context_base_priv::fd_lock, spe_context_base_priv::fd_spe_dir, spe_context_base_priv::flags, spe_gang_context_base_priv::gangname, spe_context_base_priv::loaded_program, LS_SIZE, spe_context_base_priv::mem_mmap_base, spe_context_base_priv::mfc_mmap_base, MFC_OFFSET, MFC_SIZE, MSS_SIZE, spe_context_base_priv::mssync_mmap_base, MSSYNC_OFFSET, NUM_MBOX_FDS, spe_context_base_priv::psmap_mmap_base, PSMAP_SIZE, spe_context_base_priv::signal1_mmap_base, SIGNAL1_OFFSET, spe_context_base_priv::signal2_mmap_base, SIGNAL2_OFFSET, SIGNAL_SIZE, SPE_AFFINITY_MEMORY, SPE_CFG_SIGNOTIFY1_OR, SPE_CFG_SIGNOTIFY2_OR, SPE_EVENTS_ENABLE, spe_context_base_priv::spe_fds_array, SPE_ISOLATE, SPE_ISOLATE_EMULATE, and SPE_MAP_PS.

{
        char pathname[256];
        int i, aff_spe_fd = 0;
        unsigned int spu_createflags = 0;
        struct spe_context *spe = NULL;
        struct spe_context_base_priv *priv;

        /* We need a loader present to run in emulated isolated mode */
        if (flags & SPE_ISOLATE_EMULATE
                        && !_base_spe_emulated_loader_present()) {
                errno = EINVAL;
                return NULL;
        }

        /* Put some sane defaults into the SPE context */
        spe = malloc(sizeof(*spe));
        if (!spe) {
                DEBUG_PRINTF("ERROR: Could not allocate spe context.\n");
                return NULL;
        }
        memset(spe, 0, sizeof(*spe));

        spe->base_private = malloc(sizeof(*spe->base_private));
        if (!spe->base_private) {
                DEBUG_PRINTF("ERROR: Could not allocate "
                                "spe->base_private context.\n");
                free(spe);
                return NULL;
        }

        /* just a convenience variable */
        priv = spe->base_private;

        priv->fd_spe_dir = -1;
        priv->mem_mmap_base = MAP_FAILED;
        priv->psmap_mmap_base = MAP_FAILED;
        priv->mssync_mmap_base = MAP_FAILED;
        priv->mfc_mmap_base = MAP_FAILED;
        priv->cntl_mmap_base = MAP_FAILED;
        priv->signal1_mmap_base = MAP_FAILED;
        priv->signal2_mmap_base = MAP_FAILED;
        priv->loaded_program = NULL;

        for (i = 0; i < NUM_MBOX_FDS; i++) {
                priv->spe_fds_array[i] = -1;
                pthread_mutex_init(&priv->fd_lock[i], NULL);
        }

        /* initialise spu_createflags */
        if (flags & SPE_ISOLATE) {
                flags |= SPE_MAP_PS;
                spu_createflags |= SPU_CREATE_ISOLATE | SPU_CREATE_NOSCHED;
        }

        if (flags & SPE_EVENTS_ENABLE)
                spu_createflags |= SPU_CREATE_EVENTS_ENABLED;

        if (aff_spe)
                spu_createflags |= SPU_CREATE_AFFINITY_SPU;

        if (flags & SPE_AFFINITY_MEMORY)
                spu_createflags |= SPU_CREATE_AFFINITY_MEM;

        /* Make the SPUFS directory for the SPE */
        if (gctx == NULL)
                sprintf(pathname, "/spu/spethread-%i-%lu",
                        getpid(), (unsigned long)spe);
        else
                sprintf(pathname, "/spu/%s/spethread-%i-%lu",
                        gctx->base_private->gangname, getpid(),
                        (unsigned long)spe);

        if (aff_spe)
                aff_spe_fd = aff_spe->base_private->fd_spe_dir;

        priv->fd_spe_dir = spu_create(pathname, spu_createflags,
                        S_IRUSR | S_IWUSR | S_IXUSR, aff_spe_fd);

        if (priv->fd_spe_dir < 0) {
                int errno_saved = errno; /* save errno to prevent being overwritten */
                DEBUG_PRINTF("ERROR: Could not create SPE %s\n", pathname);
                perror("spu_create()");
                free_spe_context(spe);
                /* we mask most errors, but leave ENODEV, etc */
                switch (errno_saved) {
                case ENOTSUP:
                case EEXIST:
                case EINVAL:
                case EBUSY:
                case EPERM:
                case ENODEV:
                        errno = errno_saved; /* restore errno */
                        break;
                default:
                        errno = EFAULT;
                        break;
                }
                return NULL;
        }

        priv->flags = flags;

        /* Map the required areas into process memory */
        priv->mem_mmap_base = mapfileat(priv->fd_spe_dir, "mem", LS_SIZE);
        if (priv->mem_mmap_base == MAP_FAILED) {
                DEBUG_PRINTF("ERROR: Could not map SPE memory.\n");
                free_spe_context(spe);
                errno = ENOMEM;
                return NULL;
        }

        if (flags & SPE_MAP_PS) {
                /* It's possible to map the entire problem state area with
                 * one mmap - try this first */
                priv->psmap_mmap_base =  mapfileat(priv->fd_spe_dir,
                                "psmap", PSMAP_SIZE);

                if (priv->psmap_mmap_base != MAP_FAILED) {
                        priv->mssync_mmap_base =
                                priv->psmap_mmap_base + MSSYNC_OFFSET;
                        priv->mfc_mmap_base =
                                priv->psmap_mmap_base + MFC_OFFSET;
                        priv->cntl_mmap_base =
                                priv->psmap_mmap_base + CNTL_OFFSET;
                        priv->signal1_mmap_base =
                                priv->psmap_mmap_base + SIGNAL1_OFFSET;
                        priv->signal2_mmap_base =
                                priv->psmap_mmap_base + SIGNAL2_OFFSET;

                } else {
                        /* map each region separately */
                        priv->mfc_mmap_base =
                                mapfileat(priv->fd_spe_dir, "mfc", MFC_SIZE);
                        priv->mssync_mmap_base =
                                mapfileat(priv->fd_spe_dir, "mss", MSS_SIZE);
                        priv->cntl_mmap_base =
                                mapfileat(priv->fd_spe_dir, "cntl", CNTL_SIZE);
                        priv->signal1_mmap_base =
                                mapfileat(priv->fd_spe_dir, "signal1",
                                                SIGNAL_SIZE);
                        priv->signal2_mmap_base =
                                mapfileat(priv->fd_spe_dir, "signal2",
                                                SIGNAL_SIZE);

                        if (priv->mfc_mmap_base == MAP_FAILED ||
                                        priv->cntl_mmap_base == MAP_FAILED ||
                                        priv->signal1_mmap_base == MAP_FAILED ||
                                        priv->signal2_mmap_base == MAP_FAILED) {
                                DEBUG_PRINTF("ERROR: Could not map SPE "
                                                "PS memory.\n");
                                free_spe_context(spe);
                                errno = ENOMEM;
                                return NULL;
                        }
                }
        }

        if (flags & SPE_CFG_SIGNOTIFY1_OR) {
                if (setsignotify(priv->fd_spe_dir, "signal1_type")) {
                        DEBUG_PRINTF("ERROR: Could not open SPE "
                                        "signal1_type file.\n");
                        free_spe_context(spe);
                        errno = EFAULT;
                        return NULL;
                }
        }

        if (flags & SPE_CFG_SIGNOTIFY2_OR) {
                if (setsignotify(priv->fd_spe_dir, "signal2_type")) {
                        DEBUG_PRINTF("ERROR: Could not open SPE "
                                        "signal2_type file.\n");
                        free_spe_context(spe);
                        errno = EFAULT;
                        return NULL;
                }
        }

        return spe;
}

Here is the call graph for this function:

int _base_spe_context_destroy ( spe_context_ptr_t  spectx)

_base_spe_context_destroy cleans up what is left when an SPE executable has exited. Closes open file handles and unmaps memory areas.

Parameters:
spectxSpecifies the SPE context

Definition at line 418 of file create.c.

References __spe_context_update_event().

{
        int ret = free_spe_context(spe);

        __spe_context_update_event();

        return ret;
}

Here is the call graph for this function:

void _base_spe_context_lock ( spe_context_ptr_t  spe,
enum fd_name  fd 
)

_base_spe_context_lock locks members of the SPE context

Parameters:
spectxSpecifies the SPE context
fdSpecifies the file

Definition at line 91 of file create.c.

References spe_context::base_private, and spe_context_base_priv::fd_lock.

Referenced by _base_spe_close_if_open(), and _base_spe_open_if_closed().

{
        pthread_mutex_lock(&spe->base_private->fd_lock[fdesc]);
}
int _base_spe_context_run ( spe_context_ptr_t  spe,
unsigned int *  entry,
unsigned int  runflags,
void *  argp,
void *  envp,
spe_stop_info_t stopinfo 
)

_base_spe_context_run starts execution of an SPE context with a loaded image

Parameters:
spectxSpecifies the SPE context
entryentry point for the SPE programm. If set to 0, entry point is determined by the ELF loader.
runflagsvalid values are:
SPE_RUN_USER_REGS Specifies that the SPE setup registers r3, r4, and r5 are initialized with the 48 bytes pointed to by argp.
SPE_NO_CALLBACKS do not use built in library functions.
argpAn (optional) pointer to application specific data, and is passed as the second parameter to the SPE program.
envpAn (optional) pointer to environment specific data, and is passed as the third parameter to the SPE program.

Definition at line 99 of file run.c.

References __spe_current_active_context, _base_spe_handle_library_callback(), _base_spe_program_load_complete(), spe_context::base_private, DEBUG_PRINTF, spe_context_base_priv::emulated_entry, spe_context_base_priv::entry, spe_context_base_priv::fd_spe_dir, spe_context_base_priv::flags, LS_SIZE, spe_context_base_priv::mem_mmap_base, spe_context_info::npc, spe_context_info::prev, spe_stop_info::result, spe_stop_info::spe_callback_error, SPE_CALLBACK_ERROR, SPE_DEFAULT_ENTRY, SPE_EVENTS_ENABLE, SPE_EXIT, spe_stop_info::spe_exit_code, spe_context_info::spe_id, SPE_ISOLATE, SPE_ISOLATE_EMULATE, spe_stop_info::spe_isolation_error, SPE_ISOLATION_ERROR, SPE_NO_CALLBACKS, SPE_PROGRAM_ISO_LOAD_COMPLETE, SPE_PROGRAM_ISOLATED_STOP, SPE_PROGRAM_LIBRARY_CALL, SPE_PROGRAM_NORMAL_END, SPE_RUN_USER_REGS, spe_stop_info::spe_runtime_error, SPE_RUNTIME_ERROR, spe_stop_info::spe_runtime_exception, SPE_RUNTIME_EXCEPTION, spe_stop_info::spe_runtime_fatal, SPE_RUNTIME_FATAL, spe_stop_info::spe_signal_code, SPE_SPU_HALT, SPE_SPU_INVALID_CHANNEL, SPE_SPU_INVALID_INSTR, SPE_SPU_STOPPED_BY_STOP, SPE_SPU_WAITING_ON_CHANNEL, SPE_STOP_AND_SIGNAL, spe_stop_info::spu_status, spe_context_info::status, spe_stop_info::stop_reason, addr64::ui, and addr64::ull.

Referenced by _event_spe_context_run().

{
        int retval = 0, run_rc;
        unsigned int run_status, tmp_entry;
        spe_stop_info_t stopinfo_buf;
        struct spe_context_info this_context_info __attribute__((cleanup(cleanupspeinfo)));

        /* If the caller hasn't set a stopinfo buffer, provide a buffer on the
         * stack instead. */
        if (!stopinfo)
                stopinfo = &stopinfo_buf;


        /* In emulated isolated mode, the npc will always return as zero.
         * use our private entry point instead */
        if (spe->base_private->flags & SPE_ISOLATE_EMULATE)
                tmp_entry = spe->base_private->emulated_entry;

        else if (*entry == SPE_DEFAULT_ENTRY)
                tmp_entry = spe->base_private->entry;
        else 
                tmp_entry = *entry;

        /* If we're starting the SPE binary from its original entry point,
         * setup the arguments to main() */
        if (tmp_entry == spe->base_private->entry &&
                        !(spe->base_private->flags &
                                (SPE_ISOLATE | SPE_ISOLATE_EMULATE))) {

                addr64 argp64, envp64, tid64, ls64;
                unsigned int regs[128][4];

                /* setup parameters */
                argp64.ull = (uint64_t)(unsigned long)argp;
                envp64.ull = (uint64_t)(unsigned long)envp;
                tid64.ull = (uint64_t)(unsigned long)spe;

                /* make sure the register values are 0 */
                memset(regs, 0, sizeof(regs));

                /* set sensible values for stack_ptr and stack_size */
                regs[1][0] = (unsigned int) LS_SIZE - 16;       /* stack_ptr */
                regs[2][0] = 0;                                                         /* stack_size ( 0 = default ) */

                if (runflags & SPE_RUN_USER_REGS) {
                        /* When SPE_USER_REGS is set, argp points to an array
                         * of 3x128b registers to be passed directly to the SPE
                         * program.
                         */
                        memcpy(regs[3], argp, sizeof(unsigned int) * 12);
                } else {
                        regs[3][0] = tid64.ui[0];
                        regs[3][1] = tid64.ui[1];

                        regs[4][0] = argp64.ui[0];
                        regs[4][1] = argp64.ui[1];

                        regs[5][0] = envp64.ui[0];
                        regs[5][1] = envp64.ui[1];
                }
                
                /* Store the LS base address in R6 */
                ls64.ull = (uint64_t)(unsigned long)spe->base_private->mem_mmap_base;
                regs[6][0] = ls64.ui[0];
                regs[6][1] = ls64.ui[1];

                if (set_regs(spe, regs))
                        return -1;
        }

        /*Leave a trail of breadcrumbs for the debugger to follow */
        if (!__spe_current_active_context) {
                __spe_current_active_context = &this_context_info;
                if (!__spe_current_active_context)
                        return -1;
                __spe_current_active_context->prev = NULL;
        } else {
                struct spe_context_info *newinfo;
                newinfo = &this_context_info;
                if (!newinfo)
                        return -1;
                newinfo->prev = __spe_current_active_context;
                __spe_current_active_context = newinfo;
        }
        /*remember the ls-addr*/
        __spe_current_active_context->spe_id = spe->base_private->fd_spe_dir;

do_run:
        /*Remember the npc value*/
        __spe_current_active_context->npc = tmp_entry;

        /* run SPE context */
        run_rc = spu_run(spe->base_private->fd_spe_dir,
                        &tmp_entry, &run_status);

        /*Remember the npc value*/
        __spe_current_active_context->npc = tmp_entry;
        __spe_current_active_context->status = run_status;

        DEBUG_PRINTF("spu_run returned run_rc=0x%08x, entry=0x%04x, "
                        "ext_status=0x%04x.\n", run_rc, tmp_entry, run_status);

        /* set up return values and stopinfo according to spu_run exit
         * conditions. This is overwritten on error.
         */
        stopinfo->spu_status = run_rc;

        if (spe->base_private->flags & SPE_ISOLATE_EMULATE) {
                /* save the entry point, and pretend that the npc is zero */
                spe->base_private->emulated_entry = tmp_entry;
                *entry = 0;
        } else {
                *entry = tmp_entry;
        }

        /* Return with stopinfo set on syscall error paths */
        if (run_rc == -1) {
                DEBUG_PRINTF("spu_run returned error %d, errno=%d\n",
                                run_rc, errno);
                stopinfo->stop_reason = SPE_RUNTIME_FATAL;
                stopinfo->result.spe_runtime_fatal = errno;
                retval = -1;

                /* For isolated contexts, pass EPERM up to the
                 * caller.
                 */
                if (!(spe->base_private->flags & SPE_ISOLATE
                                && errno == EPERM))
                        errno = EFAULT;

        } else if (run_rc & SPE_SPU_INVALID_INSTR) {
                DEBUG_PRINTF("SPU has tried to execute an invalid "
                                "instruction. %d\n", run_rc);
                stopinfo->stop_reason = SPE_RUNTIME_ERROR;
                stopinfo->result.spe_runtime_error = SPE_SPU_INVALID_INSTR;
                errno = EFAULT;
                retval = -1;

        } else if ((spe->base_private->flags & SPE_EVENTS_ENABLE) && run_status) {
                /* Report asynchronous error if return val are set and
                 * SPU events are enabled.
                 */
                stopinfo->stop_reason = SPE_RUNTIME_EXCEPTION;
                stopinfo->result.spe_runtime_exception = run_status;
                stopinfo->spu_status = -1;
                errno = EIO;
                retval = -1;

        } else if (run_rc & SPE_SPU_STOPPED_BY_STOP) {
                /* Stop & signals are broken down into three groups
                 *  1. SPE library call
                 *  2. SPE user defined stop & signal
                 *  3. SPE program end.
                 *
                 * These groups are signified by the 14-bit stop code:
                 */
                int stopcode = (run_rc >> 16) & 0x3fff;

                /* Check if this is a library callback, and callbacks are
                 * allowed (ie, running without SPE_NO_CALLBACKS)
                 */
                if ((stopcode & 0xff00) == SPE_PROGRAM_LIBRARY_CALL
                                && !(runflags & SPE_NO_CALLBACKS)) {

                        int callback_rc, callback_number = stopcode & 0xff;

                        /* execute library callback */
                        DEBUG_PRINTF("SPE library call: %d\n", callback_number);
                        callback_rc = _base_spe_handle_library_callback(spe,
                                                                        callback_number, *entry);

                        if (callback_rc) {
                                /* library callback failed; set errno and
                                 * return immediately */
                                DEBUG_PRINTF("SPE library call failed: %d\n",
                                                callback_rc);
                                stopinfo->stop_reason = SPE_CALLBACK_ERROR;
                                stopinfo->result.spe_callback_error =
                                        callback_rc;
                                errno = EFAULT;
                                retval = -1;
                        } else {
                                /* successful library callback - restart the SPE
                                 * program at the next instruction */
                                tmp_entry += 4;
                                goto do_run;
                        }

                } else if ((stopcode & 0xff00) == SPE_PROGRAM_NORMAL_END) {
                        /* The SPE program has exited by exit(X) */
                        stopinfo->stop_reason = SPE_EXIT;
                        stopinfo->result.spe_exit_code = stopcode & 0xff;

                        if (spe->base_private->flags & SPE_ISOLATE) {
                                /* Issue an isolated exit, and re-run the SPE.
                                 * We should see a return value without the
                                 * 0x80 bit set. */
                                if (!issue_isolated_exit(spe))
                                        goto do_run;
                                retval = -1;
                        }

                } else if ((stopcode & 0xfff0) == SPE_PROGRAM_ISOLATED_STOP) {

                        /* 0x2206: isolated app has been loaded by loader;
                         * provide a hook for the debugger to catch this,
                         * and restart
                         */
                        if (stopcode == SPE_PROGRAM_ISO_LOAD_COMPLETE) {
                                _base_spe_program_load_complete(spe);
                                goto do_run;
                        } else {
                                stopinfo->stop_reason = SPE_ISOLATION_ERROR;
                                stopinfo->result.spe_isolation_error =
                                        stopcode & 0xf;
                        }

                } else if (spe->base_private->flags & SPE_ISOLATE &&
                                !(run_rc & 0x80)) {
                        /* We've successfully exited isolated mode */
                        retval = 0;

                } else {
                        /* User defined stop & signal, including
                         * callbacks when disabled */
                        stopinfo->stop_reason = SPE_STOP_AND_SIGNAL;
                        stopinfo->result.spe_signal_code = stopcode;
                        retval = stopcode;
                }

        } else if (run_rc & SPE_SPU_HALT) {
                DEBUG_PRINTF("SPU was stopped by halt. %d\n", run_rc);
                stopinfo->stop_reason = SPE_RUNTIME_ERROR;
                stopinfo->result.spe_runtime_error = SPE_SPU_HALT;
                errno = EFAULT;
                retval = -1;

        } else if (run_rc & SPE_SPU_WAITING_ON_CHANNEL) {
                DEBUG_PRINTF("SPU is waiting on channel. %d\n", run_rc);
                stopinfo->stop_reason = SPE_RUNTIME_EXCEPTION;
                stopinfo->result.spe_runtime_exception = run_status;
                stopinfo->spu_status = -1;
                errno = EIO;
                retval = -1;

        } else if (run_rc & SPE_SPU_INVALID_CHANNEL) {
                DEBUG_PRINTF("SPU has tried to access an invalid "
                                "channel. %d\n", run_rc);
                stopinfo->stop_reason = SPE_RUNTIME_ERROR;
                stopinfo->result.spe_runtime_error = SPE_SPU_INVALID_CHANNEL;
                errno = EFAULT;
                retval = -1;

        } else {
                DEBUG_PRINTF("spu_run returned invalid data: 0x%04x\n", run_rc);
                stopinfo->stop_reason = SPE_RUNTIME_FATAL;
                stopinfo->result.spe_runtime_fatal = -1;
                stopinfo->spu_status = -1;
                errno = EFAULT;
                retval = -1;

        }

        freespeinfo();
        return retval;
}

Here is the call graph for this function:

void _base_spe_context_unlock ( spe_context_ptr_t  spe,
enum fd_name  fd 
)

_base_spe_context_unlock unlocks members of the SPE context

Parameters:
spectxSpecifies the SPE context
fdSpecifies the file

Definition at line 96 of file create.c.

References spe_context::base_private, and spe_context_base_priv::fd_lock.

Referenced by _base_spe_close_if_open(), and _base_spe_open_if_closed().

{
        pthread_mutex_unlock(&spe->base_private->fd_lock[fdesc]);
}
int _base_spe_cpu_info_get ( int  info_requested,
int  cpu_node 
)

_base_spe_info_get

Definition at line 105 of file info.c.

References _base_spe_count_physical_cpus(), _base_spe_count_physical_spes(), _base_spe_count_usable_spes(), SPE_COUNT_PHYSICAL_CPU_NODES, SPE_COUNT_PHYSICAL_SPES, and SPE_COUNT_USABLE_SPES.

                                                             {
        int ret = 0;
        errno = 0;
        
        switch (info_requested) {
        case  SPE_COUNT_PHYSICAL_CPU_NODES:
                ret = _base_spe_count_physical_cpus(cpu_node);
                break;
        case SPE_COUNT_PHYSICAL_SPES:
                ret = _base_spe_count_physical_spes(cpu_node);
                break;
        case SPE_COUNT_USABLE_SPES:
                ret = _base_spe_count_usable_spes(cpu_node);
                break;
        default:
                errno = EINVAL;
                ret = -1;
        }
        return ret;
}

Here is the call graph for this function:

int _base_spe_emulated_loader_present ( void  )

Check if the emulated loader is present in the filesystem

Returns:
Non-zero if the loader is available, otherwise zero.

Definition at line 159 of file load.c.

References _base_spe_verify_spe_elf_image().

Referenced by _base_spe_context_create().

{
        spe_program_handle_t *loader = emulated_loader_program();

        if (!loader)
                return 0;

        return !_base_spe_verify_spe_elf_image(loader);
}

Here is the call graph for this function:

spe_gang_context_ptr_t _base_spe_gang_context_create ( unsigned int  flags)

creates the directory in SPUFS that will contain all SPEs that are considered a gang Note: I would like to generalize this to a "group" or "set" Additional attributes maintained at the group level should be used to define scheduling constraints such "temporal" (e.g., scheduled all at the same time, i.e., a gang) "topology" (e.g., "closeness" of SPEs for optimal communication)

Definition at line 376 of file create.c.

References spe_gang_context::base_private, DEBUG_PRINTF, and spe_gang_context_base_priv::gangname.

{
        char pathname[256];
        struct spe_gang_context_base_priv *pgctx = NULL;
        struct spe_gang_context *gctx = NULL;

        gctx = malloc(sizeof(*gctx));
        if (!gctx) {
                DEBUG_PRINTF("ERROR: Could not allocate spe context.\n");
                return NULL;
        }
        memset(gctx, 0, sizeof(*gctx));

        pgctx = malloc(sizeof(*pgctx));
        if (!pgctx) {
                DEBUG_PRINTF("ERROR: Could not allocate spe context.\n");
                free(gctx);
                return NULL;
        }
        memset(pgctx, 0, sizeof(*pgctx));

        gctx->base_private = pgctx;

        sprintf(gctx->base_private->gangname, "gang-%i-%lu", getpid(),
                        (unsigned long)gctx);
        sprintf(pathname, "/spu/%s", gctx->base_private->gangname);

        gctx->base_private->fd_gang_dir = spu_create(pathname, SPU_CREATE_GANG,
                                S_IRUSR | S_IWUSR | S_IXUSR);

        if (gctx->base_private->fd_gang_dir < 0) {
                DEBUG_PRINTF("ERROR: Could not create Gang %s\n", pathname);
                free_spe_gang_context(gctx);
                errno = EFAULT;
                return NULL;
        }

        gctx->base_private->flags = flags;

        return gctx;
}
int _base_spe_gang_context_destroy ( spe_gang_context_ptr_t  gctx)

_base_spe_gang_context_destroy destroys a gang context and frees associated resources

Parameters:
gctxSpecifies the SPE gang context

Definition at line 427 of file create.c.

{
        return free_spe_gang_context(gctx);
}
int _base_spe_image_close ( spe_program_handle_t handle)

_base_spe_image_close unmaps an SPE ELF object that was previously mapped using spe_open_image.

Parameters:
handlehandle to open file
Return values:
0On success, spe_close_image returns 0.
-1On failure, -1 is returned and errno is set appropriately.
Possible values for errno:
EINVAL From spe_close_image, this indicates that the file, specified by filename, was not previously mapped by a call to spe_open_image.

Definition at line 96 of file image.c.

References spe_program_handle::elf_image, image_handle::map_size, image_handle::speh, and spe_program_handle::toe_shadow.

{
        int ret = 0;
        struct image_handle *ih;

        if (!handle) {
                errno = EINVAL;
                return -1;
        }
        
        ih = (struct image_handle *)handle;

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

        if (ih->speh.toe_shadow)
                free(ih->speh.toe_shadow);

        ret = munmap(ih->speh.elf_image, ih->map_size );
        free(handle);

        return ret;
}
spe_program_handle_t* _base_spe_image_open ( const char *  filename)

_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 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 loaded. These libraries are then linked with the associated PPE code to provide a direct symbol reference to the SPE ELF object. The symbols in this scheme are equivalent to the address returned from the spe_open_image function. SPE ELF objects loaded using this function are not shared with other processes, but SPE ELF objects loaded using the other scheme, mentioned above, can be shared if so desired.

Parameters:
filenameSpecifies the filename of an SPE ELF executable to be loaded and mapped into system memory.
Returns:
On success, spe_open_image returns the address at which the specified SPE ELF object has been mapped. On failure, NULL is returned and errno is set appropriately.
Possible values for errno include:
EACCES The calling process does not have permission to access the specified file.
EFAULT The filename 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 open(2), fstat(2), mmap(2), munmap(2), or close(2) system calls which may be utilized by the spe_open_image or spe_close_image functions.

See also:
spe_create_thread

Definition at line 37 of file image.c.

References _base_spe_toe_ear(), _base_spe_verify_spe_elf_image(), spe_program_handle::elf_image, spe_program_handle::handle_size, image_handle::map_size, image_handle::speh, and spe_program_handle::toe_shadow.

{
        /* allocate an extra integer in the spe handle to keep the mapped size information */
        struct image_handle *ret;
        int binfd = -1, f_stat;
        struct stat statbuf;
        size_t ps = getpagesize ();

        ret = malloc(sizeof(struct image_handle));
        if (!ret)
                return NULL;

        ret->speh.handle_size = sizeof(spe_program_handle_t);
        ret->speh.toe_shadow = NULL;

        binfd = open(filename, O_RDONLY);
        if (binfd < 0)
                goto ret_err;

        f_stat = fstat(binfd, &statbuf);
        if (f_stat < 0)
                goto ret_err;

        /* Sanity: is it executable ?
         */
        if(!(statbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
                errno=EACCES;
                goto ret_err;
        }
        
        /* now store the size at the extra allocated space */
        ret->map_size = (statbuf.st_size + ps - 1) & ~(ps - 1);

        ret->speh.elf_image = mmap(NULL, ret->map_size,
                                                        PROT_WRITE | PROT_READ,
                                                        MAP_PRIVATE, binfd, 0);
        if (ret->speh.elf_image == MAP_FAILED)
                goto ret_err;

        /*Verify that this is a valid SPE ELF object*/
        if((_base_spe_verify_spe_elf_image((spe_program_handle_t *)ret)))
                goto ret_err;

        if (_base_spe_toe_ear(&ret->speh))
                goto ret_err;

        /* ok */
        close(binfd);
        return (spe_program_handle_t *)ret;

        /* err & cleanup */
ret_err:
        if (binfd >= 0)
                close(binfd);

        free(ret);
        return NULL;
}

Here is the call graph for this function:

int _base_spe_in_mbox_status ( spe_context_ptr_t  spectx)

The _base_spe_in_mbox_status function fetches the status of the SPU inbound mailbox for the SPE thread specified by the speid parameter. A 0 value is return if the mailbox is full. A non-zero value specifies the number of available (32-bit) mailbox entries.

Parameters:
spectxSpecifies the SPE context whose mailbox status is to be read.
Returns:
On success, returns the current status of the mailbox, respectively. On failure, -1 is returned.
See also:
spe_read_out_mbox, spe_write_in_mbox, read (2)

Definition at line 202 of file mbox.c.

References _base_spe_open_if_closed(), spe_context::base_private, spe_context_base_priv::cntl_mmap_base, FD_WBOX_STAT, spe_context_base_priv::flags, SPE_MAP_PS, and spe_spu_control_area::SPU_Mbox_Stat.

{
        int rc, ret;
        volatile struct spe_spu_control_area *cntl_area =
                spectx->base_private->cntl_mmap_base;

        if (spectx->base_private->flags & SPE_MAP_PS) {
                ret = (cntl_area->SPU_Mbox_Stat >> 8) & 0xFF;
        } else {
                rc = read(_base_spe_open_if_closed(spectx,FD_WBOX_STAT, 0), &ret, 4);
                if (rc != 4)
                        ret = -1;
        }

        return ret;
        
}

Here is the call graph for this function:

int _base_spe_in_mbox_write ( spe_context_ptr_t  spectx,
unsigned int  mbox_data[],
int  count,
int  behavior_flag 
)

The _base_spe_in_mbox_write function writes mbox_data to the SPE inbound mailbox for the SPE thread speid.

If the behavior flag indicates ALL_BLOCKING the call will try to write exactly count mailbox entries and block until the write request is satisfied, i.e., exactly count mailbox entries have been written. If the behavior flag indicates ANY_BLOCKING the call will try to write up to count mailbox entries, and block until the write request is satisfied, i.e., at least 1 mailbox entry has been written. If the behavior flag indicates ANY_NON_BLOCKING the call will not block until the write request is satisfied, but instead write whatever is immediately possible and return the number of mailbox entries written. spe_stat_in_mbox can be called to ensure that data can be written prior to calling the function.

Parameters:
spectxSpecifies the SPE thread whose outbound mailbox is to be read.
mbox_data
count
behavior_flagALL_BLOCKING
ANY_BLOCKING
ANY_NON_BLOCKING
Return values:
>=0the number of 32-bit mailbox messages written
-1error condition and errno is set
Possible values for errno:
EINVAL spectx is invalid
Exxxx what else do we need here??
void* _base_spe_ls_area_get ( struct spe_context spectx)

_base_spe_ls_area_get returns a pointer to the start of the memory mapped local store area

Parameters:
spectxSpecifies the SPE context
int _base_spe_ls_size_get ( spe_context_ptr_t  spe)

_base_spe_ls_size_get returns the size of the local store area

Parameters:
spectxSpecifies the SPE context

Definition at line 105 of file accessors.c.

References LS_SIZE.

{
        return LS_SIZE;
}
int _base_spe_mfcio_get ( spe_context_ptr_t  spectx,
unsigned int  ls,
void *  ea,
unsigned int  size,
unsigned int  tag,
unsigned int  tid,
unsigned int  rid 
)

The _base_spe_mfcio_get function places a get DMA command on the proxy command queue of the SPE thread specified by speid. The get command transfers size bytes of data starting at the effective address specified by ea to the local store address specified by ls. The DMA is identified by the tag id specified by tag and performed according to the transfer class and replacement class specified by tid and rid respectively.

Parameters:
spectxSpecifies the SPE context
lsSpecifies the starting local store destination address.
eaSpecifies the starting effective address source address.
sizeSpecifies the size, in bytes, to be transferred.
tagSpecifies the tag id used to identify the DMA command.
tidSpecifies the transfer class identifier of the DMA command.
ridSpecifies the replacement class identifier of the DMA command.
Returns:
On success, return 0. On failure, -1 is returned.

Definition at line 160 of file dma.c.

References MFC_CMD_GET.

{
        return spe_do_mfc_get(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_GET);
}
int _base_spe_mfcio_getb ( spe_context_ptr_t  spectx,
unsigned int  ls,
void *  ea,
unsigned int  size,
unsigned int  tag,
unsigned int  tid,
unsigned int  rid 
)

The _base_spe_mfcio_getb function is identical to _base_spe_mfcio_get except that it places a getb (get with barrier) DMA command on the proxy command queue. The barrier form ensures that this command and all sequence commands with the same tag identifier as this command are locally ordered with respect to all previously issued commands with the same tag group and command queue.

Parameters:
spectxSpecifies the SPE context
lsSpecifies the starting local store destination address.
eaSpecifies the starting effective address source address.
sizeSpecifies the size, in bytes, to be transferred.
tagSpecifies the tag id used to identify the DMA command.
tidSpecifies the transfer class identifier of the DMA command.
ridSpecifies the replacement class identifier of the DMA command.
Returns:
On success, return 0. On failure, -1 is returned.

Definition at line 171 of file dma.c.

References MFC_CMD_GETB.

{
        return spe_do_mfc_get(spectx, ls, ea, size, tag, rid, rid, MFC_CMD_GETB);
}
int _base_spe_mfcio_getf ( spe_context_ptr_t  spectx,
unsigned int  ls,
void *  ea,
unsigned int  size,
unsigned int  tag,
unsigned int  tid,
unsigned int  rid 
)

The _base_spe_mfcio_getf function is identical to _base_spe_mfcio_get except that it places a getf (get with fence) DMA command on the proxy command queue. The fence form ensure that this command is locally ordered with respect to all previously issued commands with the same tag group and command queue.

Parameters:
spectxSpecifies the SPE context
lsSpecifies the starting local store destination address.
eaSpecifies the starting effective address source address.
sizeSpecifies the size, in bytes, to be transferred.
tagSpecifies the tag id used to identify the DMA command.
tidSpecifies the transfer class identifier of the DMA command.
ridSpecifies the replacement class identifier of the DMA command.
Returns:
On success, return 0. On failure, -1 is returned.

Definition at line 182 of file dma.c.

References MFC_CMD_GETF.

{
        return spe_do_mfc_get(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_GETF);
}
int _base_spe_mfcio_put ( spe_context_ptr_t  spectx,
unsigned int  ls,
void *  ea,
unsigned int  size,
unsigned int  tag,
unsigned int  tid,
unsigned int  rid 
)

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 address specified by ea. The DMA is identified by the tag id specified by tag and performed according transfer class and replacement class specified by tid and rid respectively.

Parameters:
spectxSpecifies the SPE context
lsSpecifies the starting local store destination address.
eaSpecifies the starting effective address source address.
sizeSpecifies the size, in bytes, to be transferred.
tagSpecifies the tag id used to identify the DMA command.
tidSpecifies the transfer class identifier of the DMA command.
ridSpecifies the replacement class identifier of the DMA command.
Returns:
On success, return 0. On failure, -1 is returned.

Definition at line 126 of file dma.c.

References MFC_CMD_PUT.

{
        return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUT);
}
int _base_spe_mfcio_putb ( spe_context_ptr_t  spectx,
unsigned int  ls,
void *  ea,
unsigned int  size,
unsigned int  tag,
unsigned int  tid,
unsigned int  rid 
)

The _base_spe_mfcio_putb function is identical to _base_spe_mfcio_put except that it places a putb (put with barrier) DMA command on the proxy command queue. The barrier form ensures that this command and all sequence commands with the same tag identifier as this command are locally ordered with respect to all previously i ssued commands with the same tag group and command queue.

Parameters:
spectxSpecifies the SPE context
lsSpecifies the starting local store destination address.
eaSpecifies the starting effective address source address.
sizeSpecifies the size, in bytes, to be transferred.
tagSpecifies the tag id used to identify the DMA command.
tidSpecifies the transfer class identifier of the DMA command.
ridSpecifies the replacement class identifier of the DMA command.
Returns:
On success, return 0. On failure, -1 is returned.

Definition at line 137 of file dma.c.

References MFC_CMD_PUTB.

{
        return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUTB);
}
int _base_spe_mfcio_putf ( spe_context_ptr_t  spectx,
unsigned int  ls,
void *  ea,
unsigned int  size,
unsigned int  tag,
unsigned int  tid,
unsigned int  rid 
)

The _base_spe_mfcio_putf function is identical to _base_spe_mfcio_put except that it places a putf (put with fence) DMA command on the proxy command queue. The fence form ensures that this command is locally ordered with respect to all previously issued commands with the same tag group and command queue.

Parameters:
spectxSpecifies the SPE context
lsSpecifies the starting local store destination address.
eaSpecifies the starting effective address source address.
sizeSpecifies the size, in bytes, to be transferred.
tagSpecifies the tag id used to identify the DMA command.
tidSpecifies the transfer class identifier of the DMA command.
ridSpecifies the replacement class identifier of the DMA command.
Returns:
On success, return 0. On failure, -1 is returned.

Definition at line 148 of file dma.c.

References MFC_CMD_PUTF.

{
        return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUTF);
}
int _base_spe_mfcio_tag_status_read ( spe_context_ptr_t  spectx,
unsigned int  mask,
unsigned int  behavior,
unsigned int *  tag_status 
)

_base_spe_mfcio_tag_status_read

No Idea

Definition at line 307 of file dma.c.

References spe_context_base_priv::active_tagmask, spe_context::base_private, spe_context_base_priv::flags, SPE_MAP_PS, SPE_TAG_ALL, SPE_TAG_ANY, and SPE_TAG_IMMEDIATE.

{
        if ( mask != 0 ) {
                if (!(spectx->base_private->flags & SPE_MAP_PS)) 
                        mask = 0;
        } else {
                if ((spectx->base_private->flags & SPE_MAP_PS))
                        mask = spectx->base_private->active_tagmask;
        }

        if (!tag_status) {
                errno = EINVAL;
                return -1;
        }

        switch (behavior) {
        case SPE_TAG_ALL:
                return spe_mfcio_tag_status_read_all(spectx, mask, tag_status);
        case SPE_TAG_ANY:
                return spe_mfcio_tag_status_read_any(spectx, mask, tag_status);
        case SPE_TAG_IMMEDIATE:
                return spe_mfcio_tag_status_read_immediate(spectx, mask, tag_status);
        default:
                errno = EINVAL;
                return -1;
        }
}
int _base_spe_mssync_start ( spe_context_ptr_t  spectx)

_base_spe_mssync_start starts Multisource Synchronisation

Parameters:
spectxSpecifies the SPE context

Definition at line 335 of file dma.c.

References _base_spe_open_if_closed(), spe_context::base_private, FD_MSS, spe_context_base_priv::flags, spe_mssync_area::MFC_MSSync, spe_context_base_priv::mssync_mmap_base, and SPE_MAP_PS.

{
        int ret, fd;
        unsigned int data = 1; /* Any value can be written here */

        volatile struct spe_mssync_area *mss_area = 
                spectx->base_private->mssync_mmap_base;

        if (spectx->base_private->flags & SPE_MAP_PS) {
                mss_area->MFC_MSSync = data; 
                return 0;
        } else {
                fd = _base_spe_open_if_closed(spectx, FD_MSS, 0);
                if (fd != -1) {
                        ret = write(fd, &data, sizeof (data));
                        if ((ret < 0) && (errno != EIO)) {
                                perror("spe_mssync_start: internal error");
                        }
                        return ret < 0 ? -1 : 0;
                } else 
                        return -1;
        }
}

Here is the call graph for this function:

int _base_spe_mssync_status ( spe_context_ptr_t  spectx)

_base_spe_mssync_status retrieves status of Multisource Synchronisation

Parameters:
spectxSpecifies the SPE context

Definition at line 359 of file dma.c.

References _base_spe_open_if_closed(), spe_context::base_private, FD_MSS, spe_context_base_priv::flags, spe_mssync_area::MFC_MSSync, spe_context_base_priv::mssync_mmap_base, and SPE_MAP_PS.

{
        int ret, fd;
        unsigned int data;

        volatile struct spe_mssync_area *mss_area = 
                spectx->base_private->mssync_mmap_base;

        if (spectx->base_private->flags & SPE_MAP_PS) {
                return  mss_area->MFC_MSSync;
        } else {
                fd = _base_spe_open_if_closed(spectx, FD_MSS, 0);
                if (fd != -1) {
                        ret = read(fd, &data, sizeof (data));
                        if ((ret < 0) && (errno != EIO)) {
                                perror("spe_mssync_start: internal error");
                        }
                        return ret < 0 ? -1 : data;
                } else 
                        return -1;
        }
}

Here is the call graph for this function:

int _base_spe_out_intr_mbox_read ( spe_context_ptr_t  spectx,
unsigned int  mbox_data[],
int  count,
int  behavior_flag 
)

The _base_spe_out_intr_mbox_read function reads the contents of the SPE outbound interrupting mailbox for the SPE context.

Definition at line 255 of file mbox.c.

References _base_spe_open_if_closed(), FD_IBOX, FD_IBOX_NB, SPE_MBOX_ALL_BLOCKING, SPE_MBOX_ANY_BLOCKING, and SPE_MBOX_ANY_NONBLOCKING.

{
        int rc;
        int total;

        if (mbox_data == NULL || count < 1){
                errno = EINVAL;
                return -1;
        }

        switch (behavior_flag) {
        case SPE_MBOX_ALL_BLOCKING: // read all, even if blocking
                total = rc = 0;
                while (total < 4*count) {
                        rc = read(_base_spe_open_if_closed(spectx,FD_IBOX, 0),
                                  (char *)mbox_data + total, 4*count - total);
                        if (rc == -1) {
                                break;
                        }
                        total += rc;
                }
                break;

        case  SPE_MBOX_ANY_BLOCKING: // read at least one, even if blocking
                total = rc = read(_base_spe_open_if_closed(spectx,FD_IBOX, 0), mbox_data, 4*count);
                break;

        case  SPE_MBOX_ANY_NONBLOCKING: // only reaad, if non blocking
                rc = read(_base_spe_open_if_closed(spectx,FD_IBOX_NB, 0), mbox_data, 4*count);
                if (rc == -1 && errno == EAGAIN) {
                        rc = 0;
                        errno = 0;
                }
                total = rc;
                break;

        default:
                errno = EINVAL;
                return -1;
        }

        if (rc == -1) {
                errno = EIO;
                return -1;
        }

        return rc / 4;
}

Here is the call graph for this function:

int _base_spe_out_intr_mbox_status ( spe_context_ptr_t  spectx)

The _base_spe_out_intr_mbox_status function fetches the status of the SPU outbound interrupt mailbox for the SPE thread specified by the speid parameter. A 0 value is return if the mailbox is empty. A non-zero value specifies the number of 32-bit unread mailbox entries.

Parameters:
spectxSpecifies the SPE context whose mailbox status is to be read.
Returns:
On success, returns the current status of the mailbox, respectively. On failure, -1 is returned.
See also:
spe_read_out_mbox, spe_write_in_mbox, read (2)

Definition at line 238 of file mbox.c.

References _base_spe_open_if_closed(), spe_context::base_private, spe_context_base_priv::cntl_mmap_base, FD_IBOX_STAT, spe_context_base_priv::flags, SPE_MAP_PS, and spe_spu_control_area::SPU_Mbox_Stat.

{
        int rc, ret;
        volatile struct spe_spu_control_area *cntl_area =
                spectx->base_private->cntl_mmap_base;

        if (spectx->base_private->flags & SPE_MAP_PS) {
                ret = (cntl_area->SPU_Mbox_Stat >> 16) & 0xFF;
        } else {
                rc = read(_base_spe_open_if_closed(spectx,FD_IBOX_STAT, 0), &ret, 4);
                if (rc != 4)
                        ret = -1;

        }
        return ret;
}

Here is the call graph for this function:

int _base_spe_out_mbox_read ( spe_context_ptr_t  spectx,
unsigned int  mbox_data[],
int  count 
)

The _base_spe_out_mbox_read function reads the contents of the SPE outbound interrupting mailbox for the SPE thread speid.

The call will not block until the read request is satisfied, but instead return up to count currently available mailbox entries.

spe_stat_out_intr_mbox can be called to ensure that data is available prior to reading the outbound interrupting mailbox.

Parameters:
spectxSpecifies the SPE thread whose outbound mailbox is to be read.
mbox_data
count
Return values:
>0the number of 32-bit mailbox messages read
=0no data available
-1error condition and errno is set
Possible values for errno:
EINVAL speid is invalid
Exxxx what else do we need here??

Definition at line 58 of file mbox.c.

References _base_spe_open_if_closed(), spe_context::base_private, DEBUG_PRINTF, FD_MBOX, spe_context_base_priv::flags, and SPE_MAP_PS.

{
        int rc;

        if (mbox_data == NULL || count < 1){
                errno = EINVAL;
                return -1;
        }

        if (spectx->base_private->flags & SPE_MAP_PS) {
                rc = _base_spe_out_mbox_read_ps(spectx, mbox_data, count);
        } else {
                rc = read(_base_spe_open_if_closed(spectx,FD_MBOX, 0), mbox_data, count*4);
                DEBUG_PRINTF("%s read rc: %d\n", __FUNCTION__, rc);
                if (rc != -1) {
                        rc /= 4;
                } else {
                        if (errno == EAGAIN ) { // no data ready to be read
                                errno = 0;
                                rc = 0;
                        }
                }
        }
        return rc;
}

Here is the call graph for this function:

int _base_spe_out_mbox_status ( spe_context_ptr_t  spectx)

The _base_spe_out_mbox_status function fetches the status of the SPU outbound mailbox for the SPE thread specified by the speid parameter. A 0 value is return if the mailbox is empty. A non-zero value specifies the number of 32-bit unread mailbox entries.

Parameters:
spectxSpecifies the SPE context whose mailbox status is to be read.
Returns:
On success, returns the current status of the mailbox, respectively. On failure, -1 is returned.
See also:
spe_read_out_mbox, spe_write_in_mbox, read (2)

Definition at line 220 of file mbox.c.

References _base_spe_open_if_closed(), spe_context::base_private, spe_context_base_priv::cntl_mmap_base, FD_MBOX_STAT, spe_context_base_priv::flags, SPE_MAP_PS, and spe_spu_control_area::SPU_Mbox_Stat.

{
        int rc, ret;
        volatile struct spe_spu_control_area *cntl_area =
                spectx->base_private->cntl_mmap_base;

        if (spectx->base_private->flags & SPE_MAP_PS) {
                ret = cntl_area->SPU_Mbox_Stat & 0xFF;
        } else {
                rc = read(_base_spe_open_if_closed(spectx,FD_MBOX_STAT, 0), &ret, 4);
                if (rc != 4)
                        ret = -1;
        }

        return ret;
        
}

Here is the call graph for this function:

int _base_spe_program_load ( spe_context_ptr_t  spectx,
spe_program_handle_t program 
)

_base_spe_program_load loads an ELF image into a context

Parameters:
spectxSpecifies the SPE context
programhandle to the ELF image

Definition at line 203 of file load.c.

References _base_spe_load_spe_elf(), _base_spe_program_load_complete(), spe_context::base_private, DEBUG_PRINTF, spe_context_base_priv::emulated_entry, spe_ld_info::entry, spe_context_base_priv::entry, spe_context_base_priv::flags, spe_context_base_priv::loaded_program, spe_context_base_priv::mem_mmap_base, SPE_ISOLATE, and SPE_ISOLATE_EMULATE.

{
        int rc = 0;
        struct spe_ld_info ld_info;

        spe->base_private->loaded_program = program;

        if (spe->base_private->flags & SPE_ISOLATE) {
                rc = spe_start_isolated_app(spe, program);

        } else if (spe->base_private->flags & SPE_ISOLATE_EMULATE) {
                rc = spe_start_emulated_isolated_app(spe, program, &ld_info);

        } else {
                rc = _base_spe_load_spe_elf(program,
                                spe->base_private->mem_mmap_base, &ld_info);
                if (!rc)
                        _base_spe_program_load_complete(spe);
        }

        if (rc != 0) {
                DEBUG_PRINTF ("Load SPE ELF failed..\n");
                return -1;
        }

        spe->base_private->entry = ld_info.entry;
        spe->base_private->emulated_entry = ld_info.entry;

        return 0;
}

Here is the call graph for this function:

void _base_spe_program_load_complete ( spe_context_ptr_t  spectx)

Signal that the program load has completed. For normal apps, this is called directly in the load path. For (emulated) isolated apps, the load is asynchronous, so this needs to be called when we know that the load has completed

Precondition:
spe->base_priv->loaded_program is a valid SPE program
Parameters:
spectxThe spe context that has been loaded.

Register the SPE program's start address with the oprofile and gdb, by writing to the object-id file.

Definition at line 38 of file load.c.

References __spe_context_update_event(), spe_context::base_private, DEBUG_PRINTF, spe_program_handle::elf_image, spe_context_base_priv::fd_spe_dir, and spe_context_base_priv::loaded_program.

Referenced by _base_spe_context_run(), and _base_spe_program_load().

{
        int objfd, len;
        char buf[20];
        spe_program_handle_t *program;

        program = spectx->base_private->loaded_program;

        if (!program || !program->elf_image) {
                DEBUG_PRINTF("%s called, but no program loaded\n", __func__);
                return;
        }

        objfd = openat(spectx->base_private->fd_spe_dir, "object-id", O_RDWR);
        if (objfd < 0)
                return;

        len = sprintf(buf, "%p", program->elf_image);
        write(objfd, buf, len + 1);
        close(objfd);

        __spe_context_update_event();
}

Here is the call graph for this function:

void* _base_spe_ps_area_get ( struct spe_context spectx,
enum ps_area  area 
)

_base_spe_ps_area_get returns a pointer to the start of memory mapped problem state area

Parameters:
spectxSpecifies the SPE context
areaspecifes the area to map
int _base_spe_signal_write ( spe_context_ptr_t  spectx,
unsigned int  signal_reg,
unsigned int  data 
)

The _base_spe_signal_write function writes data to the signal notification register specified by signal_reg for the SPE thread specified by the speid parameter.

Parameters:
spectxSpecifies the SPE context whose signal register is to be written to.
signal_regSpecified the signal notification register to be written. Valid signal notification registers are:
SPE_SIG_NOTIFY_REG_1 SPE signal notification register 1
SPE_SIG_NOTIFY_REG_2 SPE signal notification register 2
dataThe 32-bit data to be written to the specified signal notification register.
Returns:
On success, spe_write_signal returns 0. On failure, -1 is returned.
See also:
spe_get_ps_area, spe_write_in_mbox

Definition at line 307 of file mbox.c.

References _base_spe_close_if_open(), _base_spe_open_if_closed(), spe_context::base_private, FD_SIG1, FD_SIG2, spe_context_base_priv::flags, spe_context_base_priv::signal1_mmap_base, spe_context_base_priv::signal2_mmap_base, SPE_MAP_PS, SPE_SIG_NOTIFY_REG_1, SPE_SIG_NOTIFY_REG_2, spe_sig_notify_1_area::SPU_Sig_Notify_1, and spe_sig_notify_2_area::SPU_Sig_Notify_2.

{
        int rc;

        if (spectx->base_private->flags & SPE_MAP_PS) {
                if (signal_reg == SPE_SIG_NOTIFY_REG_1) {
                        spe_sig_notify_1_area_t *sig = spectx->base_private->signal1_mmap_base;

                        sig->SPU_Sig_Notify_1 = data;
                } else if (signal_reg == SPE_SIG_NOTIFY_REG_2) {
                        spe_sig_notify_2_area_t *sig = spectx->base_private->signal2_mmap_base;

                        sig->SPU_Sig_Notify_2 = data;
                } else {
                        errno = EINVAL;
                        return -1;
                }
                rc = 0;
        } else {
                if (signal_reg == SPE_SIG_NOTIFY_REG_1)
                        rc = write(_base_spe_open_if_closed(spectx,FD_SIG1, 0), &data, 4);
                else if (signal_reg == SPE_SIG_NOTIFY_REG_2)
                        rc = write(_base_spe_open_if_closed(spectx,FD_SIG2, 0), &data, 4);
                else {
                        errno = EINVAL;
                        return -1;
                }
                
                if (rc == 4)
                        rc = 0;
        
                if (signal_reg == SPE_SIG_NOTIFY_REG_1)
                        _base_spe_close_if_open(spectx,FD_SIG1);
                else if (signal_reg == SPE_SIG_NOTIFY_REG_2)
                        _base_spe_close_if_open(spectx,FD_SIG2);
        }

        return rc;
}

Here is the call graph for this function:

int _base_spe_stop_reason_get ( spe_context_ptr_t  spectx)

_base_spe_stop_reason_get

Parameters:
spectxone thread for which to check why it was stopped
Return values:
0success - eventid and eventdata set appropriately
1spe has not stopped after checking last, so no data was written to event
-1an error has happened, event was not touched, errno gets set
Possible vales for errno:
EINVAL speid is invalid
Exxxx what else do we need here??
int _base_spe_stop_status_get ( spe_context_ptr_t  spectx)

_base_spe_stop_status_get

Parameters:
spectxSpecifies the SPE context